//GooglePlay var mysql = require('mysql'); var mysqlcn = require('../../terry/mysqlcn.js'); var query = mysqlcn.query; var qs = require('querystring'); var encryption = require('../ordinary/encryption.js'); var checkorder = require('../../terry/checkorder.js'); var config = require('../config.js'); var express = require('express'); var router = express.Router(); var https = require('https'); var http = require('http'); var crypto = require('crypto'); // var IS_TEST = 2 //1是测试2是正式 Date.prototype.Format = function (fmt) { //author: meizz var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 "m+": this.getMinutes(), //分 "s+": this.getSeconds(), //秒 "q+": Math.floor((this.getMonth() + 3) / 3), //季度 "S": this.getMilliseconds() //毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt; } var sql_insert = function(orderid, serverid,uid,rmb,moneytype,cfid,platform,channel,overtime,flag,product_id,user_id,purchase_date_ms,talkingdata,payment_type,istest){ var sql = "INSERT INTO payinfo SET orderid=?, serverid=?, channel=?, submittime=?, flag=?, user_id=?, channel_order_id=?, money=?, cfid=?, platform=?,overtime=?,product_id=?,uid=?,moneytype=?,talkingdata=?,payment_type=?,istest=?"; var values = [orderid, serverid, channel,purchase_date_ms,flag,user_id,orderid,rmb,cfid,platform,overtime,product_id,uid,moneytype,talkingdata,payment_type,istest]; sql = mysql.format(sql, values); return sql; } function insert_str(str, insert_str, sn) { var newstr = ""; for (var i = 0; i < str.length; i += sn) { var tmp = str.substring(i, i + sn); newstr += tmp + insert_str; } return newstr; } var RsaSha1Check = function(str,sig,publicKey){ var public_key = insert_str(publicKey, '\n', 64); public_key = '-----BEGIN PUBLIC KEY-----\n' + public_key + '-----END PUBLIC KEY-----'; var verifier = crypto.createVerify('RSA-SHA1'); console.log('验证签名public key:\n' + public_key); console.log('验证签名src_sign:' + str); verifier.update(new Buffer(str, 'utf-8')); return verifier.verify(public_key, sig, 'base64'); }; var pay_success = function(args,res){ if (args==null){ console.log("[GooglePlay] 无效的充值请求!"); try{res.send("error,1");} catch(e){} return; } var obj = null try { obj = qs.parse(args); } catch(e){ console.log("[GooglePlay] 无效的充值请求!"); try{res.send("error,1");} catch(e){} return } var orderid = obj.orderid; //订单号 var serverid = obj.serverid;//服务器id var userid = obj.userid; //玩家的渠道帐号 var uid = obj.uid; //玩家游戏uid var platformid = obj.platformid;//googleplay var gp_appid = obj.channel; //渠道 var channel = config.get_channel(gp_appid) var inapp_purchase_data = obj.inapp_purchase_data; var inapp_data_signature = obj.inapp_data_signature; var ti = new Date().Format("yyyy-MM-dd hh:mm:ss"); var payment_type = "GooglePlay" + gp_appid var is_test = obj.is_test var IS_TEST = config.get_istest(gp_appid) console.log("[GooglePlay] 订单 %s 请求 (%s):\n\tserverid=%s,uid=%s,userid=%s,platform=%s,channel=%s,inapp_purchase_data=%s,inapp_data_signature=%s,gp_appid=%s", orderid, ti, serverid,uid,userid,platformid,channel,inapp_purchase_data,inapp_data_signature,gp_appid); if (is_test != IS_TEST){ console.log("订单状态不正常is_test:%s,IS_TEST:%s",is_test,IS_TEST) try{res.send("error,2");} catch(e){} return } if (config.allowed_googleplay_channel(channel) == false) { try{res.send("error,2");} catch(e){} console.log("[GooglePlay] 订单 %s: 不支持的渠道!,channel:%s", orderid,channel); return } if (platformid != "googleplay"){ try{res.send("error,7");} catch(e){} console.log("[GooglePlay] 订单 %s: 不支持的平台!,platformid:%s", orderid,platformid); return } var token = config.get_googleplay_sig(gp_appid); //签名验证 var istrue = false // if(config.get_googleplay_sig(gp_appid)){ // console.log("[GooglePlay] 不验证md5 渠道:appid %s:%s", channel,gp_appid); // istrue = true // }else{ console.log("[GooglePlay] 验证md5 渠道:appid %s:%s", channel,gp_appid); console.log("inapp_purchase_data:%s",inapp_purchase_data) console.log("inapp_data_signature:%s",inapp_data_signature) console.log("token:%s",token) istrue=RsaSha1Check(inapp_purchase_data,inapp_data_signature,token); // } console.log(istrue); if(istrue){ var result = JSON.parse(inapp_purchase_data); //var consumptionState = result.consumptionState;//inapp产品的消费状态。0:还有待消耗,1:消费 //var developerPayload = result.developerPayload;//包含有关订单的补充信息的开发人员指定的字符串。 //var kind = result.kind; //这种类型表示androidpublisher服务中的一个inappPurchase对象。 var channelorderID = result.orderId // GooglePlay订单 var purchaseState = result.purchaseState; //订单的购买状态。0:购买,1:取消 var purchaseTime = result.purchaseTime; //购买产品的时间,以毫秒为单位 //var purchaseType = result.purchaseType; //购买inapp产品的类型。如果此购买不是使用标准应用内结算流程进行的,则仅设置此字段。0:测试 var productId = result.productId; //玩家购买的产品包 console.log("[GooglePlay] cp订单 %s, GooglePlay订单 %s, 购买参数(0:购买,1:取消) %s, 时间 %s, 购买的产品包 %s", orderid, channelorderID,purchaseState,purchaseTime,productId) if (purchaseState != 0){ try {res.send('erron,3');} catch(e){} console.log("[GooglePlay] 未购买!") return } // //检查订单 purchaseTime = purchaseTime / 1000; var conf = config.parse(platformid, channel, productId); var appId = config.getAppID(channel); var chargeTime = Date.parse(new Date()) / 1000; var rmb = conf.price; var cfid = conf.cfid; var moneytype = conf.typename; if (cfid == 0){ console.log("[GooglePlay] channel:%s获取cfid失败为platformid:%s,productId:%s",channel,platformid,productId); try{res.send("fail");} catch(e){} return } console.log("[GooglePlay] 订单 %s 处理:\n\t商品配置:%s, 金额:%s, 类型:%s, 用户:%s, 服务器:%s", channelorderID,cfid,rmb,moneytype,uid,serverid); var callback = function(code) { var errnoa = "error," + code try{res.send(errnoa);} catch(e){} } var sql = sql_insert(channelorderID, serverid,uid,rmb,moneytype,cfid,"android",channel,chargeTime,1,productId,userid,purchaseTime,1,payment_type,is_test); var execute = function(channelo_rderID,_cfid,_rmb,_conf) { query(sql,function(qerr,vals,fields){ try { if (qerr) { if (qerr.errno == 1062) { // 视为成功,但不再发货。 try{res.send('erron,0#' + channelo_rderID);} catch(e){} console.log("[GooglePlay] 订单 %s: 已存在!", channelo_rderID); } else { callback(7); console.log("[GooglePlay] 订单 %s: 存储失败!\n\t%s",channelo_rderID, JSON.stringify(qerr)); } } else { //通知游戏服务器发货 serverid = parseInt(serverid); checkorder.pushproduct(query,channelo_rderID,uid,serverid,_cfid, function(ok){ if (ok) { try{res.send("ok#" + channelo_rderID);} catch(e){} console.log("[GooglePlay] 订单 %s: 成功发货!",channelo_rderID); } else{ callback(8) console.log("[GooglePlay] 订单 %s: 发货地址无效!", channelo_rderID); } }) // 向 TalkingData 报告充值数据 checkorder.pushtalkingdata(query,appId,"android",uid,channelo_rderID,_conf.price,_conf.typename,_conf.diamond,chargeTime,"GooglePlay",serverid); } } catch(err) { console.log(err); } }) } // 存盘并发货 execute(channelorderID, cfid, rmb, conf) // try{res.send("ok");} // catch(e){} console.log("[GooglePlay] 订单 %s 交易成功!", orderid); }else{ try {res.send('erron,4');} catch(e){} console.log("[GooglePlay] 非法的订单数据!") return } } router.post('/googleplay', function(req, res) { console.log("谷歌,post ,host:%s, ip:%s,date:%s",req.hostname,req.ip,new Date()); var data = ""; req.on("data",function(chunk){ data += chunk; }) req.on("end",function(){ pay_success(data,res); }) req.on("error",function(err){ res.send('erron,1'); }) }); module.exports = router;