1. 程式人生 > >微信掃碼支付精簡版

微信掃碼支付精簡版

其實這個文件僅僅作為參考,如果應用到線上請完成簽名驗證

1.因為微信支付sdk非常全全面,而我值需要掃碼支付即可,所以就把主要的程式碼提出來了

<?php

class WxApi {
    private $config = array();
    private $unifiedorder_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    private $sign = NULL ;
    
    public function __construct($config = array()){
        
$this -> config = $config ; } /** * @desc 統一下單介面 * * */ public function unifiedOrder($input = array()){ $return = array(); //檢查必填引數 if(!$input['out_trade_no']){ $return['code_status'] = 1 ; $return['code_messate'] = '缺少統一支付介面必填引數out_trade_no!' ; }
else if(!$input['body']){ $return['code_status'] = 2 ; $return['code_messate'] = '缺少統一支付介面必填引數body!' ; }else if(!$input['total_fee']){ $return['code_status'] = 3 ; $return['code_messate'] = '缺少統一支付介面必填引數total_fee!' ; }else if(!$input['trade_type']){
$return['code_status'] = 4 ; $return['code_messate'] = '缺少統一支付介面必填引數trade_type!' ; } if($input['trade_type'] == 'JSAPI' && !$input['openid']){ $return['code_status'] = 5 ; $return['code_messate'] = '統一支付介面中,缺少必填引數openid!trade_type為JSAPI時,openid為必填引數!' ; } if($input['trade_type'] == 'NATIVE' && !$input['product_id']){ $return['code_status'] = 5 ; $return['code_messate'] = 'trade_type=NATIVE時,此引數必傳。此引數為二維碼中包含的商品ID,商戶自行定義。' ; } if(!$input['notify_url'] && $this -> config['notify_url'] != '' ){ $input['notify_url'] = $this -> config['notify_url']; } //當缺少必要引數時需要返回資料重新配置必須的引數 if(!empty($return)){ return $return ; } $input['appid'] = $this -> config['appid']; $input['mch_id'] = $this -> config['mch_id']; $input['spbill_create_ip'] = $this -> config['ip']; $input['nonce_str'] = $this -> getNonceStr(); //簽名 $sign = $this -> setMySign($input); //var_dump($sign);die; $input['sign'] = $sign ; $xml = $this -> arrayToXml($input); //開始請求訂單 $response = $this -> postXmlCurl($this -> config,$xml,$this -> unifiedorder_url,false,6); $result = $this -> xmlToArray($response); //這裡需要驗證一下簽名,暫時先不驗證 方便測試 //self::reportCostTime($config, $url, $startTimeStamp, $result);//上報請求花費時間 return $result; } private function setMySign($params,$signType = TRUE){ //簽名步驟一:按字典序排序引數並拼接字串 ksort($params); //var_dump($params); $string = ""; foreach ($params as $k => $v){ if($k != "sign" && $v != "" && !is_array($v)){ $string .= $k . "=" . $v . "&"; } } $string = trim($string, "&"); //echo $string ; //簽名步驟二:在string後加入KEY $string = $string . "&key=" . $this -> config['key']; //簽名步驟三:MD5加密或者HMAC-SHA256 if($this -> config['sign_type'] == "MD5"){ $string = md5($string); } else if($this -> config['sign_type'] == "HMAC-SHA256") { $string = hash_hmac("sha256",$string ,$this -> config['key']); } //簽名步驟四:所有字元轉為大寫 $result = strtoupper($string); $this -> sign = $result ; return $result; } /** * * 產生隨機字串,不長於32位 * @param int $length * @return 產生的隨機字串 */ 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; } /** * 輸出xml字元 * @throws WxPayException **/ private function arrayToXml($array = array()) { if(!is_array($array) || count($array) <= 0) { throw new WxPayException("陣列資料異常!"); } $xml = "<xml>"; foreach ($array as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } /** * 將xml轉為array * @param string $xml * @throws WxPayException */ private function xmlToArray($xml) { if(!$xml){ throw new WxPayException("xml資料異常!"); } //將XML轉為array //禁止引用外部xml實體 libxml_disable_entity_loader(true); $array = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $array; } /** * 以post方式提交xml到對應的介面url * * @param WxPayConfigInterface $config 配置物件 * @param string $xml 需要post的xml資料 * @param string $url url * @param bool $useCert 是否需要證書,預設不需要 * @param int $second url執行超時時間,預設30s * @throws WxPayException */ private static function postXmlCurl($config, $xml, $url, $useCert = false, $second = 30) { $ch = curl_init(); $curlVersion = curl_version(); $ua = "WXPaySDK/3.0.9 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']." " . $config['mch_id']; //設定超時 curl_setopt($ch, CURLOPT_TIMEOUT, $second); $proxyHost = "0.0.0.0"; $proxyPort = 0; //$config->GetProxy($proxyHost, $proxyPort); //如果有配置代理這裡就設定代理 if($proxyHost != "0.0.0.0" && $proxyPort != 0){ curl_setopt($ch,CURLOPT_PROXY, $proxyHost); curl_setopt($ch,CURLOPT_PROXYPORT, $proxyPort); } 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);//嚴格校驗 } curl_setopt($ch,CURLOPT_USERAGENT, $ua); //設定header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求結果為字串且輸出到螢幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if($useCert == true){ //設定證書 //使用證書:cert 與 key 分別屬於兩個.pem檔案 //證書檔案請放入伺服器的非web目錄下 $sslCertPath = $config['sslcert_path']; $sslKeyPath = $config['sslkey_path']; $config->GetSSLCertPath($sslCertPath, $sslKeyPath); curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath); curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLKEY, $sslKeyPath); } //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); curl_close($ch); die("curl出錯,錯誤碼:$error"); } } }

2.使用方法:

require EXTEND_PATH . 'sdk.php';
class pay{
    $payConfig = array(
        'appid' => 'wx5f9d09f208cfa',
        'mch_id' => '124002',
        'key' => '8b15d56f894fab8035ac241cb39',
        'app_secret' => '2e3fd5b24241646917265ee',
        'sslcert_path' => '',
        'sslkey_path' => '',
        'ip' => '',
        'sign_type' => 'MD5',
    );
    /**
     * @desc 初始化方法
     */
    public function __construct(){
        
        $this -> weixinConfig['sslcert_path'] = EXTEND_PATH . '/weixinpaysdk-3.0.9/cert/apiclient_cert.pem';
        $this -> weixinConfig['sslkey_path'] = EXTEND_PATH . '/weixinpaysdk-3.0.9/cert/apiclient_key.pem';
        $request = Request::instance();
        $this -> weixinConfig['ip'] = $request -> ip(0,true);
    }  

    /**
     * @desc 微信訂單
     * @author [email protected]
     * @version 1.0
     * @date 2018-12-14
     */
    public function getWeixinOrder(){
        
        $wxpayObj = new \WxApi($this -> weixinConfig);
        $time = time();
        $input = array(
            'body' => '測試內容',
            'attach' => '鴨題鴨課程PC版本',
            'out_trade_no' => '1234567891',
            'total_fee' => '1',
            'time_start' => date("YmdHis",$time),
            'time_expire' => date("YmdHis", $time + 600),
            'notify_url' => 'http://paysdk.weixin.qq.com/notify.php',
            'trade_type' => 'NATIVE',
            'product_id' => '1000000003',
        );
        
        $result = $wxpayObj -> unifiedOrder($input);
        $QRcode = new \QRcode();
        $level = 'L';
        $size =4;
        ob_start();
        $QRcode->png($result['code_url'],false,$level,$size,2);
        $imageString ="data:image/jpg;base64," . base64_encode(ob_get_contents());
        ob_end_clean();
        echo "<img src='$imageString' />";
    }

}


$obj = new pay();
$obj -> getWeixinOrder();