Install Link & Deep Link
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.
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:
{ "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_xxxxxProteksi CSRF
Selalu gunakan parameter state untuk mencegah serangan cross-site request forgery:
import crypto from 'crypto';
// Generate a random state value and store it in the sessionconst 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 callbackconst 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:
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:
# Set as environment variableexport 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.detailMembuka pengaturan di modal
https://dashboard.stripe.com/live/acct_xxxxx/settings ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.settingsMembuka alur onboarding
https://dashboard.stripe.com/live/acct_xxxxx/dashboard ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.onboardingMembuka 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.detailMembuat deep link secara terprogram
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 profileconst customerLink = generateDeepLink({ accountId: 'acct_xxxxx', page: 'customers/cus_xxxxx', viewport: 'stripe.dashboard.customer.detail',});
// Generate a link to app settingsconst 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”
<!-- 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:
- Pengguna mengeklik install link dari situs web atau email Anda
- Pengguna memasang aplikasi lalu diarahkan ke URL callback Anda
- Callback Anda memproses instalasi dan mengarahkan pengguna ke deep link yang membuka viewport onboarding
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.