支付服务

下单 / 查询 / 退款

支付走"两段式":SMP 持有 ISV 凭证调微信 / 支付宝下单 → 资金结算到该订单指定的子商户。 所有接口的 X-Service-Codepayments

支持的渠道

  • 微信支付 — 服务商 Native(PC 二维码) + JSAPI(小程序)
  • 支付宝 — page(PC 跳转) + wap(H5)+ jsapi / precreate(按需)

创建订单

POST/v1/payments/orders
ts
const order = await smp("POST", "/v1/payments/orders", "payments", {
  outTradeNo: "your_unique_id",       // 自家系统的唯一交易号
  amount: 99.00,                      // 单位:元
  description: "年费会员",
  channel: "wechat",                  // wechat | alipay
  notifyUrl: "https://your.domain/notify",
  returnUrl: "https://...",           // 可选;alipay page 模式跳回
  subMerchantId: "",                  // 可选;指定子商户 id
  distributorExternalUserId: "...",   // 可选;按 (platformId, distributor_user_id) 解析子商户
});

子商户解析优先级

  1. 显式 subMerchantId(payment_onboarding 主键)
  2. distributorExternalUserId → 按 (本 platform, 该 distributor user) 查
  3. 都没传 → 取本 platform 自身的子商户(distributor_external_user_id IS NULL

返回(微信 Native)

json
{
  "id": "<smp 内部订单 id>",
  "outTradeNo": "your_unique_id",
  "amount": 99,
  "channel": "wechat",
  "status": "pending",
  "payParams": {
    "codeUrl": "weixin://wxpay/bizpayurl?pr=...",
    "code_url": "weixin://wxpay/bizpayurl?pr=..."
  }
}

返回(支付宝 page)

json
{
  "payParams": {
    "payUrl": "https://openapi.alipay.com/...",
    "formHtml": "<form>...</form>"
  }
}

查询订单

GET/v1/payments/orders/{id}

如果订单仍是 pending,SMP 会顺带主动 query 一次上游状态再返回。id 也接受outTradeNo

列出订单

GET/v1/payments/orders?status=&channel=&distributor_tenant_id=&limit=&offset=

distributor_tenant_id 通过 metadata.distributor_tenant_id 后过滤。

退款

POST/v1/payments/refunds
ts
await smp("POST", "/v1/payments/refunds", "payments", {
  orderId: order.id,
  amount: 99.00,            // 元,可小于订单金额(部分退)
  reason: "用户申请",
});

status === "paid" 的订单可退款。退款发起后会异步收到微信/wechat/refund/notify,SMP 处理后再转发到该订单的 notifyUrl, 转发 body 里 metadata.notify_event = "refund"status 变成refunded

订单生命周期

diagram
pending  ──支付成功──▶  paid  ──退款──▶  refunded
   │
   └─用户放弃──▶  cancelled
   │
   └─下单失败──▶  failed

常见问题

  • 下单时报"未完成微信进件或缺少 sub_mchid" — 该 platform 或对应的 distributor user 还没完成进件, 先走子商户进件
  • 支付宝订单返回 formHtml 不知怎么用 — 把它直接 inject 到页面里 submit 即可,或解析其中的 action/params 改 GET 跳转。
  • 退款回调没收到 — 确认 SMP 启动时配了 WECHAT_REFUND_NOTIFY_URL;微信要求该地址必须是公网 https。