# 道具直购

道具直购是虚拟支付的核心能力,允许玩家在游戏内直接购买虚拟道具。本文将详细介绍道具直购的接入流程和注意事项。

# 功能介绍

道具直购支持玩家使用真实货币购买游戏内的虚拟道具,包括但不限于:

  • 游戏货币(钻石、金币等)
  • 角色皮肤、装扮
  • 游戏道具、装备
  • 会员服务、特权

# 接入流程

# 1. 配置商品

在 TapTap 开发者后台配置需要售卖的商品:

配置项 说明
商品 ID(productId) 道具的唯一标识,需与游戏内一致
商品名称 道具的显示名称
商品价格 道具的售价(单位:分)
分区 ID(zoneId) 游戏分区标识,默认为 "1"

# 2. 实现服务端接口

# 签名生成

服务端需要实现 paySigsignature 的签名生成逻辑,详细算法请参考 tap.requestPaymentGameItem 文档。

# 发货回调

服务端需要实现发货回调接口,用于接收支付成功后的发货通知。详细协议请参考发货消息协议文档。

# 3. 客户端调用

使用 tap.requestPaymentGameItem API 发起支付请求:

// 1. 向服务端请求支付参数
const payParams = await requestPayParamsFromServer({
  productId: 'diamond_100',
  quantity: 1
})

// 2. 调用支付 API
tap.requestPaymentGameItem({
  signData: payParams.signData,
  paySig: payParams.paySig,
  signature: payParams.signature,
  success(res) {
    console.log('支付成功', res)
    // 等待服务端发货回调确认后,再给用户发放道具
  },
  fail(err) {
    console.error('支付失败', err.errCode, err.errMsg)
    handlePaymentError(err.errCode)
  }
})

# 支付参数说明

# signData 参数

signData 是支付原串,包含以下关键字段:

参数 类型 必填 说明
mode string 固定为 "goods" 表示道具直购
offerId string 应用 ID
productId string 商品 ID,需与后台配置一致
goodsPrice number 商品单价(单位:分),需与后台配置一致
buyQuantity number 购买数量
outTradeNo string 业务订单号,需保证唯一性
currencyType string 币种,如 "CNY"
zoneId string 分区 ID,默认 "1"
env number 环境:0-正式环境,1-沙箱环境
attach string 透传数据,发货时原样返回

# 发货流程

┌─────────┐      ┌─────────┐      ┌─────────┐      ┌─────────┐
│  客户端  │      │  服务端  │      │ TapTap  │      │ 支付渠道 │
└────┬────┘      └────┬────┘      └────┬────┘      └────┬────┘
     │                │                │                │
     │ 1.请求支付参数   │                │                │
     │───────────────>│                │                │
     │                │                │                │
     │ 2.返回签名参数   │                │                │
     │<───────────────│                │                │
     │                │                │                │
     │ 3.调用支付API   │                │                │
     │────────────────────────────────>│                │
     │                │                │                │
     │                │                │ 4.调起支付      │
     │                │                │───────────────>│
     │                │                │                │
     │                │                │ 5.支付结果      │
     │                │                │<───────────────│
     │                │                │                │
     │                │ 6.发货回调      │                │
     │                │<───────────────│                │
     │                │                │                │
     │                │ 7.返回发货结果  │                │
     │                │───────────────>│                │
     │                │                │                │
     │ 8.支付结果回调   │                │                │
     │<────────────────────────────────│                │
     │                │                │                │

# 注意事项

# 价格校验

  • goodsPrice 会与后台配置的商品价格进行校验,必须完全一致
  • 价格单位为「分」,1 元 = 100 分

# 订单号唯一性

  • outTradeNo 每个订单只能使用一次
  • 建议使用时间戳 + 随机数生成唯一订单号
  • 订单号要求:32 个字符内,只能是数字、大小写字母、符号 _-|*@ 组成,不能以下划线开头

# 防沉迷限制

  • 未成年用户受防沉迷系统限制,可能无法完成支付
  • 错误码 -15009 表示由于健康系统限制,支付已超过限额

# 沙箱测试

  • 测试时设置 env: 1 使用沙箱环境
  • 需要在开发者后台将测试账号加入沙箱白名单
  • 沙箱环境的支付不会真实扣款

# 错误处理

常见错误码及处理建议:

错误码 说明 处理建议
-1 系统失败 提示用户稍后重试
-15003 订单重复 检查订单号是否重复使用
-15006 货币类型不支持 检查 currencyType 是否为 CNY
-15012 签名错误 检查 signature 签名算法
-15014 支付签名错误 检查 paySig 签名算法
-15016 商品价格错误 检查 goodsPrice 是否与后台配置一致
1 用户取消支付 无需特殊处理

完整错误码列表请参考 tap.requestPaymentGameItem 文档。