## 小游戏礼物索要接入指南

该能力已废弃

> 此功能为beta版，暂仅支持Android用户发起索要及支付。

### 基础库版本

2.11.0及以上支持小游戏礼物索要能力.

### 发起索要

通过调用`wx.requestMidasFriendPayment`即可发起一次礼物索要请求，请求参数与米大师支付[wx.requestMidasPayment](/minigame/dev/api/midas-payment/wx.requestMidasPayment.md)类似，需要额外传入唯一的游戏业务单号`outTradeNo`用于订单关联和去重。

玩家成功发起索要后，会自动唤起微信通讯录，玩家可将礼物索要链接发送给好友和微信群。

收到礼物索要链接的微信用户可点击链接进行支付。

#### 接口参数说明

[wx.requestMidasFriendPayment](/minigame/dev/api/midas-payment/wx.requestMidasFriendPayment.md)

#### 时序图
```seq
用户->游戏: 点击发起索要
游戏->开发者后台: 创建业务索要单
开发者后台-->游戏: 返回业务索要单号及下单参数
游戏->游戏: wx.requestMidasFriendPayment
游戏-->用户: 分享索要单
游戏->开发者后台: 传递加密数据
开发者后台->开发者后台: 解密得到系统索要单号并记录
```
![image.png](https://res8.wxqcloud.qq.com.cn/wxdoc/3bb4b7d1-c318-46e2-a74a-4ad8680d2a44.png)

#### 示例代码
```js
wx.requestMidasFriendPayment({
  mode: 'game',
  env: 0,
  offerId: 'xxxxxxxx',
  currencyType: 'CNY',
  buyQuantity: 10,
  platform: 'android',
  zoneId: '1',
  outTradeNo: 'xxxxxxxx',  // 游戏业务单号
  nonceStr: 'xxxxxxxx',
  timeStamp: 1585212938,
  signature: 'xxxxxxxx',
  success(res) {
    console.log(res.encryptedData) // 加密数据，包含微信索要单号
    console.log(res.iv)            // 加密算法的初始向量
    console.log(res.cloudID)       // 敏感数据对应的云ID
  },
  fail(err) {
    console.log(err.errCode)
    console.log(err.errMsg)
  }
})
```

#### 注意事项
1. 每个`outTradeNo`只能使用一次，重复用于创建不同索要单时，接口会报错；开发者需合理利用`outTradeNo`的去重能力，避免玩家发起多次索要导致多买
2. 接口填写创建过的索要单参数，可重新拉起索要分享；如果创建过的索要单状态是已支付/已超时，不可重新拉起索要分享，接口会返回特定错误码
3. 微信索要单有效期为24小时

#### 签名算法

签名算法为：
```
signature = hmac_sha256([appId, mode, ... , nonceStr, timeStamp].sort().join(''), sessionKey)
```

具体来说，这个算法分为几个步骤：
1. 将所有接口传入的参数（除了signature之外）的值表示成字符串形式，对值按照字典序排序；
2. 将排好序的多个字符串拼接在一起；
3. 使用`session_key`作为`key`，使用`hmac_sha256`算法对步骤2中的结果字符串做计算，所得结果即为`signature`

#### 解密结果

解密算法详细见[加密数据解密算法](signature)

#### 示例结果
```json
{
  "outTradeNo": "xxxxxxxx",
  "orderNo": "PBgAAHMjeOhixxxx",
  "watermark": {
    "timestamp": 1585537091,
    "appid": "wx7a727ff7d940xxxx"
  }
}
```

### 索要成功消息

微信用户支付成功后，微信平台会调用米大师充值游戏币，充值成功后，会向开发者后台推送索要成功消息。消息推送接入方法详见 [消息推送](/minigame/dev/guide/base-ability/message-push)
开发者后台需要接收处理，执行发货逻辑，并按文档规范返回应答(空串或"success")。

索要功能支持2类场景：
1. 索要米大师游戏币
索要成功消息通知时，微信已确保发起方的米大师游戏币充值完成，游戏侧理论上无需再做任何发货动作。
2. 索要游戏内道具
索要成功消息通知时，微信已确保发起方的米大师游戏币充值完成（同1），游戏侧需要扣减相应的米大师游戏币，并换成游戏内道具。
游戏内道具由开发者自由定义，可以为任意的一种或多种物品。

#### 时序图
```seq
用户->微信后台: 支付成功
微信后台->开发者后台: 索要成功消息
开发者后台->微信后台: 查询用户余额
微信后台-->开发者后台: 查询成功
开发者后台->微信后台: 扣除余额
微信后台-->开发者后台: 扣除成功
开发者后台->开发者后台: 发放道具
开发者后台-->微信后台: 处理成功
```
![image.png](https://res8.wxqcloud.qq.com.cn/wxdoc/aac69d47-892b-4577-ad56-ae81bb79afd4.png)

#### 示例消息
```xml
<xml>
  <ToUserName><![CDATA[gh_31b2a1c7xxxx]]></ToUserName>
  <FromUserName><![CDATA[oUrsf0TSXNtiZjP7JL9UUFiGxxxx]]></FromUserName>
  <CreateTime>1584075435</CreateTime>
  <MsgType><![CDATA[event]]></MsgType>
  <Event><![CDATA[minigame_ask_order_deliver]]></Event>
  <MiniGame>
    <BusiDeliverCallbackData>
      <outTradeNo><![CDATA[xxxxxxxx]]></outTradeNo>
      <orderNo><![CDATA[PBgAAHMjeOhixxxx]]></orderNo>
      <appid><![CDATA[wx7a727ff7d940xxxx]]></appid>
      <openid><![CDATA[oUrsf0SMlbE3YH2hnlEhO03Zxxxx]]></openid>
      <amount>100</amount>
      <zoneId><![CDATA[1]]></zoneId>
      <env>0</env>
      <payTime>1584067989</payTime>
    </BusiDeliverCallbackData>
  </MiniGame>
</xml>
```

#### 注意事项
1. 同样的通知可能会多次发送给开发者后台，系统必须能够正确处理重复的通知。
2. 后台通知交互时，如果微信收到开发者后台的应答不符合规范或超时，微信会判定本次通知失败，重新发送通知，直到成功为止（在通知一直不成功的情况下，微信总共会发起多次通知，通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m），但微信不保证通知最终一定能成功。
3. 在索要单状态不明或者没有收到索要成功结果通知的情况下，建议开发者后台主动调用【索要单查询】接口确认订单状态。
4. 当收到通知进行处理时，首先检查对应业务数据的状态，判断该通知是否已经处理过，如果没有处理过再进行处理，如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前，要采用数据锁进行并发控制，以避免函数重入造成的数据混乱。

#### 字段说明
| 字段名 | 说明 |
| - | - |
| ToUserName | 小游戏原始id |
| FromUserName | 固定取值，可忽略 |
| CreateTime | 消息时间 |
| MsgType | 消息类型，取值event |
| Event | 消息名称，取值minigame_ask_order_deliver |
| outTradeNo | 游戏业务单号 |
| orderNo | 微信索要单号 |
| appid | 小游戏appid |
| openid | 索要单下单用户openid |
| amount | 金额（单位分） |
| zoneId | 米大师发货分区 |
| env | 米大师环境 |
| payTime | 支付时间 |

### 索要单查询

第三方后台可以通过 https 调用索要单查询相关后台接口

需要调用查询接口的情况：
1. 当后台、网络、服务器等出现异常，最终未接收到索要成功消息
2. 其他异常错误时，可查询比对确认索要单信息是否一致
