Liên kết cài đặt và liên kết sâu
Liên kết cài đặt giúp bạn phân phối Stripe App bên ngoài marketplace, còn liên kết sâu đưa người dùng thẳng tới một màn hình cụ thể bên trong ứng dụng đã cài. Cả hai đều thiết yếu để luồng làm quen và luồng tích hợp diễn ra mượt mà.
Liên kết cài đặt
Liên kết cài đặt cung cấp một URL trực tiếp để nhà bán hàng cài ứng dụng của bạn. Khi người dùng nhấp vào liên kết cài đặt, Stripe xử lý luồng cài đặt rồi chuyển hướng trở lại URI mà bạn đã chỉ định.
Điều kiện tiên quyết
Trước khi dùng liên kết cài đặt, hãy cấu hình allowed_redirect_uris trong manifest của ứng dụng:
{ "id": "com.tajo.brevo-integration", "allowed_redirect_uris": [ "https://tajo.io/stripe/callback", "https://tajo.io/stripe/oauth/complete" ]}Định dạng liên kết cài đặt
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ó | ID ứng dụng của bạn (ví dụ com.tajo.brevo-integration) |
redirect_uri | Có | Phải khớp với một trong các allowed_redirect_uris của bạn |
state | Nên có | Chuỗi ngẫu nhiên để chống CSRF |
Tham số chuyển hướng
Sau khi cài đặt thành công, Stripe chuyển hướng người dùng tới redirect_uri của bạn kèm các tham số truy vấn sau:
| Tham số | Mô tả |
|---|---|
user_id | ID người dùng Stripe của tài khoản thực hiện cài đặt |
account_id | ID tài khoản Stripe (ví dụ acct_xxxxx) |
state | Giá trị state bạn đã cung cấp (để xác minh chống CSRF) |
install_signature | Chữ ký HMAC dùng để xác minh lượt cài đặt là hợp lệ |
Ví dụ URL chuyển hướng:
https://tajo.io/stripe/callback ?user_id=usr_xxxxx &account_id=acct_xxxxx &state=abc123random &install_signature=sig_xxxxxChống CSRF
Luôn dùng tham số state để ngăn các cuộc tấn công giả mạo yêu cầu liên trang:
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');};Xác minh chữ ký
Xác minh install_signature bằng khóa ký bí mật của ứng dụng:
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 dùng crypto.timingSafeEqual khi so sánh chữ ký để chống tấn công dựa trên thời gian. Đừng bao giờ so sánh chuỗi theo cách đơn giản (===).
Khóa ký bí mật
Khóa ký bí mật của ứng dụng nằm trong Stripe Dashboard, ở phần cài đặt ứng dụng của bạn. Hãy dùng nó để:
- Xác minh chữ ký cài đặt từ các lệnh gọi lại chuyển hướng
- Kiểm tra tính hợp lệ của payload webhook từ Stripe
- Xác thực các yêu cầu giữa backend của bạn và Stripe
Lưu khóa ký bí mật ở nơi an toàn:
# Set as environment variableexport STRIPE_APP_SIGNING_SECRET="whsec_xxxxx"Đừng bao giờ gán cứng khóa ký bí mật trong mã nguồn hay commit chúng vào hệ thống quản lý phiên bản.
Liên kết sâu
Liên kết sâu đưa người dùng thẳng tới một màn hình cụ thể bên trong Stripe App đã cài. Hãy dùng chúng để dẫn người dùng từ các kênh liên lạc bên ngoài (email, thông báo, trang hỗ trợ) tới đúng ngữ cảnh trong ứng dụng.
Định dạng URL của liên kết sâu
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 | ID tài khoản Stripe đích | acct_1234567890 |
PAGE | Đường dẫn trang trong Dashboard | customers/cus_xxxxx |
APP_ID | ID ứng dụng của bạn | com.tajo.brevo-integration |
TARGET | drawer hoặc modal | drawer |
VIEWPORT_ID | Viewport cần mở | stripe.dashboard.customer.detail |
So sánh đích drawer và modal
| Đích | Hành vi | Trường hợp sử dụng |
|---|---|---|
drawer | Mở ứng dụng trong bảng bên cạnh (drawer) | Tương tác mặc định, xem ngữ cảnh song song với trang đang mở |
modal | Mở ứng dụng trong lớp phủ modal toàn màn hình | Quy trình cần tập trung, luồng làm quen, biểu mẫu phức tạp |
Ví dụ về liên kết sâu
Mở màn hình chi tiết khách hàng trong drawer
https://dashboard.stripe.com/live/acct_xxxxx/customers/cus_xxxxx ?apps[com.tajo.brevo-integration][drawer]=stripe.dashboard.customer.detailMở phần cài đặt trong modal
https://dashboard.stripe.com/live/acct_xxxxx/settings ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.settingsMở luồng làm quen
https://dashboard.stripe.com/live/acct_xxxxx/dashboard ?apps[com.tajo.brevo-integration][modal]=stripe.dashboard.onboardingMở màn hình chi tiết thanh toán ở chế độ test
https://dashboard.stripe.com/test/acct_xxxxx/payments/pi_xxxxx ?apps[com.tajo.brevo-integration][drawer]=stripe.dashboard.payment.detailTạo liên kết sâu bằng mã lệ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()}`;};
// 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',});Dùng liên kết sâu trong các kênh liên lạc
Liên kết sâu đặc biệt hữu ích trong:
- Email thông báo: “Xem trạng thái đồng bộ Brevo của 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 làm quen: “Hoàn tất thiết lập Brevo của bạn”
- Cảnh báo lỗi: “Xem lại sự cố đồng bộ của khách hàng 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>Kết hợp liên kết cài đặt với liên kết sâu
Để có trải nghiệm làm quen tốt nhất, hãy kết hợp liên kết cài đặt với liên kết sâu chạy sau khi cài:
- Người dùng nhấp vào một liên kết cài đặt từ website hoặc email của bạn
- Người dùng cài ứng dụng và được chuyển hướng tới URL gọi lại của bạn
- Lệnh gọi lại của bạn xử lý việc cài đặt rồi chuyển hướng người dùng tới một liên kết sâu mở viewport làm quen
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
Luôn kiểm thử liên kết cài đặt và liên kết sâu ở cả chế độ live lẫn test để chắc chắn chúng hoạt động đúng trong mọi môi trường.