龙空技术网

微信小程序的支付和微信APP的支付流程

PHP互联网架构师 183

前言:

现在咱们对“php对接微信支付教程”大概比较讲究,朋友们都想要剖析一些“php对接微信支付教程”的相关资讯。那么小编在网上收集了一些有关“php对接微信支付教程””的相关内容,希望我们能喜欢,朋友们一起来了解一下吧!

最近在做应用商城涉及到小程序微信支付和app微信支付,所以也大概地将这方面的东西看了一个遍,整个流程梳理总结一下。

环境是:tp5 + 小程序 + App

appid 小程序的appid

appsecret 小程序appsecret

mch_id 商户号

key 商户支付密钥Key

文件位置 \extends\service\PayService//微信支付类 <?php/**	微信支付类,可直接根据各种框架复制里面的方法直接引用!*	*	作者 (1612666131@qq.com)*	Date:2021-03-12*/namespace service;use think\Controller;use think\Db;use think\db\Query;class PayService extends Controller {	private $appid; //小程序appid	private $appsecret; //小程序的secret	private $MCHID; //商户号id	private $KEY; //商户号key	private $url=';; //商户号key	public function __construct($config){		$this->appid=$config['appid'];		$this->appsecret=$config['appsecret'];		$this->MCHID=$config['MCHID'];		$this->KEY=$config['KEY'];           }    public function dopay($out_trade_no,$money,$notify_url){        //总金额(分)        $total_fee = intval($money*100);          //商品类型信息        $body='';                //附加数据        $attach=date('YmdHis');        $out_trade_no=$out_trade_no.rand(1111,9999);    	//构造请求参数        $key= $this->KEY;        $appid='wxacd6ff08cd2e7b6f';        $mch_id=$this->MCHID;        $device_info='WEB';        $nonce_str=$this->randomkeys(32);               $fee_type='CNY';            $spbill_create_ip=getIP();        $trade_type='APP';        $limit_pay='no_credit';             $sign=$this->sign($appid,$mch_id,$attach,$body,$nonce_str,$key,$out_trade_no,$total_fee,$spbill_create_ip,$notify_url,$trade_type);              $signs = md5($sign);            $signss=strtoupper($signs);             $transData='<xml>                   <appid><![CDATA['.$appid.']]></appid>                   <attach><![CDATA['.$attach.']]></attach>                   <body><![CDATA['.$body.']]></body>                   <mch_id><![CDATA['.$mch_id.']]></mch_id>                   <nonce_str><![CDATA['.$nonce_str.']]></nonce_str>                   <notify_url><![CDATA['.$notify_url.']]></notify_url>                   <out_trade_no><![CDATA['.$out_trade_no.']]></out_trade_no>                   <spbill_create_ip><![CDATA['.$spbill_create_ip.']]></spbill_create_ip>                   <total_fee><![CDATA['.$total_fee.']]></total_fee>                   <trade_type><![CDATA['.$trade_type.']]></trade_type>                   <sign>'.$signss.'</sign>                   </xml>';        $data=$this->curl_post(";,$transData);          $sinsagin=$this->again($data,$appid,$out_trade_no,$nonce_str,$key);         $weixin = $this->fors($data,$appid,$nonce_str,$out_trade_no,$sinsagin);          return $weixin;    }	//发送请求	public function curl_get_contents($url){        $ch = curl_init();        curl_setopt($ch, CURLOPT_URL, $url);        //忽略证书错误信息        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);        @curl_setopt($ch, CURLOPT_GET, true);                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);        $result=curl_exec($ch);        // $result = json_decode($resp,true);        curl_close($ch);        return $result;	}	public function payOrder($order){			    $total_fee =$order['money']; //支付金额	  	    if(empty($order['money']) || empty($order['openid'])){ //一定要有用户Openid和支付金额	        die("缺少参数!");	    }	    $total_fee            = $total_fee * 100; //支付金额单位是分的,所以要乘100	    $appid                = $this->appid; 	    $MCHID                = $this->MCHID; //商户号	    $KEY                  =  $this->KEY; //商户key	    $data['appid']        = $appid;  //小程序appid	    $data['mch_id']       = $MCHID;	//商户号id	    $data['nonce_str']    = md5($MCHID.time()); //验证的支付	    $data['openid']       = $order['openid']; //用户openid	    $data['body']         = '油BOSS订单【'.$order['pay_no'].'】'; //微信支付对应的商家/公司主体名	    $data['out_trade_no'] = $order['pay_no'].rand(1111,9999); //订单号id,用于回调改订单状态	    $data['total_fee']    = $total_fee; //支付金额,单位为分!!	    $data['spbill_create_ip'] = '8.8.8.8'; //验证ip地址,这个不用改随意	    $data['notify_url']       = $order['notify_url']; //微信支付成功的回调路径,要写死这个路径,记得要是小程序允许访问的路径	    $data['trade_type']       = "JSAPI"; //小程序支付,所以是JSAPI	    // --------------------以下这一串都不用改--------------------------------	    ksort($data); 	    $sign_str = $this->ToUrlParams($data);	    $sign_str = $sign_str."&key=".$KEY;	   // echo $sign_str;	    $data['sign'] = strtoupper(md5($sign_str));	    $xml = $this->arrayToXml($data);	    $r = $this->postXmlCurl($xml,$this->url,true);	    $result = json_decode($this->xml_to_json($r));	    if($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS' ){	        $sdata['appId'] = $appid;	        $sdata['timeStamp'] = (string)time();	        $sdata['nonceStr'] = md5(time().rand().rand().$data['openid']);	        $sdata['package'] = "prepay_id=".$result->prepay_id;	        $sdata['signType'] = "MD5";	        ksort($sdata);	        $sign_str = $this->ToUrlParams($sdata);	        $sign_str = $sign_str."&key=".$KEY;	        $sdata['paySign'] = strtoupper(md5($sign_str));	        $info['code']='1';	        $info['data']=$sdata;	        $data['msg']='';	        return $info;	    }else{	    	$info['code']='0';	        $info['data']=array();	        $info['msg']=$result->err_code_des;	        return $info;	    }	    // -----------------------都不用改-----------------------------------------------	}	/**	 * 【支付成功后回调】	 *	 *  by: leoyi 	 *  Date:2018-04-08	*/	public function suc_call(Request $request) {	    $data=file_get_contents('php://input');	    	    $msg = (array)simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);		if($msg['result_code'] == "SUCCESS") {			// 支付成功这里要做的操作!			$sql = "update ....";//可以修改订单的状态之类的			$result = DB::update($sql);		} 		echo '<xml>	      <return_code><![CDATA[SUCCESS]]></return_code>	      <return_msg><![CDATA[OK]]></return_msg>	    </xml>';	}	/**	 * 【退款的接口】	 *	 * by:leoyi 	 * Date: 2018-04-08	*/	private function payRefund(Request $request){		// 具体代码后期另外写 也可以联系我私发	}	/*	*	注意:以下方法都是为了方便直接调取转换格式用的方法,	*	个人需要可以另外抽取出来放	*==========================================	*	以下代码不需要修改!!	*/	/**	 * 用户post方法请求xml信息用的	 * @author write by leoyi 2018-04-8	*/	public function postXmlCurl($xml, $url, $useCert = false, $second = 10)	{	    $ch = curl_init();	    //设置超时	    curl_setopt($ch, CURLOPT_TIMEOUT, $second);	    curl_setopt($ch,CURLOPT_URL, $url);	    curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);	    curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验2	    //设置header	    curl_setopt($ch, CURLOPT_HEADER, FALSE);	    //要求结果为字符串且输出到屏幕上	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);	    curl_setopt($ch, CURLOPT_POST, TRUE);	    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);	    //运行curl	    $data = curl_exec($ch);	    //返回结果	    if($data){	      curl_close($ch);	      return $data;	    } else {	      $error = curl_errno($ch);	      curl_close($ch);	      return $error;	    }	}	/*	*   用于微信支付转换认证的信息用的	*   by:leoyi	*   date:2018-4-8	*/	public function ToUrlParams($data)	{	  $buff = "";	  foreach ($data as $k => $v)	  {	    if($k != "sign" && $v != "" && !is_array($v)){	      $buff .= $k . "=" . $v . "&";	    }	  }	  $buff = trim($buff, "&");	  return $buff;	}	/*	*   微信支付-数组转xml	*   by:leoyi	*   date:2018-4-8	*/	public function arrayToXml($arr)	{	    $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;	}	/*	*   微信支付-数组转xml	*   by:leoyi	*   date:2018-4-8	*/	public function  xml_to_json($xmlstring) {	    return json_encode($this->xml_to_array($xmlstring),JSON_UNESCAPED_UNICODE);	}	/*	*   post方法	*   by:leoyi	*   date:2018-4-8	*/	public function post_url($post_data, $url)	{	  $ch = curl_init();	  //设置超时	  curl_setopt($ch, CURLOPT_TIMEOUT, 10);	  curl_setopt($ch,CURLOPT_URL, $url);	  curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);	  curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验2	  curl_setopt($ch, CURLOPT_HEADER, FALSE);	  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);	  curl_setopt($ch, CURLOPT_POST, TRUE);	  curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);	  $data = curl_exec($ch);	  curl_close($ch);	  return $data;	}	/*	* 把xml转换成array	* by:leoyi	* Date:2018-4-11	*/	public function xml_to_array($xml) {	    //return ((array) simplexml_load_string($xmlstring));	  return simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA);	    //return json_decode(xml_to_json($xmlstring));	}	private function sign($appid,$mch_id,$attach,$body,$nonce_str,$key,$out_trade_no,$total_fee,$spbill_create_ip,$notify_url,$trade_type)    {        $sign='';        $stringSignTemp='';        $stringSignTemp="appid=".$appid."&attach=".$attach."&body=".$body."&mch_id=".$mch_id."&nonce_str=".$nonce_str."¬ify_url=".$notify_url."&out_trade_no=".$out_trade_no."&spbill_create_ip=".$spbill_create_ip."&total_fee=".$total_fee."&trade_type=".$trade_type."&key=$key";        $sign=$stringSignTemp;        return $sign;    }     private function curl_post($url,$data)    {        if(is_array($data)) $data=http_build_query($data);        $curl = curl_init();        //$url=$url;        curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);        curl_setopt($curl, CURLOPT_HEADER, false);        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);        curl_setopt($curl, CURLOPT_URL, $url);        curl_setopt($curl, CURLOPT_POST, true);        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,false); // 对认证证书来源的检查        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);        $result = curl_exec($curl);        curl_close($curl);        if($result === false){            return curl_error($curl);        }        else{            return $result;        }    }     private function again($data,$appid,$out_trade_no,$nonce_str,$key)    {                $res = simplexml_load_string($data,NULL,LIBXML_NOCDATA);                $res = json_decode(json_encode($res),true);         if ($res['result_code'] == "FAIL") {        	echoJson($res['err_code_des'],"1001");                 }        $partnerid=$out_trade_no;        $prepayid=$res['prepay_id'];        $package='Sign=WXPay';        $noncestr=$nonce_str;        $timestamp=time();        $sign='';        $stringSignTemp='';        $stringSignTemp="appid=".$appid."&noncestr=".$noncestr."&package=".$package."&partnerid=".$partnerid."&prepayid=".$prepayid."×tamp=".$timestamp."&key=$key";        $sign=MD5($stringSignTemp);        $signs=strtoupper($sign);        return $signs;    }      private function fors($data,$appid,$nonce_str,$out_trade_no,$sinsagin)    {        $time=(string)time();        $res = simplexml_load_string($data,NULL,LIBXML_NOCDATA);                 $res = json_decode(json_encode($res),true);                return array(                'appid'=>$appid,                'noncestr'=>$nonce_str,                'package'=>'Sign=WXPay',                'partnerid'=>$out_trade_no,                'prepayid'=>$res['prepay_id'],                'timestamp'=>$time,                'sign'=>$sinsagin        );    }    /**     * 生成32位随机字符串  WX     * @param unknown $length     * @return string     */    private function randomkeys($length)    {        $key='';        $pattern='1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ';        for ($i = 0; $i < $length; $i++) {            $key.= $pattern{mt_rand(1,60)};    //生成php随机数        }        return $key;    }}

小程序微信支付调用

use service\PayService;<?php/**	pay_no string 支付单号	*	money  string 支付金额(单位分)* openid 用户openID* notify_url 支付后回调地址*	Date:2021-03-12*///微信支付function parampay($pay_no,$money,$openid,$notify_url){         $config['appid']      = '';// 小程序appid    $config['appsecret']  = '';// 小程序appsecret    $config['MCHID']      = ''; //微信商户    $config['KEY']        = ''; //微信商户key    $pay = new PayService($config);    $order['money']     = $money;    $order['openid']    = $$openid;    $order['pay_no']    = $pay_no;    $order['notify_url']= $notify_url;       return $pay->payOrder($order);}?>

app微信支付

use service\PayService;<?php/**	pay_no string 支付单号	*	money  string 支付金额(单位分)* notify_url 支付后回调地址*	Date:2021-03-12*///微信支付function parampay($pay_no,$money,$notify_url){         $config['appid']      = '';// 小程序appid    $config['appsecret']  = '';// 小程序appsecret    $config['MCHID']      = ''; //微信商户    $config['KEY']        = ''; //微信商户key       $notify_url= WEB_URL.'/api/Onilnestudy/notifyUrl';                     $PayService=new PayService($config);     return $PayService->dopay($pay_no,$money,$notify_url);}?>

异步回调消息处理

 public function notifyUrl(){        $xmlData = file_get_contents('php://input');        libxml_disable_entity_loader(true);        $result = json_decode(json_encode(simplexml_load_string($xmlData, 'SimpleXMLElement', LIBXML_NOCDATA)), true);        ksort($result);                $str = '';        foreach ($result as $k => $v) {            $str .= $k.':'.$v."\r\n";        }        $fp = fopen("./wechatnotify.txt","a");        flock($fp, LOCK_EX) ;        fwrite($fp,"--返回微信支付数据--执行日期:".strftime("%Y-%m-%d %H:%M:%S",time())."--------------------\r\n".$str."\r\n\r\n");        flock($fp, LOCK_UN);        fclose($fp);        // $result['result_code']='SUCCESS';        // $result['out_trade_no']='650380663249821367350';                if($result['result_code'] == 'SUCCESS'){            //此处应该更新一下订单状态,商户自行增删操作            $map = [];            $map['pay_no'] = substr($result['out_trade_no'],0,-4);            $info = DB::name("onilne_study_buy")->where($map)->find();            if ($info['is_status'] > 0) {                die('success');            }                        if ($info) {                $data = [                    "is_status" => 1,                    "pay_time" => date('Y-m-d H:i:s'),                ];                $re = DB::name("onilne_study_buy")->where($map)->update($data);                if ($re) {                                  die("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");                                }            }                   }else{            die("fail");        }    }

标签: #php对接微信支付教程