游戏服务端接入指引¶
玩家token有效性检查接口¶
请求地址¶
请求协议¶
- http POST
- Content-Type: application/json
- Accept: application/json
请求参数¶
参数 | 必传 | 类型 | 含义 |
---|---|---|---|
app_id | Yes | string | yofun给游戏分配的app_id |
user_id | Yes | string | 登录成功后,yofun返回给游戏的user_id |
channel_token | Yes | string | sdk返给游戏的token |
返回值¶
参数 | 类型 | 含义 |
---|---|---|
code | int | 响应码 |
当成功返回,即状态码为200时,无此项,仅在出现错误时才有. | ||
msg | string | 响应提示 |
响应码说明:
值 | 含义 |
---|---|
1001 | 无效的参数和格式 |
4001 | 用户凭证过期 |
订单支付成功回调接口¶
接口描述¶
接入SDK的游戏,在客户端创建订单接口时传入对应的回调接口地址。用户支付成功后,游戏服务器通过这个接口接收支付成功的订单信息。
请求协议¶
- http POST
- Content-Type: application/json
- Accept: application/json
请求参数¶
Http请求头包含以下字段:
参数 | 必传 | 类型 | 含义 |
---|---|---|---|
X-Param-Sign | Yes | string | 使用网易私钥签名,游戏需使用网易提供的公钥进行验签。 |
Http请求体为json对象,字段描述如下:
参数 | 类型 | 含义 |
---|---|---|
order_id | string | sdk订单号 |
game_order_id | string | app订单号 |
app_id | string | 游戏编号 |
user_id | string | yofun用户id |
status | int | 订单状态: 1初始化;2成功;3失败; 理论上成功才会通知 |
order_price | int | 订单金额 单位分 |
goods_info | json | 商品信息 字典格式(dict) |
create_time | int | 订单创建时间 Unix时间戳(Unix timestamp)精确到秒 |
pay_time | int | 订单支付完成时间 Unix时间戳(Unix timestamp)精确到秒 |
pay_method | string | 支付方式 例如支付宝、银联、平台币等 |
reserved | string | 透传字段 客户端创建的时候传入 |
返回值¶
返回值为json格式,字段描述如下:
参数 | 类型 | 含义 |
---|---|---|
code | int | 状态码 |
msg | string | 描述信息 |
code 含义如下:
code | msg | 中文描述 |
---|---|---|
200 | success | 成功,不再通知 |
201 | duplicate | 重复通知,不再通知 |
500 | other error | 其它错误,继续通知 |
失败重试机制¶
游戏服务器在收到支付成功的通知后,如果没有返回200给SDK服务器,SDK服务器会认为游戏服务器没有收到通知,并重复通知直至成功,或者超时(24小时)。
请求示例¶
请求地址示例(游戏服务端提供):
http://{apphost}:{port}/notify?someother=xxx
Body
{ "order_id": 1194, "game_order_id": "hub_test_1542167165", "app_id": "mumu", "user_id": "aebvxkqr6uaaaadm", "status": 2, "order_price": 1, "goods_info": "{\"goods_id\": \"product_01\", \"goods_name\": \"好吃的ddd\", \"goods_count\": 1, \"goods_price\": 1}", "create_time": 1542167166, "pay_time": 1542167171, "pay_method": "ALIPAY" "reserved": "{\"key3\": \"value3\", \"key2\": \"value2\", \"key1\": \"value1\"}", }
- 签名公钥:
平台提供, 签名方式SHA1RSA
- 签名原文:url+body
sign = sha1rsa(PATH_QS+BODY) PATH_QS 为URL中除请求协议以及域名端口之外的部分,如/notify?someother=xxx
注意:如果回调地址本身没有带参数,只是url,也需要加上?号做拼接
待签名串:
/notify?someother=xxx{ "order_id": 1194, "game_order_id": "hub_test_1542167165", "app_id": "mumu", "user_id": "aebvxkqr6uaaaadm", "status": 2, "order_price": 1, "goods_info": "{\"goods_id\": \"product_01\", \"goods_name\": \"好吃的ddd\", \"goods_count\": 1, \"goods_price\": 1}", "create_time": 1542167166, "pay_time": 1542167171, "pay_method": "ALIPAY" "reserved": "{\"key3\": \"value3\", \"key2\": \"value2\", \"key1\": \"value1\"}", }
签名(注意是16进制):
95b95cefb164085bd7f2acaeb6088986e75b641741b560dfea4e3d8e4e30d4a773f7d5744b65eefdb74e42ccd3f3bacab7a2fc8c40584424495bbd4898eae5baaf0e42a98ac01267b8c567af653fae76c0d6e37a120f5c6d276f636dea3a3fdb733e489c6a90a5db41bbfb6c3e15ac758d2af805a395679a003635ec9561a73d
Http Header:
X-Param-Sign: 95b95cefb164085bd7f2acaeb6088986e75b641741b560dfea4e3d8e4e30d4a773f7d5744b65eefdb74e42ccd3f3bacab7a2fc8c40584424495bbd4898eae5baaf0e42a98ac01267b8c567af653fae76c0d6e37a120f5c6d276f636dea3a3fdb733e489c6a90a5db41bbfb6c3e15ac758d2af805a395679a003635ec9561a73d
游戏服务器验证订单的准确性之后返回:
{ "code": 200, "msg": "ok", }
签名Demo:¶
原文:QueryString+body, QueryString是带有?的,即使回调接口没有参数,也需要带上? 如: /callback/yofun?{xxxxx}
获取body内容,签名原文拼接切记直接将body拿来拼接,不要转成json再转回来,否则顺序就会被改变。
JAVA
//验签 public boolean verify(String plain, String signature,String keycode) { //获取公钥 try { KeyFactory keyFactory= KeyFactory.getInstance("RSA"); // 如果 Base64.decodeBase64() 需要以 byte[] 为参数,则需要将 keycode 转为 byte[],比如 keycode.getBytes() byte[] keyByte= Base64.decodeBase64(keycode); X509EncodedKeySpec encodeRule=new X509EncodedKeySpec(keyByte); PublicKey publicKey= keyFactory.generatePublic(encodeRule); Signature sign=Signature.getInstance("SHA1WithRSA"); sign.initVerify(publicKey); sign.update(plain.getBytes()); //将16进制码转成字符数组 //注意这里是hex的 byte[] hexByte= Hex.decodeHex(signature.toCharArray()); //验证签名 return sign.verify(hexByte); } catch (Exception e) { e.printStackTrace(); } return false; } //获取body public static String readData(HttpServletRequest request) { BufferedReader br = null; try { StringBuilder ret; br = request.getReader(); String line = br.readLine(); if (line != null) { ret = new StringBuilder(); ret.append(line); } else { return ""; } while ((line = br.readLine()) != null) { ret.append('\n').append(line); } return ret.toString(); } catch (IOException e) { throw new RuntimeException(e); } finally { if (br != null) { try {br.close();} catch (IOException e) { e.printStackTrace();} } } }
PHP
//plain=url+body function verify($plain, $sign, $pubKey) { $openssl_public_key = openssl_get_publickey($pubkey); //注意这里是hex2bin $ok = openssl_verify($plain, hex2bin('sign'), $openssl_public_key, OPENSSL_ALGO_SHA1); openssl_free_key($openssl_public_key); return $ok; }