Bazaar支付的服务端验证

游戏上线后充值被破解

由于之前对Bazzar支付方式的了解不够透彻,以至于我以为支付的验证放在客户端便能解决问题,等到上线之后发现游戏的充值分分钟钟被lucky pacher破解,真是后悔莫及.因为对于服务端而言,现有的参数远远不能做任何验证的.无奈,只能在新包中重新对好API后等待游戏包强制更新了.

游戏服务端API验证功能

Cafebazaar Developer API is a REST API that allows you to automatically perform some of your product management tasks. Using this API, you can check the status of your products and subscriptions sales from your personal server.

Bazaar充值验证的OAuth2授权

因为Bazzar的充值验证功能是需要经过OAuth2授权之后才能请求的,所以在此之前需要预先通过授权获取refresh_token 和 access_token并保存在指定地方.一旦access_token失效之后需要通过refresh_token重新获取,并重新保存.当然,前提是你必须要现在开发者后台先创建好client_id和client_secret以及redirect_uri.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function getAccessToken(){
$jsonAccess = file_get_contents($this->dirConfig."/access.json");
$arrDataAccess = json_decode($jsonAccess,true);
if(isset($arrDataAccess['dateline']) && $this->getAccessTokenExpire($arrDataAccess['dateline'])){
$arrGetAccessTokenWhere = array(
"grant_type" => "refresh_token",
"client_id" => $this->idClient,
"client_secret" => $this->secretClient,
"refresh_token" => $this->tokenRefresh,
);
$jsonAccess = $this->apiCurl->curlByPost(json_encode($this->uriGetToken),$arrGetAccessTokenWhere);
$arrDataAccess = json_decode($jsonAccess,true);
if(isset($arrDataAccess['access_token'])){
$arrDataAccess['dateline'] = $this->getCurrentTimeStamp() + $arrDataAccess['expires_in'];
$jsonAccess = json_encode($arrDataAccess);
file_put_contents($this->dirConfig."/access.json",$jsonAccess);
}
}
return $arrDataAccess;
}

Bazaar充值验证API的接入

获取到Bazzar的授权access_token之后,方可通过purchase validation api 获取相应的数据.

1
2
3
4
5
6
7
8
9
function getPurchaseValidation($arrData){
$arrDataAccess = $this->getAccessToken();
$urlPurchaseValidation = "https://pardakht.cafebazaar.ir/devapi/v2/api/validate/{$arrData['packagename']}/inapp/{$arrData['productId']}/purchases/{$arrData['purchaseToken']}?access_token=".$arrDataAccess['access_token'];
$timeLog = @date('[d/M/Y:H:i:s]');
file_put_contents($this->dirRoot."/purchaseValidation.txt",$timeLog."-".$urlPurchaseValidation.PHP_EOL,FILE_APPEND);
$jsonPurchaseValidation = file_get_contents($urlPurchaseValidation);
file_put_contents($this->dirRoot."/purchaseValidation.txt",$timeLog."-".$jsonPurchaseValidation.PHP_EOL,FILE_APPEND);
return $jsonPurchaseValidation;
}

如果请求成功无误的话,将会从purchase validation api获取到一段json格式的数据,如下所示:

1
2
3
4
5
6
7
{
"consumptionState": 1,
"purchaseState": 0,
"kind": "androidpublisher#inappPurchase",
"developerPayload": "something",
"purchaseTime": 1414181378566
}

程序通过上述参数就可以判断该订单是否充值成功.

以下是官方对各个参数的说明.

Name Description
consumptionState This field is 0, if the purchase is consumed, and 1 otherwise.
purchaseState Normally this field is 0, but if the purchase is refunded it is 1.
kind Type of the returned resource. This will always be androidpublisher#inappPurchase
developerPayload The payload string that is sent to Bazaar by app when making the purchase.
purchaseTime Time of the purchase as milliseconds from EPOCh (1970/1/1).

补充说明

Bazaar充值中也使用到了RSA加密验证确保数据传输的完整性以防止他人的篡改,在Bazaar开发者后台中找到一串经过base64加密过的公钥.当客户端向服务端发起充值请求之后,Bazaar服务器端相应的会返回一系列参数.而这部分校验过程中需要使用到RSA加解密.

总结

  • 生活难免会有糊涂的时候,这时候的我们更需要拿起自身的勇气和耐心,敢于承担与付出.
  • Bazaar的充值流程和google play的充值流程是相似的,甚至于他们的验证方式.
  • 此次的经验教训加深了我对OAuth2的权限的了解以及RESTFUL的异同.

参考资料

In-app-developer-api-oauth2
In-app-purchase-validation

文章目录
  1. 1. 游戏上线后充值被破解
  2. 2. 游戏服务端API验证功能
    1. 2.1. Bazaar充值验证的OAuth2授权
    2. 2.2. Bazaar充值验证API的接入
  3. 3. 补充说明
  4. 4. 总结
  5. 5. 参考资料