QQ咨询 官方微信

添加微信好友

官方小程序

百度小程序

微信小程序

头条小程序

关于我们

PHP基础

phpcms封装的微信h5支付源码DEMO参考

 admin  2019-08-30 22:48:03
根据phpcms封装的微信H5支付类
  1. class Wxh5pay 
  2. {    
  3.     //接口API URL前缀 
  4.     const API_URL_PREFIX = 'https://api.mch.weixin.qq.com'
  5.     //下单地址URL 
  6.     const UNIFIEDORDER_URL = "/pay/unifiedorder"
  7.     //查询订单URL 
  8.     const ORDERQUERY_URL = "/pay/orderquery"
  9.     //关闭订单URL 
  10.     const CLOSEORDER_URL = "/pay/closeorder"
  11.     protected $mchid; 
  12.     protected $appid; 
  13.     protected $apiKey; 
  14.     public function __construct($mchid, $appid, $key){ 
  15.         $this->mchid = $mchid; 
  16.         $this->appid = $appid; 
  17.         $this->apiKey = $key; 
  18.         $this->trade_type = 'MWEB'
  19.     } 
  20.     /** 
  21.      * 下单方法 
  22.      * @param   $params 下单参数 
  23.      */ 
  24.     public function unifiedOrder($totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp){ 
  25.         $sceneInfo = '{"h5_info": {"type":"Wap","wap_url": '.APP_PATH.',"wap_name": "在线订单"}}'
  26.         $this->body  = $orderName; 
  27.         $this->out_trade_no = $outTradeNo; 
  28.         $this->total_fee = $totalFee; 
  29.         $this->trade_type = $this->trade_type; 
  30.         $this->scene_info = $sceneInfo; 
  31.         $this->notify_url = $notifyUrl; 
  32.          
  33.         $this->nonce_str = $this->genRandomString(); 
  34.         $this->spbill_create_ip = $_SERVER['REMOTE_ADDR']; 
  35.         $this->params['appid'] = $this->appid; 
  36.         $this->params['mch_id'] = $this->mchid; 
  37.         $this->params['nonce_str'] = $this->nonce_str; 
  38.         $this->params['body'] = $this->body; 
  39.         $this->params['out_trade_no'] = $this->out_trade_no; 
  40.         $this->params['total_fee'] = $this->total_fee; 
  41.         $this->params['spbill_create_ip'] = $this->get_client_ip(); 
  42.         $this->params['notify_url'] = $this->notify_url; 
  43.         $this->params['trade_type'] = $this->trade_type; 
  44.         $this->params['scene_info'] = $this->scene_info; 
  45.         //获取签名数据 
  46.         $this->sign = $this->MakeSign($this->params); 
  47.         $this->params['sign'] = $this->sign; 
  48.         $xml = $this->data_to_xml($this->params); 
  49.         $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::UNIFIEDORDER_URL); 
  50.         if( !$response ){ 
  51.             return false
  52.         } 
  53.         $result = $this->xml_to_data( $response ); 
  54.         if( !empty($result['result_code']) && !empty($result['err_code']) ){ 
  55.             $result['err_msg'] = $this->error_code( $result['err_code'] ); 
  56.         } 
  57.         return $result; 
  58.     } 
  59.     /** 
  60.      * 查询订单信息 
  61.      * @param $out_trade_no     订单号 
  62.      * @return array 
  63.      */ 
  64.     public function orderQuery( $out_trade_no ){ 
  65.         $this->params['appid'] = $this->appid; 
  66.         $this->params['mch_id'] = $this->mchid; 
  67.         $this->params['nonce_str'] = $this->genRandomString(); 
  68.         $this->params['out_trade_no'] = $out_trade_no; 
  69.         //获取签名数据 
  70.         $this->sign = $this->MakeSign( $this->params ); 
  71.         $this->params['sign'] = $this->sign; 
  72.         $xml = $this->data_to_xml($this->params); 
  73.         $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::ORDERQUERY_URL); 
  74.         if( !$response ){ 
  75.             return false
  76.         } 
  77.         $result = $this->xml_to_data( $response ); 
  78.         if( !empty($result['result_code']) && !empty($result['err_code']) ){ 
  79.             $result['err_msg'] = $this->error_code( $result['err_code'] ); 
  80.         } 
  81.         return $result; 
  82.     } 
  83.     /** 
  84.      * 关闭订单 
  85.      * @param $out_trade_no     订单号 
  86.      * @return array 
  87.      */ 
  88.     public function closeOrder( $out_trade_no ){ 
  89.         $this->params['appid'] = $this->appid; 
  90.         $this->params['mch_id'] = $this->mchid; 
  91.         $this->params['nonce_str'] = $this->genRandomString(); 
  92.         $this->params['out_trade_no'] = $out_trade_no; 
  93.         //获取签名数据 
  94.         $this->sign = $this->MakeSign( $this->params ); 
  95.         $this->params['sign'] = $this->sign; 
  96.         $xml = $this->data_to_xml($this->params); 
  97.         $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::CLOSEORDER_URL); 
  98.         if( !$response ){ 
  99.             return false
  100.         } 
  101.         $result = $this->xml_to_data( $response ); 
  102.         return $result; 
  103.     } 
  104.     /** 
  105.      *  
  106.      * 获取支付结果通知数据 
  107.      * return array 
  108.      */ 
  109.     public function getNotifyData(){ 
  110.         //获取通知的数据 
  111.         $xml = $GLOBALS['HTTP_RAW_POST_DATA']; 
  112.         //echo 123;die; 
  113.         $data = array(); 
  114.         if( empty($xml) ){ 
  115.             return false
  116.         } 
  117.         $data = $this->xml_to_data( $xml ); 
  118.         if( !empty($data['return_code']) ){ 
  119.             if( $data['return_code'] == 'FAIL' ){ 
  120.                 return false
  121.             } 
  122.         } 
  123.         return $data; 
  124.     } 
  125.     /** 
  126.      * 接收通知成功后应答输出XML数据 
  127.      * @param string $xml 
  128.      */ 
  129.     public function replyNotify(){ 
  130.         $data['return_code'] = 'SUCCESS'
  131.         $data['return_msg'] = 'OK'
  132.         $xml = $this->data_to_xml( $data ); 
  133.         echo $xml; 
  134.         die(); 
  135.     } 
  136.     /** 
  137.      * 生成APP端支付参数 
  138.      * @param  $prepayid   预支付id 
  139.      */ 
  140.     public function getAppPayParams( $prepayid ){ 
  141.         $data['appid'] = $this->appid; 
  142.         $data['partnerid'] = $this->mchid; 
  143.         $data['prepayid'] = $prepayid; 
  144.         $data['package'] = 'Sign=WXPay'
  145.         $data['noncestr'] = $this->genRandomString(); 
  146.         $data['timestamp'] = time(); 
  147.         $data['sign'] = $this->MakeSign( $data );  
  148.         return $data; 
  149.     } 
  150.     /** 
  151.      * 生成签名 
  152.      *  @return 签名 
  153.      */ 
  154.     public function MakeSign( $params ){ 
  155.         //签名步骤一:按字典序排序数组参数 
  156.         ksort($params); 
  157.         $string = $this->ToUrlParams($params); 
  158.         //签名步骤二:在string后加入KEY 
  159.         $string = $string . "&key=".$this->apiKey; 
  160.         //签名步骤三:MD5加密 
  161.         $string = md5($string); 
  162.         //签名步骤四:所有字符转为大写 
  163.         $result = strtoupper($string); 
  164.         return $result; 
  165.     } 
  166.     /** 
  167.      * 将参数拼接为url: key=value&key=value 
  168.      * @param   $params 
  169.      * @return  string 
  170.      */ 
  171.     public function ToUrlParams( $params ){ 
  172.         $string = ''
  173.         if( !empty($params) ){ 
  174.             $array = array(); 
  175.             foreach( $params as $key => $value ){ 
  176.                 $array[] = $key.'='.$value; 
  177.             } 
  178.             $string = implode("&",$array); 
  179.         } 
  180.         return $string; 
  181.     } 
  182.     /** 
  183.      * 输出xml字符 
  184.      * @param   $params     参数名称 
  185.      * return   string      返回组装的xml 
  186.      **/ 
  187.     public function data_to_xml( $params ){ 
  188.         if(!is_array($params)|| count($params) <= 0) 
  189.         { 
  190.             return false
  191.         } 
  192.         $xml = "<xml>"
  193.         foreach ($params as $key=>$val) 
  194.         { 
  195.             if (is_numeric($val)){ 
  196.                 $xml.="<".$key.">".$val."</".$key.">"
  197.             }else
  198.                 $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"
  199.             } 
  200.         } 
  201.         $xml.="</xml>"
  202.         return $xml;  
  203.     } 
  204.     /** 
  205.      * 将xml转为array 
  206.      * @param string $xml 
  207.      * return array 
  208.      */ 
  209.     public function xml_to_data($xml){   
  210.         if(!$xml){ 
  211.             return false
  212.         } 
  213.         //将XML转为array 
  214.         //禁止引用外部xml实体 
  215.         libxml_disable_entity_loader(true); 
  216.         $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);         
  217.         return $data; 
  218.     } 
  219.     /** 
  220.      * 获取毫秒级别的时间戳 
  221.      */ 
  222.     private static function getMillisecond(){ 
  223.         //获取毫秒的时间戳 
  224.         $time = explode ( " ", microtime () ); 
  225.         $time = $time[1] . ($time[0] * 1000); 
  226.         $time2 = explode( ".", $time ); 
  227.         $time = $time2[0]; 
  228.         return $time; 
  229.     } 
  230.     /** 
  231.      * 产生一个指定长度的随机字符串,并返回给用户  
  232.      * @param type $len 产生字符串的长度 
  233.      * @return string 随机字符串 
  234.      */ 
  235.     private function genRandomString($len = 32) { 
  236.         $chars = array( 
  237.             "a""b""c""d""e""f""g""h""i""j""k"
  238.             "l""m""n""o""p""q""r""s""t""u""v"
  239.             "w""x""y""z""A""B""C""D""E""F""G"
  240.             "H""I""J""K""L""M""N""O""P""Q""R"
  241.             "S""T""U""V""W""X""Y""Z""0""1""2"
  242.             "3""4""5""6""7""8""9" 
  243.         ); 
  244.         $charsLen = count($chars) - 1; 
  245.         // 将数组打乱  
  246.         shuffle($chars); 
  247.         $output = ""
  248.         for ($i = 0; $i < $len; $i++) { 
  249.             $output .= $chars[mt_rand(0, $charsLen)]; 
  250.         } 
  251.         return $output; 
  252.     } 
  253.     /** 
  254.      * 以post方式提交xml到对应的接口url 
  255.      *  
  256.      * @param string $xml  需要post的xml数据 
  257.      * @param string $url  url 
  258.      * @param bool $useCert 是否需要证书,默认不需要 
  259.      * @param int $second   url执行超时时间,默认30s 
  260.      * @throws WxPayException 
  261.      */ 
  262.     private function postXmlCurl($xml, $url, $useCert = false, $second = 30){        
  263.         $ch = curl_init(); 
  264.         //设置超时 
  265.         curl_setopt($ch, CURLOPT_TIMEOUT, $second); 
  266.         curl_setopt($ch,CURLOPT_URL, $url); 
  267.         curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); 
  268.         curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2); 
  269.         //设置header 
  270.         curl_setopt($ch, CURLOPT_HEADER, FALSE); 
  271.         //要求结果为字符串且输出到屏幕上 
  272.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
  273.         if($useCert == true){ 
  274.             //设置证书 
  275.             //使用证书:cert 与 key 分别属于两个.pem文件 
  276.             curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); 
  277.             //curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH); 
  278.             curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); 
  279.             //curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH); 
  280.         } 
  281.         //post提交方式 
  282.         curl_setopt($ch, CURLOPT_POST, TRUE); 
  283.         curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 
  284.         //运行curl 
  285.         $data = curl_exec($ch); 
  286.         //返回结果 
  287.         if($data){ 
  288.             curl_close($ch); 
  289.             return $data; 
  290.         } else {  
  291.             $error = curl_errno($ch); 
  292.             curl_close($ch); 
  293.             return false
  294.         } 
  295.     } 
  296.     function get_client_ip() { 
  297.         static $realip; 
  298.         if (isset($_SERVER)) { 
  299.             if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) { 
  300.                 $realip = $_SERVER["HTTP_X_FORWARDED_FOR"]; 
  301.             } else if (isset($_SERVER["HTTP_CLIENT_IP"])) { 
  302.                 $realip = $_SERVER["HTTP_CLIENT_IP"]; 
  303.             } else { 
  304.                 $realip = $_SERVER["REMOTE_ADDR"]; 
  305.             } 
  306.         } else { 
  307.             if (getenv("HTTP_X_FORWARDED_FOR")) { 
  308.                 $realip = getenv("HTTP_X_FORWARDED_FOR"); 
  309.             } else if (getenv("HTTP_CLIENT_IP")) { 
  310.                 $realip = getenv("HTTP_CLIENT_IP"); 
  311.             } else { 
  312.                 $realip = getenv("REMOTE_ADDR"); 
  313.             } 
  314.         } 
  315.         return $realip; 
  316.     } 
  317.     /** 
  318.      * 错误代码 
  319.      * @param  $code       服务器输出的错误代码 
  320.      * return string 
  321.      */ 
  322.     public function error_code( $code ){ 
  323.         $errList = array( 
  324.         'NOAUTH'                =>  '商户未开通此接口权限'
  325.         'NOTENOUGH'             =>  '用户帐号余额不足'
  326.         'ORDERNOTEXIST'         =>  '订单号不存在'
  327.         'ORDERPAID'             =>  '商户订单已支付,无需重复操作'
  328.         'ORDERCLOSED'           =>  '当前订单已关闭,无法支付'
  329.         'SYSTEMERROR'           =>  '系统错误!系统超时'
  330.         'APPID_NOT_EXIST'       =>  '参数中缺少APPID'
  331.         'MCHID_NOT_EXIST'       =>  '参数中缺少MCHID'
  332.         'APPID_MCHID_NOT_MATCH' =>  'appid和mch_id不匹配'
  333.         'LACK_PARAMS'           =>  '缺少必要的请求参数'
  334.         'OUT_TRADE_NO_USED'     =>  '同一笔交易不能多次提交'
  335.         'SIGNERROR'             =>  '参数签名结果不正确'
  336.         'XML_FORMAT_ERROR'      =>  'XML格式错误'
  337.         'REQUIRE_POST_METHOD'   =>  '未使用post传递参数 '
  338.         'POST_DATA_EMPTY'       =>  'post数据不能为空'
  339.         'NOT_UTF8'              =>  '未使用指定编码格式'
  340.         );  
  341.         if( array_key_exists( $code , $errList ) ){ 
  342.         return $errList[$code]; 
  343.         } 
  344.     } 
调用方法:

  1. $outTradeNo = $trade_sn;     //你自己的商品订单号 
  2. $payAmount  = $allmoney*100;          //付款金额,单位:分 
  3. $orderName  = $trade_sn;    //订单标题 
  4. $notifyUrl  = APP_PATH.'wx/h5notify.php';     //付款成功后的回调地址(不要有问号) 
  5. $payTime    = time();      //付款时间 
  6. pc_base::load_app_class('Wxh5pay','pay',0); 
  7. $wxh5Pay = new Wxh5pay($mchid,$appid,$apiKey); 
  8. $result = $wxh5Pay->unifiedOrder($payAmount,$outTradeNo,$orderName,$notifyUrl,$payTime); 
  9. $redirect_url = urlencode(APP_PATH.'wx/wxh5notify.php?trade_sn='.$trade_sn); 
  10. $wxh5url = $result['mweb_url'].'&redirect_url='.$redirect_url;//redirect_url 是支付完成后返回的页面 
前端调用
  1. <a href="{$wxh5url}"><button class="wx-btn">手机微信支付</button></a>  

¥ 打赏
×
如果您觉得文章帮助了您就打赏一下吧
非常感谢你的打赏,我们将继续分享更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

本文《phpcms封装的微信h5支付源码DEMO参考》发布于石头博客文章,作者:admin,如若转载,请注明出处:https://www.pweb123.com/html/php/782.html,否则禁止转载,谢谢配合!

文章点评

我来说两句 已有0条评论
点击图片更换

添加微信好友

添加微信好友

微信小程序

百度小程序