---
title: "ลิงก์ติดตั้งและ Deep Link | Tajo"
description: "สร้าง URL สำหรับติดตั้งเพื่อแจกจ่ายแอป และ deep link เพื่อพาผู้ใช้ไปยังหน้าที่ต้องการภายในแอป"
url: https://tajo.io/th/docs/stripe-apps/install-links/
markdown: https://tajo.io/th/docs/stripe-apps/install-links.md
lang: th-TH
author: "Set Noa"
author_url: https://tajo.io/th/set-noa/
robots: noindex
---

ขอสิทธิ์ใช้งานล่วงหน้า

กรอกชื่อและที่อยู่อีเมลที่ทำงานของคุณ เราจะส่งลิงก์เพื่อยืนยันคำขอเข้าใช้งาน Tajo ทางอีเมล

# ลิงก์ติดตั้งและ Deep Link

[Set Noa](https://tajo.io/th/set-noa/)

ลิงก์ติดตั้งช่วยให้คุณแจกจ่าย Stripe App ของคุณนอกมาร์เก็ตเพลสได้ ส่วน deep link จะพาผู้ใช้ไปยังหน้าที่ต้องการภายในแอปที่ติดตั้งไว้แล้วโดยตรง ทั้งสองอย่างจำเป็นต่อการเริ่มต้นใช้งานและขั้นตอนการเชื่อมต่อที่ราบรื่น

Caution

**สถานะ: วางแผนไว้ ยังไม่ได้สร้าง** Tajo ไม่มี Stripe App จึงยังไม่มีสิ่งใดในส่วนนี้ที่ติดตั้งได้ในปัจจุบัน ตัวระบุแอป URL รวมถึงข้อมูลรับรองในหน้านี้เป็นตัวอย่างประกอบคำอธิบาย ไม่ใช่ปลายทางที่ใช้งานได้จริง

## ลิงก์ติดตั้ง

ลิงก์ติดตั้งคือ URL ที่ร้านค้าใช้ติดตั้งแอปของคุณได้โดยตรง เมื่อผู้ใช้คลิกลิงก์ติดตั้ง Stripe จะจัดการขั้นตอนการติดตั้งให้ แล้วรีไดเรกต์กลับมายัง URI ที่คุณระบุไว้

### สิ่งที่ต้องเตรียม

ก่อนใช้ลิงก์ติดตั้ง ให้กำหนดค่า `allowed_redirect_uris` ใน manifest ของแอป:

```json
{
  "id": "com.tajo.brevo-integration",
  "allowed_redirect_uris": [
    "https://tajo.io/stripe/callback",
    "https://tajo.io/stripe/oauth/complete"
  ]
}
```

### รูปแบบของลิงก์ติดตั้ง

```
https://marketplace.stripe.com/oauth/v2/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&state=STATE_VALUE
```

| พารามิเตอร์ | จำเป็น | คำอธิบาย |
| --- | --- | --- |
| `client_id` | ใช่ | ID ของแอปคุณ (เช่น `com.tajo.brevo-integration`) |
| `redirect_uri` | ใช่ | ต้องตรงกับค่าใดค่าหนึ่งใน `allowed_redirect_uris` |
| `state` | แนะนำ | สตริงสุ่มสำหรับป้องกัน CSRF |

### พารามิเตอร์ในการรีไดเรกต์

หลังการติดตั้งสำเร็จ Stripe จะรีไดเรกต์ผู้ใช้ไปยัง `redirect_uri` ของคุณพร้อม query parameter เหล่านี้:

| พารามิเตอร์ | คำอธิบาย |
| --- | --- |
| `user_id` | Stripe user ID ของบัญชีที่ทำการติดตั้ง |
| `account_id` | Stripe account ID (เช่น `acct_xxxxx`) |
| `state` | ค่า `state` ที่คุณส่งไป (ใช้ตรวจสอบ CSRF) |
| `install_signature` | ลายเซ็น HMAC สำหรับยืนยันว่าการติดตั้งนั้นถูกต้อง |

ตัวอย่าง URL ที่รีไดเรกต์กลับมา:

```
https://tajo.io/stripe/callback
  ?user_id=usr_xxxxx
  &account_id=acct_xxxxx
  &state=abc123random
  &install_signature=sig_xxxxx
```

### การป้องกัน CSRF

ใช้พารามิเตอร์ `state` เสมอเพื่อป้องกันการโจมตีแบบ cross-site request forgery:

```javascript
import crypto from 'crypto';

// Generate a random state value and store it in the session
const generateInstallLink = (req, res) => {
  const state = crypto.randomBytes(32).toString('hex');

  // Store state in session for later verification
  req.session.stripeInstallState = state;

  const installUrl = new URL('https://marketplace.stripe.com/oauth/v2/authorize');
  installUrl.searchParams.set('client_id', 'com.tajo.brevo-integration');
  installUrl.searchParams.set('redirect_uri', 'https://tajo.io/stripe/callback');
  installUrl.searchParams.set('state', state);

  res.redirect(installUrl.toString());
};

// Handle the redirect callback
const handleInstallCallback = async (req, res) => {
  const { state, user_id, account_id, install_signature } = req.query;

  // Verify state matches what we stored
  if (state !== req.session.stripeInstallState) {
    return res.status(403).json({ error: 'Invalid state parameter' });
  }

  // Clear the stored state
  delete req.session.stripeInstallState;

  // Verify the install signature
  if (!verifyInstallSignature(install_signature, account_id)) {
    return res.status(403).json({ error: 'Invalid install signature' });
  }

  // Process the successful installation
  await processInstallation(user_id, account_id);

  res.redirect('/dashboard/stripe-connected');
};
```

### การตรวจสอบลายเซ็น

ตรวจสอบ `install_signature` ด้วย signing secret ของแอปคุณ:

```javascript
import crypto from 'crypto';

const verifyInstallSignature = (signature, accountId) => {
  const signingSecret = process.env.STRIPE_APP_SIGNING_SECRET;

  const expectedSignature = crypto
    .createHmac('sha256', signingSecret)
    .update(accountId)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
};
```

Caution

ใช้ `crypto.timingSafeEqual` ในการเปรียบเทียบลายเซ็นเสมอ เพื่อป้องกันการโจมตีแบบ timing attack อย่าใช้การเปรียบเทียบสตริงแบบธรรมดา (`===`)

### Signing secret

Signing secret ของแอปคุณดูได้ใน Stripe Dashboard ที่หน้าการตั้งค่าของแอป ใช้สำหรับ:

- ตรวจสอบลายเซ็นการติดตั้งจาก redirect callback
- ตรวจสอบความถูกต้องของ webhook payload จาก Stripe
- ยืนยันตัวตนของคำขอระหว่างแบ็กเอนด์ของคุณกับ Stripe

จัดเก็บ signing secret อย่างปลอดภัย:

```bash
# Set as environment variable
export STRIPE_APP_SIGNING_SECRET="whsec_xxxxx"
```

อย่าฝัง signing secret ไว้ในซอร์สโค้ด และอย่าคอมมิตเข้าระบบควบคุมเวอร์ชัน

## Deep Link

Deep link พาผู้ใช้ไปยังหน้าที่ต้องการภายใน Stripe App ที่ติดตั้งไว้แล้วโดยตรง ใช้เพื่อนำผู้ใช้จากช่องทางสื่อสารภายนอก (อีเมล การแจ้งเตือน หน้าสนับสนุน) มายังบริบทที่เกี่ยวข้องในแอป

### รูปแบบ URL ของ deep link

```
https://dashboard.stripe.com/MODE/acct_ID/PAGE?apps[APP_ID][TARGET]=VIEWPORT_ID
```

| ส่วนประกอบ | คำอธิบาย | ตัวอย่าง |
| --- | --- | --- |
| `MODE` | `live` หรือ `test` | `live` |
| `acct_ID` | Stripe account ID ปลายทาง | `acct_1234567890` |
| `PAGE` | พาธของหน้าในแดชบอร์ด | `customers/cus_xxxxx` |
| `APP_ID` | ID ของแอปคุณ | `com.tajo.brevo-integration` |
| `TARGET` | `drawer` หรือ `modal` | `drawer` |
| `VIEWPORT_ID` | viewport ที่ต้องการเปิด | `stripe.dashboard.customer.detail` |

### เป้าหมายแบบ drawer และ modal

| เป้าหมาย | พฤติกรรม | กรณีใช้งาน |
| --- | --- | --- |
| `drawer` | เปิดแอปในแผงด้านข้าง (drawer) | การใช้งานแอปแบบปกติ ดูบริบทควบคู่ไปกับหน้าเดิม |
| `modal` | เปิดแอปเป็น modal เต็มหน้าจอ | เวิร์กโฟลว์ที่ต้องโฟกัส การเริ่มต้นใช้งาน ฟอร์มที่ซับซ้อน |

### ตัวอย่าง deep link

#### เปิดหน้ารายละเอียดลูกค้าใน drawer

```
https://dashboard.stripe.com/live/acct_xxxxx/customers/cus_xxxxx
  ?apps[com.tajo.brevo-integration][drawer]=stripe.dashboard.customer.detail
```

#### เปิดการตั้งค่าใน modal

```
https://dashboard.stripe.com/live/acct_xxxxx/settings
  ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.settings
```

#### เปิดขั้นตอนการเริ่มต้นใช้งาน

```
https://dashboard.stripe.com/live/acct_xxxxx/dashboard
  ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.onboarding
```

#### เปิดหน้ารายละเอียดการชำระเงินในโหมดทดสอบ

```
https://dashboard.stripe.com/test/acct_xxxxx/payments/pi_xxxxx
  ?apps[com.tajo.brevo-integration][drawer]=stripe.dashboard.payment.detail
```

### สร้าง deep link ด้วยโค้ด

```javascript
const generateDeepLink = ({
  accountId,
  mode = 'live',
  page,
  appId = 'com.tajo.brevo-integration',
  target = 'drawer',
  viewport,
}) => {
  const baseUrl = `https://dashboard.stripe.com/${mode}/${accountId}/${page}`;
  const params = new URLSearchParams();
  params.set(`apps[${appId}][${target}]`, viewport);

  return `${baseUrl}?${params.toString()}`;
};

// Generate a link to view a customer's Brevo profile
const customerLink = generateDeepLink({
  accountId: 'acct_xxxxx',
  page: 'customers/cus_xxxxx',
  viewport: 'stripe.dashboard.customer.detail',
});

// Generate a link to app settings
const settingsLink = generateDeepLink({
  accountId: 'acct_xxxxx',
  page: 'settings',
  viewport: 'stripe.dashboard.settings',
  target: 'modal',
});
```

### ใช้ deep link ในการสื่อสาร

Deep link มีประโยชน์เป็นพิเศษใน:

- **อีเมลแจ้งเตือน**: “ดูสถานะการซิงค์ Brevo ของลูกค้ารายนี้”
- **การตอบกลับของฝ่ายสนับสนุน**: “คลิกที่นี่เพื่อตรวจสอบการตั้งค่าการเชื่อมต่อของคุณ”
- **อีเมลเริ่มต้นใช้งาน**: “ตั้งค่า Brevo ของคุณให้เสร็จสมบูรณ์”
- **การแจ้งเตือนข้อผิดพลาด**: “ตรวจสอบปัญหาการซิงค์ของลูกค้า X”

```html
<!-- Example in an email template -->
<a href="https://dashboard.stripe.com/live/acct_xxxxx/customers/cus_xxxxx?apps[com.tajo.brevo-integration][drawer]=stripe.dashboard.customer.detail">
  View Brevo Profile in Stripe
</a>
```

## ใช้ลิงก์ติดตั้งร่วมกับ deep link

เพื่อประสบการณ์เริ่มต้นใช้งานที่ดีที่สุด ให้ใช้ลิงก์ติดตั้งควบคู่กับ deep link หลังการติดตั้ง:

1. ผู้ใช้คลิก**ลิงก์ติดตั้ง**จากเว็บไซต์หรืออีเมลของคุณ
2. ผู้ใช้ติดตั้งแอปแล้วถูกรีไดเรกต์ไปยัง callback URL ของคุณ
3. callback ของคุณประมวลผลการติดตั้ง แล้วรีไดเรกต์ผู้ใช้ไปยัง **deep link** ที่เปิด viewport สำหรับการเริ่มต้นใช้งาน

```javascript
const handleInstallCallback = async (req, res) => {
  const { account_id, install_signature, state } = req.query;

  // Verify state and signature
  // ... (verification code)

  // Process installation
  await processInstallation(account_id);

  // Redirect to the app's onboarding view via deep link
  const onboardingLink = generateDeepLink({
    accountId: account_id,
    page: 'dashboard',
    viewport: 'stripe.dashboard.onboarding',
    target: 'modal',
  });

  res.redirect(onboardingLink);
};
```

Tip

ทดสอบลิงก์ติดตั้งและ deep link ทั้งในโหมด live และ test เสมอ เพื่อให้มั่นใจว่าทำงานได้ถูกต้องในทุกสภาพแวดล้อม
