不多说,上代码:
const Base = require('./base.js');
const crypto = require('crypto');
const urllib = require('urllib');
const xml2js = require('xml2js');
const { ctx } = require('./base.js');
const ThinkSessionFile = require('think-session-file');
const { Console } = require('console');
const { request } = require('http');
module.exports = class extends Base {
async verify_token(channel, user_id, token) {
let url =
think.config('quick').check_user + "?product_code=" +
think.config('quick').product_code + "&channel_code=" +
channel + "&uid=" + user_id + "&token=" + token;
let request_data = {
method: "GET",
}
const quest_func = async () =>
{
return new Promise((resolve, reject) => {
try {
urllib.request( url, request_data,
(err, data, response) => {
if( err == null )
return resolve(data.toString());
else
return resolve('0');
} )
} catch (e) {
return resolve('0');
}
});
};
let query_result = await quest_func();
return query_result;
}
decode(str, key) {
if( str.length <= 0 ) {
return '';
}
let list = new Array();
let result_match = str.match( /\d+/g );
for( let i = 0; i < result_match.length; i ++ ) {
list.push( result_match[i] );
}
if( list.length <= 0 ) {
return '';
}
let keys_byte = this.string_to_bytes( key );
let data_byte = new Array();
for( let i = 0 ; i < list.length ; i++ ) {
data_byte[i] = parseInt( list[i]) - ( 0xff & parseInt( keys_byte[i % keys_byte.length] ) );
}
if( data_byte.length <= 0 ) {
return '';
}
let result = this.bytes_to_string( data_byte );
return result;
}
string_to_bytes(str) {
let ch, st, re = [];
for( let 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;
}
bytes_to_string(array) {
return String.fromCharCode.apply( String, array );
}
convert_xml(xml) {
let parser = new xml2js.Parser( {
explicitArray : false,
ignoreAttrs : true
} );
let result = '';
parser.parseString( xml, function(err, retval)
{
if( think.isEmpty(retval) == false ) {
result = retval;
} else {
console.log( err );
}
} );
return result;
}
async verifyAction() {
let channel = this.get('cid');
let user_id = this.get('uid');
let token = this.get('token');
if( think.isEmpty(channel) ||
think.isEmpty(user_id) ||
think.isEmpty(token) )
{
return this.fail( 6000, 'invalid arguments' );
}
let query_result = await this.verify_token( channel, user_id, token );
if( query_result != '1' )
{
return this.fail( 6007, 'verify token failed: ' + query_result );
}
return this.success();
}
async submit_orderAction() {
let account = this.get('account');
let item_name = this.get('item_name'); // goods id
let count = this.get('count');
let comment = this.get('comment');
if( think.isEmpty(account) ||
think.isEmpty(item_name) ||
think.isEmpty(count) )
{
return this.fail( 6000, "invalid argument" );
}
if( think.isEmpty(comment) ) {
comment = '';
}
// 查询得到商品的数据=
let item = await this.model('commodity', 'mysql_nova').find_item( item_name );
if( think.isEmpty(item) ) {
return this.fail( 6001, "invalid item" );
}
// 填充商品数据
let detail = item.name + " * " + count; // 比如xxx * 3
let sale_off = item.sale_off;
let original_price = item.price * count;
let actual_price = original_price * sale_off;
// 创建订单并插入到数据库中
let order_id = await this.model('order', 'mysql_nova').save(
account, item_name, detail, count, original_price, actual_price, sale_off, comment );
if( think.isEmpty(order_id) ) {
return this.fail( 6002, "create order failed" );
}
return this.success( {
order_id : order_id,
sale_off : sale_off,
original_price : original_price,
actual_price : actual_price,
detail : detail,
} );
}
async notifyAction() {
let nt_data = this.post('nt_data');
let sign = this.post('sign');
let md5Sign = this.post('md5Sign');
if( think.isEmpty(nt_data) ||
think.isEmpty(sign) ||
think.isEmpty(md5Sign) )
{
return this.json( 'FAILED, Invalid arguments' );
}
// 校验
let md5key = think.config('quick').md5_key;
let verify = crypto.createHash('md5').update(nt_data + sign + md5key).digest("hex");
if( verify != md5Sign )
{
return this.json( 'FAILED, MD5 checksum failed' );
}
// 解码xml
let xml = this.decode( nt_data, think.config('quick').callback_key );
if( think.isEmpty(xml) )
{
return this.json( 'FAILED, decrypto failed' );
}
// 分析xml,获取json
let data = this.convert_xml( xml );
if( think.isEmpty(data) )
{
return this.json( 'FAILED, XML Parser report error');
}
// 获取订单信息
let is_test = data.quicksdk_message.message.is_test;
let state = data.quicksdk_message.message.status;
let order_id = data.quicksdk_message.message.game_order;
let payment_sn = data.quicksdk_message.message.order_no;
let pay_amount = data.quicksdk_message.message.amount * 100; // convert to cent
// 如果状态失败,返回failed
if( state == '1' )
{
return this.json( 'FAILED, status = 1' );
}
// 如果是测试,返回failed
if( is_test == '1' )
{
return this.json( 'FAILED, is_test = 1' );
}
// 更新订单(仅更新一个标志,反复读写不会有任何障碍)
let retval = await this.model('order', 'mysql_nova').
update_payment(order_id, payment_sn, parseInt(pay_amount) );
console.log( retval );
if( retval == 1 ) {
return this.json( 'SUCCESS' );
}
return this.json( 'FAILED, Invalid order id or pay amount' );
}
}