# 小游戏消息推送
# 接入小游戏消息推送
首先您得告诉我们您的服务器地址
# 第一步:确定你要接入的推送能力
小游戏目前提了两种消息推送能力,分别是页面(微信公众平台)「功能」-「虚拟支付2.0」-「基本配置」-「基础配置」下的 “事件订阅配置” 和“发货推送配置”。
# 第二步:填写服务器配置
以发货推送配置为例子,点击“配置”填写服务器地址(URL)、令牌(Token) 和 消息加密密钥(EncodingAESKey)等信息。
URL: 开发者用来接收道具发货消息事件的接口 URL。开发者所填写的URL 必须以 http:// 或 https:// 开头,分别支持 80 端口和 443 端口。(如果你的url请求时间超过3s,会发生超时错误)
Token: 可由开发者可以任意填写,用作生成签名(该 Token 会和接口 URL 中包含的 Token 进行比对,从而验证安全性)。
EncodingAESKey: 由开发者手动填写或随机生成,将用作消息体加解密密钥。
同时,开发者可选择消息加解密方式:明文模式、和安全模式(推荐)。注意:消息数据格式仅支持JSON 格式,使用安全模式开发者需要对收到的消息进行解密,但回复微信服务器的消息不需要加密。
# 第三步:验证消息来自微信服务器
点击“模拟推送”,微信服务器会发送GET请求到填写的服务器地址URL上,GET请求(例如: https://your_host?signature=6298f2b139f33959c59d69da33f5c4215d9df26a×tamp=1700735027&nonce=50328042&echostr=Mzi3wDcVa5uI)携带参数如下表所示:
| 参数 | 描述 |
|---|---|
| signature | 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 |
| timestamp | 时间戳 |
| nonce | 随机数 |
| echostr | 随机字符串 |
开发者通过检验 signature 对请求进行校验(下面有校验方式)。若确认此次 GET 请求来自微信服务器,请原样返回 echostr 参数内容,则接入生效,页面的“测试状态”会显示“已通过”,否则接入失败。
签名校验流程如下:
将token、timestamp、nonce三个参数进行字典序排序
将三个参数字符串拼接成一个字符串进行sha1加密
开发者获得加密后的字符串可与signature对比,确认该请求来源于微信
检验signature的PHP示例代码:
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if ($tmpStr == $signature ) {
return true;
} else {
return false;
}
}
PHP示例代码下载:下载链接文档
# 第四步:配置测试链接
如果开发者有测试需求,可以点击“修改”生成一个发布中的版本,发布中的版本可以添加白名单用于测试。
服务器配置完成后,有的推送业务(例如“直购道具”和“商城道具”的发货推送)还需要进行业务消息的推送测试才可以开启推送,操作流程看下文的消息推送测试。
# 消息推送协议
# 直购/商城道具发货消息
# 请求参数
| 参数 | 类型 | 描述 |
|---|---|---|
| ToUserName | String | 小游戏原始ID |
| FromUserName | String | 该事件消息的openid,道具发货场景固定为微信官方的openid |
| CreateTime | Number | 消息发送时间 |
| MsgType | String | 消息类型,道具发货场景固定为:event |
| Event | String | 事件类型 商城道具场景固定为: minigame_h5_goods_deliver_notify道具直购(游戏内)场景固定为: minigame_game_pay_goods_deliver_notify |
| MiniGame | Object | 道具直购发货参数 |
MiniGame
| 字段 | 类型 | 说明 |
|---|---|---|
| Payload | String | 携带的具体内容,格式为json,具体内容如下表格Payload(因为这里需要对消息内容统一签名,所以统一把消息内容设计成json格式) |
| PayEventSig | String | 见 支付请求签名算法说明 (PayEventSig) |
| IsMock | Bool | True: 模拟测试推送 False:真实推送 |
Payload(JSON)
| 字段 | 类型 | 说明 |
|---|---|---|
| OpenId | String | 接收道具的玩家openid |
| Env | Number | 环境配置 0:现网环境(也叫正式环境) 1:沙箱环境 |
| OutTradeNo | String | 订单号 |
| GoodsInfo | Object | 发货道具 |
GoodsInfo
| 字段 | 类型 | 说明 |
|---|---|---|
| ProductId | String | 游戏道具id标识 |
| Quantity | Number | 购买道具数量 |
| ZoneId | String | 分区 |
| OrigPrice | Number | 物品原始价格 (单位:分) |
| ActualPrice | Number | 物品实际支付价格(单位:分) |
| Attach | String | 透传数据 |
| OrderSource | Number | 1 游戏内 2 商城下单 3 商城测试下单 |
# 返回参数
| 字段 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
| ErrCode | Number | 是 | 发送状态。0:成功,其他:失败 todo |
| ErrMsg | String | 否 | 错误原因,用于调试。在errcode非0 的情况下可以返回 |
# 消息推送测试
在完成相应业务的消息推送测试后,才会开启对应业务的消息推送服务,以“直购道具”的发货推送为例。用户在(微信公众平台)「功能」-「虚拟支付2.0」-「基本配置」-「直购配置」拉到页面最下面,有个开启道具发货推送的选项。
点击“开启推送”-“执行测试”后,微信服务器会发送以下消息内容到开发者在页面「功能」-「虚拟支付2.0」-「基本配置」-「基础配置」- 「发货推送配置」填写的服务器。安全模式是指开发者在 “发货推送配置”的消息加密方式中选择了“安全模式”, 明文模式是指开发者在 “发货推送配置”的消息加密方式中选择了“明文模式”
# URL参数:
微信服务器发往开发者服务器的请求会附带如下的url参数,其中signature用于验证消息来自微信服务器, msg_signature, nonce, timestamp用于安全模式下对消息内容的解密。
| 参数 | 是否必填 | 描述 |
|---|---|---|
| signature | 是 | 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 |
| timestamp | 是 | 时间戳 |
| nonce | 是 | 随机数 |
| msg_signature | 否 | 安全模式会有此参数, 消息体签名串,用于安全模式的加解密 |
| encrypt_type | 否 | 安全模式会有此参数,值固定为"aes" |
# 消息解密
如果您选择了安全模式,公众平台推送的消息格式如下
{ "Encrypt":"$encrpy",
"ToUserName":"$your_username"
}
"$encrypy"是加密后的密文, 这里的加密方法跟小程序消息推送的加密方法一致,开发者将其解密后即可得到原始消息。对于小游戏推送消息,不管是否加密, 开发者回复明文消息即可。(python3 解密代码下载)
# 消息协议格式:
# 直购道具发货
服务器发送:
{
"ToUserName": "$your_username",
"FromUserName": "oUrsf0TSXNtiZjP7JL9UUFiGJzmQ",
"CreateTime": $current_timestamp,
"MsgType": "event",
"Event": "minigame_game_pay_goods_deliver_notify",
"MiniGame": {
"Payload": "{\"OpenId\":\"example_open_id\",\"OutTradeNo\":\"example_out_trade_no\",\"WeChatPayInfo\":{\"MchOrderNo\":\"example_mch_order_no\",\"TransactionId\":\"example_transaction_id\"},\"Env\":1,\"GoodsInfo\":{\"ProductId\":\"example_product_id\",\"Quantity\":1,\"ZoneId\":\"example_zone_id\",\"OrigPrice\":1000,\"ActualPrice\":1000,\"Attach\":\"example_attach_data\",\"OrderSource\":1}}",
"PayEventSig": "$your_pay_event_sig",
"IsMock":true
}
}
需要返回
{"ErrCode":0,"ErrMsg":"Success"}
# 商城道具发货
服务器发送:
{
"ToUserName": "$your_username",
"FromUserName": "oUrsf0TSXNtiZjP7JL9UUFiGJzmQ",
"CreateTime": $current_timestamp,
"MsgType": "event",
"Event": "minigame_deliver_h5_pay_products",
"MiniGame": {
"Payload": "{\"OpenId\":\"example_open_id\",\"OutTradeNo\":\"example_out_trade_no\",\"WeChatPayInfo\":{\"MchOrderNo\":\"example_mch_order_no\",\"TransactionId\":\"example_transaction_id\"},\"Env\":1,\"GoodsInfo\":{\"ProductId\":\"example_product_id\",\"Quantity\":1,\"ZoneId\":\"example_zone_id\",\"OrigPrice\":1000,\"ActualPrice\":1000,\"Attach\":\"example_attach_data\",\"OrderSource\":2}}",
"PayEventSig": "$your_pay_event_sig",
"IsMock":true
}
}
需要返回
{"ErrCode":0,"ErrMsg":"Success"}