游戏支付后端API文档

一、支付Webhook回调

微游与游戏CP约定webhook回调地址。用户完成支付之后,微游服务端发送HTTP请求通知该地址。

请求格式


方法URL
POST游戏开发者预先提供webhook地址给MiniGame

请求头


名称描述类型是否必须示例
sign签名stringca25acec11d7b89259f277b557c0841b9ae68391dd3e35bb3cda7f0c9a790e9e
ts毫秒时间戳,13位数字int641749193616816
x-md-global-cid商户唯一标识,微游提供string205150566760842225
content-type固定取 application/json,表示请求体为json格式stringapplication/json

请求参数

整个请求体是一个json对象,其字段包括:

名称描述类型是否必须示例
purchaseToken对应游戏SDK前端minigame.payments.purchaseAsync方法回调中的 purchaseToken 字段,是支付订单的唯一标识string37040d4dbfa04fcb880404b107818840
gameID游戏ID,与商户平台游戏详情中的游戏ID对应stringpopstone
userIDSDK用户信息接口返回的idstring
productID调用游戏SDK支付接口purchaseAsync时传的productID参数string
developerPayload调用游戏SDK支付接口purchaseAsync时传的developerPayload参数中的order字段string
usdPrice用户支付的商品价格,单位为美分int32
createTs用户下单时间,毫秒时间戳int64
finishTs用户完成支付的时间,毫秒时间戳int64
status支付状态,固定为paid,支付失败时不回调stringpaid

返回参数


名称描述类型是否必须示例
code状态码int200表示成功,500表示失败。
message错误信息string处理失败时传错误信息,处理成功时可不返回或返回任意值

需要注意的是,如果接口返回的code不是200,微游服务器会重试。需要确保接口具有幂等性,即重复调用不会带来问题。由于purchaseToken是支付订单的唯一标识 ,保证幂等性的一个实现方法是在程序中先检查该purchaseToken所关联的数据是否已经处理过。

签名规则

  1. 针对请求体的所有参数以及header中的ts,按 参数名=参数值 的形式拼接,多个参数之间用 & 分隔符连接。

  2. 所有参数按参数名的 ASCII 码从小到大排序(字典序),再按顺序拼接。

  3. 上述拼接后的字符串,前面追加appSecret应用密钥(由微游提供)进行SHA256运算,生成的字符串即为签名字符串。

签名代码示例(Node.js)

const crypto = require("crypto");
const express = require("express");

const app = express();
app.use(express.json()); // 解析 application/json

const appSecret = "LAmOGqDljtR7IaeHBS";   // 商户密钥,由微游提供,根据实际值替换

app.post('/payment/webhook', (req, res) => { // URL地址根据实际填写
    // 将请求体的所有参数以及请求头中的ts合并一起放到一个对象中
    const signParam = {...req.body, ts: req.headers["ts"]};
    
    // 计算和对比签名
    const expectedSign = generateSignature(params);
    if (expectedSign !== req.headers["sign"]) {
        res.json({code: 500, "message": "invalid sign"}); // 如果校验不通过,返回错误
        return;
    }
    // ... 校验通过,继续执行其他业务逻辑
});

/**
 * 生成签名
 */
function generateSignature(params) {
    const keys = Object.keys(params).sort().filter(k => k !== "sign");
    console.log("参与签名的字段为:", keys);

    const signData = appSecret + keys.map(k => `${k}=${params[k]}`).join("&");
    console.log("签名原始字符串为:", signData);

    // 生成SHA256签名
    const sign = crypto.createHash("sha256").update(signData).digest("hex");
    console.log("SHA256生成的签名为:", sign);

    return sign;
}
商务对接
商务对接
公众号
公众号