ailingfei

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

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 646943067@qq.com
     * @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();

 

分类:

技术点:

相关文章: