---
title: "Install Link & Deep Link | Tajo"
description: "Buat URL instalasi untuk distribusi aplikasi dan deep link untuk mengarahkan pengguna ke tampilan tertentu di dalam aplikasi"
url: https://tajo.io/in/docs/stripe-apps/install-links/
markdown: https://tajo.io/in/docs/stripe-apps/install-links.md
lang: id-ID
author: "Set Noa"
author_url: https://tajo.io/in/set-noa/
robots: noindex
---

Ajukan akses awal

Masukkan nama depan dan alamat email kerja Anda. Kami akan mengirim tautan untuk mengonfirmasi permintaan akses Tajo.

# Install Link & Deep Link

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

Install link memungkinkan Anda mendistribusikan Stripe App di luar marketplace, sedangkan deep link mengarahkan pengguna langsung ke tampilan tertentu di dalam aplikasi yang sudah terpasang. Keduanya penting untuk alur onboarding dan integrasi yang mulus.

Caution

**Status: direncanakan, belum dibangun.** Tajo tidak memiliki Stripe App, jadi saat ini tidak ada apa pun di bagian ini yang dapat dipasang. Identifier aplikasi, URL, serta kredensial pada halaman ini adalah placeholder ilustratif, bukan endpoint aktif.

## Install link

Install link menyediakan URL langsung yang dapat digunakan merchant untuk memasang aplikasi Anda. Ketika pengguna mengeklik install link, Stripe menangani alur instalasi lalu mengarahkan pengguna kembali ke URI yang Anda tentukan.

### Prasyarat

Sebelum menggunakan install link, konfigurasikan `allowed_redirect_uris` pada manifest aplikasi Anda:

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

### Format install link

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

| Parameter | Wajib | Deskripsi |
| --- | --- | --- |
| `client_id` | Ya | ID aplikasi Anda (misalnya `com.tajo.brevo-integration`) |
| `redirect_uri` | Ya | Harus cocok dengan salah satu `allowed_redirect_uris` Anda |
| `state` | Disarankan | String acak untuk proteksi CSRF |

### Parameter pengalihan

Setelah instalasi berhasil, Stripe mengarahkan pengguna ke `redirect_uri` Anda beserta parameter query berikut:

| Parameter | Deskripsi |
| --- | --- |
| `user_id` | ID pengguna Stripe dari akun yang memasang aplikasi |
| `account_id` | ID akun Stripe (misalnya `acct_xxxxx`) |
| `state` | Nilai `state` yang Anda kirimkan (untuk verifikasi CSRF) |
| `install_signature` | Tanda tangan HMAC untuk memastikan instalasi sah |

Contoh URL pengalihan:

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

### Proteksi CSRF

Selalu gunakan parameter `state` untuk mencegah serangan 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');
};
```

### Verifikasi tanda tangan

Verifikasi `install_signature` menggunakan signing secret aplikasi Anda:

```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

Selalu gunakan `crypto.timingSafeEqual` untuk membandingkan tanda tangan agar terhindar dari timing attack. Jangan pernah memakai perbandingan string biasa (`===`).

### Signing secret

Signing secret aplikasi Anda tersedia di Stripe Dashboard pada halaman pengaturan aplikasi. Gunakan signing secret untuk:

- Memverifikasi tanda tangan instalasi dari callback pengalihan
- Memvalidasi payload webhook dari Stripe
- Mengautentikasi permintaan antara backend Anda dan Stripe

Simpan signing secret dengan aman:

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

Jangan pernah menuliskan signing secret secara hardcode di kode sumber Anda atau menyimpannya ke version control.

## Deep link

Deep link mengarahkan pengguna langsung ke tampilan tertentu di dalam Stripe App yang sudah terpasang. Gunakan deep link untuk membawa pengguna dari komunikasi eksternal (email, notifikasi, halaman dukungan) ke konteks aplikasi yang relevan.

### Format URL deep link

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

| Komponen | Deskripsi | Contoh |
| --- | --- | --- |
| `MODE` | `live` atau `test` | `live` |
| `acct_ID` | ID akun Stripe tujuan | `acct_1234567890` |
| `PAGE` | Path halaman dasbor | `customers/cus_xxxxx` |
| `APP_ID` | ID aplikasi Anda | `com.tajo.brevo-integration` |
| `TARGET` | `drawer` atau `modal` | `drawer` |
| `VIEWPORT_ID` | Viewport yang akan dibuka | `stripe.dashboard.customer.detail` |

### Target drawer vs modal

| Target | Perilaku | Kasus penggunaan |
| --- | --- | --- |
| `drawer` | Membuka aplikasi di panel samping (drawer) | Interaksi aplikasi bawaan, konteks berdampingan dengan halaman |
| `modal` | Membuka aplikasi dalam overlay modal layar penuh | Alur kerja terfokus, onboarding, formulir kompleks |

### Contoh deep link

#### Membuka tampilan detail pelanggan di drawer

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

#### Membuka pengaturan di modal

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

#### Membuka alur onboarding

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

#### Membuka tampilan detail pembayaran di mode test

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

### Membuat deep link secara terprogram

```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',
});
```

### Menggunakan deep link dalam komunikasi

Deep link sangat berguna untuk:

- **Notifikasi email**: “Lihat status sinkronisasi Brevo untuk pelanggan ini”
- **Balasan dukungan**: “Klik di sini untuk memeriksa pengaturan integrasi Anda”
- **Email onboarding**: “Selesaikan penyiapan Brevo Anda”
- **Peringatan error**: “Tinjau masalah sinkronisasi untuk pelanggan 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>
```

## Menggabungkan install link dan deep link

Untuk pengalaman onboarding terbaik, gabungkan install link dengan deep link pasca-instalasi:

1. Pengguna mengeklik **install link** dari situs web atau email Anda
2. Pengguna memasang aplikasi lalu diarahkan ke URL callback Anda
3. Callback Anda memproses instalasi dan mengarahkan pengguna ke **deep link** yang membuka viewport onboarding

```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

Selalu uji install link dan deep link di mode live maupun test untuk memastikan keduanya bekerja dengan benar di semua environment.
