Home  >  Article  >  WeChat Applet  >  How to place unified orders through WeChat payment using PHP? (Full code)

How to place unified orders through WeChat payment using PHP? (Full code)

php是最好的语言
php是最好的语言Original
2018-07-26 09:29:179333browse

What should I do if "signature error" occurs during H5 payment? Note that after calling WeChat's "Unified Ordering" interface and returning pre_pay_id, the user needs to sign again and return the HTML; "Payment directory is not authorized", just enter the WeChat merchant management background settings.

1. Model layer, Wxpay.php

<?php
namespace app\common\model;
class Wxpay
{
    private $appid = &#39;wxe8*****d4&#39;;                            //微信公众号appid
    private $secret = &#39;37c4*******5f0&#39;;                        //微信公众号appsecret               
    private $mchid = &#39;13******02&#39;;                             //商家号
    private $key = &#39;5363e******49e8&#39;;                          //支付密钥
    private $sslcert_path = &#39;apiclient_cert.pem&#39;;              //证书所在绝对路径
    private $sslkey_path = &#39;apiclient_key.pem&#39;;                //证书所在绝对路径
    
    public function __construct($appid = &#39;&#39;, $secret = &#39;&#39;, $mchid = &#39;&#39;, $key = &#39;&#39;)
    {
        if(!empty($appid))     $this->appid = $appid;
        if(!empty($secret))    $this->secret = $secret;
        if(!empty($mchid))     $this->mchid  = $mchid;
        if(!empty($key))       $this->key= $key;
    }
    /*
     * 微信内H5调起支付
     * @params string $openid : 微信用户openid
     * @params string $out_trade_no : 商家生成的订单号(唯一性)
     * @params int $total_fee : 支付金额,单位分
     * return array $ret : 返回支付时所需要的数据
     * */
    public function payForWeixin($openid,$out_trade_no,$total_fee,$attach=&#39;微信支付&#39;,$body=&#39;微信支付&#39;)
    {
        //支付数据
        $data[&#39;openid&#39;] = $openid;
        $data[&#39;out_trade_no&#39;] = $out_trade_no;
        $data[&#39;total_fee&#39;] = $total_fee*100;
        $data[&#39;spbill_create_ip&#39;] = $_SERVER["REMOTE_ADDR"];
        $data[&#39;attach&#39;] = $attach;
        $data[&#39;body&#39;] = $body;
        $data[&#39;appid&#39;] = $this->appid;
        $data[&#39;mch_id&#39;] = $this->mchid;
        $data[&#39;nonce_str&#39;] = random(12);
        $data[&#39;trade_type&#39;] = "JSAPI";
        $data[&#39;notify_url&#39;] = "http://****.com/home/wxpaynofiy/notify.html";

        $sign = $this->getParam($data);
        $dataXML = "<xml>
           <appid>".$data[&#39;appid&#39;]."</appid>
           <attach>".$data[&#39;attach&#39;]."</attach>
           <body>".$data[&#39;body&#39;]."</body>
           <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
           <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
           <notify_url>".$data[&#39;notify_url&#39;]."</notify_url>
           <openid>".$data[&#39;openid&#39;]."</openid>
           <out_trade_no>".$data[&#39;out_trade_no&#39;]."</out_trade_no>
           <spbill_create_ip>".$data[&#39;spbill_create_ip&#39;]."</spbill_create_ip>
           <total_fee>".$data[&#39;total_fee&#39;]."</total_fee>
           <trade_type>".$data[&#39;trade_type&#39;]."</trade_type>
           <sign>".$sign."</sign>
        </xml>";
        $url = &#39;https://api.mch.weixin.qq.com/pay/unifiedorder&#39;;
        $result =  $this->https_post($url,$dataXML);
        $ret = $this->xmlToArray($result);
        
        if($ret[&#39;return_code&#39;] == &#39;SUCCESS&#39; && $ret[&#39;return_msg&#39;] == &#39;OK&#39;) {
            return array(
                &#39;appId&#39;     => $this->appid,
                &#39;timeStamp&#39; => time(),
                &#39;nonceStr&#39;  => $data[&#39;nonce_str&#39;],
                &#39;package&#39;   => &#39;prepay_id=&#39;.$ret[&#39;prepay_id&#39;],
                &#39;signType&#39;  => &#39;MD5&#39;,
                &#39;paySign&#39;   => $sign
            );
        } else {
            $this->errorLog("微信支付失败,",$ret);
            return null;
        }
    }
     /*
     *   微信二维码支付
     *   @params string $openid : 用户的openid
     *   @params string $out_trade_no : 商户订单号
     *   @params number $total_fee : 订单金额,单位分
     *   return string $code_url : 二维码URL链接
     */
    public function payForQrcode($out_trade_no,$total_fee,$body="魔盒CMS",$attach="微信支付")
    {
        //支付数据
        $data[&#39;out_trade_no&#39;] = $out_trade_no;
        $data[&#39;total_fee&#39;] = $total_fee*100;
        $data[&#39;spbill_create_ip&#39;] = $_SERVER["REMOTE_ADDR"];
        $data[&#39;attach&#39;] = $attach;
        $data[&#39;body&#39;] = $body;
        $data[&#39;appid&#39;] = $this->appid;
        $data[&#39;mch_id&#39;] = $this->mchid;
        $data[&#39;nonce_str&#39;] = random(12);
        $data[&#39;trade_type&#39;] = "NATIVE";
        $data[&#39;notify_url&#39;] = "http://****.com/home/wxpaynofiy/notify.html";

        $sign = $this->getParam($data);
        $dataXML = "<xml>
           <appid>".$data[&#39;appid&#39;]."</appid>
           <attach>".$data[&#39;attach&#39;]."</attach>
           <body>".$data[&#39;body&#39;]."</body>
           <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
           <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
           <notify_url>".$data[&#39;notify_url&#39;]."</notify_url>
           <out_trade_no>".$data[&#39;out_trade_no&#39;]."</out_trade_no>
           <spbill_create_ip>".$data[&#39;spbill_create_ip&#39;]."</spbill_create_ip>
           <total_fee>".$data[&#39;total_fee&#39;]."</total_fee>
           <trade_type>".$data[&#39;trade_type&#39;]."</trade_type>
           <sign>".$sign."</sign>
        </xml>";
        $url = &#39;https://api.mch.weixin.qq.com/pay/unifiedorder&#39;;
        $result =  $this->https_post($url,$dataXML);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;] == &#39;SUCCESS&#39; && $ret[&#39;return_msg&#39;] == &#39;OK&#39;) {
            return $ret[&#39;code_url&#39;];
        } else {
            $this->errorLog("获取微信支付二维码失败,",$ret);
            return null;
        }
    }

    /*
     * 订单查询
     * @params string $transaction_id : 微信订单号
     * @params string $out_trade_no : 商家订单号(与微信订单号二选一)
     * */
    public function findOrder($out_trade_no)
    {
        $data[&#39;appid&#39;] = $this->appid;
        $data[&#39;mch_id&#39;] = $this->mchid;
        $data[&#39;nonce_str&#39;] = random(12);
        $data[&#39;out_trade_no&#39;] = $out_trade_no;
        $sign = $this->getParam($data);
        $dataXML = "<xml>
            <appid>".$data[&#39;appid&#39;]."</appid>
            <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
            <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
            <out_trade_no>".$data[&#39;out_trade_no&#39;]."</out_trade_no>
            <sign>".$sign."</sign>
         </xml>";
        $url = &#39;https://api.mch.weixin.qq.com/pay/orderquery&#39;;
        $result =  $this->https_post($url,$dataXML);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;] == &#39;SUCCESS&#39; && $ret[&#39;return_msg&#39;] == &#39;OK&#39;) {
            return $ret;
        } else {
            $this->errorLog("查询微信支付订单失败,",$ret);
            return null;
        }
    }
    /*
    * 退款订单查询
    * @params string $transaction_id : 微信订单号
    * @params string $out_trade_no : 商家订单号(与微信订单号二选一)
    * */
    public function findRefundOrder($out_trade_no)
    {
        $data[&#39;appid&#39;] = $this->appid;
        $data[&#39;mch_id&#39;] = $this->mchid;
        $data[&#39;nonce_str&#39;] = random(12);
        $data[&#39;out_trade_no&#39;] = $out_trade_no;
        $sign = $this->getParam($data);
        $dataXML = "<xml>
            <appid>".$data[&#39;appid&#39;]."</appid>
            <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
            <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
            <out_trade_no>".$data[&#39;out_trade_no&#39;]."</out_trade_no>
            <sign>".$sign."</sign>
         </xml>";
        $url = &#39;https://api.mch.weixin.qq.com/pay/refundquery&#39;;
        $result =  $this->https_post($url,$dataXML);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;] == &#39;SUCCESS&#39; && $ret[&#39;return_msg&#39;] == &#39;OK&#39;) {
            return $ret;
        } else {
            $this->errorLog("查询微信支付退款订单失败,",$ret);
            return $ret[&#39;err_code_des&#39;];
        }
    }
    /*
     * 申请退款
     * @params string $out_trade_no : 商户订单号
     * @params string $out_refund_no : 商户退款单号
     * @params int $total_fee : 订单金额
     * @params int $refund_fee : 退款金额
     * @params string $refund_desc : 退款原因
     * */
    public function refund($out_trade_no,$out_refund_no,$total_fee,$refund_fee,$refund_desc=&#39;退款&#39;)
    {
        $data[&#39;appid&#39;]  = $this->appid;
        $data[&#39;mch_id&#39;] = $this->mchid;
        $data[&#39;nonce_str&#39;] = random(12);
        $data[&#39;out_trade_no&#39;] = $out_trade_no;
        $data[&#39;out_refund_no&#39;] = $out_refund_no;
        $data[&#39;total_fee&#39;] = $total_fee*100;
        $data[&#39;refund_fee&#39;] = $refund_fee*100;
        $data[&#39;refund_desc&#39;] = $refund_desc;
        $data[&#39;notify_url&#39;] = "http://*****.com/home/wxpaynofiy/refund.html";
        $sign = $this->getParam($data);
        $dataXML = "<xml>
           <appid>".$data[&#39;appid&#39;]."</appid>
           <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
           <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
           <out_trade_no>".$data[&#39;out_trade_no&#39;]."</out_trade_no>
           <out_refund_no>".$data[&#39;out_refund_no&#39;]."</out_refund_no>
           <total_fee>".$data[&#39;total_fee&#39;]."</total_fee>
           <refund_fee>".$data[&#39;refund_fee&#39;]."</refund_fee>
           <refund_desc>".$data[&#39;refund_desc&#39;]."</refund_desc>
           <notify_url>".$data[&#39;notify_url&#39;]."</notify_url>
           <sign>".$sign."</sign>
        </xml>";
        $url = &#39;https://api.mch.weixin.qq.com/secapi/pay/refund&#39;;
        $result =  $this->https_post($url,$dataXML,true);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;] == &#39;SUCCESS&#39; && $ret[&#39;return_msg&#39;] == &#39;OK&#39;) {
            return $ret;
        } else {
            $this->errorLog("微信退款失败,",$ret);
            return null;
        }
    }
    /*
     * 企业付款至用户零钱
     * @params string $openid : 用户openid
     * @params int $total_fee : 付款金额,单位分
     * @params string $out_trade_no : 商家订单号
     * @params string $username : 微信用户名称(注意微信昵称若为空时支付会出错)
     * @params string $desc : 付款描述
     * @params string $check_name : 是否检测用户名
     * */
    public function payForUser($openid,$total_fee,$out_trade_no,$username=&#39;魔盒CMS&#39;,$desc=&#39;魔盒CMS付款给用户&#39;,$check_name=&#39;NO_CHECK&#39;)
    {
        $data[&#39;amount&#39;] = $total_fee*100;
        $data[&#39;check_name&#39;] = $check_name;
        $data[&#39;desc&#39;] = $desc;
        $data[&#39;mch_appid&#39;] = $this->appid;
        $data[&#39;mchid&#39;] = $this->mchid;
        $data[&#39;nonce_str&#39;] = random(12);
        $data[&#39;openid&#39;] = $openid;
        $data[&#39;partner_trade_no&#39;] = $out_trade_no;
        $data[&#39;re_user_name&#39;] = $username;
        $data[&#39;spbill_create_ip&#39;] = $_SERVER["REMOTE_ADDR"];
        $sign = $this->getParam($data);

        $dataXML="<xml>
        <mch_appid>".$data[&#39;mch_appid&#39;]."</mch_appid>
        <mchid>".$data[&#39;mchid&#39;]."</mchid>
        <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
        <partner_trade_no>".$data[&#39;partner_trade_no&#39;]."</partner_trade_no>
        <openid>".$data[&#39;openid&#39;]."</openid>
        <check_name>".$data[&#39;check_name&#39;]."</check_name>
        <re_user_name>".$data[&#39;re_user_name&#39;]."</re_user_name>
        <amount>".$data[&#39;amount&#39;]."</amount>
        <desc>".$data[&#39;desc&#39;]."</desc>
        <spbill_create_ip>".$data[&#39;spbill_create_ip&#39;]."</spbill_create_ip>
        <sign>".$sign."</sign>
        </xml>";

        $url = &#39;https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers&#39;;
        $result =  $this->https_post($url,$dataXML,true);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;]==&#39;SUCCESS&#39; && $ret[&#39;result_code&#39;] == &#39;SUCCESS&#39;)
        {
            //支付成功返回商户订单号、微信订单号、微信支付成功时间
            $result[&#39;partner_trade_no&#39;] = $ret[&#39;partner_trade_no&#39;];
            $result[&#39;payment_no&#39;] = $ret[&#39;payment_no&#39;];
            $result[&#39;payment_time&#39;] = $ret[&#39;payment_time&#39;];
            return $ret;
        } else {
           $this->errorLog(&#39;付款给用户失败&#39;,$ret);
           return null;
        }
    }
     /*
     * 普通红包
     * @params string $out_trade_no : 商家订单号
     * @params string $openid : 接收红包用户的openid
     * @params int $total_fee : 红包金额,单位分
     * @params int $total_num : 红包发放总人数
     * @params string $wishing : 红包祝福语
     * @params string $act_name : 活动名称
     * @params string $remark : 备注
     * @params string $scene_id :场景值ID。发放红包使用场景,红包金额大于200或者小于1元时必传。PRODUCT_1:商品促销、PRODUCT_2:抽奖、PRODUCT_3:虚拟物品兑奖 、PRODUCT_4:企业内部福利、PRODUCT_5:渠道分润、PRODUCT_6:保险回馈、PRODUCT_7:彩票派奖、PRODUCT_8:税务刮奖
     * */
    public function redPack($openid,$total_fee,$out_trade_no,$total_num = 1,$wishing = &#39;感谢您光临***平台进行购物&#39;,$act_name=&#39;***购物发红包&#39;,$remark = &#39;购物领红包&#39;)
    {
        $data[&#39;mch_billno&#39;]     = $out_trade_no;
        $data[&#39;mch_id&#39;]         = $this->mchid;
        $data[&#39;wxappid&#39;]        = $this->appid;
        $data[&#39;send_name&#39;]      = &#39;发送红包者的名称&#39;;
        $data[&#39;re_openid&#39;]      = $openid;
        $data[&#39;total_amount&#39;]   = $total_fee;
        $data[&#39;total_num&#39;]      = $total_num;
        $data[&#39;wishing&#39;]        = $wishing;
        $data[&#39;client_ip&#39;]      = $_SERVER["REMOTE_ADDR"];
        $data[&#39;act_name&#39;]       = $act_name;
        $data[&#39;remark&#39;]         = $remark;
        $data[&#39;nonce_str&#39;]      = random(12);
        $sign = $this->getParam($data);

        $dataXML="<xml>
        <sign>".$sign."</sign>
        <mch_billno>".$data[&#39;mch_billno&#39;]."</mch_billno>
        <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
        <wxappid>".$data[&#39;wxappid&#39;]."</wxappid>
        <send_name>".$data[&#39;send_name&#39;]."</send_name>
        <re_openid>".$data[&#39;re_openid&#39;]."</re_openid>
        <total_amount>".$data[&#39;total_amount&#39;]."</total_amount>
        <total_num>".$data[&#39;total_num&#39;]."</total_num>
        <wishing>".$data[&#39;wishing&#39;]."</wishing>
        <client_ip>".$data[&#39;client_ip&#39;]."</client_ip>
        <act_name>".$data[&#39;act_name&#39;]."</act_name>
        <remark>".$data[&#39;remark&#39;]."</remark>
        <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
        </xml>";

        $url = &#39;https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack&#39;;
        $result =  $this->https_post($url,$dataXML,true);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;]==&#39;SUCCESS&#39; && $ret[&#39;result_code&#39;] == &#39;SUCCESS&#39;)
        {
            return $ret;
        } else {
            $this->errorLog(&#39;发放普通红包失败&#39;,$ret);
            return $ret[&#39;err_code_des&#39;];
        }

    }

    /*
    * 裂变红包:一次可以发放一组红包。首先领取的用户为种子用户,种子用户领取一组红包当中的一个,并可以通过社交分享将剩下的红包给其他用户。
     * 裂变红包充分利用了人际传播的优势。
    * @params string $out_trade_no : 商家订单号
    * @params string $openid : 接收红包用户的openid
    * @params int $total_fee : 红包金额,单位分
    * @params int $total_num : 红包发放总人数
    * @params string $wishing : 红包祝福语
    * @params string $act_name : 活动名称
    * @params string $remark : 备注
    * @params string $scene_id :场景值ID。发放红包使用场景,红包金额大于200或者小于1元时必传。PRODUCT_1:商品促销、PRODUCT_2:抽奖、PRODUCT_3:虚拟物品兑奖 、PRODUCT_4:企业内部福利、PRODUCT_5:渠道分润、PRODUCT_6:保险回馈、PRODUCT_7:彩票派奖、PRODUCT_8:税务刮奖
    * */
    public function redPackGroup($openid,$total_fee,$out_trade_no,$total_num,$wishing = &#39;感谢您光临***进行购物&#39;,$act_name=&#39;**购物发红包&#39;,$remark = &#39;购物领红包&#39;)
    {
        $data[&#39;mch_billno&#39;]     = $out_trade_no;
        $data[&#39;mch_id&#39;]         = $this->mchid;
        $data[&#39;wxappid&#39;]        = $this->appid;
        $data[&#39;send_name&#39;]      = &#39;发送红包者的名称&#39;;
        $data[&#39;re_openid&#39;]      = $openid;
        $data[&#39;total_amount&#39;]   = $total_fee;
        $data[&#39;amt_type&#39;]       = &#39;ALL_RAND&#39;;   //ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额
        $data[&#39;total_num&#39;]      = $total_num;
        $data[&#39;wishing&#39;]        = $wishing;
        $data[&#39;client_ip&#39;]      = $_SERVER["REMOTE_ADDR"];
        $data[&#39;act_name&#39;]       = $act_name;
        $data[&#39;remark&#39;]         = $remark;
        $data[&#39;nonce_str&#39;]      = random(12);
        $sign = $this->getParam($data);

        $dataXML="<xml>
        <sign>".$sign."</sign>
        <mch_billno>".$data[&#39;mch_billno&#39;]."</mch_billno>
        <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
        <wxappid>".$data[&#39;wxappid&#39;]."</wxappid>
        <send_name>".$data[&#39;send_name&#39;]."</send_name>
        <re_openid>".$data[&#39;re_openid&#39;]."</re_openid>
        <total_amount>".$data[&#39;total_amount&#39;]."</total_amount>
        <amt_type>".$data[&#39;amt_type&#39;]."</amt_type> 
        <total_num>".$data[&#39;total_num&#39;]."</total_num>
        <wishing>".$data[&#39;wishing&#39;]."</wishing>
        <client_ip>".$data[&#39;client_ip&#39;]."</client_ip>
        <act_name>".$data[&#39;act_name&#39;]."</act_name>
        <remark>".$data[&#39;remark&#39;]."</remark>
        <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
        </xml>";

        $url = &#39;https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack&#39;;
        $result =  $this->https_post($url,$dataXML,true);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;]==&#39;SUCCESS&#39; && $ret[&#39;result_code&#39;] == &#39;SUCCESS&#39;)
        {
            return $ret;
        } else {
            $this->errorLog(&#39;发放裂变红包失败&#39;,$ret);
            return $ret[&#39;err_code_des&#39;];
        }

    }
    /*
     * 查询红包记录
     * @params string $out_trade_no : 商家订单号
     * */
    public function findRedPack($out_trade_no)
    {
        $data[&#39;mch_billno&#39;]     = $out_trade_no;
        $data[&#39;mch_id&#39;]         = $this->mchid;
        $data[&#39;appid&#39;]          = $this->appid;
        $data[&#39;bill_type&#39;]      = &#39;MCHT&#39;;           //MCHT:通过商户订单号获取红包信息。
        $data[&#39;nonce_str&#39;]      = random(12);
        $sign = $this->getParam($data);

        $dataXML="<xml>
        <sign>".$sign."</sign>
        <mch_billno>".$data[&#39;mch_billno&#39;]."</mch_billno>
        <mch_id>".$data[&#39;mch_id&#39;]."</mch_id>
        <appid>".$data[&#39;appid&#39;]."</appid>
        <bill_type>".$data[&#39;bill_type&#39;]."</bill_type> 
        <nonce_str>".$data[&#39;nonce_str&#39;]."</nonce_str>
        </xml>";

        $url = &#39;https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo&#39;;
        $result =  $this->https_post($url,$dataXML,true);
        $ret = $this->xmlToArray($result);
        if($ret[&#39;return_code&#39;]==&#39;SUCCESS&#39; && $ret[&#39;result_code&#39;] == &#39;SUCCESS&#39;)
        {
            return $ret;
        } else {
            $this->errorLog(&#39;查询红包记录失败&#39;,$ret);
            return $ret[&#39;err_code_des&#39;];
        }
    }
    /*
     * 获取用户微信的OPENID
     * */
    public function openid($c=false)
    {
        if($_GET[&#39;state&#39;]!="zgm"){
            $t = $c ? "snsapi_userinfo" : "snsapi_base";
            $url=urlencode(get_url());
            $url="https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appid."&redirect_uri=".$url."&response_type=code&scope=".$t."&state=zgm#wechat_redirect";
            echo "<html><script>window.location.href=&#39;$url&#39;;</script></html>";
            exit;
        }
        if($_GET[&#39;code&#39;]){
            $url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->secret."&code=".$_GET[&#39;code&#39;]."&grant_type=authorization_code";
            $wx_db=json_decode($this->https_get($url));
            if($c){
                $url_2="https://api.weixin.qq.com/sns/userinfo?access_token=".$wx_db->access_token."&openid=".$wx_db->openid."&lang=zh_CN";
                $db=json_decode($this->https_get($url_2));
                return $db;
            }else{
                return $wx_db->openid;
            }
        }
    }
    /*
    * 发起网络GET请求
    * @params string $url : URL链接
    */
    private function https_get($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); 
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); 
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); 
        curl_setopt($curl, CURLOPT_HEADER, FALSE) ; 
        curl_setopt($curl, CURLOPT_TIMEOUT,60);   
        if (curl_errno($curl)) {
            return &#39;Errno&#39;.curl_error($curl);
        }
        else{$result=curl_exec($curl);}
        curl_close($curl);
        return $result;
    }
    //对参数排序,生成MD5加密签名
    private function getParam($paramArray, $isencode=false)
    {
        $paramStr = &#39;&#39;;
        ksort($paramArray);
        $i = 0;
        foreach ($paramArray as $key => $value)
        {
            if ($key == &#39;Signature&#39;){
                continue;
            }
            if ($i == 0){
                $paramStr .= &#39;&#39;;
            }else{
                $paramStr .= &#39;&&#39;;
            }
            $paramStr .= $key . &#39;=&#39; . ($isencode?urlencode($value):$value);
            ++$i;
        }
        $stringSignTemp=$paramStr."&key=".$this->key;
        $sign=strtoupper(md5($stringSignTemp));
        return $sign;
    }
    //POST提交数据
    private function https_post($url,$data,$ssl = false)
    {
        $ch = curl_init ();
        curl_setopt ( $ch, CURLOPT_URL, $url );
        curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
        curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
        if($ssl) {
            curl_setopt ( $ch,CURLOPT_SSLCERT,$this->sslcert_path);
            curl_setopt ( $ch,CURLOPT_SSLKEY,$this->sslkey_path);
        }
        curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
        curl_setopt ( $ch, CURLOPT_AUTOREFERER, 1 );
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
        $result = curl_exec($ch);
        if (curl_errno($ch)) {
            return &#39;Errno: &#39;.curl_error($ch);
        }
        curl_close($ch);
        return $result;
    }
    /*
    * XML转array
    * @params xml $xml : xml 数据
    * return array $data : 转义后的array数组
    */
    private function xmlToArray($xml)
    {
        libxml_disable_entity_loader(true);
        $xmlstring = simplexml_load_string($xml, &#39;SimpleXMLElement&#39;, LIBXML_NOCDATA);
        $val = json_decode(json_encode($xmlstring),true);
        return $val;
    }
    /*
    * 记录日志
    * @params string $msg : 提示语句
    * @params array $ret : 错误结果
    */
    private function errorLog($msg,$ret)
    {
        file_put_contents(ROOT_PATH . &#39;runtime/error/wxpay.log&#39;, "[" . date(&#39;Y-m-d H:i:s&#39;) . "] ".$msg."," .json_encode($ret).PHP_EOL, FILE_APPEND);
    }
}

2. Controller layer, Test.php

<?php
namespace app\goods\controller;
use app\common\model\Wxpay;
class Test
{
    /*
    * 调用微信支付
    * 一、获取微信用户的openid; 
    * 二、调用微信支付接口
    * 三、生成H5中使用的签名内容
    */
    public function wx()
    {
        $wxpay = new Wxpay();
        $openid = $wxpay->openid();
        $pay = $wxpay->payForWeixin($openid,date(&#39;YmdHis&#39;).rand(1,5),&#39;0.1&#39;);
        $paySign =strtoupper(MD5(&#39;appId=&#39;.$pay[&#39;appId&#39;].&#39;&nonceStr=&#39;.$pay[&#39;nonceStr&#39;].&#39;&package=&#39;.$pay[&#39;package&#39;].&#39;&signType=MD5&timeStamp=&#39;.$pay[&#39;timeStamp&#39;].&#39;&key=536*****9e8&#39;));
         $h5 = array(
            &#39;appId&#39;     => $pay[&#39;appId&#39;],
            &#39;timeStamp&#39; => $pay[&#39;timeStamp&#39;],
            &#39;nonceStr&#39;  => $pay[&#39;nonceStr&#39;],
            &#39;package&#39;   => $pay[&#39;package&#39;],
            &#39;signType&#39;  => $pay[&#39;signType&#39;],
            &#39;paySign&#39;   => $paySign
        );
        $this->assign(&#39;wxpay&#39;,$h5);
        return view();
    }
}

3. Call WeChat payment in HTML, wx.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>订单示例</title>
</head>
<body>

<script type="text/javascript">
    function onBridgeReady(){
        WeixinJSBridge.invoke(
            &#39;getBrandWCPayRequest&#39;, {
                "appId":"{$wxpay[&#39;appId&#39;]}",
                "timeStamp":"{$wxpay[&#39;timeStamp&#39;]}",
                "nonceStr":"{$wxpay[&#39;nonceStr&#39;]}",
                "package":"{$wxpay[&#39;package&#39;]}",
                "signType":"MD5",
                "paySign":"{$wxpay[&#39;paySign&#39;]}"
            },
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ){
                    // 使用以上方式判断前端返回,微信团队郑重提示:
                    //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                }
            });
    }
    if (typeof WeixinJSBridge == "undefined"){
        if( document.addEventListener ){
            document.addEventListener(&#39;WeixinJSBridgeReady&#39;, onBridgeReady, false);
        }else if (document.attachEvent){
            document.attachEvent(&#39;WeixinJSBridgeReady&#39;, onBridgeReady);
            document.attachEvent(&#39;onWeixinJSBridgeReady&#39;, onBridgeReady);
        }
    }else{
        onBridgeReady();
    }
</script>
</body>
</html>

4. Receive the WeChat payment return result and set the notify_url value during payment to ensure that this link can be accessed by the external network. wxpaynofiy.php

<?php
namespace app\home\controller;
class Wxpaynofiy
{
     public function notify()
    {
        $xml = isset($GLOBALS["HTTP_RAW_POST_DATA"]) ? $GLOBALS[&#39;HTTP_RAW_POST_DATA&#39;] : file_get_contents("php://input");
        $data = xmlToArray($xml);
        if($data[&#39;return_code&#39;] == &#39;SUCCESS&#39; && $data[&#39;result_code&#39;] == &#39;SUCCESS&#39;){
            if($this->checkSign($data)) {
                $transaction_id = $data[&#39;transaction_id&#39;];      //微信支付订单号
                $out_trade_no   = $data[&#39;out_trade_no&#39;];        //商家订单号
                $this->errorLog(&#39;微信支付返回结果,微信支付订单号:&#39;.$transaction_id.&#39;,商家订单号:&#39;.$out_trade_no,[]);

            } else {
                $this->errorLog(&#39;微信支付返回结果签名验证失败&#39;,$data);
            }
        } else {
            $this->errorLog(&#39;微信支付返回结果&#39;,$data);
        }
        echo &#39;<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>&#39;;
    }

    /*
     * 验证签名
     * @params array $result : 微信支付成功返回的结果数组
     * return bool $ret : 成功true,失败false
     * */
    private function checkSign(array $data)
    {
        $str = &#39;&#39;;
        ksort($data);
        foreach ($data as $k => $v) {
            if($k != &#39;sign&#39;) $str .= $k.&#39;=&#39;.$v.&#39;&&#39;;
        }
        $temp = $str . &#39;key=5363******49e8&#39;;     //key:商户支付密钥
        $sign = strtoupper(md5($temp));
        return $sign == $data[&#39;sign&#39;] ? true : false;
    }

    private function errorLog($msg,$ret)
    {
        file_put_contents(ROOT_PATH . &#39;runtime/error/wxpaynofiy.log&#39;, "[" . date(&#39;Y-m-d H:i:s&#39;) . "] ".$msg."," .json_encode($ret).PHP_EOL, FILE_APPEND);
    }
}

Video tutorial: php WeChat interface development practical project chat robot WeChat payment

The above is the detailed content of How to place unified orders through WeChat payment using PHP? (Full code). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn