Install Links & Deep Links
Install links cho phép bạn phân phối Stripe App bên ngoài marketplace, trong khi deep links điều hướng người dùng trực tiếp đến các views cụ thể trong app đã cài đặt của bạn. Cả hai đều thiết yếu cho trải nghiệm onboarding và luồng tích hợp mượt mà.
Install Links
Install links cung cấp URL trực tiếp mà merchants có thể sử dụng để cài đặt app của bạn. Khi người dùng nhấp vào install link, Stripe xử lý luồng cài đặt rồi chuyển hướng về URI đã chỉ định của bạn.
Điều Kiện Tiên Quyết
Trước khi sử dụng install links, hãy cấu hình allowed_redirect_uris trong app manifest:
{ "id": "com.tajo.brevo-integration", "allowed_redirect_uris": [ "https://tajo.io/stripe/callback", "https://tajo.io/stripe/oauth/complete" ]}Định Dạng Install Link
https://marketplace.stripe.com/oauth/v2/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&state=STATE_VALUE| Tham Số | Bắt Buộc | Mô Tả |
|---|---|---|
client_id | Có | App ID của bạn (ví dụ: com.tajo.brevo-integration) |
redirect_uri | Có | Phải khớp với một trong allowed_redirect_uris của bạn |
state | Khuyến nghị | Chuỗi ngẫu nhiên để bảo vệ CSRF |
Tham Số Redirect
Sau khi cài đặt thành công, Stripe chuyển hướng người dùng đến redirect_uri của bạn với các tham số query này:
| Tham Số | Mô Tả |
|---|---|
user_id | Stripe user ID của tài khoản cài đặt |
account_id | Stripe account ID (ví dụ: acct_xxxxx) |
state | Giá trị state bạn đã cung cấp (để xác minh CSRF) |
install_signature | Chữ ký HMAC để xác minh cài đặt hợp lệ |
Ví dụ URL redirect:
https://tajo.io/stripe/callback ?user_id=usr_xxxxx &account_id=acct_xxxxx &state=abc123random &install_signature=sig_xxxxxBảo Vệ CSRF
Luôn sử dụng tham số state để ngăn chặn tấn công cross-site request forgery:
import crypto from 'crypto';
// Tạo giá trị state ngẫu nhiên và lưu trong sessionconst generateInstallLink = (req, res) => { const state = crypto.randomBytes(32).toString('hex');
// Lưu state trong session để xác minh sau 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());};
// Xử lý redirect callbackconst handleInstallCallback = (req, res) => { const { state, user_id, account_id, install_signature } = req.query;
// Xác minh state khớp với những gì đã lưu if (state !== req.session.stripeInstallState) { return res.status(403).json({ error: 'Invalid state parameter' }); }
// Xóa state đã lưu delete req.session.stripeInstallState;
// Xác minh install signature if (!verifyInstallSignature(install_signature, account_id)) { return res.status(403).json({ error: 'Invalid install signature' }); }
// Xử lý cài đặt thành công await processInstallation(user_id, account_id);
res.redirect('/dashboard/stripe-connected');};Xác Minh Chữ Ký
Xác minh install_signature sử dụng signing secret của app:
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
Luôn sử dụng crypto.timingSafeEqual để so sánh chữ ký nhằm ngăn chặn timing attacks. Không bao giờ sử dụng so sánh chuỗi đơn giản (===).
Signing Secret
Signing secret của app có trong Stripe Dashboard dưới phần cài đặt app. Sử dụng nó để:
- Xác minh install signatures từ redirect callbacks
- Xác thực webhook payloads từ Stripe
- Xác thực các requests giữa backend và Stripe
Lưu trữ signing secret an toàn:
# Đặt làm biến môi trườngexport STRIPE_APP_SIGNING_SECRET="whsec_xxxxx"Không bao giờ hardcode signing secrets trong source code hoặc commit vào version control.
Deep Links
Deep links điều hướng người dùng trực tiếp đến một view cụ thể trong Stripe App đã cài đặt. Sử dụng chúng để hướng người dùng từ các thông tin liên lạc bên ngoài (email, thông báo, trang hỗ trợ) đến context app liên quan.
Định Dạng URL Deep Link
https://dashboard.stripe.com/MODE/acct_ID/PAGE?apps[APP_ID][TARGET]=VIEWPORT_ID| Thành Phần | Mô Tả | Ví Dụ |
|---|---|---|
MODE | live hoặc test | live |
acct_ID | Stripe account ID đích | acct_1234567890 |
PAGE | Đường dẫn trang Dashboard | customers/cus_xxxxx |
APP_ID | App ID của bạn | com.tajo.brevo-integration |
TARGET | drawer hoặc modal | drawer |
VIEWPORT_ID | Viewport để mở | stripe.dashboard.customer.detail |
Drawer So Với Modal Targets
| Target | Hành Vi | Trường Hợp Sử Dụng |
|---|---|---|
drawer | Mở app trong side panel (drawer) | Tương tác app mặc định, context bên cạnh trang |
modal | Mở app trong modal overlay toàn màn hình | Luồng tập trung, onboarding, forms phức tạp |
Ví Dụ Deep Link
Mở customer detail view trong drawer
https://dashboard.stripe.com/live/acct_xxxxx/customers/cus_xxxxx ?apps[com.tajo.brevo-integration][drawer]=stripe.dashboard.customer.detailMở settings trong modal
https://dashboard.stripe.com/live/acct_xxxxx/settings ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.settingsMở onboarding flow
https://dashboard.stripe.com/live/acct_xxxxx/dashboard ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.onboardingTạo Deep Links Theo Chương Trình
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()}`;};
// Tạo link để xem Brevo profile của khách hàngconst customerLink = generateDeepLink({ accountId: 'acct_xxxxx', page: 'customers/cus_xxxxx', viewport: 'stripe.dashboard.customer.detail',});
// Tạo link đến app settingsconst settingsLink = generateDeepLink({ accountId: 'acct_xxxxx', page: 'settings', viewport: 'stripe.dashboard.settings', target: 'modal',});Sử Dụng Deep Links Trong Thông Tin Liên Lạc
Deep links đặc biệt hữu ích trong:
- Email notifications: “Xem trạng thái Brevo sync cho khách hàng này”
- Phản hồi hỗ trợ: “Nhấp vào đây để kiểm tra cài đặt tích hợp của bạn”
- Email onboarding: “Hoàn thành thiết lập Brevo của bạn”
- Cảnh báo lỗi: “Xem xét vấn đề sync cho khách hàng X”
<!-- Ví dụ trong 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>Kết Hợp Install Links Và Deep Links
Để có trải nghiệm onboarding tốt nhất, kết hợp install links với post-install deep links:
- Người dùng nhấp vào install link từ website hoặc email của bạn
- Người dùng cài đặt app và được chuyển hướng đến callback URL của bạn
- Callback của bạn xử lý cài đặt và chuyển hướng người dùng đến deep link mở onboarding viewport
const handleInstallCallback = async (req, res) => { const { account_id, install_signature, state } = req.query;
// Xác minh state và signature // ... (verification code)
// Xử lý cài đặt await processInstallation(account_id);
// Chuyển hướng đến onboarding view của app qua deep link const onboardingLink = generateDeepLink({ accountId: account_id, page: 'dashboard', viewport: 'stripe.dashboard.onboarding', target: 'modal', });
res.redirect(onboardingLink);};Tip
Luôn kiểm thử install links và deep links trong cả chế độ live và test để đảm bảo chúng hoạt động chính xác trong mọi môi trường.