连接自定义支付网关

“其他”结账服务提供商让您的店铺通过您自己的支付网关收款。您需要在“店铺设置”中向 MallBasket 提供两项内容:一个支付 URL 端点(您的服务器)和一个共享密钥。MallBasket 会向您的端点发送签名请求以获取付款链接;付款完成后,您的网关会向 MallBasket 回发签名的 webhook。这是一项面向开发者的集成。

在应用中设置

在“店铺设置 → 在线支付(已启用)→ 高级版 → 结账服务提供商”中选择“其他”,然后输入您的支付 URL 端点和共享密钥(用于为双向的每条消息签名)。请妥善保管密钥:任何持有它的人都可以授权订单。

1. MallBasket 向您请求支付 URL

买家结账时,MallBasket 会向您的端点发送签名的 POST 请求。请验证签名,在您这一侧按完全相同的金额和货币创建支付会话,并返回其 URL。

POST → 您的端点 · 请求体(application/json)
{
  "orderId": "6f2a…",              // your MallBasket order id
  "transactionId": "o_6f2a…",     // echo this back in the webhook
  "storeId": "store_abc",
  "userId": "user_123",
  "amount": "12.50",              // decimal string, charge exactly this
  "currency": "USD",
  "email": "buyer@example.com",
  "webhookUrl": "https://europe-west3-mallbasket.cloudfunctions.net/otherWebhook",
  "successUrl": "https://www.mallbasket.com/en/payment/complete?orderId=6f2a…&status=success",
  "cancelUrl": "https://www.mallbasket.com/en/payment/complete?orderId=6f2a…&status=cancelled",
  "nonce": "b1d9…",
  "metadata": { "itemId": "item_1" }
}
请求头
x-mb-signature: <hex hmac-sha256 of the raw body with your secret>

返回托管支付页面的 URL,MallBasket 会为买家打开它。(也接受 data.paymentURL 和 url。)

您的响应 · 200(application/json)
{
  "paymentURL": "https://your-gateway.example.com/pay/abc123"
}

2. 您的网关通知 MallBasket(webhook)

买家付款后,以 POST 方式向我们发送给您的 webhookUrl 发送一条签名消息。MallBasket 会验证签名,确认金额与订单一致,并将订单标记为已付款。只有在付款真正完成结算后,才发送状态“success”。

POST → webhookUrl · 请求体(application/json)
{
  "orderId": "6f2a…",           // same order id
  "transactionId": "o_6f2a…",  // the transactionId we sent you
  "status": "success",          // only send this once payment truly succeeded
  "amount": "12.50",            // must equal the amount we sent
  "currency": "USD",
  "reference": "your-gateway-txn-id"   // optional, shown on the receipt
}
请求头
x-mb-signature: <hex hmac-sha256 of the raw body with your secret>

3. 签名(双向)

每个请求都带有 x-mb-signature 请求头:使用您的共享密钥对原始(RAW)请求体计算的十六进制 HMAC-SHA256。请基于实际发送的字节计算签名,并基于收到的原始字节验证传入请求(而不是重新序列化后的对象)。

// Node.js: sign the EXACT raw body bytes you are about to send
const crypto = require("crypto");

const rawBody = JSON.stringify(payload);          // the bytes you POST
const signature = crypto
  .createHmac("sha256", MALLBASKET_SECRET)        // your restricted key
  .update(rawBody, "utf8")
  .digest("hex");

// send header:  x-mb-signature: <signature>
验证传入请求
// Node.js: verify a request MallBasket sent to your endpoint
const crypto = require("crypto");

function verify(rawBody, headerSig, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody, "utf8")                        // RAW bytes, not re-parsed JSON
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(headerSig || "")
  );
}

规则与保证

  • 金额必须一致:webhook 中的金额必须与 MallBasket 发送的金额相同且货币相同,否则会被拒绝。
  • 请原样返回 transactionId。MallBasket 依据它将付款与订单匹配。
  • MallBasket 仅使用您店铺的密钥验证您的 webhook;其他店铺无法完成您的订单。
  • 完成处理是幂等的:可以安全地重试 webhook。订单记录后 MallBasket 会返回 2xx;遇到任何非 2xx 响应时请重试。
  • 在款项真正收取之前,切勿发送状态“success”。