跳到主要内容

支付回调

接口说明​

小游戏方支付流程如下图所示:

支付流程

支付流程及设置​

游戏服务端接口可访问性验证​

支付设置

⚠️ 本部分仅负责说明测试接口连通性。实际支付行为参见回调请求

为了确保回调地址的有效性和安全性,宿主服务端会向开发者配置的回调地址发送 GET 请求进行可访问性验证。该请求包含 echostr 参数,开发者需要验证请求来源的合法性并原样返回 echostr 参数值来完成验证流程。

只有当接口可访问性验证通过后,宿主服务端才会在用户完成支付时将支付订单信息推送到配置的回调地址(此时为 POST 请求)。

可访问性验证流程​

开发者需要在服务端实现以下验证逻辑来确认请求确实来自宿主服务器:

  1. 获取验证参数:从请求中提取 timestamp(时间戳)、nonce(随机字符串)、msg(消息内容)和 echostr(回显字符串)参数,
  2. 返回验证:原样返回请求中的 echostr 参数值完成验证

参数说明

字段类型是否必需描述
timestampstring是时间戳
noncestring是随机字符串
msgstring是消息内容
signaturestring是签名串
echostrstring否用于接口可访问性验证的参数

返回值说明

接口验签成功后,直接返回请求参数中的 echostr 原始字符串。

响应示例:

pong

Golang 验证示例​

type NotifyPayInfo struct {
Timestamp string `json:"timestamp"`
Nonce string `json:"nonce"`
Msg string `json:"msg"`
Signature string `json:"signature"`
Type OrderNotifyType `json:"type"`
Echostr string `json:"echostr,omitempty"`
}

func TestPaymentPong(w http.ResponseWriter, r *http.Request) {
data, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(map[string]any{
"code": 22103,
"message": "invalid body",
})
return
}
defer r.Body.Close()

var body NotifyPayInfo
if err := json.Unmarshal(data, &body); err != nil {
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(map[string]any{
"code": 22103,
"message": "invalid body",
})
return
}

w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(body.Echostr))
}

实际支付回调设置​

在完成了接口可访问性验证后,宿主服务端实际的支付回调以POST方法发送。具体设置如下:

宿主服务端回调请求​

回调请求时会带有 type 字段用于区分请求类型

参数说明

字段类型是否必需描述
timestampstring是时间戳
noncestring是随机字符串
msgstring是消息内容
signaturestring是签名串
typestring是请求类型 (payment 或 refund)
支付回调消息内容​

当回调请求中的 type 字段是 payment 时, msg 是以下内容

字段类型是否必需描述
appidstring是小游戏的Game ID
cp_order_nostring是游戏订单号
cp_extrastring否自定义透传参数,可用于传递额外信息
channel_order_nostring是渠道订单号,宿主服务端生成的唯一交易流水号
amountint64是实际支付金额
quantityint64是购买数量
currencystring是货币类型,如 CNY
coupon_deduct_amountint64否优惠券抵扣金额
product_codestring否商品编码
product_namestring否商品名称
product_priceint64否商品单价
退款回调消息内容​

当回调请求中的 type 字段是 refund 时, msg 是以下内容

字段类型是否必需描述
appidstring是小游戏的Game ID
cp_order_nostring是游戏订单号
channel_order_nostring是渠道订单号,宿主服务端生成的唯一交易流水号
refund_nostring是退款单号,发生退款时宿主服务端生成的退款流水号
refund_amountint64是退款金额

回调签名验证​

当宿主服务端向开发者的服务器发送支付回调请求时,开发者需要验证请求的真实性以确保数据安全。验证过程如下:

  1. 获取secret:在宿主宿主服务端游戏详情页获取 secret
  2. 获取验证参数:从请求中提取 timestamp(时间戳)、nonce(随机字符串)、msg(消息内容)参数,
  3. 生成签名:将 secret、timestamp、nonce、msg 四个参数按字典序排序后拼接成字符串,使用 SHA1 算法计算生成签名 signature
  4. 验证签名:将计算得到的 signature 与请求中的 signature 参数进行对比
Golang 验证签名示例​
func GenerateSignature(secret, timestamp, nonce, msg string) string {
sortedString := []string{secret, timestamp, nonce, msg}
sort.Strings(sortedString)

h := sha1.New()
h.Write([]byte(strings.Join(sortedString, "")))

return fmt.Sprintf("%x", h.Sum(nil))
}

游戏方响应结果:​

游戏方需要按照以下格式返回结果给宿主服务端,宿主服务端会根据对应的code做不同的处理。

返回值说明

字段类型描述
codeint响应状态码
msgstring消息内容

重要提示:

服务端接收回调请求后,请务必校验金额,确保收到的金额与实际物品金额一致,防止游戏金额被篡改导致损失或数据异常,确保游戏资产安全。

{
"code" : 200, //响应状态码
"message" : "message" //状态码描述信息
}

code响应码说明

状态码描述
200业务处理成功,发货成功
22100数据签名不正确
22101接口参数验证不通过
22102订单失败(例如因为无库存、商品下架等原因,明确指出该笔订单无法执行)
22103未知业务错误