我这里服务器是基于node.js的pomelo框架,前端则是用unity3d。unity3d通过一个插件实现了前端的支付功能,但是没有验证功能。具体可以看文档:https://docs.unity3d.com/Manual/UnityIAP.html和https://docs.unity3d.com/Manual/UnityIAPValidatingReceipts.html。
在文章https://www.timiguo.com/archives/92/提到了,验证有两种,我这里则是用node实现了签名验证。从这篇文章,感觉php真是强大,还好,node一样的强大,同样也有完整库。
在unity3d 支付回的received的回调中,会返回验证需要的两个数据,都是在Payload中。
在google play console里面,对应的app可以取得公钥,需要复制出来。有了上面的INAPP_PURCHASE_DATA和INAPP_DATA_SIGNATURE,就可以做支付签名认证了。
下面是具体用node的实现。原版是PHP实现,我这里则用node做了一个实现。现在用node的同学越来越多了,希望有一点帮助。
let _ = require('lodash');
const crypto = require('crypto');
//一时在node.js没有找到PHP的chunk_split对应函数,就临时写了一个
function chunk_split(paramString, paramLength, paramEnd = '\n') {
let p = [];
let s = paramString;
while(s.length > paramLength) {
let s1 = s.substr(0, paramLength);
let s2 = s.substr(paramLength);
s = s2;
p.push(s1);
}
if(s.length > 0) {
p.push(s);
}
p.push('');
return p.join(paramEnd);
}
function GooglePlayCheck(params) {
let verify = crypto.createVerify('RSA-SHA1');//请注意,这里要用RSA-SHA1也就是RSA with sha1等同于php的OPENSSL_ALGO_SHA1,我试了好多,才试出来
let PHP_EOL = '\n';//实际上就是换行符
let inappPurchaseData = '{"orderId":"XXXXXX","packageName":"yyyy.jjjj.kkkk","productId":"pppp","purchaseTime":1530004167355,"purchaseState":0,"purchaseToken":"jgehkmkjnnolimdlllaeebcc.实际更长,这里删除了"}';
let googlePublicKey = '从google play console对应的app设置找出来';
let inappDataSignature = 'base64格式的';
//这里要将公钥转换成64个字符一行的文本块。
let publicKey = "-----BEGIN PUBLIC KEY-----" + PHP_EOL + chunk_split(googlePublicKey, 64, PHP_EOL) + "-----END PUBLIC KEY-----";
verify.update(inappPurchaseData);//
let r = verify.verify(publicKey, Buffer.from(inappDataSignature,'base64')); //验证数据
console.log(params + "-->rrrrrrrrrrr:",r);
}