<?php
namespace app\api\controller;
use think\Controller;
use think\Db;
class Wxpay extends Controller
{
private $config = array (
'mchid'=>'',
'appid' => "",
'notify_url' => "",
'apiv3_private_key' => "",
'xlid'=>'',
'refund_notify_url'=> "",
);
public function wxpay(){
$out_trade_no=$this->request->param('out_trade_no','');
if(empty($order_sn)) return json(['code'=>202,'msg'=>'缺少参数order_sn']);
$url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
$urlarr = parse_url($url);
$time = time();
$noncestr = $this->getNonceStr();
$appid = $this->config['appid'];
$mchid = $this->config['mchid'];
$xlid = $this->config['xlid'];
$data = array();
$data['appid'] = $appid;
$data['mchid'] = $mchid;
$data['description'] = '商品描述';
$data['out_trade_no'] = $out_trade_no;
$data['notify_url'] = $this->config['notify_url'];
$data['amount']['total'] = 1;
$data['scene_info']['payer_client_ip'] = $_SERVER["REMOTE_ADDR"];;
$data['payer']['openid']='openid';
$data = json_encode($data);
$key = $this->getSign($data,$urlarr['path'],$noncestr,$time);
$token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"',$mchid,$xlid,$noncestr,$time,$key);
$header = array(
'Accept: application/json',
'Content-Type: application/json',
'User-Agent:*/*',
'Authorization: WECHATPAY2-SHA256-RSA2048 '.$token
);
$res = $this->curl_post_https($url,$data,$header);
$prepay_id=json_decode($res,true)['prepay_id'];
$paySign=$this->getWechartSign($appid,$time,$noncestr,'prepay_id='.$prepay_id);
$payData=[
'timeStamp'=>$time,
'nonceStr'=>$noncestr,
'package'=>'prepay_id='.$prepay_id,
'signType'=>'RSA',
'paySign'=>$paySign
];
return json(['code'=>200,'msg'=>'ok','data'=>$payData]);
}
public function getNonceStr(){
$strs="QWERTYUIOPASDFGHJKLZXCVBNM1234567890";
$name=substr(str_shuffle($strs),mt_rand(0,strlen($strs)-11),32);
return $name;
}
function getSign($data=array(),$url,$randstr,$time){
$str = "POST"."\n".$url."\n".$time."\n".$randstr."\n".$data."\n";
$key = file_get_contents('apiclient_key.pem');
$str = $this->getSha256WithRSA($str,$key);
return $str;
}
function getWechartSign($appid,$timeStamp,$noncestr,$prepay_id){
$str = $appid."\n".$timeStamp."\n".$noncestr."\n".$prepay_id."\n";
$key = file_get_contents('apiclient_key.pem');
$str = $this->getSha256WithRSA($str,$key);
return $str;
}
public function getSha256WithRSA($content, $privateKey){
$binary_signature = "";
$algo = "SHA256";
openssl_sign($content, $binary_signature, $privateKey, $algo);
$sign = base64_encode($binary_signature);
return $sign;
}
function curl_post_https($url,$data,$header){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
$tmpInfo = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Errno'.curl_error($curl);
}
curl_close($curl);
return $tmpInfo;
}
public function notify(){
$data = file_get_contents('php://input');
$data = json_decode($data, true);
$nonceStr = $data['resource']['nonce'];
$associatedData = $data['resource']['associated_data'];
$ciphertext = $data['resource']['ciphertext'];
$ciphertext = base64_decode($ciphertext);
if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) {
$orderData = \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->config['apiv3_private_key']);
$orderData = json_decode($orderData, true);
if ($orderData['trade_state']=='SUCCESS'){
$order_sn=$orderData['out_trade_no'];
$transaction_id=$orderData['transaction_id'];
Db::startTrans();
try{
Db::commit();
return json(['code' => 'SUCCESS', 'message' =>'ok']);
} catch (\Exception $e) {
Db::rollback();
return json(['code' => 'ERROR', 'message' =>'no']);
}
}
}
}
public function Refund($transaction_id,$out_trade_no){
$time=time();
$out_refund_no=$time.rand(1111,9999);
$refundData=[
'out_refund_no'=>$out_refund_no,
'reason'=>'商品退款',
'notify_url'=>$this->config['refund_notify_url'],
'funds_account'=>'AVAILABLE',
'amount'=>[
'refund'=>1,
'total'=>1,
'currency'=>'CNY'
]
];
if(!$transaction_id){
if(!$out_trade_no){
return ['code'=>0,'msg'=>'退款订单号不能为空'];
}else{
$refundData['out_trade_no']=$out_trade_no;
}
}else{
$refundData['transaction_id']=$transaction_id;
}
$url='https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
$urlarr = parse_url($url);
$mchid = $this->config['mchid'];
$xlid = $this->config['xlid'];
$refundData=json_encode($refundData);
$nonce = $this->getNonceStr();
$key = $this->getSign($refundData,$urlarr['path'],$nonce,$time);
$token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"',$mchid,$xlid,$nonce,$time,$key);
$header = array(
'Accept: application/json',
'Content-Type: application/json',
'User-Agent:*/*',
'Authorization: WECHATPAY2-SHA256-RSA2048 '.$token
);
$res=$this->curl_post_https($url,$refundData,$header);
$res_array=json_decode($res,true);
if(($res_array['status']=='PROCESSING' || $res_array['status']=='SUCCESS') && isset($res_array['status'])){
return ['code'=>1,'msg'=>'退款成功'];
}else{
return ['code'=>0,'msg'=>$res_array['message']];
}
}
public function refund_notify(){
$notifiedData = file_get_contents('php://input');
$data = json_decode($notifiedData, true);
$nonceStr = $data['resource']['nonce'];
$associatedData = $data['resource']['associated_data'];
$ciphertext = $data['resource']['ciphertext'];
$ciphertext = base64_decode($ciphertext);
if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) {
$orderData = \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->config['apiv3_private_key']);
$orderData = json_decode($orderData, true);
if ($orderData['refund_status']=='SUCCESS'){
$transaction_id=$orderData['transaction_id'];
return json(['code'=>'SUCCESS','message'=>'成功']);
}
}
}
}
|