在 iOS / Android App 收款
App 內開啟 ReBate Pay 結帳頁、付款、自動回到 App;卡號與 3D 驗證都在結帳頁完成,App 不碰卡號。
App 收款沿用網頁的 Hosted Checkout 與 Payment Link:你的後端建立一次性付款連結,App 用系統的 App 內瀏覽器開啟,付款完成後結帳頁把顧客送回你的 App。
rbp_... 金鑰打包進 App——任何人都能從 App 檔案取出來。App 只跟你自己的後端溝通。流程
- 1在主控台「開發者 → App 串接」登記你 App 的網址 scheme,例如
com.example.shop。 - 2App 請你的後端建立訂單;後端用 API 金鑰呼叫
POST /api/PaymentLink(singleUse: true),successUrl填com.example.shop://checkout/done。 - 3後端把完整網址(
REBATE_PAY_BASE_URL+ 回應的url)交給 App。 - 4App 用 ReBate Pay SDK 開啟:iOS 是
ASWebAuthenticationSession,Android 是 Chrome Custom Tabs。顧客在結帳頁刷卡、完成 3D 驗證。 - 5付款成功後,結帳頁導向
com.example.shop://checkout/done?rebatepay_checkout=chks_…&rebatepay_status=paid,SDK 把結果交回 App。 - 6App 把
rebatepay_checkout交給後端;後端用GET /api/Checkout/{id}確認這筆結帳屬於該訂單的付款連結且paid為 true(或收到payment.succeededWebhook),再出貨或開通。
1. 登記 App 網址 scheme
只有登記過的 scheme 能當 successUrl,其他非 https 的網址都會被拒絕(VALIDATION_ERROR)。最多 5 個;建議用反向網域(com.example.shop),避免和其他 App 衝突。http、https、tel、mailto、intent 等系統或網頁用的 scheme 不能登記。移除某個 scheme 後,使用它的付款連結付款完成就不會再導回 App(會停在 ReBate Pay 的完成頁)。
2. 後端建立付款連結
curl -sS -X POST "$REBATE_PAY_BASE_URL/api/PaymentLink" \
-H "Authorization: Bearer $REBATE_PAY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_1042" \
-d '{
"name": "Order #1042",
"priceId": "price_...",
"singleUse": true,
"successUrl": "com.example.shop://checkout/done?order=1042"
}'
# => { "id": "plink_...", "url": "/pay/<token>", ... }
# Give the app: $REBATE_PAY_BASE_URL + urlsuccessUrl 可以帶你自己的參數(例如 ?order=1042),ReBate Pay 會保留它們,再加上 rebatepay_checkout 與 rebatepay_status(paid 或試用的 trialing)。
3. App 開啟結帳
// Package: packages/rebatepay-ios (Swift Package "RebatePay", iOS 13+)
import RebatePay
import UIKit
final class CheckoutViewController: UIViewController {
private let checkout = RebatePayCheckout(callbackScheme: "com.example.shop")
func pay(orderId: String) async {
do {
let paymentURL = try await api.createCheckout(orderId: orderId) // your backend
let result = try await checkout.present(paymentURL: paymentURL, from: view.window!)
switch result {
case .completed(let checkoutId, _):
// Don't trust the app side: your backend checks GET /api/Checkout/{id}.
showReceipt(try await api.confirmOrder(orderId: orderId, checkoutId: checkoutId))
case .canceled:
showMessage("Payment was not completed")
}
} catch {
showMessage("Could not open checkout: \(error)")
}
}
}| iOS | Android | |
|---|---|---|
| SDK | packages/rebatepay-ios(Swift Package RebatePay) | packages/rebatepay-android(模組 :checkout) |
| 最低版本 | iOS 13 | Android 6.0(API 23) |
| 開啟方式 | ASWebAuthenticationSession(預設不共用 Safari cookie,不跳「要使用…登入」提示) | Chrome Custom Tabs;沒有支援的瀏覽器時退回預設瀏覽器 |
| 需要的 App 設定 | 不需要設定 URL Types,系統直接攔截回傳 | manifestPlaceholders["rebatepayScheme"] 設成你的 scheme |
| 顧客關掉結帳 | .canceled | RebatePayResult.Canceled |
4. 後端確認付款
App 收到的 rebatepay_status 只代表結帳頁導回了 App,任何人都能手動打開 com.example.shop://checkout/done?rebatepay_status=paid。一律由後端確認後才出貨或開通。
/api/Checkout/{id}— 查詢結帳與付款狀態(需要 payment_links:read)// POST /orders/:id/confirm — the app sends the rebatepay_checkout value it got back
app.post("/orders/:id/confirm", requireUser, async (req, res) => {
const order = await db.orders.find(req.params.id, req.user.id);
const r = await fetch(`${process.env.REBATE_PAY_BASE_URL}/api/Checkout/${req.body.checkoutId}`, {
headers: { Authorization: `Bearer ${process.env.REBATE_PAY_API_KEY}` },
});
if (!r.ok) return res.status(400).json({ paid: false });
const { data: checkout } = await r.json();
// Must be this order's link, and actually paid.
const paid = checkout.paymentLinkId === order.paymentLinkId && checkout.paid === true;
if (paid) await db.orders.markPaid(order.id, checkout.payment?.id);
res.json({ paid });
});
// Also mark the order paid from the payment.succeeded webhook — whichever arrives first wins.付款連結的 completionCount 在顧客送出結帳時就會增加,付款可能仍在處理或被拒絕,不能拿來判斷是否付款成功,請看 paid。同時訂閱 Webhook 的 payment.succeeded:顧客就算付款後沒回到 App(關掉了、手機沒電),你的後端一樣會收到通知。
不支援的做法
- 把結帳頁放進 App 內的 WebView:結帳頁禁止被嵌入(
frame-ancestors 'none'),3D 驗證的跳轉也會出問題。請用上面的 SDK。 - 在 App 裡輸入卡號後呼叫 API:卡號只能在結帳頁輸入,開發者 API 會拒絕原始卡號。
- 在 App 裡直接呼叫 Apple Pay/Google Pay:行動支付由結帳頁提供(支援的裝置會自動顯示按鈕,僅限單次付款),App 不需要也不能自己串接。
ReBate Pay Docs