支付宝小游戏SDK文档
<p>[TOC]</p>
<p><div style="background: #EE5837;padding: 12px; border-radius: 8px; color: #000;">⚠️⚠️⚠️ <strong>注意</strong>
<strong>必须提前在CPS后台填写应用私钥,否则将会返回-游戏存在未配置参数</strong>
CPS后台 > 游戏列表 > 编辑 > RsaPrivateKey</p>
<p><strong>含内购游戏:</strong>
必须启用获取openid:登录 [开放平台控制台](<a href="https://openhome.alipay.com/develop/manage">https://openhome.alipay.com/develop/manage</a> "开放平台控制台") > 应用详情页 > 开发设置 > openid配置管理 点击 设置 进行查看/修改应用openid 用户标识

</div></p>
<h1>SDK介绍</h1>
<p>SDK集成封装了部分的支付宝的前端API,直接调用SDK接口即可,无需再调用支付宝的接口;
<font color="red">接入前我方会提供接入参数,没有参数不能接入</font></p>
<h1>小游戏后台必设置:</h1>
<p>域名:https: 配置文件提供的域名地址</p>
<h2>小游戏后台</h2>
<h3>(1)域名设置</h3>
<p>在开发->开发设置->服务器域名,request合法域名增加</p>
<h1>1.SDK包以及引入说明(重要):</h1>
<h2>1.1.SDK文件包括</h2>
<pre><code> sdk_v版本号.js(主文件)
config.js(配置文件,接入前会提供参数表,没有参数不能接入,文档中的所有密钥指的是我们提供的研发密钥,非小程序密钥,加号或者点号表示拼接两个字符串)</code></pre>
<p><div style="background: #FFE4B5;padding: 12px; border-radius: 8px; color: #000;">⚠️ <strong>注意</strong>
配置文件config.js必须按照提供的资料填写完整,没有参数不能接入,文档中的所有密钥指的是我们提供的研发密钥,非小程序密钥,加号或者点号表示拼接两个字符串
</div></p>
<h2>1.2.SDK引入方式</h2>
<pre><code>import &quot;./sdk/zfbsdk.js&quot;;
//不同的引擎可能引入方式不一致,根据需求可以自行拆解拷贝。</code></pre>
<h2>1.3.接口请求方式</h2>
<p>全部POST,支持JSON和FORM,声明header格式content-type,返回的格式,如无特殊说明,code的值1为正确,0为错误</p>
<h1>2.获取用户信息(为确保数据同步,游戏初始化必接入,打开游戏即调用)</h1>
<h2>2.1.接口说明</h2>
<p><div style="background: #9efca6;padding: 12px; border-radius: 8px; color: #000;">✍获取openid,无需再单独调用login接口。</p>
<p><code>getDybUserInfo(function callback)</code>
</div>
<div style="background: #FFE4B5;padding: 12px; border-radius: 8px; color: #000;">⚠️ <strong>注意</strong>
(1)整个游戏流程只能全局初始化的时候调用一次即可,不能重复调用。
重复调用可能会刷新,session_key,access_token,影响支付授权。
(2)<font color="red">保证先接入此接口,再接入后续接口,后续接口依赖于此接口,后续接口调用可放在此接口回调函数里面,或延迟调用,不要并行</font>
(3)此接口调用login授权获取openid,如需头像等信息请自行使用原生接口userInfo获取信息接口,但是保证不能调用到wx.login
</div>
<div style="background: #fda7b4;padding: 12px; border-radius: 8px; color: #000;">⚡ <strong>校验安全</strong>
1、为了防止openid泄露被直接用于游戏接口请求,授权返回的数据中有2个字段用于游戏方后端校验用户正确性-(openid, sign)
2、返回签名sign的生成方式为:<font color="red">md5('sessV2'+appid+openid+加密密钥key)</font>, 加密密钥我方提供,+号拼接字符串
</div></p>
<pre><code class="language-javascript">例如:
appid:9921004138665385749,
openid:nmopFTNBD9mYBp3et6BGtaHoAFU1gb
加密密钥key:LBpq2CDg88slNVFurdQKXp
拼接后:
md5(sessV29921004138665385749nmopFTNBD9mYBp3et6BGtaHoAFU1gbLBpq2CDg88slNVFurdQKXp)</code></pre>
<h2>2.2.参数说明</h2>
<ul>
<li>无需传参</li>
</ul>
<h2>2.3.示例代码</h2>
<pre><code class="language-javascript">dyb.getDybUserInfo(function (callback) {
console.log(&#039;getDyUserInfo-------------:&#039; + JSON.stringify(callback));
})</code></pre>
<h2>2.4.接口返回</h2>
<pre><code class="language-javascript">getDybUserInfo:{&quot;user&quot;:{&quot;openid&quot;:&quot;0643nmopFTNBD9mYBp3et6BGtaHoAFU1gb-MPWaaq96Vrg7&quot;,&quot;sign&quot;:&quot;b707a96bb9f4083b84733e0553637dc1&quot;},&quot;shareInfo&quot;:{}}
</code></pre>
<h1>3.创角信息上报</h1>
<h2>3.1.接口说明</h2>
<p><div style="background: #9efca6;padding: 12px; border-radius: 8px; color: #000;">✍上报创角事件</p>
<pre><code>createRole(function callback)</code></pre>
<p></div>
<div style="background: #FFE4B5;padding: 12px; border-radius: 8px; color: #000;">⚠️ <strong>注意</strong>
第一次调用依赖第2步-获取用户信息,建议创角上报在授权事件后3-5s后调起
</div></p>
<h2>3.2.参数说明</h2>
<p>|参数名|必选|类型|说明|
|:---- |:---|:----- |----- |
|role_name |是 |string |角色名称,没有填个昵称或者别的信息 |
|server_id |是 |int | 区服ID,没有填个默认数字 |
|server_name |否 |string | 区服名称,没有填个默认名称 |</p>
<h2>3.3.示例代码</h2>
<pre><code class="language-javascript">let param = {
server_id: 1,
server_name: &#039;服务器&#039;,
role_name: &#039;默认昵称&#039;,
}
dyb.createRole(param, function (callback) {
console.log(&#039;roleData:&#039; + JSON.stringify(callback));
});</code></pre>
<h2>3.4.接口返回</h2>
<pre><code class="language-javascript">roleData:{&quot;code&quot;:1,&quot;msg&quot;:&quot;角色已经上报&quot;,&quot;time&quot;:&quot;1586418685&quot;,&quot;data&quot;:null}</code></pre>
<h1>4.游戏关卡/等级</h1>
<h2>4.1.接口说明</h2>
<p><div style="background: #9efca6;padding: 12px; border-radius: 8px; color: #000;">✍上报当前玩家所在的游戏关卡/等级;
(1)可以在玩家退出的时候进行上报最新的关卡/等级;
(2)也可以在玩家突破关卡/等级的时候上报</p>
<p><code>1、上报关卡:gameLevel(int level, callback)</code>
<code>2、上报等级:gameGrade(int grade, callback)</code>
<font color="red">如果两个接口需要同时调用,需确保其中一个先调用,另一个可放在回调函数里面调用,或延迟调用,不要并行</font>
</div>
<div style="background: #FFE4B5;padding: 12px; border-radius: 8px; color: #000;">⚠️ <strong>注意</strong>
第一次调用依赖第2步-获取用户信息,建议在授权事件后3-5s后调起
</div></p>
<h2>4.2.参数说明</h2>
<p><strong>上报关卡:</strong></p>
<p>|参数名|必选|类型|说明|
|:---- |:---|:----- |----- |
|level |是 |int |关卡 |</p>
<p><strong>上报等级:</strong></p>
<p>|参数名|必选|类型|说明|
|:---- |:---|:----- |----- |
|grade |是 |int |等级 |</p>
<h2>4.3.示例代码</h2>
<pre><code class="language-javascript">//上报关卡:
//关卡2
dyb.gameLevel(2,function (callback) {
console.log(&#039;game_level:&#039; + JSON.stringify(callback));
});
//上报等级:
//等级3
dyb.gameGrade(3, function (callback) {
console.log(&#039;game_grade:&#039; + JSON.stringify(callback));
});</code></pre>
<h2>4.4.接口返回</h2>
<pre><code class="language-javascript">{
&quot;code&quot;: 1, //0调用失败,1调用成功
&quot;msg&quot;: &quot;成功&quot;
}</code></pre>
<h1>5.支付接口</h1>
<h2>5.1.接口说明</h2>
<p><div style="background: #9efca6;padding: 12px; border-radius: 8px; color: #000;">✍小游戏订单提交,生成支付订单并保存,调用支付后,<font color="red">游戏发货必须以服务端支付回调为准</font>。</p>
<p>下单顺序:游戏内部先生成自己的订单号,再来调用SDK下单接口</p>
<p><code>submitOrder(Object param, callback)</code>
</div></p>
<h2>5.2.参数说明</h2>
<p>|参数名|必选|类型|说明|
|:---- |:---|:----- |----- |
|goods_count |是 |int |商品数量 由接入方提供 如:1 |
|goods_des |是 |string |商品描述 由接入方提供 如:游戏币 |
|goods_identifier |是 |string |小游戏道具id,商品id |
|goods_name |是 |string |商品名称 由接入方提供 如:元宝 |
|pay_amount |是 |int |支付总金额(元)=单价乘数量,由接入方提供,整数(最低1元)<span style="color:red">金额限制详见下方「pay_amount限制说明」</span> |
|redirect_uri |是 |string |异步通知游戏支付结果地址 由接入方提供(我们通过这个通知你们支付结果) |
|extra_info |是 |string |额外拓展参数(将在服务端支付回调原样透传),可以为空字符串,a=b&c=d |
|order_sn |是 |string |订单编号(游戏方生成的订单号) |
|role_id |是 |string |角色ID 由接入方提供,没有默认一个 |
|role_name |是 |string |角色名称 由接入方提供 |
|server_id |是 |string |区服ID 由接入方提供,没有默认一个 |
|server_name |是 |string |区服名称 由接入方提供 |</p>
<h2>5.3.示例代码</h2>
<pre><code class="language-javascript">let pay_data = {
goods_count: 1,
goods_desc: &#039;商品描述&#039;,
goods_identifier: 1,
goods_name: &#039;测试商品&#039;,
pay_amount: 1,
redirect_uri: &#039;https://cps.moyangmoyang.com/market/testss&#039;,
extra_info: &#039;a=b&#039;,
order_sn: randomNumber(),
role_id: 1001,
role_name: &#039;无角色&#039;,
server_id: 1,
server_name: &#039;默认服务器&#039;
}
dyb.submitOrder(pay_data, function (callback) {
console.log(&#039;发起支付:&#039; + JSON.stringify(callback));
});</code></pre>
<h2>5.4.接口返回</h2>
<pre><code class="language-javascript">{
&quot;code&quot;: 1, //(0支付失败,直接提示,1支付成功)//不可信,此处仅提供前端参考,游戏发货必须以服务端支付回调为准
&quot;msg&quot;: &quot;成功&quot;
}</code></pre>
<h2>5.5.pay_amount限制说明</h2>
<p><strong>限定价格等级(单位:元)</strong></p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>78</td>
<td>240</td>
<td>1300</td>
</tr>
<tr>
<td>3</td>
<td>88</td>
<td>256</td>
<td>1312</td>
</tr>
<tr>
<td>4</td>
<td>90</td>
<td>270</td>
<td>1398</td>
</tr>
<tr>
<td>6</td>
<td>93</td>
<td>272</td>
<td>1440</td>
</tr>
<tr>
<td>8</td>
<td>98</td>
<td>300</td>
<td>1568</td>
</tr>
<tr>
<td>9</td>
<td>100</td>
<td>328</td>
<td>1640</td>
</tr>
<tr>
<td>10</td>
<td>108</td>
<td>340</td>
<td>1696</td>
</tr>
<tr>
<td>12</td>
<td>118</td>
<td>348</td>
<td>1768</td>
</tr>
<tr>
<td>14</td>
<td>120</td>
<td>384</td>
<td>1896</td>
</tr>
<tr>
<td>18</td>
<td>128</td>
<td>400</td>
<td>1944</td>
</tr>
<tr>
<td>20</td>
<td>135</td>
<td>512</td>
<td>1968</td>
</tr>
<tr>
<td>25</td>
<td>136</td>
<td>600</td>
<td>1998</td>
</tr>
<tr>
<td>28</td>
<td>138</td>
<td>618</td>
<td>2000</td>
</tr>
<tr>
<td>30</td>
<td>148</td>
<td>640</td>
<td>2128</td>
</tr>
<tr>
<td>34</td>
<td>150</td>
<td>648</td>
<td>2256</td>
</tr>
<tr>
<td>35</td>
<td>153</td>
<td>656</td>
<td>2296</td>
</tr>
<tr>
<td>36</td>
<td>158</td>
<td>768</td>
<td>2384</td>
</tr>
<tr>
<td>38</td>
<td>168</td>
<td>896</td>
<td>2424</td>
</tr>
<tr>
<td>40</td>
<td>180</td>
<td>984</td>
<td>2552</td>
</tr>
<tr>
<td>45</td>
<td>188</td>
<td>998</td>
<td>2592</td>
</tr>
<tr>
<td>50</td>
<td>198</td>
<td>1000</td>
<td>2624</td>
</tr>
<tr>
<td>54</td>
<td>200</td>
<td>1288</td>
<td>2752</td>
</tr>
<tr>
<td>60</td>
<td>204</td>
<td>1256</td>
<td>2880</td>
</tr>
<tr>
<td>68</td>
<td>210</td>
<td>1288</td>
<td>2952</td>
</tr>
<tr>
<td>73</td>
<td>228</td>
<td>1296</td>
<td>2998</td>
</tr>
</tbody>
</table>
<h1>6.支付成功回调通知(服务端接口)</h1>
<h2>6.1.接口说明</h2>
<p><div style="background: #9efca6;padding: 12px; border-radius: 8px; color: #000;">✍
1.回调地址在客户端调用支付接口时传入,字段<font color="red">redirect_uri</font>。
2.回调方式为POST(请使用post方式接收回调值),数据提交为表单方式(Content-Type: application/x-www-form-urlencoded)
3.此接口地址由游戏服务方提供,用于接收用户支付结果的接口,控制游戏内发货,2S不响应则超时,做好过滤,防止重复通知
</div></p>
<h2>6.2.回调参数说明(post)</h2>
<p>|参数名|说明|
|:---- |----- |
|order_sn |订单编号(游戏的订单号) |
|extra_info |透传参数(原样返回,游戏在创建订单时传入,不允许有空格) |
|pay_amount |订单金额(单位:元,double类型,精确到小数点后两位)一定要校验价格 |
|pay_status |订单支付状态(1或0;1为成功支付,0为未支付) |
|pay_time |支付时间(若为三方或渠道支付,此时间为平台接收到支付成功时间) |
|uid |用户的唯一id,与客户端的openid字段相同 |
|goods_identifier |小游戏道具id(商品id) |
|sign |签名(为了安全,请校验签名)签名规则看回调签名 |</p>
<h2>6.3.回调签名(为了安全,请校验签名)</h2>
<p>1)去除sign,其他所有POST的参数均参与签名,签名小写
2)参数名进行升序排序后
3)按照key1=val1&key2=val2&key3=val3格式生成源字符串。
4)sha1(源字符串+加密secret_key)生成签名sign;
如:key1=val1&key2=val2&key3=val3<span style="color:red">secret_key</span></p>
<p>签名示例:</p>
<pre><code class="language-javascript">假设现有参数为:
{
&quot;extra_info&quot;:&quot;a=b&quot;,
&quot;goods_identifier&quot;:&quot;f4355f16858fc0244ea74ac540581148&quot;,
&quot;order_sn&quot;:&quot;202562793756161&quot;,
&quot;pay_amount&quot;:&quot;1.00&quot;,
&quot;pay_status&quot;:1,
&quot;pay_time&quot;:1750988310,
&quot;uid&quot;:&quot;0643nmopFTNBD9mYBp3et6BGtaHoAFU1gb-MPWaaq96Vrg7&quot;
}
密钥为:LBpq2CDg88slNVFurdQKXp
参数名排序后拼接的字符串为:
extra_info=a=b&amp;goods_identifier=f4355f16858fc0244ea74ac540581148&amp;order_sn=202562793756161&amp;pay_amount=1.00&amp;pay_status=1&amp;pay_time=1750988310&amp;uid=0643nmopFTNBD9mYBp3et6BGtaHoAFU1gb-MPWaaq96Vrg7LBpq2CDg88slNVFurdQKXp
Sha1加密为:3dd256d86256f0a42c588bc12e4e8f1d394923df</code></pre>
<h2>6.4.回调返回(json)</h2>
<pre><code class="language-javascript">1.游戏服务端在收到支付回调后,如果游戏发货成功,必须返回
{
&quot;code&quot;:0,
&quot;message&quot;:&quot;success&quot;
}
代表游戏发货成功。否则会重复回调
其他code码,游戏服务端自己定义。
2.可能存在重复通知的情况,如果对应订单已经发货成功,也请直接返回
{
&quot;code&quot;:0,
&quot;message&quot;:&quot;success&quot;
}</code></pre>
<h1>7.激励视频广告</h1>
<h2>7.1.接口说明</h2>
<p><div style="background: #9efca6;padding: 12px; border-radius: 8px; color: #000;">✍创建激励视频接口</p>
<p><code>createVideoAd(string auditID, callback)</code>
</div>
<div style="background: #FFE4B5;padding: 12px; border-radius: 8px; color: #000;">⚠️ <strong>注意</strong>
调用一次,拉起一次广告,游戏需要根据回调状态处理奖励的发送
</div></p>
<h2>7.2.参数说明</h2>
<p>|参数名|必选|类型|说明|
|:---- |:---|:----- |----- |
|auditID |是 |string |视频广告ID,小程序后台生成 |</p>
<h2>7.3.示例代码</h2>
<pre><code class="language-javascript">dyb.createVideoAd(&#039;ad_tiny_32432423432_2424242&#039;, function (call) {
//call返回的state有三种状态,分别是show,close,error
//show {&quot;state&quot;:&quot;show&quot;,&quot;isEnded&quot;:false,&quot;msg&quot;:&quot;视频展示成功&quot;}
//close {&quot;state&quot;:&quot;close&quot;,&quot;isEnded&quot;:true,&quot;msg&quot;:&quot;视频广告关闭&quot;}
//error {&quot;state&quot;:&quot;error&quot;,&quot;isEnded&quot;:false,&quot;msg&quot;:&quot;视频广告错误&quot;}
console.log(JSON.stringify(call), &#039;createRewardedVideoAd&#039;)
if (call.state == &#039;close&#039;) {
if (call.isEnded) {
//视频完整看完,进行发送奖励
console.log(&#039;//视频完整看完,进行发送奖励&#039;)
} else {
//视频没看完
console.log(&#039;//视频没看完&#039;)
}
}
})</code></pre>