Files
xin-procurement/docs/api/mini-online-payment.md
T
2026-08-27 21:17:02 +08:00

9.0 KiB
Raw Blame History

小程序接口文档:在线支付(旺铺网关 JSAPI)

门店端在线支付:选择本店未支付账单合并付款,后端经旺铺支付网关(统一下单B-JSAPI)下单, 小程序调起 wx.requestPayment 完成支付;支付结果由网关后台通知自动结账, 小程序端也可主动查询同步结果(回调延迟/丢失时的兜底)。

结账效果与线下凭证审核一致:关联账单批量置「已支付」、累加门店总采购金额、门店收到支付成功通知。

整体流程

小程序                后端                     旺铺网关              微信
  │  wx.login → code    │                        │                   │
  │  POST /mini/payment/online (bill_ids, code)  │                   │
  │────────────────────▶│ code2session 换 openid │──────────────────▶│
  │                     │ 创建支付单+锁定账单      │                   │
  │                     │ 统一下单(mer_order_id=支付单号) ──────────▶│
  │  返回 pay_params     │◀────────  order_id + 调起参数 ────────────│
  │◀────────────────────│                        │                   │
  │  wx.requestPayment(pay_params) ─────────────────────────────────▶│
  │                     │  POST /mini/payment/notify(支付成功通知)   │
  │                     │◀───────────────────────│                   │
  │                     │ 验签 → 幂等结账 → 应答 {"code":"00"}        │
  │  GET .../query 主动同步(兜底)                │                   │
  │────────────────────▶│ 交易查询 → 已支付则结账  │                   │

通用约定

鉴权 门店 tokenAuthorization: Bearer <token>(登录见 /mini/auth/login
响应格式 `{ "success": true
金额单位 元,字符串/数字两位小数(如 150.50

1. 发起在线支付(合并账单下单)

请求方式 POST
路径 /mini/payment/online
鉴权 门店 token

请求参数

参数 类型 必填 说明
bill_ids int[] 要合并付款的账单 ID 数组(GET /mini/bill?payable=1 返回的 id),至少 1 个
code string 小程序 wx.login() 返回的登录凭证(后端用它换付款人 openid)
remark string 付款备注,最长 255 字

校验规则(失败均返回 success:false

  • 账单必须全部属于当前门店,且为「未支付」且未被其他支付单锁定;
  • 任一账单已支付 / 正在支付中(含凭证审核中)→ 拒绝并提示对应账单号;
  • 合计金额必须大于 0
  • 微信 code 无效(code2session 失败)→ 报错,不产生支付单;
  • 网关下单失败 → 支付单自动作废、账单释放,可重新发起。

响应示例

{
  "success": true,
  "msg": "下单成功,请调起支付",
  "data": {
    "id": 12,
    "payment_no": "ZF202608270001",
    "amount": "150.50",
    "pay_params": {
      "order_id": "202608271201444525348059",
      "tradeNo": "2021082722001407831438768160",
      "user_openid": "oXxx123"
    }
  }
}

字段说明

字段 说明
payment_no 本系统支付单号(即上送网关的商户订单号 mer_order_id),后续查询/对账用
amount 应付金额(= 所选账单总额合计,元)
pay_params 旺铺网关 data 节点原样透传。调起支付所需参数以网关返回为准(服务商配置后通常包含 timeStamp/nonceStr/package/signType/paySign 等),直接透传给 wx.requestPayment 即可

小程序端调用示例

// 1. 获取登录凭证
const { code } = await wx.login();

// 2. 后端下单
const res = await request.post('/mini/payment/online', { bill_ids: [101, 102], code });
const { payment_no, pay_params } = res.data;

// 3. 调起微信支付(pay_params 以旺铺网关实际返回的调起参数为准)
await wx.requestPayment({
  timeStamp: pay_params.timeStamp,
  nonceStr: pay_params.nonceStr,
  package: pay_params.package,
  signType: pay_params.signType || 'RSA',
  paySign: pay_params.paySign,
});

// 4. 支付完成后主动同步结果(回调兜底)
const q = await request.get(`/mini/payment/online/${payment_no}/query`);
// q.data.status === 1 → 支付成功,刷新账单列表

2. 查询支付结果(主动同步)

请求方式 GET
路径 /mini/payment/online/{payment_no}/query
鉴权 门店 token(仅可查询本店支付单)

路径参数

参数 说明
payment_no 下单返回的支付单号(如 ZF202608270001

行为说明

  • 本地已是「支付成功」→ 直接返回,不再请求网关;
  • 否则向旺铺网关发起「交易查询」,网关返回已支付(order_status=1)则立即结账(与后台通知同一幂等逻辑);
  • 建议在 wx.requestPayment 成功回调后、以及付款页 onShow 时各调一次;
  • 用户中途取消支付时本接口返回 status: 0,账单仍处于锁定中,可稍后重试或联系客服释放。

响应示例

{
  "success": true,
  "msg": "支付成功",
  "data": {
    "payment_no": "ZF202608270001",
    "status": 1,
    "status_name": "支付成功",
    "paid_at": "2026-08-27 10:00:00",
    "trade_no": "2021082722001407831438768160"
  }
}

status 取值

含义
0 待支付(网关未确认)
1 支付成功(账单已置已支付)
2 支付失败(网关下单失败作废,账单已释放,可重新下单)

3. 支付结果后台通知(服务端对接,无需小程序调用)

请求方式 POST(表单)
路径 /mini/payment/notify
鉴权 无(公开路由,以报文 sign 验签)
来源 旺铺网关(下单时上送的 notifyurl,由后端自动生成:{APP_URL}/mini/payment/notify

处理逻辑

  1. 按旺铺加签规则验签(参数 ASCII 升序 key=value& 拼接 + &key=SignKeyMD5 大写);
  2. 验签失败 → 应答 {"code":"01"}
  3. mer_order_id 定位支付单,校验 order_status=1order_amt 与支付单金额一致(防篡改);
  4. 幂等结账:支付单置成功(记录 trade_no/order_id/支付时间)→ 关联账单批量置已支付 → 累加门店总采购金额(只统计商品金额)→ 站内通知门店;
  5. 重复通知直接应答成功,不重复结账。

应答报文(网关约定格式)

{ "code": "00", "msg": "成功", "timestamp": "20260827100000123" }

网关收到 code=00 才认为通知成功,否则按 2ⁿ 分钟重试 7 次。


后台配置(上线前必配)

配置优先级:后台「系统设置 → 支付配置」> .env

后台支付配置(site_config pay 组,已内置配置项)

配置项 说明
wangpu_base_url 旺铺网关域名(接口地址前缀)
wangpu_organiz_no 合作机构渠道号 organiz_no
wangpu_mer_no 旺铺内部商户号 mer_no(进件入网后返回)
wangpu_mer_code 商户号 mer_code
wangpu_term_code 终端号 term_code
wangpu_sign_key 加签专用 KeySignKey
wangpu_sub_appid 下单微信子 appid,留空取小程序自身 appid
wangpu_payway_code 支付方式代码(默认 WECHAT_MINI,以旺铺数据词典为准)

.env 备选配置

WECHAT_MINI_APPID=        # 小程序 AppIDcode2session 必需)
WECHAT_MINI_SECRET=       # 小程序 Secretcode2session 必需)
WANGPU_BASE_URL=
WANGPU_ORGANIZ_NO=
WANGPU_MER_NO=
WANGPU_MER_CODE=
WANGPU_TERM_CODE=
WANGPU_SIGN_KEY=
WANGPU_SUB_APPID=
WANGPU_PAYWAY_CODE=WECHAT_MINI

注意:APP_URL 必须是网关可访问的公网 HTTPS 地址,否则支付成功通知无法送达(此时依赖小程序主动查询兜底结账)。

与线下凭证支付的关系

两种付款方式并存,同一张账单同一时刻只能处于一条支付链路:

在线支付(本档) 线下凭证支付
入口 POST /mini/payment/online POST /mini/payment
支付单 pay_type 2 1
支付单 pay_method 4 旺铺支付 1 微信 / 2 支付宝 / 3 对公汇款
结账方式 网关通知/主动查询自动结账 后台审核通过
失败/拒绝 账单自动释放可重新付款 审核拒绝后释放

账单被任一支付单锁定期间(payment_id ≠ 0),两种入口均会拒绝重复提交。