基础类WechatPay.php
<?php
namespace App\Library;
class WechatPay{
const KEY = '2nlp59yio07cgmz6qk1rwtdbu34xa8sj'; //支付秘钥需要更改成自己的
const APPID = 'wx3bf59e7749b9cb05'; //APPID需要更改为自己的
const MCHID = '1617949930'; //商户号需要更改成自己的
// const SECRET = 'b9840976e63916e233d1d380549514a3'; //开发者密码需要更改为自己的
const UOURL = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; //无需更改 统一下单API地址
// const NOTIFY = 'http://tpmapi.vfinemusic.com/fontend/pay/sendWechatNO'; //支付通知地址需要更改成你自己服务器的地址
public function __construct() {
}
//获取签名
public function getSign($arr){
//去除数组的空值
array_filter($arr);
if(isset($arr['sign'])){
unset($arr['sign']);
}
//排序
ksort($arr);
//组装字符
$str = $this->arrToUrl($arr) . '&key=' . self::KEY;
//使用md5 加密 转换成大写
return strtoupper(md5($str));
}
//获取带签名的数组
public function setSign($arr){
$arr['sign'] = $this->getSign($arr);
return $arr;
}
//校验签名
public function checkSign($arr){
//生成新签名
$sign = $this->getSign($arr);
//和数组中原始签名比较
if($sign == $arr['sign']){
return true;
}else{
return false;
}
}
//数组转URL字符串 不带key
public function arrToUrl($arr){
return urldecode(http_build_query($arr));
}
//记录到文件
public function logs($file,$data){
$data = is_array($data) ? print_r($data,true) : $data;
file_put_contents('/www/paylog/' .$file, $data);
}
public function getPost(){
return file_get_contents('php://input');
}
//Xml 文件转数组
public function XmlToArr($xml)
{
if($xml == '') return '';
libxml_disable_entity_loader(true);
$arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $arr;
}
//数组转XML
public function ArrToXml($arr)
{
if(!is_array($arr) || count($arr) == 0) return '';
$xml = "<xml>";
foreach ($arr as $key=>$val)
{
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
//post 字符串到接口
public function postStr($url,$postfields){
$ch = curl_init();
$params[CURLOPT_URL] = $url; //请求url地址
$params[CURLOPT_HEADER] = false; //是否返回响应头信息
$params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
$params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
$params[CURLOPT_POST] = true;
$params[CURLOPT_SSL_VERIFYPEER] = false;//禁用证书校验
$params[CURLOPT_SSL_VERIFYHOST] = false;
$params[CURLOPT_POSTFIELDS] = $postfields;
curl_setopt_array($ch, $params); //传入curl参数
$content = curl_exec($ch); //执行
curl_close($ch); //关闭连接
return $content;
}
//统一下单
public function unifiedorder($params){
//获取到带签名的数组
$params = $this->setSign($params);
//数组转xml
$xml = $this->ArrToXml($params);
//发送数据到统一下单API地址
$data = $this->postStr(self::UOURL, $xml);
$arr = $this->XmlToArr($data);
if($arr['return_code']=='FAIL'){
$this->logs('wechatpayfail.txt','写入时间'.date('Y-m-d H:i:s',time()).$arr['return_msg']);
return $arr;
}
if($arr['result_code'] == 'SUCCESS' && $arr['return_code'] == 'SUCCESS'){
return $arr;
}else{
$this->logs('wechatpayfail.txt','写入时间'.date('Y-m-d H:i:s',time()).$arr['return_msg']);
return $arr;
}
}
//获取构建二维码的URL地址
public function getQRurl(){
$params = [
'appid' => self::APPID,
'mch_id' => self::MCHID,
'product_id' => 1,
'time_stamp' => time(),
'nonce_str' => md5(time()),
];
return 'weixin://wxpay/bizpayurl?' . $this->arrToUrl($this->setSign($params));
}
}
?>
项目中生成微信支付二维码接口
/*发起微信支付请求
@author tjg
@param string total_amount 订单金额
@param string desc 订单描述
@return json
*/
public function sendWechatPay($param=''){
if(!empty($param['total_amount'])){
$total_fee=$param['total_amount'];
}else{
$total_fee=1;
}
if(!empty($param['desc'])){
$body=$param['desc'];
}else{
$body='微信扫码支付模式二';
}
$notify_url=Env('APP_URL').'/fontend/pay/sendWechatNO';
$order_no=$param['order_no'];//订单号
$user_id=$param['user_id'];//用户id
$order_money=$total_fee;//订单金额
$attach=$order_no.','.$user_id.','.$order_money;
$WechatPay=new WechatPay();
$params = [
'appid' => config('auth.wechat.APPID'),
'mch_id' => config('auth.wechat.MCHID'),
// 'product_id' => $oid,
// 'time_stamp' => time(),
'nonce_str' => md5(time()),
'body'=> $body,
'out_trade_no'=> date('YmdHis'),
'total_fee'=> $total_fee,
'notify_url'=> Env('APP_URL').'/fontend/pay/sendWechatNO',
'trade_type'=>'NATIVE',
'attach'=>$attach,
];
$arr = $WechatPay->unifiedorder($params);
//判断支付结果
if($arr['return_code']=='SUCCESS' && $arr['result_code']=='SUCCESS' && $arr['return_msg']=='OK'){
$data['wechatpay_code']=$arr['code_url'];
return json_encode(['code'=>0,'msg'=>'请求成功','data'=>$data]);
}else{
$data['wechatpay_code']='';
return json_encode(['code'=>-1,'msg'=>$arr['return_msg'],'data'=>$data]);
}
}
/*微信支付异步回调地址
@author tjg
@return json
*/
public function sendWechatNO($result=''){
$WechatPay=new WechatPay();
$arr = $WechatPay->XmlToArr($result);
if(!empty($arr)){
$attach=$arr['attach'];
$attach_arr=explode(',',$attach);
$order_no=$attach_arr[0];
$user_id=$attach_arr[1];
$order_money=$attach_arr[2];
//调用异步处理接口
if($arr['result_code']=='SUCCESS' && $arr['return_code']=='SUCCESS'){
$addTrade['trade_no']=$arr['out_trade_no'];
$addTrade['pay_id']=1;
$addTrade['subject']='购买商品';
$addTrade['body']='购买商品';
$addTrade['price']=$order_money;
$addTrade['pay_amount']=$arr['total_fee'];
$addTrade['receipt_amount']=$arr['total_fee'];
$addTrade['trade_status']=1;
$addTrade['pay_time']=date('Y-m-d H:i:s',time());
$addTrade['create_at']=date('Y-m-d H:i:s',time());
$addTrade['row_data']=$result;
$addTrade['order_no']=$order_no;
$findPayTrade=DB::table('info_pay_trade')->where(['order_no'=>$order_no])->first();
if(empty($findPayTrade)){
DB::table('info_pay_trade')->insert($addTrade);
}
$file='wechatpaysuccess.txt';
$strsuccess='异步回调写入时间'.date('Y-m-d H:i:s',time()).$result;
$WechatPay->logs($file,$strsuccess);
$pay_type='WX_PAY';
$ret = OrderService::payFinished($order_no, $user_id,$order_money,$pay_type);
echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
}else{
$addTrade['trade_no']=$arr['out_trade_no'];
$addTrade['pay_id']=1;
$addTrade['subject']='购买商品';
$addTrade['body']='购买商品';
$addTrade['price']=$order_money;
$addTrade['pay_amount']=$arr['total_fee'];
$addTrade['receipt_amount']=$arr['total_fee'];
$addTrade['trade_status']=2;
$addTrade['pay_time']=date('Y-m-d H:i:s',time());
$addTrade['create_at']=date('Y-m-d H:i:s',time());
$addTrade['row_data']=$result;
$addTrade['order_no']=$order_no;
$findPayTrade=DB::table('info_pay_trade')->where(['order_no'=>$order_no])->first();
if(empty($findPayTrade)){
DB::table('info_pay_trade')->insert($addTrade);
}
$file='wechatpayfail.txt';
$strfail='异步回调写入时间'.date('Y-m-d H:i:s',time()).$result;
$WechatPay->logs($file,$strfail);
echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
}
}
}