1.1 小程序支付接入

公告:微信小程序「P云支付插件」已停止维护。已接入的插件版本可继续使用,但新接入请一律使用「半屏小程序拉起支付」方案(本文档),体验更好、接入更简单。

1 适用场景与角色

说明
场景 第三方自有小程序(微信 / 支付宝)内需要收款,由 P云 提供收银台与支付通道
你的角色 商户(对接方):提供小程序 + 后端服务
平台角色 提供下单接口、半屏收银台小程序、支付结果通知
支持端 微信小程序、支付宝小程序

2 整体流程

sequenceDiagram participant U as 用户 participant MP as 商户小程序 participant MS as 商户后端 participant CP as P云收银台(半屏小程序) participant PY as P云平台 participant CH as 微信/支付宝 U->>MP: 点击支付 MP->>MS: 创建订单(金额/商品/订单号) MS->>PY: POST /payment/trade/prepare Note over MS,PY: 服务端签名调用,禁止前端直连 PY-->>MS: code=1001, pay_id MS-->>MP: 返回 pay_id MP->>CP: openEmbeddedMiniProgram(appId, path?pay_id=xxx) CP->>PY: 校验 pay_id 并展示收银台 PY-->>CP: 订单信息 U->>CP: 确认支付 CP->>CH: 发起支付 CH-->>CP: 支付结果 CP-->>MP: 回传结果(App.onShow / referrerInfo.extraData) Note over MP: 仅用于页面展示,不可作为业务凭证 PY->>MS: POST notify_url (支付结果异步通知) Note over PY,MS: 未返回 code=1001 将重复通知 MS->>MS: 验签 + 按 pay_order 幂等处理 MS-->>PY: {"code":"1001"} MS->>MP: 下发最终订单状态(建议前端轮询或订阅) opt 超时未收到通知 / 状态不一致 MS->>PY: 查询交易状态 trade/query PY-->>MS: 平台实际状态 MS->>MS: 修正本地订单终态 end
步骤 动作 调用方 必须
商户前端请求后端创建订单 商户小程序 Y
发起交易预请求 trade/prepare 商户后端 Y
半屏小程序跳转 P云收银台 商户小程序 Y
前端支付结果回调(App.onShow) 平台 → 商户小程序 建议(页面展示)
支付结果异步通知 notify_url 平台 → 商户后端 Y(唯一可靠的到账依据
查询交易状态 商户后端 建议(对账 / 兜底补偿)

关键原则:④ 前端回调仅用于 UI 展示,不能作为发货或业务凭证;业务状态必须以 ⑤ 服务端通知 或 ⑥ 主动查询为准。

3 接入前置条件

  1. 提供公司全称给商务,由研发开通并下发:
    • app_id:平台分配的接入应用 ID
    • app_secret:签名密钥(仅存服务端,严禁下发到小程序端
    • merchant:商户号
  2. 确认交易场景值 trade_sceneextra 字段要求(见附录),场景传错将无法正常支付。
  3. 下单接口必须在服务端调用,禁止在小程序端直接请求(会泄露 app_secret)。

4 接入步骤

4.1 第一步:服务端下单

POST https://papi.4pyun.com/gate/1.0/payment/trade/prepare
Content-Type: application/x-www-form-urlencoded

完整字段说明见 2.2 发起交易预请求。小程序场景只需关注以下几点:

  • 必传:app_idmerchantpay_ordersubjectvaluenotify_urltrade_scenesign(签名规则见签名算法);
  • 金额 value 单位为pay_order 在同一 app_id唯一
  • trade_scene / extra 按业务场景传递,见附录
  • callback_url 半屏小程序场景不传(仅历史插件场景传小程序内页路径);
  • 该接口只能由服务端发起,小程序端只拿服务端下发的 pay_id

返回关键字段

字段 说明
code 1001 下单成功;1403 订单号已存在;其余读 message
pay_id 平台支付 ID,第三步拉起收银台需要使用
pay_url H5 收银台链接,小程序场景一般不使用
seqno 服务端日志标识,报障时请提供

返回示例

{
  "code": "1001",
  "seqno": "92a78431551bd293",
  "data_node": "CN-South/HS3-1",
  "pay_url": "https://app.4pyun.com/payment/trade/create?pay_id=621722601479223111111111",
  "pay_id": "621722601479223111111111"
}

下单失败时以 hint / message 为准排障:

{
  "code": "400",
  "message": "请求参数错误",
  "hint": "`merchant` Required!",
  "seqno": "94929a9b0874aa46"
}

4.2 第二步:小程序拉起半屏收银台

4.3.1 微信小程序

  1. app.json 声明跳转目标 appId(P云收银台小程序):
{
  "embeddedAppIdList": ["wxa204074068ad40ef"]
}

参考微信官方文档: 配置 embeddedAppIdList wx.openEmbeddedMiniProgram

  1. 在需要支付的位置调用(pay_id 由服务端下发,切勿在前端生成):
wx.openEmbeddedMiniProgram({
  appId: 'wxa204074068ad40ef',
  path: `/external/payment/trade/create/index?pay_id=${payId}`,
  success: () => {},
  fail: (err) => {
    // 建议提示用户稍后重试,或降级走 H5 收银台 pay_url
  }
})

4.3.2 支付宝小程序

my.openEmbeddedMiniProgram({
  appId: '2021004130621008',
  path: `/external/payment/trade/create/index?pay_id=${payId}`,
})

参考支付宝官方文档:my.openEmbeddedMiniProgram

4.3.3 收银台参数说明

微信 appId wxa204074068ad40ef
支付宝 appId 2021004130621008
path /external/payment/trade/create/index?pay_id=xxxxxxxxxxxxxx
  • pay_id 为第一步返回的平台支付 ID;
  • 有效期:受下单时 expire_time 限制,默认 3 分钟,过期需重新下单;
  • 一单一用:不要复用同一个 pay_id 反复拉起。

4.3 第三步:接收前端支付结果(用于页面展示)

支付结束后,收银台小程序会把结果回传给宿主小程序:

  • 微信:在 App.onLaunch / App.onShow 中通过 options.referrerInfo.extraData 获取;
  • 支付宝:在 App.onLaunch(options) / App.onShow(options) 中通过 options.referrerInfo?.extraData 获取。
App({
  onShow(options) {
    const data = options.referrerInfo && options.referrerInfo.extraData
    if (!data || !data.pay_order) return

    // 仅用于页面展示与跳转,业务状态以后端通知为准
    if (data.status === 1) {
      // 展示成功页
    } else if (data.status === 0) {
      // 支付中,建议轮询后端订单状态
    } else {
      // 失败 / 用户取消
    }
  }
})

回调字段

字段 类型 必须 说明
pay_order string Y 商户支付订单号
channel string Y 支付渠道
pay_serial string Y 平台支付流水
value string Y 支付金额,单位:分
status short Y 交易状态:1 成功、0 支付中、-1 失败
trade_time long Y 交易时间,毫秒时间戳

注意:用户可能直接关闭半屏小程序而不触发回调,因此该回调不可作为业务依据。

4.4 第四步:接收服务端支付结果通知(必接)

  • 请求方式HTTP POST + application/x-www-form-urlencoded 表单提交
  • 通知地址:第一步下单时传的 notify_url
  • 由对接方实现,平台主动调用

完整字段说明见 2.6 支付结果异步通知。接入时只需关注:

字段 说明
pay_order 商户支付订单号,与下单时一致,幂等键
value 支付金额,单位:分,需与本地订单核对
status 1 成功、0 支付中、-1 失败
trade_time 交易时间,毫秒时间戳
sign 签名,必须校验

处理要求

  1. 校验签名,并校验 app_idmerchantvalue 与本地订单一致;
  2. pay_order 做幂等处理(平台会重复通知);
  3. 仅当 status == 1 时执行发货 / 业务履约;
  4. 处理成功必须返回 code = 1001,否则平台将持续重投;
  5. 已处理过的通知,直接返回 1001 即可停止重投。

响应:返回 code = 1001 表示接收成功,message / hint 选填。

{ "code": "1001", "message": "通知成功", "hint": "" }

4.5 第五步:主动查询(兜底)

长时间未收到通知、或前端回调丢失时,调用查询交易状态,以平台实际状态为准修正本地订单。建议配合定时任务扫描「支付中」的超时订单并做终态判定。

5 状态与错误码

交易状态 status

含义 处理建议
1 支付成功 履约 / 发货
0 支付中 等待通知,或主动查询
-1 失败 / 已关闭 释放库存,引导重新下单

下单接口常见 code

code 含义 处理建议
1001 下单成功 pay_id 拉起收银台
1403 支付订单号已存在 更换 pay_order 重新下单,或先查询原单状态
400 参数错误 hint 定位缺失 / 非法字段
其它 message 携带 seqno 联系平台排查

6 接入自检清单

  • [ ] app_id / app_secret 已开通,app_secret 仅存服务端
  • [ ] 下单接口在服务端调用,未暴露给小程序端
  • [ ] pay_order 全局唯一(建议:业务前缀 + 时间戳 + 序列)
  • [ ] 金额单位统一为value 与业务金额一致
  • [ ] trade_scene / extra 按场景要求正确传递
  • [ ] app.json 已配置 embeddedAppIdList(微信)
  • [ ] 使用 pay_id 拼接半屏 path,未使用已废弃的支付插件
  • [ ] notify_url 公网可达、验签、幂等、返回 code=1001
  • [ ] 前端回调仅做展示,业务状态以后端通知 / 查询为准
  • [ ] 已实现超时未通知的主动查单补偿

7 相关文档

© 2026 Shenzhen ChinaRoad Technology Co., Ltd. © All Rights Reserved            UPDATED 2026/09/23 16:13:12

results matching ""

    No results matching ""