1. 程式人生 > >tp5集合h5 wap和公眾號支付

tp5集合h5 wap和公眾號支付

控制器controller:

index.php

<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
use  app\index\model\Weixin;
use  app\index\model\Weixin_pay;
use  think\Session;
use think\Db;
use think\Log;



class Index extends Controller
{
    public function index()
    {

        
$Weixin=new Weixin(); $code=(input('param.code')); if (!empty($code)) { $res=$Weixin->get_access_token($code); $userinfo=$Weixin->get_openid_userinfo($res['access_token'],$res['openid']); halt($userinfo); }
$res=$Weixin->code_shouquan(); } public function pay() { $userAgent = $_SERVER['HTTP_USER_AGENT']; if (strpos($userAgent, 'MicroMessenger')) { $Weixin=new Weixin(); $code=(input('param.code')); if (!empty($code)) {
$res=$Weixin->get_access_token($code); $userinfo=$Weixin->get_openid_userinfo($res['access_token'],$res['openid']); $openid=$userinfo['openid']; // halt($openid); $Weixin_pay=new Weixin_pay(); $total_fee=1; $body="JSAPI支付測試"; $order_sn=time(); $res=$Weixin_pay->pay($openid,$total_fee,$body,$order_sn); $this->assign("res",$res); return $this->fetch("index"); }else{ $res=$Weixin->code_shouquan(); } }else{ //非微信瀏覽器 $Weixin_pay=new Weixin_pay(); //h5支付不用傳遞openid 此處與微信jsapi支付不同 $openid=""; $total_fee=1; $body="wamp支付測試"; $order_sn=time(); $res=$Weixin_pay->payh5($openid,$total_fee,$body,$order_sn); // halt($res); $this->assign("res",$res); return $this->fetch("h5"); } } public function orderquery(){ $Weixin_pay=new Weixin_pay(); // $openid="oZX2QwaUBh37C4Ev7I-NUdp6udao"; $total_fee=1; $body="JSAPI支付測試"; $order_sn=time(); $res=$Weixin_pay-> orderquery(); } public function notify(){ $xml = $GLOBALS['HTTP_RAW_POST_DATA']; Log::record($xml); } }

model層

Weixin.php

<?php
namespace app\index\model;
use think\Db;
use think\Validate;
use think\Loader;
use think\Model;

class Weixin extends model
{
    protected $appScrect;
    protected $appId;

    public function __construct($appScrect="xxxxxxxxx",$appId="xxxxxxxx"){
            $this->appScrect=$appScrect;
            $this->appId=$appId;

    }

    public function code_shouquan(){
        // echo $this->appScrect;
        // echo $this->appId;

          $redirect_uri=urlencode("你自己的域名/index/index/pay");//微信獲取網頁授權地址
            // 1、引導使用者進入授權頁面同意授權,獲取code 
            // 2、通過code換取網頁授權access_token
            // 3、如果需要,開發者可以重新整理網頁授權access_token,避免過期 
            // 4、通過網頁授權access_token和openid獲取使用者基本資訊(支援UnionID機制) 
         $url="https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appId."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
    
        header("Location: $url");
    }


    public function get_access_token($code){

        //檢測快取中是否有access_token(2小時),如果存在直接返回,不存在則檢測快取中的refresh_token(30天),
        // refresh_token如果存在呼叫重新整理快取;如果不存在重新發起授權code授權
        $url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appId."&secret=".$this->appScrect."&code=".$code."&grant_type=authorization_code";

        $res= file_get_contents($url);
        $res=json_decode($res,true);

        return $res;
    }


    public function get_refresh_token($refresh_token){

        $url="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=".$this->appId."&grant_type=refresh_token&refresh_token=".$refresh_token;

        $res= file_get_contents($url);
        $res=json_decode($res,true);

        return $res;


    }

     public function get_openid_userinfo($access_token,$openid){
         $url="https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
         $res= file_get_contents($url);
        $res=json_decode($res,true);

        return $res;
     }


}

Weixin_pay.php

<?php
namespace app\index\model;
use think\Db;
use think\Validate;
use think\Loader;
use think\Model;

class Weixin_pay extends model
{
    protected $appScrect;//微信公眾平臺的appscrect
    protected $appId;//微信公眾平臺appid
    protected $key;//微信商戶平臺配置的祕鑰
    protected $mch_id;//微信商戶號
    protected $values = array();

    public function __construct($appScrect="xxxxxx",$appId="xxxxxx", $key="xxxxxx",$mch_id ='xxxxxx'){
            $this->appScrect=$appScrect;
            $this->appId=$appId;
            $this->key=$key;
            $this->mch_id=$mch_id;

    }

    public function pay($openid,$total_fee,$body,$out_trade_no){
          $config= config('wxpay');

           $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
               $notify_url   ='http://'.$_SERVER['HTTP_HOST'].'/index/index/notify';

        $onoce_str = $this->createNoncestr();
 
        $data["appid"] = $this->appId;
        $data["body"] = $body;
        $data["mch_id"] = $this->mch_id;
        $data["nonce_str"] = $onoce_str;
        $data["notify_url"] = $notify_url;
        $data["out_trade_no"] = $out_trade_no;
        $data["spbill_create_ip"] = $this->get_client_ip();
        $data["total_fee"] = $total_fee;
        $data["trade_type"] = "JSAPI";
        $data["openid"] = $openid;
        $sign = $this->getSign($data);
         // halt($data);
        $data["sign"] = $sign;
 
        $xml = $this->arrayToXml($data);
        $response = $this->postXmlCurl($xml, $url);

  
 
        //將微信返回的結果xml轉成陣列
        $response = $this->xmlToArray($response);
        
        $response['package']="prepay_id=".$response['prepay_id'];
       

        $jsapi=array();
        $timeStamp = time();
        $jsapi['appId']=($response["appid"]);    
        $jsapi['timeStamp']=("$timeStamp");
        $jsapi['nonceStr']=($this->createNoncestr());
        $jsapi['package']=("prepay_id=" . $response['prepay_id']);
        $jsapi['signType']=("MD5");
        $jsapi['paySign']=($this->getSign($jsapi));
        $parameters = json_encode($jsapi);
        // halt($jsapi);

              
            //請求資料,統一下單  
                      
            return $parameters; 
    }



    public function payh5($openid,$total_fee,$body,$out_trade_no){
          $config= config('wxpay');
            $ip= request()->ip();
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $notify_url   ='http://'.$_SERVER['HTTP_HOST'].'/index/index/notify';

        $onoce_str = $this->createNoncestr();
 
        $data["appid"] = $this->appId;
        $data["body"] = $body;
        $data["mch_id"] = $this->mch_id;
        $data["nonce_str"] = $onoce_str;
        $data["notify_url"] = $notify_url;
        $data["out_trade_no"] = $out_trade_no;
        $data["spbill_create_ip"] = $ip;
        $data["total_fee"] = $total_fee;
        $data["trade_type"] = "MWEB";
        // $data["openid"] = $openid;
        $data["scene_info"] = "{'h5_info': {'type':'Wap','wap_url':  $notify_url,'wap_name': '測試充值'}}";
        $sign = $this->getSign($data);
         // halt($data);
        $data["sign"] = $sign;

 
        $xml = $this->arrayToXml($data);
        $response = $this->postXmlCurl($xml, $url);

        //將微信返回的結果xml轉成陣列
        $response = $this->xmlToArray($response);
        

              
            //請求資料,統一下單  
                      
            return $response; 
    }

   


  




    public static function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    //   /*生成簽名*/
    public function getSign($Obj){
        foreach ($Obj as $k => $v){
            $Parameters[$k] = $v;
        }
        //簽名步驟一:按字典序排序引數
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //echo '【string1】'.$String.'</br>';
        //簽名步驟二:在string後加入KEY
        $String = $String."&key=".$this->key;
        //echo "【string2】".$String."</br>";
        //簽名步驟三:MD5加密
        $String = md5($String);
        //echo "【string3】 ".$String."</br>";
        //簽名步驟四:所有字元轉為大寫
        $result_ = strtoupper($String);
        //echo "【result】 ".$result_."</br>";
        return $result_;
    }
 
 
    /**
    *  作用:產生隨機字串,不長於32位
    */
    public function createNoncestr( $length = 32 ){
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; 
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  { 
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1); 
        } 
        return $str;
    }
 
 
    //陣列轉xml
    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轉為array
    */
    public function xmlToArray($xml){  
        //將XML轉為array       
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);   
        return $array_data;
    }
 
 
    /**
    *  作用:以post方式提交xml到對應的介面url
    */
    public function postXmlCurl($xml,$url,$second=30){  
        //初始化curl       
        $ch = curl_init();
        //設定超時
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        //這裡設定代理,如果有的話
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //設定header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求結果為字串且輸出到螢幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        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);
            echo "curl出錯,錯誤碼:$error"."<br>";
            curl_close($ch);
            return false;
        }
    }
 
 
    /*
    獲取當前伺服器的IP
    */
    public function get_client_ip(){
        if ($_SERVER['REMOTE_ADDR']) {
            $cip = $_SERVER['REMOTE_ADDR'];
        } elseif (getenv("REMOTE_ADDR")) {
            $cip = getenv("REMOTE_ADDR");
        } elseif (getenv("HTTP_CLIENT_IP")) {
            $cip = getenv("HTTP_CLIENT_IP");
        } else {
            $cip = "unknown";
        }
        return $cip;
    }
     
 
    /**
    *  作用:格式化引數,簽名過程需要使用
    */
    public function formatBizQueryParaMap($paraMap, $urlencode){
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v){
            if($urlencode){
                $v = urlencode($v);
            }
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar;
        if (strlen($buff) > 0){
            $reqPar = substr($buff, 0, strlen($buff)-1);
        }
        return $reqPar;
    }
    
        public function MakeSign($unifiedorder)
    {
        $this->values=$unifiedorder;
        //簽名步驟一:按字典序排序引數
        // ksort($this->values);
        $string = $this->ToUrlParams();
//        halt($string);
        //簽名步驟二:在string後加入KEY
        $string = $string . "&key=".$this->key;
        //簽名步驟三:MD5加密
        $string = md5($string);
        //簽名步驟四:所有字元轉為大寫
        $result = strtoupper($string);
        return $result;
    }

    public function ToUrlParams()
    {
        $buff = "";
        foreach ($this->values as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }


          function array2xml($array)
    {
        $xml='<xml>';
        foreach($array as $key=>$val){
            if(is_numeric($key)){
                $key="item id=\"$key\"";
            }else{
                //去掉空格,只取空格之前文字為key
                list($key,)=explode(' ',$key);
            } 
            $xml.="<$key>";
            $xml.=is_array($val)?$this->_array2xml($val):$val;
            //去掉空格,只取空格之前文字為key
            list($key,)=explode(' ',$key);
            $xml.="</$key>";
            
        }
            $xml.="</xml>";

        return $xml;
    }

       function xml2array($xml)
    {    
        //禁止引用外部xml實體
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);        
        return $values;
    }

    
    public  function request_post($url = '', $param = '')
    {
        if (empty($url) || empty($param)) {
            return false;
        }
        $postUrl = $url;
        $curlPost = $param;
        $ch = curl_init(); //初始化curl
        curl_setopt($ch, CURLOPT_URL, $postUrl); //抓取指定網頁
        curl_setopt($ch, CURLOPT_HEADER, 0); //設定header
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求結果為字串且輸出到螢幕上
        curl_setopt($ch, CURLOPT_POST, 1); //post提交方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
        $data = curl_exec($ch); //執行curl
        curl_close($ch);
        return $data;
    }

    function curl_post_ssl($url, $vars, $second=30,$aHeader=array())
    {
                $ch = curl_init();
                //curl_setopt($ch,CURLOPT_VERBOSE,'1');
                curl_setopt($ch,CURLOPT_TIMEOUT,$second);
                curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch,CURLOPT_URL,$url);
                curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
                curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
                curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
                curl_setopt($ch,CURLOPT_SSLCERT,'/data/cert/php.pem');
                curl_setopt($ch,CURLOPT_SSLCERTPASSWD,'1234');
                curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
                curl_setopt($ch,CURLOPT_SSLKEY,'/data/cert/php_private.pem');
 
                if( count($aHeader) >= 1 ){
                        curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
                }
 
                curl_setopt($ch,CURLOPT_POST, 1);
                curl_setopt($ch,CURLOPT_POSTFIELDS,$vars);
                $data = curl_exec($ch);
                curl_close($ch);
                if($data){

                        return $data;

                }else{
                        return false;

                }
                   
    }
}