外观
看购支付接入文档
简介
本文档仅介绍如何利用看购jssdk,在看购 App 内的 H5 页面中唤起微信支付, 适用于在看购平台上架 H5APP 商城的开发者。
更详细的看购支付(KGPay)帮助文档,请登录看购支付平台pay.citv.cc查看 。
读完本文,你应该能让自己的 H5 商城在看购 App 里完成一笔真实付款。
一、业务流程
支付有三方参与,签名只在你自己的服务器上生成:
① 你的业务服务器 持有看购支付系统的 appSecret,生成订单 + 签名
│ 下发签好名的表单(表单里没有 appSecret)
▼
② 你的 H5 商城(运行在看购 App 的 WebView 中)
│ kg.chooseWXPay({ form })
▼
③ 看购 App ──▶ 看购服务端 ──▶ KGPay 网关 ──▶ 微信
(只转发 + 记流水) (校验你的签名)看购 App 与看购服务端只做转发:不生成签名、不修改表单、不参与定价。款项直接进入你在 KGPay 的商户号,不经过看购平台。
三条红线
上线前请确认你没有踩到这三条中的任何一条:
appSecret绝不能出现在 H5 页面里。 前端能读到,就等于任何人打开开发者工具都能把amount改成 1 分再重新签名下单。签名必须在你的服务器上完成。- 表单签好名后一个字段都不能改。 签名覆盖表单里全部非空字段,中途改动任何一处,KGPay 会直接拒单。
- 不要拿"支付界面关闭了"当作支付成功。 用户可能付款成功但回程时进程被系统回收。最终结果一律以KGPay服务端回调或主动查单为准。
二、接入前准备
| 步骤 | 在哪里做 | 拿到什么 |
|---|---|---|
| 1. 注册商户 | KGPay 支付平台 | mchNo(商户号)、appId(应用 ID)、appSecret(应用密钥) |
| 2. 配置回调 | KGPay 商户后台 | 配置回调地址:你自己的业务服务器回调网址 |
| 3. 登记渠道 | 看购开发者中心 → 你的应用 → 支付渠道 | 把上面三个值 + 网关地址 + 微信 AppID 填入 |
| 4. 部署密钥 | 你自己的业务服务器 | appSecret 写进服务端配置(环境变量或配置中心,不要提交进代码库) |
在开发者中心登记支付渠道
进入「应用设置 → 支付渠道」,新建一条渠道并启用:

三、第一步:业务服务器生成下单表单
3.1 请求参数
以微信 App 支付(wayCode=WX_APP)为例。完整字段以 KGPay 官方文档为准,下面是常用字段与看购侧的额外要求:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
mchNo | string | 是 | KGPay 商户号。必须与你在看购开发者中心登记的支付渠道一致**,不一致看购会拒绝转发 |
appId | string | 是 | KGPay 应用 ID。同上,必须与登记值一致 |
mchOrderNo | string | 是 | 你自己的订单号,见 3.2 |
wayCode | string | 是 | 支付方式,微信 App 支付填 WX_APP |
amount | int | 是 | 金额,单位分,必须大于 0 |
currency | string | 是 | 固定 cny |
clientIp | string | 是 | 用户 IP |
subject | string | 是 | 商品标题,会显示在微信支付界面 |
body | string | 否 | 商品描述 |
notifyUrl | string | 是 | 你自己业务服务器的回调地址,不要填看购的地址 |
returnUrl | string | 否 | 同步跳转地址,App 内支付通常用不到 |
reqTime | string | 是 | 13 位毫秒时间戳 |
version | string | 是 | 固定 1.0 |
signType | string | 是 | 固定 MD5 |
sign | string | 是 | 签名,见 3.3 |
参数类型不能写错
amount 必须是 JSON 数字(1 而不是 "1"),reqTime 必须是 JSON 字符串("1788000000000" 而不是 1788000000000)。
类型写错时网关返回的是"参数有误",不是签名错误——照着签名方向排查会白费很长时间。
3.2 关于 mchOrderNo
- 由你自己生成,看购和 KGPay 都不会替你生成
- 在你自己的系统内必须唯一
- 看购侧按「你的应用 +
mchOrderNo」建立唯一约束,同一个订单号重复提交会复用原支付单,不会重复下单(这是幂等保护,用户点两次不会付两次) - 要改金额就必须换一个新的
mchOrderNo。同号不同价会让流水对不上账,看购侧以第一次的金额为准
3.3 签名算法 ,下面仅是简单举例说明,(具体请查看 KGPay支付系统官方文档)
1. 取表单里所有【非空】字段(跳过 sign 本身),每个拼成 "key=value&" 一个片段
2. 对【整个片段字符串】按【忽略大小写】排序 —— 注意不是只按 key 排,也不是区分大小写排
3. 按排序结果顺序拼接,末尾接上 "key=" + appSecret
4. 对结果做 MD5,输出十六进制【大写】四、第二步:H5 页面唤起支付
从你的服务器拿到签好名的表单后,直接交给 JSSDK:
js
// 页面加载时初始化一次(必须先于支付调用)
kg.config({ appId: "YOUR_APP_KEY" });
kg.ready(async () => {
if (kg.getInitError()) return;
// 1. 向你自己的服务器要签好名的表单
const form = await fetch("/api/my-shop/create-pay-form", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ orderId: "xxx" }),
}).then((r) => r.json());
// 2. 交给看购 App
kg.chooseWXPay({
payType: "wechat",
form, // 原样传,不要在这里改任何字段
goods: [{ name: "商品A", price: 1, qty: 1 }], // 可选,仅用于平台侧留存快照
success(res) {
// res.status: 'success' | 'failed' | 'closed' | 'pending'
if (res.status === "success") {
location.href = "/order/success?no=" + res.payNo;
} else {
location.href = "/order/detail?no=" + res.payNo;
}
},
cancel() {
/* 用户取消 */
},
fail(res) {
showToast(res.errMsg);
},
});
});
要点:
form原样传,SDK 不会修改- 唤起后到回调返回之间可能有较长间隔,不要关闭页面
- 回调
res.status取值:
| 值 | 含义 |
|---|---|
success | 支付成功 |
failed | 支付失败 |
closed | 订单已关闭 |
pending | 看购在轮询窗口内没等到确定结果。不代表失败,以你自己收到的回调为准 |
五、第三步:接收支付回调
这是你判断订单是否付款成功的唯一依据。 前端回调只用于改善体验,不能拿来发货。
KGPay 会向你在 notifyUrl 中填写的地址推送支付结果。
5.1 验签
用同一套签名算法对收到的参数(去掉 sign 本身)重新计算,与请求里的 sign 比对。
DANGER
验签不通过一律丢弃。 否则任何人构造一个请求就能让你白白发货。
5.2 判断状态
| 字段 | 说明 |
|---|---|
mchOrderNo | 你的订单号,用它定位自己的订单 |
state | 订单状态,见下表 |
payOrderId | KGPay 支付单号 |
channelOrderNo | 渠道(微信)交易号 |
wayCode | 支付方式 |
state | 含义 | 建议处理 |
|---|---|---|
0 | 订单生成 | 保持待支付 |
1 | 支付中 | 保持待支付 |
2 | 支付成功 | 发货 |
3 | 支付失败 | 置失败 |
4 | 已撤销 | 置失败 |
5 | 已退款 | 走退款流程 |
6 | 订单关闭 | 置关闭 |
5.3 应答
处理成功后返回 HTTP 200 + 纯文本 success(不是 JSON)。返回其他内容,KGPay 会认为投递失败并重复推送。
5.4 幂等
回调会重复投递,这是正常现象而不是故障。 你的处理必须幂等:
- 先查自己的订单状态,已经是"已支付"就直接回
success,不要重复发货、不要覆盖支付时间 - 更新语句建议带状态守卫,例如
UPDATE ... WHERE order_no = ? AND pay_status <> 1
5.5 兜底
回调可能因网络问题丢失。建议对超过 5 分钟仍是待支付的订单,主动调用 KGPay 查单接口确认真实状态。
六、常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
商户信息与渠道配置不符 | 表单里的 mchNo / appId 和你在看购开发者中心登记的对不上 | 核对两处配置;换过商户号要同步更新 |
该渠道未接入 KGPay 网关 | 开发者中心的"网关地址"没填 | 补填 KGPay 网关地址 |
支付渠道未配置 | 该应用下没有对应支付方式的渠道记录,或状态不是"正常" | 新建渠道并启用 |
网关返回参数有误 | amount 传成了字符串,或 reqTime 传成了数字 | 见 3.1 的类型说明,不要往签名方向排查 |
| 网关返回签名错误 | 排序没忽略大小写 / 空值字段没跳过 / 中文用了非 UTF-8 编码 | 用 3.4 的两个样例逐个排查 |
form 缺少 mchOrderNo 或 sign | 表单没签名就传上来了 | 检查你服务器返回的结构 |
form.amount 非法 | amount 不是正整数,或误传了"元" | 金额单位是分 |
| 唤起微信后立刻失败,无提示 | App 的包名 / 签名与微信开放平台登记的不一致 | 联系看购运营核对开放平台配置 |
| 用户付了钱但订单还是待支付 | 回调丢失,或验签失败被丢弃 | 检查回调日志;补上主动查单兜底 |
支付状态一直是 pending | 看购侧没配回调,或看购的回调地址填错 | 在 KGPay 商户后台确认配了两个回调 |
七、上线自检清单
上线前逐条确认:
- [ ]
appSecret只存在于服务器,H5 打包产物里搜不到 - [ ] 签名跑通了 3.4 的两个样例(含中文那个)
- [ ]
amount是 JSON 数字,reqTime是 JSON 字符串 - [ ]
mchOrderNo在自己系统内唯一 - [ ]
amount单位是分 - [ ]
notifyUrl填的是自己的地址,且公网可达 - [ ] 回调做了验签,验签失败直接丢弃
- [ ] 回调处理是幂等的,重复投递不会重复发货
- [ ] 回调应答是纯文本
success - [ ] 对超时未支付的订单有主动查单兜底
八、支付的其他问题
以下的关于支付的其他问题,均在 KGPay(https://pay.citv.cc/)支付系统处理,你的业务服务器可以通过相关api接口向 KGPay支付系统发起请求。
- 申请退款
- 查询订单状态
- 查询退款状态
- 发起异常退款
- 下载账单
- 申请交易账单
- 支付单号查订单