基於tp5的微信app支付及回調


基於tp5的微信app支付及回調

1.微信開放平台創建移動應用,獲取appid和商戶號,並申請微信支付,商戶平台中設置key
2.生成訂單信息,調用wxTradePay

$wxpay = new model\Wxpay();
$wxpay_info = $wxpay->wxTradePay($order);

生成微信預支付訂單

public function wxTradePay($order)
{
        $order['order_amount'] = $order['order_amount'] * 100;//接口中參數支付金額單位為【分】,參數值不能帶小數。對賬單中的交易金額單位為【元】。
        $nonce_str = $this->rand_code();        //調用隨機字符串生成方法獲取隨機字符串
        $data['appid'] ='appid';
        $data['attach'] = $order['log_id'].'-'.$order['order_amount']; //自定義數據
        $data['mch_id'] = '商戶號' ; 
        $data['body'] = $order['order_sn']; //商品描述
        $data['spbill_create_ip'] = $_SERVER['REMOTE_ADDR'];   //ip地址
        $data['total_fee'] = $order['order_amount'];                         //總金額,單位為【分】
        $data['out_trade_no'] = $out_trade_no;    //商戶訂單號,不能重復
        $data['nonce_str'] = $this->rand_code();                   //隨機字符串
        $data['notify_url'] = '回調地址';   //回調地址,用戶接收支付后的通知,必須為能直接訪問的網址,不能跟參數
        $data['trade_type'] = 'APP';      //支付方式
        //將參與簽名的數據保存到數組  注意:以上幾個參數是追加到$data中的,$data中應該同時包含開發文檔中要求必填的剔除sign以外的所有數據
        $data['sign'] = $this->getSign($data);        //獲取簽名
        $xml = $this->ToXml($data);            //數組轉xml
        //curl 傳遞給微信方
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $ch = curl_init();
        curl_setopt($ch,CURLOPT_URL, $url);
        if(stripos($url,"https://")!==FALSE){
            curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }    else    {
            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//嚴格校驗
        }
        //設置header
        curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求結果為字符串且輸出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //設置超時
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_POST, TRUE);
        //傳輸文件
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //運行curl
        $data = curl_exec($ch);
        
        $ssr = array();
        //返回結果
        if($data){
            curl_close($ch);
            
            //返回成功,將xml數據轉換為數組.
            $re = $this->FromXml($data);
            //print_r($re);die;
            if($re['return_code'] != 'SUCCESS'){
                $ssr['code'] = 201;
                $ssr['msg'] = '簽名失敗';
                return $ssr;
            }
            else{
            //接收微信返回的數據,傳給APP!
                $arr =array(
                    'prepayid' =>$re['prepay_id'],
                    'appid' => 'appud',
                    'partnerid' => '商戶號',
                    'package' => 'Sign=WXPay',
                    'noncestr' => $nonce_str,
                    'timestamp' =>time(),
                );
                //第二次生成簽名
                $sign = $this->getSign($arr);
                $arr['sign'] = $sign;
                $arr['code'] = 200;
                $arr['msg'] = '簽名成功';
                return $arr;
            }
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            $ssr['code'] = 201;
            $ssr['msg'] = 'curl出錯,錯誤碼:$error';
            return $ssr;
            
        }
}

隨機字符串

public function rand_code()
{
        $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';//62個字符
        $str = str_shuffle($str);
        $str = substr($str,0,32);
        return  $str;
}

生成簽名

public function getSign($params) 
{
        ksort($params);        //將參數數組按照參數名ASCII碼從小到大排序
        foreach ($params as $key => $item) {
            if (!empty($item)) {         //剔除參數值為空的參數
                $newArr[] = $key.'='.$item;     // 整合新的參數數組
            }
        }
        $stringA = implode("&", $newArr);         //使用 & 符號連接參數
        $stringSignTemp = $stringA."&key="."key";        // key是在商戶平台API安全里自己設置的
        $stringSignTemp = MD5($stringSignTemp);       //將字符串進行MD5加密
        $sign = strtoupper($stringSignTemp);      //將所有字符轉換為大寫
        return $sign;
 }

xml處理

public function ToXml($data=array())
{
        if(!is_array($data) || count($data) <= 0)
        {
           return '數組異常';
        }
        $xml = "<xml>";
        foreach ($data as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
}
public function FromXml($xml)
{
        if(!$xml){
            echo "xml數據異常!";
        }
        //將XML轉為array
        //禁止引用外部xml實體
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
}

這樣就生成了微信預支付信息,正確的信息應該是這樣,data里的pay_info就是客戶端調起微信app支付需要的信息

{
        "code": 200,
        "msg": "待支付",
        "data": {
            "order_id": 1432,
            "pay_info": {
                    "prepayid": "x'x'x'x'x",
                    "appid": "x'x'x'x'x",
                    "partnerid": "x'x'x'x",
                    "package": "Sign=WXPay",
                    "noncestr": "jdNypx'x'x'x1Q3tSWXGEq7PnDKo",
                    "timestamp": 1539689298,
                    "sign": "937FEB782F2F43126",
                    "code": 200,
                    "msg": "簽名成功"
            }
        }
}

3.回調

public function wxNotify()
{
        $wx = new model\Wxpay();
        //接收微信返回的數據數據,返回的xml格式
        $xmlData = file_get_contents('php://input');
        //將xml格式轉換為數組
        $data = $wx->FromXml($xmlData);
        $arr = array();
        //為了防止假數據,驗證簽名是否和返回的一樣。
        //記錄一下,返回回來的簽名,生成簽名的時候,必須剔除sign字段。
        $sign = $data['sign'];
        unset($data['sign']);
        if($sign == $wx->getSign($data))
        {
            //簽名驗證成功后,判斷返回微信返回的
            if ($data['result_code'] == 'SUCCESS' &&  && $data['return_code']=="SUCCESS")
            {
                //根據返回的訂單號做業務邏輯
                $flow = new model\Flow();
                $flow->order_paid($data['out_trade_no'],$data['transaction_id']);
                //處理完成之后,告訴微信成功結果!
                echo '<xml>
                        <return_code><![CDATA[SUCCESS]]></return_code>
                        <return_msg><![CDATA[OK]]></return_msg>
                        </xml>';
                exit();    
            }
            else
            {
                $file = fopen('./log.txt', 'a+');
                fwrite($file,"錯誤信息:".$data['return_msg'].date("Y-m-d H:i:s"),time()."\r\n");    
            }
        }
        else
        {
            $file = fopen('./log.txt', 'a+');
            fwrite($file,"錯誤信息:簽名驗證失敗".date("Y-m-d H:i:s"),time()."\r\n");    
        }    
}

到這里,微信APP支付結束,大致流程就是這樣,可根據自己業務流程編寫。

參考文檔
微信支付統一下單 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

轉載:https://blog.csdn.net/weixin_42555539/article/details/88845854


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM