quick.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. //QUICK
  2. var https = require('https');
  3. var http = require('http');
  4. var mysql = require('mysql');
  5. var config = require('../../pay/config');
  6. var crypto = require('crypto');
  7. var qs = require('querystring');
  8. var checkorder = require('../checkorder');
  9. var url = require('url');
  10. var xml2js = require('xml2js');
  11. var parser = new xml2js.Parser(); //xml -> json
  12. var builder = new xml2js.Builder(); // JSON->xml
  13. //md5加密
  14. var md5 = function (str){
  15. var md5sum = crypto.createHash('md5');
  16. md5sum.update(str);
  17. str = md5sum.digest('hex');
  18. return str;
  19. };
  20. //quick解密操作
  21. function stringToBytes (str) {
  22. var ch, st, re = [];
  23. for (var i = 0; i < str.length; i++ ) {
  24. ch = str.charCodeAt(i);
  25. st = [];
  26. do {
  27. st.push( ch & 0xFF );
  28. ch = ch >> 8;
  29. }while ( ch );
  30. re = re.concat( st.reverse() );
  31. }
  32. return re;
  33. }
  34. function bytesToString(array) {
  35. return String.fromCharCode.apply(String, array);
  36. }
  37. //将quick的加密文件解密成XML文件
  38. function decode(str,key){
  39. if(str.length <= 0){
  40. return '';
  41. }
  42. var list = new Array();
  43. var resultMatch = str.match(/\d+/g);
  44. for(var i= 0;i<resultMatch.length;i++){
  45. list.push(resultMatch[i]);
  46. }
  47. if(list.length <= 0){
  48. return '';
  49. }
  50. var keysByte = stringToBytes(key);
  51. var dataByte = new Array();
  52. for(var i = 0 ; i < list.length ; i++){
  53. dataByte[i] = parseInt(list[i]) - (0xff & parseInt(keysByte[i % keysByte.length]));
  54. }
  55. if(dataByte.length <= 0){
  56. return '';
  57. }
  58. var parseStr = bytesToString(dataByte);
  59. return parseStr;
  60. }
  61. //充值成功的时候修改库中数据
  62. var sql_update_quick = function(order_no,timestamp,flag,ordermoney,cfida,platform,channel,payment_type,moneytype,sdcustomno){
  63. //填充充值信息
  64. var sql_2 = "UPDATE payinfo SET channel_order_id=?,overtime=?,flag=?,money=?,cfid=?,platform=?,channel=?,payment_type=?,moneytype=?,talkingdata=? WHERE orderid=? AND flag=2";
  65. var timestamp = Date.parse(new Date()) / 1000;
  66. var cfid = ordermoney;
  67. var values_2 = [order_no,timestamp,1,ordermoney,cfida,platform,channel,payment_type,moneytype,1,sdcustomno];
  68. var sql = mysql.format(sql_2, values_2);
  69. return sql;
  70. }
  71. exports.quick_pay_success = function(args,query,res,quick_proto){
  72. var obj = qs.parse(args);
  73. var nt_data = obj.nt_data; //通知数据(XML格式)
  74. var sign = obj.sign; //签名串
  75. var md5Sign = obj.md5Sign; //string 签名计算方法为MD5
  76. var outputname = quick_proto.outputname //使用quick的渠道
  77. var callback_key = quick_proto.callback_key //quick解密编码
  78. var md5_key = quick_proto.md5_key //MD5加密编码
  79. console.log(outputname+"quick回调来了");
  80. //将加密文件解密成XML文件
  81. var xml = decode(nt_data,callback_key);
  82. console.log(xml);
  83. //解析xml文件转json
  84. parser.parseString(xml, function (err, result)
  85. {
  86. if (err)
  87. {
  88. console.log("err:%s",err);
  89. try{res.send("FAILED");}
  90. catch(e){}
  91. }
  92. else
  93. {
  94. var aa = JSON.stringify(result);
  95. var dat_js = JSON.parse(aa);
  96. var jsons = dat_js.quicksdk_message.message[0];
  97. var nt_dat_js = jsons;
  98. var is_test = nt_dat_js.is_test[0]; //是否为测试订单 1为测试 0为线上正式订单
  99. console.log("is_test:%s",is_test);
  100. var pay_channel = nt_dat_js.channel[0]; //渠道标示ID
  101. var channel_uid = nt_dat_js.channel_uid[0]; //渠道用户唯一标示,该值从客户端GetUserId()中可获取
  102. var game_order = nt_dat_js.game_order[0]; //游戏在调用QucikSDK发起支付时传递的游戏方订单,这里会原样传回
  103. var order_no = nt_dat_js.order_no[0]; //QuickSDK唯一订单号
  104. var pay_time = nt_dat_js.pay_time[0]; //支付时间
  105. var amount = nt_dat_js.amount[0]; //成交金额,单位元
  106. var status = nt_dat_js.status[0]; //充值状态 0成功 1失败(为1时 应返回FAILED失败)
  107. var extras_params = nt_dat_js.extras_params[0];//额外参数,现在使用的配置sid
  108. console.log("status:%s",status);
  109. if (status==1)
  110. {
  111. try{
  112. console.log(outputname+"quick支付失败,state=%s",status);
  113. var sql = "UPDATE payinfo SET flag=? WHERE orderid=?";
  114. var values = [-2,game_order]; //玩家获取了订单,但是支付失败,因此把flag设置为-2
  115. sql = mysql.format(sql, values);
  116. query(sql,function(_qerr,_vals,_fields){});
  117. }catch(err){}
  118. try{res.send("FAILED");}
  119. catch(e){}
  120. return
  121. }
  122. else
  123. {
  124. try{
  125. var sql_1 = mysql.format("SELECT * FROM payinfo where orderid=?", [game_order]);//在mysql库中检查订单号
  126. query(sql_1,function(qerr,vals,fields_)
  127. {
  128. console.log("quick_pay_success,1");
  129. if(qerr){
  130. //"逻辑错误,请检查数据表结构和sql语句"
  131. console.log(outputname+"quick逻辑错误,请检查数据表结构和sql语句");
  132. try{res.send("FAILED");}
  133. catch(e){}
  134. return;
  135. }
  136. if (vals[0]==null){
  137. console.log(outputname+"quick没有找到该订单");
  138. try{res.send("FAILED");}
  139. catch(e){}
  140. return;
  141. }
  142. if (vals[0].overtime>0){
  143. console.log(outputname+"quick已经处理的订单");
  144. try{res.send("SUCCESS");}
  145. catch(e){}
  146. return;
  147. }
  148. var genSign = md5(nt_data+sign+md5_key);
  149. if(md5Sign != genSign){
  150. console.log(outputname+"quick支付签名验证失败,md5Sign:%s,genSign:%s",md5Sign,genSign);
  151. try{res.send("FAILED");}
  152. catch(e){}
  153. return;
  154. }
  155. //var des = "null";//描述订单支付成功或失败的系统备注
  156. var platform = 'android'; // 只存储 ios 和 android
  157. var channel = quick_proto.channel; // 只存储 qianxun、zaya、limayao, zhangyu, friday, wudiyongshi, banli, zhiyu, cloud
  158. var payment_type = pay_channel.toString(); // 具体的子渠道,比如 quick 的 微信、手Q、UC、应用宝等, 新增一个 paymentType 字段来填充
  159. var timestamp = Date.parse(new Date()) / 1000;
  160. var option = config.parse(platform,channel,extras_params)//extras_params
  161. var cfid = option.cfid//config.quick_dollar(parseInt(amount));//购买商品ID--parseInt转int
  162. if (cfid == 0){
  163. console.log(outputname+"QUICK获取cfid失败为:%s,extras_params:%s", cfid,extras_params);
  164. try{res.send("FAILED");}
  165. catch(e){}
  166. return;
  167. }
  168. if (amount != option.price){
  169. console.log(outputname+"QUICK金额不一致为amount:%s,option.price:%s", amount,option.price);
  170. try{res.send("FAILED");}
  171. catch(e){}
  172. return;
  173. }
  174. var sql_2 = sql_update_quick(order_no,timestamp,1,amount,cfid,platform,channel,payment_type,option.typename,game_order)
  175. query(sql_2,function(qerr,rows,fields_)
  176. {
  177. if (qerr){
  178. console.log(qerr);
  179. try{res.send("FAILED");} //"逻辑错误,请检查数据表结构和sql语句"}
  180. catch(e){}
  181. return;
  182. }
  183. if (rows.affectedRows <= 0){//判断修改了多少个记录
  184. console.log(outputname+"quick已经处理的订单");
  185. try{res.send("SUCCESS");}
  186. catch(e){}
  187. return;
  188. }
  189. console.log(outputname+"quick支付成功了,现在通知游戏服务器, game_order:%s, username:%s, playerid:%s, serverid:%s ,cfid:%s",
  190. game_order,vals[0].username,vals[0].playerid,vals[0].serverid,cfid);
  191. //send_2_game(query,game_order,vals[0].username,vals[0].playerid,vals[0].serverid,cfid, function(ok){
  192. checkorder.pushproduct(query,game_order,vals[0].uid,vals[0].serverid,cfid, function(ok){
  193. if (ok) {
  194. console.log(outputname+"QUICK 订单 %s: 成功发货!", game_order);
  195. try{res.send("SUCCESS");}
  196. catch(e){}
  197. } else{
  198. console.log(outputname+"QUICK 订单 %s: 发货地址无效!", game_order);
  199. try{res.send("FAILED");}
  200. catch(e){}
  201. }
  202. });
  203. // 向 TalkingData 报告充值数据
  204. var appId = config.getAppID(channel);
  205. checkorder.pushtalkingdata(query,appId,platform,vals[0].uid,game_order,option.price,option.typename,option.diamond,timestamp,payment_type,vals[0].serverid);
  206. })
  207. });
  208. }catch(err){
  209. console.log(outputname+"quick_err ,%s",err);
  210. try{res.send("FAILED");}
  211. catch(e){}
  212. }
  213. }
  214. }
  215. })
  216. }