当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP微信H5支付开发实例

发布:smiling 来源: PHP粉丝网  添加日期:2021-10-19 19:39:47 浏览: 评论:0 

最近由于业务所需,对接了微信H5支付,然而微信支付对这块并没有现成的demo可用,所以就必须自己老老实实对照开发文档去写咯!但这对于刚接触的童鞋来说,坑多多少少还是有的,所以寻思着把自己的经验分享出来,毕竟现成的用的还是多巴适的嘛!

好了,官方文档的那一套就不多说了,详情见官方文档。

在这里,我主要分成了三个文件:WxPay.Config.php(支付配置文件)、Weixin.class.php(支付类)以及PayMentController.class.php(支付文件)。

首先,WxPay.Config.php配置文件主要包含了商户appId、商户号、商家key、异步回调URL、支付场景信息,如下:

  1. class WxPayConfig 
  2.   public static $appid = '微信支付的公众号appid'
  3.   public static $mchid = '微信支付分配的商户号'
  4.   public static $key = '微信商户自己设置的安全key'
  5.   public static $notify_url = '商户侧接收微信支付异步通知的URL'
  6.   public static $scene_info = '{"h5_info":{"type":"Wap","wap_url":" 发起微信H5支付H5的URL","wap_name":"支付"}}';  

然后,封装Weixin.class.php支付类,主要调用统一下单Api,这里不多说了,直接上代码:

  1. <?php 
  2. require_once "lib/WxPay.Config.php"
  3. class Weixin 
  4.      /** 
  5.    * 微信H5下单付款 
  6.    *   @order 付款信息 
  7.      *   @bodys 付款内容 
  8.    * */ 
  9.      function getCode($order,$bodys){ 
  10.           $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信传参地址 
  11.           //1.获取调用统一下单接口所需必备参数 
  12.     $appid =WxPayConfig::$appid;//微信公众号appid 
  13.     $mch_id = WxPayConfig::$mchid;//微信支付商户号 
  14.     $key = WxPayConfig::$key;//自己设置的微信商家key 
  15.     $out_trade_no = $order['order_sn'];//平台内部订单号 
  16.     $nonce_str=MD5($out_trade_no);//随机字符串 
  17.     $body = $bodys;//付款内容 
  18.     $total_fee = $order['order_amount']*100;//付款金额,单位为分 
  19.     $spbill_create_ip = getIP(); //获得用户设备IP 
  20.     $attach = 'weixinh5';//附加数据(自定义,在支付通知中原样返回) 
  21.     $notify_url = WxPayConfig::$notify_url//异步回调地址,需外网可以直接访问 
  22.     $trade_type = 'MWEB';//交易类型,微信H5支付时固定为MWEB 
  23.     $scene_info =WxPayConfig::$scene_info;//场景信息 
  24.           //2.将参数按照key=value的格式,并按照参数名ASCII字典序排序生成字符串 
  25.     $signA ="appid=$appid&attach=$attach&body=$body&mch_id=$mch_id&nonce_str=$nonce_str&notify_url=$notify_url&out_trade_no=$out_trade_no&scene_info=$scene_info&spbill_create_ip=$spbill_create_ip&total_fee=$total_fee&trade_type=$trade_type"
  26.     //3.拼接字符串 
  27.           $strSignTmp = $signA."&key=$key"
  28.           //4.MD5加密后转换成大写 
  29.     $sign = strtoupper(MD5($strSignTmp)); 
  30.           //5.拼接成所需XML格式 
  31.     $post_data = "<xml>  
  32.             <appid>$appid</appid>  
  33.             <attach>$attach</attach>  
  34.             <body>$body</body>  
  35.             <mch_id>$mch_id</mch_id>  
  36.             <nonce_str>$nonce_str</nonce_str>  
  37.             <notify_url>$notify_url</notify_url>  
  38.             <out_trade_no>$out_trade_no</out_trade_no>  
  39.             <spbill_create_ip>$spbill_create_ip</spbill_create_ip>  
  40.             <total_fee>$total_fee</total_fee>  
  41.             <trade_type>$trade_type</trade_type> 
  42.             <scene_info>$scene_info</scene_info> 
  43.             <sign>$sign</sign>  
  44.           </xml>"; 
  45.           //6.以POST方式向微信传参,并取得微信返回的支付参数 
  46.     $dataxml = httpRequest($url,'POST',$post_data); 
  47.     $objectxml = (array)simplexml_load_string($dataxml'SimpleXMLElement', LIBXML_NOCDATA); //将微信返回的XML转换成数组 
  48.     return $objectxml
  49.   } 

最后,PayMentController.class.php支付文件,支付文件接收前端发起支付的请求并处理后,调用Weixin.class.php支付类并接受结果后返回给前端(此处分享已经去掉接口验证等系列代码逻辑):

  1. public function getPay(){ 
  2.      //1.引入支付类文件 
  3.      include_once "plugins/Payment/weixin/Weixin.class.php"
  4.      $payment = new \Weixin(); 
  5.      $order_id = I('order_id'); 
  6.      //2.判断参数是否为空 
  7.      if (!emptyempty($order_id)){ 
  8.           //3.根据订单id查询订单是否存在 
  9.           $order = M('Order')->where(array('id'=>$order_id))->find(); 
  10.           if ($order){//订单存在 
  11.               //4.判断该笔订单是否已经支付,如已支付则返回支付失败并给出相应提示 
  12.               if ($order['pay_status'] == '1'){ 
  13.                    exit(json_encode(array('status'=>'205','msg'=>'该订单已支付,请勿重复提交!'))); 
  14.               } 
  15.               $bodys = '订单:'.$order['order_sn'] . '支付'
  16.               //5.调用支付类中封装的支付方法并对应传参 
  17.               $result = $payment->getCode($order,$bodys); 
  18.               //6.当return_code和result_code均为SUCCESS,代表下单成功,将支付参数返回 
  19.               if($result['return_code'] == 'SUCCESS'){ 
  20.                    if($result['result_code'] == 'SUCCESS'){ 
  21.                         exit(json_encode(array('status'=>'0','msg'=>'下单成功,请支付!','result'=>$result['mweb_url']))); 
  22.                    }elseif($result['result_code'] == 'FAIL'){ 
  23.                         exit(json_encode(array('status'=>'-201','msg'=>$result['err_code_des']))); 
  24.                    } 
  25.               }else
  26.         exit(json_encode(array('status'=>'-1','msg'=>'未知错误,请稍后重试!'))); 
  27.                   } 
  28.           }else
  29.               //报错:数据不存在 
  30.               exit(json_encode(array('status'=>'-200','msg'=>'订单不存在,请核实后再提交!'))); 
  31.           } 
  32.      }else
  33.           //报错:缺少参数 
  34.           exit(json_encode(array('status'=>'-204','msg'=>'参数缺失,请核实!'))); 
  35.      } 

前端在接收到支付URL后执行即可唤醒微信支付。

附一:获取用户终端设备ip方法

  1. function getIP(){       
  2.     if (getenv("HTTP_CLIENT_IP")) 
  3.        $ip = getenv("HTTP_CLIENT_IP"); 
  4.     else if(getenv("HTTP_X_FORWARDED_FOR")) 
  5.         $ip = getenv("HTTP_X_FORWARDED_FOR"); 
  6.     else if(getenv("REMOTE_ADDR")) 
  7.        $ip = getenv("REMOTE_ADDR"); 
  8.     else $ip = "Unknow"
  9.     return $ip

######附二:CURL请求方法

  1. /** 
  2.    * CURL请求 
  3.    * @param $url 请求url地址 
  4.    * @param $method 请求方法 get post 
  5.    * @param null $postfields post数据数组 
  6.    * @param array $headers 请求header信息 
  7.    * @param bool|false $debug 调试开启 默认false 
  8.    * @return mixed 
  9.    */ 
  10.   function httpRequest($url$method$postfields = null, $headers = array(), $debug = false) { 
  11.     $method = strtoupper($method); 
  12.     $ci = curl_init(); 
  13.     /* Curl settings */ 
  14.     curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 
  15.     curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"); 
  16.     curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */ 
  17.     curl_setopt($ci, CURLOPT_TIMEOUT, 7); /* 设置cURL允许执行的最长秒数 */ 
  18.     curl_setopt($ci, CURLOPT_RETURNTRANSFER, true); 
  19.     switch ($method) { 
  20.       case "POST"
  21.         curl_setopt($ci, CURLOPT_POST, true); 
  22.         if (!emptyempty($postfields)) { 
  23.           $tmpdatastr = is_array($postfields) ? http_build_query($postfields) : $postfields
  24.           curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr); 
  25.         } 
  26.         break
  27.       default
  28.         curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */ 
  29.         break
  30.     } 
  31.     $ssl = preg_match('/^https:\/\//i',$url) ? TRUE : FALSE; 
  32.     curl_setopt($ci, CURLOPT_URL, $url); 
  33.     if($ssl){ 
  34.       curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts 
  35.       curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在 
  36.     } 
  37.     curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1); 
  38.     curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的*/ 
  39.     curl_setopt($ci, CURLOPT_HTTPHEADER, $headers); 
  40.     curl_setopt($ci, CURLINFO_HEADER_OUT, true); 
  41.     $response = curl_exec($ci); 
  42.     $requestinfo = curl_getinfo($ci); 
  43.     if ($debug) { 
  44.       echo "=====post data======\r\n"
  45.       var_dump($postfields); 
  46.       echo "=====info===== \r\n"
  47.       print_r($requestinfo); 
  48.       echo "=====response=====\r\n"
  49.       print_r($response); 
  50.     } 
  51.     curl_close($ci); 
  52.     return $response

好了,一点点菜鸟心得,有不当之处欢迎留言指证交流,一起成长!

Tags: PHP微信支付开发

分享到: