微信扫码支付精简版

其实这个文档仅仅作为参考,如果应用到线上请完成签名验证

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();

猜你喜欢

转载自www.cnblogs.com/ailingfei/p/10118690.html