[//统一返回
async function( kuo,Context,context){
Context.headers["content-type"] = 'application/json; charset=UTF-8';
let $THIS = this;
let $features = await Kuoplus(kuo.class);
let $LANG = this.LANG();
let $DATA = Object.assign({},this.$DATA);
let $_POST = kuo.post;
let $_GET = kuo.get;
let $method =kuo.Path['0']&&kuo.Path['0'] != ""?kuo.Path['0']:"submit";
let $filename = kuo.func_;
let $PAYHTTP = 'https://api.mch.weixin.qq.com/v3/pay/transactions/native'; //支付发起地址
let $PAYYB = KuoLink(["pay",$filename,"notify"]);
let $PAYTB = KuoLink(["pay",$filename,"return"]);
let $APPID = $features['configure'][$filename]?$features['configure'][$filename]['0']:""; //公众号ID
let $MCHID = $features['configure'][$filename]?$features['configure'][$filename]['1']:"";//mchid
let $APPKEY = $features['configure'][$filename]?$features['configure'][$filename]['2']:""; //私钥
let $SERIAL = $features['configure'][$filename]?$features['configure'][$filename]['3']:"";//证书id
let $V3KEY = $features['configure'][$filename]?$features['configure'][$filename]['4']:"";//v3 密钥
if($method == 'return'){
//同步返回
let uuul = $features['configure']['同步跳转']?$features['configure']['同步跳转']:[];
Context.statusCode = 302;
Context.headers["Location"] = KuoLink(uuul)+'?out_trade_no='+$_GET['out_trade_no'];
Context.body = "";
return ;
}else if($method == 'notify'){
let BODY = kuo.body ;
let HEAD = kuo.headers;
let $wenxinzznegshu = await Mem.Get("weixinzhengshu");
if(!$wenxinzznegshu){
$wenxinzznegshu = {};
let $canonical_url = "/v3/certificates";
let $timestamp = Mode("Tools").Time();
let $nonce = Md5(Mode("Tools").Uuid());
let $message = "GET\n"+
$canonical_url+"\n"+
$timestamp+"\n"+
$nonce+"\n\n";
let $sign = SHA256_sign($message,$APPKEY);
let $Authorization = mchid="${$MCHID}",serial_no="${$SERIAL}",nonce_str="${$nonce}",timestamp="${$timestamp}",signature="${$sign}";
let $fan = await GET("https://api.mch.weixin.qq.com/v3/certificates",{
headers:{
"Content-Type":"application/json",
"Accept":"application/json",
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
"Authorization": "WECHATPAY2-SHA256-RSA2048 "+$Authorization
}
});
$fan = json_decode($fan,true);
if($fan && $fan['data']){
for(var xx in $fan['data']){
var tazhi = $fan['data'][xx];
let $resource = tazhi['encrypt_certificate'];
let cipherText = Buffer.from( $resource['ciphertext'],'base64');
var decipher = CRYPTO.createDecipheriv('aes-256-gcm', $V3KEY , $resource['nonce']);
let authTag = cipherText.slice(cipherText.length - 16);
let data = cipherText.slice(0, cipherText.length - 16);
decipher.setAuthTag(authTag);
let rst = decipher.update(data, 'binary', 'utf8');
try {
rst += decipher.final('utf-8');
} catch (e) {}
const x509_1 = require('@fidm/x509');
const certificate = x509_1.Certificate.fromPEM(rst);
let xxx = certificate.publicKeyRaw.toString('base64');
$wenxinzznegshu[tazhi.serial_no] = xxx;
}
await Mem.Set("weixinzhengshu",$wenxinzznegshu,3600*24);
}
}
let $wechatpay_serial =kuo.headers["wechatpay-serial"]?kuo.headers["wechatpay-serial"]:reset($wenxinzznegshu);
if(!$wechatpay_serial){
Context.body = 'fail';
return ;
}
let qiankey = $wenxinzznegshu[$wechatpay_serial];
if(!qiankey){
Context.body = 'fail';
return ;
}
let $message = HEAD['wechatpay-timestamp']+"\n"+
HEAD['wechatpay-nonce']+"\n"+
BODY+"\n";
let fanx = SHA256_verify($message, HEAD['wechatpay-signature'] , qiankey);
if(!fanx){
Context.body = 'fail';
return ;
}
BODY = json_decode(BODY);
if(BODY && BODY['resource']){
let cipherText = Buffer.from( BODY.resource['ciphertext'],'base64');
var decipher = CRYPTO.createDecipheriv('aes-256-gcm', $V3KEY , BODY.resource['nonce']);
let authTag = cipherText.slice(cipherText.length - 16);
let data = cipherText.slice(0, cipherText.length - 16);
decipher.setAuthTag(authTag);
let rst = decipher.update(data, 'binary', 'utf8');
try {
rst += decipher.final('utf-8');
} catch (e) {}
rst = json_decode(rst);
if(rst && rst.trade_state == "SUCCESS"){
let $canonical_url = "/v3/pay/transactions/id/"+rst['transaction_id']+'?mchid='+$MCHID;
let $timestamp = Mode("Tools").Time();
let $nonce = Md5(Mode("Tools").Uuid());
let $message = "GET\n"+
$canonical_url+"\n"+
$timestamp+"\n"+
$nonce+"\n\n";
let $sign = SHA256_sign($message,$APPKEY);
let $Authorization = mchid="${$MCHID}",serial_no="${$SERIAL}",nonce_str="${$nonce}",timestamp="${$timestamp}",signature="${$sign}";
let $fanxxx = await GET("https://api.mch.weixin.qq.com/v3/pay/transactions/id/"+rst['transaction_id']+'?mchid='+$MCHID,{
headers:{
"Content-Type":"application/json",
"Accept":"application/json",
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
"Authorization": "WECHATPAY2-SHA256-RSA2048 "+$Authorization
}
});
$fanxxx = json_decode($fanxxx);
if(!$fanxxx || !$fanxxx['amount']){
Context.body = 'fail';
return ;
}
if(rst['amount']['total'] != $fanxxx['amount']['total'] ){
Context.body = 'fail';
return ;
}
if(rst['amount']['payer_total'] != $fanxxx['amount']['payer_total'] ){
Context.body = 'fail';
return ;
}
await $THIS.UnifiedBack({
'out_trade_no': $fanxxx['out_trade_no'],
'money':$fanxxx['amount']['payer_total']/100,
'transaction_id':$fanxxx['transaction_id'],
'huomoney':$fanxxx['amount']['total']/100
});
Context.body = 'success';
return ;
}
Context.body = 'fail';
return ;
}
Context.body = 'fail';
return ;
}else{
//提交订单
if($APPID == "" || $APPKEY == ""){
$DATA.code = -1;$DATA.msg = $LANG.tong_off;Context.body = JSON.stringify($DATA);
return ;
}
let $ORDER = null;
let $db = await db('pay_payment');
if($method == 'submit'){
let $Security = await Mem.Get("session/"+kuo.sessionid);
if(!$Security ){
$Security = {'uid':0};
}
if(!$Security || !$Security['uid'] || $Security['uid'] < 1){
$DATA.code = -1;$DATA.msg = $LANG.no_login;Context.body = JSON.stringify($DATA);
return ;
}
let $type = 1;
let $money = $_GET['money']?$_GET['money']:1;
if($money <= 0){
$money = 1;
}
$ORDER = await $THIS.PayMent_Add({
'uid':$Security['uid'],
'type': $type ,
'money': $money,
'plus': kuo.class,
'remarks': $_GET['remarks']??'' ,
'ip':kuo.ip,
'agent':kuo.agent
});
}else{
let $safe = await Mem.Add("orderid/"+$method,1,$THIS.$findtime );
if($safe > $THIS.$safenum ){
$DATA.code = -1;$DATA.msg = $LANG.shouhoufang;Context.body = JSON.stringify($DATA);
return ;
}
$ORDER = await $db.Where({'out_trade_no': $method}).Find();
}
if(!$ORDER){
$DATA.code = -1;$DATA.msg = $LANG.add_no;Context.body = JSON.stringify($DATA);
return ;
}
if($ORDER['off'] != 0){
$DATA.code = -1;$DATA.msg = $LANG.off_error;Context.body = JSON.stringify($DATA);
return ;
}
await $db.Where({'id': $ORDER['id']}).Update({off:1});
let $shuju ={
'appid' : $APPID,
'mchid' : $MCHID,
'description': $ORDER['subject'] == ''?"pay":$ORDER['subject'],
'out_trade_no':$ORDER['out_trade_no'],
'notify_url':$PAYYB,
'amount':{
'total': $ORDER['money'] *100
},
'scene_info':{
'payer_client_ip':kuo.ip
}
};
$shuju = json_encode($shuju);
let $canonical_url = "/v3/pay/transactions/native";
let $timestamp = Mode("Tools").Time();
let $nonce = Md5(Mode("Tools").Uuid());
let $message = "POST\n"+
$canonical_url+"\n"+
$timestamp+"\n"+
$nonce+"\n"+
$shuju+"\n";
let $sign = SHA256_sign($message,$APPKEY);
let $Authorization = mchid="${$MCHID}",serial_no="${$SERIAL}",nonce_str="${$nonce}",timestamp="${$timestamp}",signature="${$sign}";
var $fan = await POST($PAYHTTP ,$shuju ,{
formData:null,
body: $shuju,
headers:{
"Content-Type":"application/json",
"Accept":"application/json",
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
"Authorization": "WECHATPAY2-SHA256-RSA2048 "+$Authorization
}
});
$fan = json_decode($fan);
if($fan && $fan['code']){
$DATA.code = -1;$DATA.msg = $fan['message'];Context.body = JSON.stringify($DATA);
return ;
}
let EWM = $fan['code_url'];
let uuul = $features['configure']['同步跳转']?$features['configure']['同步跳转']:[];
let CHENGGON = KuoLink(uuul)+'?out_trade_no='+$ORDER['out_trade_no'];
let KUOchaurl = KuoLink(["pay","find"])+'?out_trade_no='+$ORDER['out_trade_no'];
Context.headers["content-type"] = 'text/html; charset=UTF-8';
Context.body = EWM;
return ;
}
}
]