从来没有做过支付相关的,然后接到新任务是写支付的文档,写了几天发现支付状态跟产品需求有出入(加一些中间状态没什么,对外转一下暴露不存在),但是增加的状态没用就搞不懂了,除了这个还有逻辑上的漏洞,存在无限制补单情况!!!
好吧,请问了产品,然后决定填上这个坑!
....
改好后做google 支付验证,google 存在两种支付验证:
- 查询订单状态
- 根据客户端返回的rsa公钥校验订单数据
第二种没有订单详细情况,只有付款成功,跟失败,没有中间状态(支付未到账)
这里说说我遇到用第二种方式去做验证,在做请求google验证时一直失败,因为不懂,只能一点一点调试,最终发现是 自己做验证的秘钥不是google 应用上的秘钥(秘钥被存在数据库,我换了另一个库连接,不知道这里的秘钥不是最新的)最终将数据库的秘钥跟新到跟google 提供的秘钥一致就验证通过了。
秘钥地址在: 点击进入应用 -> 开发工具 - > 服务和API -> 许可与应用内购买结算
贴一下用nodejs 写的验证代码
import * as crypto from 'crypto';
interface IGoogleVerifyReceipt {
orderId: string;
packageName: string;
productId: string;
purchaseState: number;
developerPayload: string;
}
class GooglePaymentClass {
base64Decode(str: string) {
return new Buffer(str, 'base64').toString();
}
async verifyReceipt(params, publicKey): Promise<any> {
return new Promise((resolve, reject) => {
let pmd = '-----BEGIN PUBLIC KEY-----';
const base64 = publicKey;
const size = base64.length;
for (let i = 0; i < size; i = i + 64) {
const end = i + 64 < size ? i + 64 : size;
pmd = pmd + '\n' + base64.substring(i, end);
}
pmd = pmd + '\n-----END PUBLIC KEY-----';
// verifier
const verifier = crypto.createVerify('sha1');
const inAppData = GoolgePayment.base64Decode(params.purchaseToken);
console.log(`inAppData: ${inAppData}`);
verifier.update(inAppData);
const ret = {} ;
try {
console.log('开始验证');
console.log(`pmd: ${pmd}`);
console.dir(params.signature);
const isValid = verifier.verify(pmd, params.signature, 'base64');
console.log(isValid);
}catch (e) {
}
resolve(ret);
});
}
}
export const GoolgePayment = new GooglePaymentClass();
let content = '{"outerOrderId":"villas","productId":"villas","purchaseToken":"eyJvcmRlcklkIjoiR1BBLjMzMTMtOTcxNC0yMDk4LTg3ODM3IiwicGFja2FnZU5hbWUiOiJjb20u\\nc2hpbmV6b25lLmRlbW8iLCJwcm9kdWN0SWQiOiJ2aWxsYXMiLCJwdXJjaGFzZVRpbWUiOjE1Mjk5\\nMTg1NDk3MjIsInB1cmNoYXNlU3RhdGUiOjAsImRldmVsb3BlclBheWxvYWQiOiJ7XCJhcHBJZFwi\\nOjExMTQsXCJndWlkXCI6XCI4MDAxMDI1Nzg5NTQyNFwiLFwicHJvZHVjdElkXCI6XCJ2aWxsYXNc\\nIixcInN6T3JkZXJJZFwiOlwiODAxMTQxODQzNTk5MzZcIixcInBheW1lbnRNZXRob2RcIjoyLFwi\\ncmVhbEN1cnJlbmN5XCI6XCJIS0RcIixcInJlYWxBbW91bnRcIjpcIjguMDBcIn0iLCJwdXJjaGFz\\nZVRva2VuIjoia2xramRhb29lbG9mbWpkb21kb21wbmdqLkFPLUoxT3prOGNrei10Z1JtRzJGZE1G\\nZld2NDI5ZnBOaHJzOHQ1V2xjMG1QWXI0UmZpM3RkVHNHV0VsWV9ZbHBqRjM1OE4zQU9TWWNYY0ZH\\nenU0N2ZsejBDdVpnYXFweXE3em5BcDBpUkVxeGZYNGpYZTRqdFRRIn0=\\n","realAmount":8,"realCurrency":"HKD","signature":"C2z4nz9j0lJLbtAXJetl5ky/hs0BQ9GNrSX2Txjg50bBUkrUg6TF1EX07FWxcWkUaqIs46TGjCrXm7QX3tSrrLJww5V4mj77J6dVNZ1C6/U0+gfbZNaLnRFfwPk+AXXtq6IlYGkqrYQdi5uH0/BEjAnBIKWKBED/ToMJEVMV8OYxT9ipKKJlUgQasRks7jbV79LifF7ZduC7X+nsuKsTWh4LUg2vNmvAg24tu2D9LB7AYYcztN9xEwHsPy3sTvbmti8PpZWKxUSqZBp7OtXx8fYzrmME2ILPz0cjXMrLNFdTWekFPsszais8XAf7yV/695unXaG4Deb4Od1Tr74CSA=="}';
const params = JSON.parse(content);
let publicKey = '服务器提供的秘钥';
const res = GoolgePayment.verifyReceipt(params, publicKey);