123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- //QUICK
- var https = require('https');
- var http = require('http');
- var mysql = require('mysql');
- var config = require('../../pay/config');
- var crypto = require('crypto');
- var qs = require('querystring');
- var checkorder = require('../checkorder');
- var url = require('url');
- var xml2js = require('xml2js');
- var parser = new xml2js.Parser(); //xml -> json
- var builder = new xml2js.Builder(); // JSON->xml
- //md5加密
- var md5 = function (str){
- var md5sum = crypto.createHash('md5');
- md5sum.update(str);
- str = md5sum.digest('hex');
- return str;
- };
- //quick解密操作
- function stringToBytes (str) {
- var ch, st, re = [];
- for (var i = 0; i < str.length; i++ ) {
- ch = str.charCodeAt(i);
- st = [];
- do {
- st.push( ch & 0xFF );
- ch = ch >> 8;
- }while ( ch );
- re = re.concat( st.reverse() );
- }
- return re;
- }
- function bytesToString(array) {
- return String.fromCharCode.apply(String, array);
- }
- //将quick的加密文件解密成XML文件
- function decode(str,key){
- if(str.length <= 0){
- return '';
- }
- var list = new Array();
- var resultMatch = str.match(/\d+/g);
- for(var i= 0;i<resultMatch.length;i++){
- list.push(resultMatch[i]);
- }
- if(list.length <= 0){
- return '';
- }
-
- var keysByte = stringToBytes(key);
- var dataByte = new Array();
- for(var i = 0 ; i < list.length ; i++){
- dataByte[i] = parseInt(list[i]) - (0xff & parseInt(keysByte[i % keysByte.length]));
- }
- if(dataByte.length <= 0){
- return '';
- }
- var parseStr = bytesToString(dataByte);
- return parseStr;
- }
- //充值成功的时候修改库中数据
- var sql_update_quick = function(order_no,timestamp,flag,ordermoney,cfida,platform,channel,payment_type,moneytype,sdcustomno){
- //填充充值信息
- var sql_2 = "UPDATE payinfo SET channel_order_id=?,overtime=?,flag=?,money=?,cfid=?,platform=?,channel=?,payment_type=?,moneytype=?,talkingdata=? WHERE orderid=? AND flag=2";
- var timestamp = Date.parse(new Date()) / 1000;
- var cfid = ordermoney;
- var values_2 = [order_no,timestamp,1,ordermoney,cfida,platform,channel,payment_type,moneytype,1,sdcustomno];
- var sql = mysql.format(sql_2, values_2);
- return sql;
- }
-
- exports.quick_pay_success = function(args,query,res,quick_proto){
- var obj = qs.parse(args);
- var nt_data = obj.nt_data; //通知数据(XML格式)
- var sign = obj.sign; //签名串
- var md5Sign = obj.md5Sign; //string 签名计算方法为MD5
- var outputname = quick_proto.outputname //使用quick的渠道
- var callback_key = quick_proto.callback_key //quick解密编码
- var md5_key = quick_proto.md5_key //MD5加密编码
- console.log(outputname+"quick回调来了");
- //将加密文件解密成XML文件
- var xml = decode(nt_data,callback_key);
- console.log(xml);
- //解析xml文件转json
- parser.parseString(xml, function (err, result)
- {
- if (err)
- {
- console.log("err:%s",err);
- try{res.send("FAILED");}
- catch(e){}
- }
- else
- {
- var aa = JSON.stringify(result);
- var dat_js = JSON.parse(aa);
- var jsons = dat_js.quicksdk_message.message[0];
- var nt_dat_js = jsons;
- var is_test = nt_dat_js.is_test[0]; //是否为测试订单 1为测试 0为线上正式订单
- console.log("is_test:%s",is_test);
- var pay_channel = nt_dat_js.channel[0]; //渠道标示ID
- var channel_uid = nt_dat_js.channel_uid[0]; //渠道用户唯一标示,该值从客户端GetUserId()中可获取
- var game_order = nt_dat_js.game_order[0]; //游戏在调用QucikSDK发起支付时传递的游戏方订单,这里会原样传回
- var order_no = nt_dat_js.order_no[0]; //QuickSDK唯一订单号
- var pay_time = nt_dat_js.pay_time[0]; //支付时间
- var amount = nt_dat_js.amount[0]; //成交金额,单位元
- var status = nt_dat_js.status[0]; //充值状态 0成功 1失败(为1时 应返回FAILED失败)
- var extras_params = nt_dat_js.extras_params[0];//额外参数,现在使用的配置sid
- console.log("status:%s",status);
- if (status==1)
- {
- try{
- console.log(outputname+"quick支付失败,state=%s",status);
- var sql = "UPDATE payinfo SET flag=? WHERE orderid=?";
- var values = [-2,game_order]; //玩家获取了订单,但是支付失败,因此把flag设置为-2
- sql = mysql.format(sql, values);
- query(sql,function(_qerr,_vals,_fields){});
- }catch(err){}
- try{res.send("FAILED");}
- catch(e){}
- return
- }
- else
- {
- try{
- var sql_1 = mysql.format("SELECT * FROM payinfo where orderid=?", [game_order]);//在mysql库中检查订单号
- query(sql_1,function(qerr,vals,fields_)
- {
- console.log("quick_pay_success,1");
- if(qerr){
- //"逻辑错误,请检查数据表结构和sql语句"
- console.log(outputname+"quick逻辑错误,请检查数据表结构和sql语句");
- try{res.send("FAILED");}
- catch(e){}
- return;
- }
- if (vals[0]==null){
- console.log(outputname+"quick没有找到该订单");
- try{res.send("FAILED");}
- catch(e){}
- return;
- }
- if (vals[0].overtime>0){
- console.log(outputname+"quick已经处理的订单");
- try{res.send("SUCCESS");}
- catch(e){}
- return;
- }
- var genSign = md5(nt_data+sign+md5_key);
- if(md5Sign != genSign){
- console.log(outputname+"quick支付签名验证失败,md5Sign:%s,genSign:%s",md5Sign,genSign);
- try{res.send("FAILED");}
- catch(e){}
- return;
- }
- //var des = "null";//描述订单支付成功或失败的系统备注
- var platform = 'android'; // 只存储 ios 和 android
- var channel = quick_proto.channel; // 只存储 qianxun、zaya、limayao, zhangyu, friday, wudiyongshi, banli, zhiyu, cloud
- var payment_type = pay_channel.toString(); // 具体的子渠道,比如 quick 的 微信、手Q、UC、应用宝等, 新增一个 paymentType 字段来填充
- var timestamp = Date.parse(new Date()) / 1000;
- var option = config.parse(platform,channel,extras_params)//extras_params
- var cfid = option.cfid//config.quick_dollar(parseInt(amount));//购买商品ID--parseInt转int
- if (cfid == 0){
- console.log(outputname+"QUICK获取cfid失败为:%s,extras_params:%s", cfid,extras_params);
- try{res.send("FAILED");}
- catch(e){}
- return;
- }
- if (amount != option.price){
- console.log(outputname+"QUICK金额不一致为amount:%s,option.price:%s", amount,option.price);
- try{res.send("FAILED");}
- catch(e){}
- return;
- }
-
- var sql_2 = sql_update_quick(order_no,timestamp,1,amount,cfid,platform,channel,payment_type,option.typename,game_order)
- query(sql_2,function(qerr,rows,fields_)
- {
- if (qerr){
- console.log(qerr);
- try{res.send("FAILED");} //"逻辑错误,请检查数据表结构和sql语句"}
- catch(e){}
- return;
- }
-
- if (rows.affectedRows <= 0){//判断修改了多少个记录
- console.log(outputname+"quick已经处理的订单");
- try{res.send("SUCCESS");}
- catch(e){}
- return;
- }
- console.log(outputname+"quick支付成功了,现在通知游戏服务器, game_order:%s, username:%s, playerid:%s, serverid:%s ,cfid:%s",
- game_order,vals[0].username,vals[0].playerid,vals[0].serverid,cfid);
- //send_2_game(query,game_order,vals[0].username,vals[0].playerid,vals[0].serverid,cfid, function(ok){
- checkorder.pushproduct(query,game_order,vals[0].uid,vals[0].serverid,cfid, function(ok){
- if (ok) {
- console.log(outputname+"QUICK 订单 %s: 成功发货!", game_order);
- try{res.send("SUCCESS");}
- catch(e){}
- } else{
- console.log(outputname+"QUICK 订单 %s: 发货地址无效!", game_order);
- try{res.send("FAILED");}
- catch(e){}
- }
- });
- // 向 TalkingData 报告充值数据
- var appId = config.getAppID(channel);
- checkorder.pushtalkingdata(query,appId,platform,vals[0].uid,game_order,option.price,option.typename,option.diamond,timestamp,payment_type,vals[0].serverid);
-
- })
- });
- }catch(err){
- console.log(outputname+"quick_err ,%s",err);
- try{res.send("FAILED");}
- catch(e){}
- }
- }
- }
- })
- }
|