有关微信公众号和H5支付的一些记录

Posted cuculus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有关微信公众号和H5支付的一些记录相关的知识,希望对你有一定的参考价值。

最近项目里面需要做公众号和H5支付的功能,根据自己的体验,整理了一下,做个记录。

首先我解释一下,为什么有公众号支付还要做H5支付?因为不确定每个用户在公众号上打开网站,所以另外做了H5支付。

以下是官方的解释:

H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。

主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。

提醒:H5支付不建议在APP端使用,如需要在APP中使用微信支付,请接APP支付,文档详见微信支付开发文档

既然是公众号支付,准备工作要做好(下载的SDK是V3版本):

  必须是认证的服务号才能支付,详细接口权限见官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433401084。

  1.登陆公众号:

  

  2.

  

  3.登陆商户平台(pay.weixin.qq.com)

    在开发配中设置如下:

    H5支付直接填写服务器的域名即可。

    JSAPI授权目录这里需要注意,如果支付授权目录没有设置正确,在请求JSAPI时,会提示“-1当前页面的url未注册”的错误。” 

      首先要看你支付的当前页面URL,

      比如是:http://www.xxx.com/wxpay/jsapi.php

        你就必须填写:http://www.xxx.com/wxpay/

      假如是:http://www.xxx.com/wxpay/order/id/56.html

        你就必须写: http://www.xxx.com/wxpay/order/id/    

      假如是:http://www.xxx.com/wxpay/order?id=56

        你就必须写:http://www.xxx.com/wxpay/order/       

  

下面是代码部分(没有自己封装代码,直接用官方的示例代码进行修改)

  下载好官方的sdk,我是放到网站的根目录,看网上有把SDK进行集成封装好的,大家可自行搜索。

  1.在lib----->下的Wxpay.Config.php文件中,填好APPID、MCHID、KEY(操作密码)、APPSECRET(公众帐号secert)

  设置证书

  

  在配置文件的最后最好加上回调地址(当时我没有设置报错了,想不起来是什么错误了,没及时记录……)

    

  2.写一个验证token的方法(代码是网上找的,顺便找了一下有关token的登陆介绍:http://blog.csdn.net/resilient/article/details/72673222)

 1 <?php
 2     /**
 3      * wechat php test
 4      */
 5     //define your token
 6     define("TOKEN", "shendai");
 7     $wechatObj = new wechatCallbackapiTest();
 8     $wechatObj->valid();
 9 
10     class wechatCallbackapiTest
11     {
12         public function valid()
13         {
14             $echoStr = $_GET["echostr"];
15             //valid signature , option
16             if ($this->checkSignature())
17             {
18                 echo $echoStr;
19                 exit;
20             }
21         }
22         public function responseMsg()
23         {
24             //get post data, May be due to the different environments
25             $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
26             //extract post data
27             if (!empty($postStr))
28             {
29                 $postObj = simplexml_load_string($postStr, \'SimpleXMLElement\', LIBXML_NOCDATA);
30                 $fromUsername = $postObj->FromUserName;
31                 $toUsername = $postObj->ToUserName;
32                 $keyword = trim($postObj->Content);
33                 $time = time();
34                 $textTpl = "<xml>
35                             <ToUserName><![CDATA[%s]]></ToUserName>
36                             <FromUserName><![CDATA[%s]]></FromUserName>
37                             <CreateTime>%s</CreateTime>
38                             <MsgType><![CDATA[%s]]></MsgType>
39                             <Content><![CDATA[%s]]></Content>
40                             <FuncFlag>0</FuncFlag>
41                             </xml>";
42                 if (!empty($keyword))
43                 {
44                     $msgType = "text";
45                     $contentStr = "Welcome to wechat world!";
46                     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
47                     echo $resultStr;
48                 }
49                 else
50                 {
51                     echo "Input something...";
52                 }
53             }
54             else
55             {
56                 echo "";
57                 exit;
58             }
59         }
60         private function checkSignature()
61         {
62             $signature = $_GET["signature"];
63             $timestamp = $_GET["timestamp"];
64             $nonce = $_GET["nonce"];
65             $token = TOKEN;
66             $tmpArr = array($token, $timestamp, $nonce);
67             sort($tmpArr);
68             $tmpStr = implode($tmpArr);
69             $tmpStr = sha1($tmpStr);
70             if ($tmpStr == $signature)
71             {
72                 return true;
73             }
74             else
75             {
76                 return false;
77             }
78         }
79 
80 
81     }
82 
83 ?>
View Code

  3.公众号支付文件jsapi.php,只用示例代码进行了修改

  1 <?php
  2     ini_set(\'date.timezone\',\'Asia/Shanghai\');
  3     //error_reporting(E_ERROR);
  4     require_once "$wx_root/lib/WxPay.Api.php";
  5     require_once "WxPay.JsApiPay.php";
  6     require_once \'log.php\';
  7 
  8     //初始化日志
  9     $logHandler= new CLogFileHandler("$wx_root/logs/".date(\'Y-m-d\').\'.log\');
 10     $log = Log::Init($logHandler, 15);
 11 
 12     //打印输出数组信息
 13     function printf_info($data)
 14     {
 15         foreach($data as $key=>$value){
 16             echo "<font color=\'#00ff55;\'>$key</font> : $value <br/>";
 17         }
 18     }
 19 
 20     //①、获取用户openid
 21     $tools = new JsApiPay();
 22     $openId = $tools->GetOpenid();
 23 
 24     //②、统一下单
 25     $input = new WxPayUnifiedOrder();
 26     $input->SetBody("xxx充值");
 27     $input->SetAttach("xxx");
 28     $input->SetOut_trade_no($orderNo); //订单号
 29     $input->SetTotal_fee($trade[\'fee\']); //充值的金额
 30     $input->SetTime_start(date("YmdHis"));
 31     $input->SetTime_expire(date("YmdHis", time() + 600));
 32     $input->SetGoods_tag("xxx充值");
 33     $input->SetNotify_url("http://xxx.xxx.com/xxx/notify");//支付成功的回调地址
 34     $input->SetTrade_type("JSAPI"); //支付类型
 35     $input->SetOpenid($openId);
 36     $order = WxPayApi::unifiedOrder($input);
 37 //    echo \'<font color="#f00"><b>xxx支付页面</b></font><br/>\';
 38 //    printf_info($order);
 39     $jsApiParameters = $tools->GetJsApiParameters($order);
 40 
 41     //获取共享收货地址js函数参数
 42     $editAddress = $tools->GetEditAddressParameters();
 43 
 44     //③、在支持成功回调通知中处理成功之后的事宜,见 notify.php
 45     /**
 46      * 注意:
 47      * 1、当你的回调地址不可访问的时候,回调通知会失败,可以通过查询订单来确认支付是否成功
 48      * 2、jsapi支付时需要填入用户openid,WxPay.JsApiPay.php中有获取openid流程 (文档可以参考微信公众平台“网页授权接口”,
 49      * 参考http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html)
 50      */
 51 ?>
 52 
 53 <html>
 54 <head>
 55     <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
 56     <meta name="viewport" content="width=device-width, initial-scale=1"/>
 57     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 58     <title>xxx-支付</title>
 59     <style>
 60         html, body {
 61             margin: 0;
 62             width: 100%;
 63             height: 100%;
 64         }
 65         .modal {
 66             position: relative;
 67             width: 100%;
 68             height: 100%;
 69             background-color: rgba(0, 0, 0, .6);
 70         }
 71         .dialog {
 72             position: absolute;
 73             top: 50%;
 74             left: 50%;
 75             width: 210px;
 76             transform: translate(-50%, -50%);
 77             background-color: #fff;
 78             border-radius: 4px;
 79         }
 80         .dialog .head {
 81             height: 36px;
 82             line-height: 36px;
 83             border-bottom: 1px solid #1aad19;
 84             text-align: center;
 85             font-size: 14px;
 86         }
 87 
 88         .dialog .paymoney {
 89             padding: 14px;
 90 
 91         }
 92         .dialog .paymoney span {
 93             display: block;
 94             font-size: 14px;
 95             text-align: center;
 96         }
 97         .dialog .paymoney b {
 98             display: block;
 99             font-size: 28px;
100             text-align: center;
101         }
102         .dialog .paymoney a {
103             background: #1aad19;
104             padding: 8px 0;
105             margin-top:5px;
106             display: block;
107             border-radius: 4px;
108             text-decoration: none;
109             text-align: center;
110             font-size: 18px;
111             color: #fff;
112         }
113         .dialog .btn-pay {
114 
115         }
116     </style>
117     <script type="text/javascript">
118         //调用微信JS api 支付
119         function jsApiCall()
120         {
121             WeixinJSBridge.invoke(
122                 \'getBrandWCPayRequest\',
123                 <?php echo $jsApiParameters; ?>,
124                 function(res){
125                     if(res.err_msg == \'get_brand_wcpay_request:ok\')
126                     {
127                         window.location.href = \'支付成功后跳转地址\';
128                     }
129                 }
130             );
131         }
132 
133         function callpay()
134         {
135             if (typeof WeixinJSBridge == "undefined"){
136                 if( document.addEventListener ){
137                     document.addEventListener(\'WeixinJSBridgeReady\', jsApiCall, false);
138                 }else if (document.attachEvent){
139                     document.attachEvent(\'WeixinJSBridgeReady\', jsApiCall);
140                     document.attachEvent(\'onWeixinJSBridgeReady\', jsApiCall);
141                 }
142             }else{
143                 jsApiCall();
144             }
145         }
146     </script>
147     <script type="text/javascript">
148         //获取共享地址
149         //    function editAddress()
150         //    {
151         //        WeixinJSBridge.invoke(
152         //            \'editAddress\',
153         //            <?php //echo $editAddress; ?>//,
154         //            function(res){
155         //                var value1 = res.proviceFirstStageName;
156         //                var value2 = res.addressCitySecondStageName;
157         //                var value3 = res.addressCountiesThirdStageName;
158         //                var value4 = res.addressDetailInfo;
159         //                var tel = res.telNumber;
160         //
161         //                alert(value1 + value2 + value3 + value4 + ":" + tel);
162         //            }
163         //        );
164         //    }
165         //
166         //    window.onload = function(){
167         //        if (typeof WeixinJSBridge == "undefined"){
168         //            if( document.addEventListener ){
169         //                document.addEventListener(\'WeixinJSBridgeReady\', editAddress, false);
170         //            }else if (document.attachEvent){
171         //                document.attachEvent(\'WeixinJSBridgeReady\', editAddress);
172         //                document.attachEvent(\'onWeixinJSBridgeReady\', editAddress);
173         //            }
174         //        }else{
175         //            editAddress();
176         //        }
177         //    };
178 
179     </script>
180 </head>
181 <body>
182 <div class="modal">
183     <div class="dialog">
184         <div class="head">
185             支付
186         </div>
187         <div class="paymoney">
188             <span>xxx有限公司</span>
189             <b>¥<?php echo $trade[\'fee\']; ?></b>
190 
191             <a type="button" onclick="callpay()" >立即支付</a>
192         </div>
193 
194     </div>
195 </div>
196  <br/>
197 </body>
198 </html>
View Code

  4.在notify.php文件中写成功支付后的业务代码

 1 //重写回调处理函数
 2 public function NotifyProcess($data, &$msg)
 3 {
 4     Log::DEBUG("call back:" . json_encode($data));
 5     $notfiyOutput = array();
 6         
 7     if(!array_key_exists("transaction_id", $data)){
 8         $msg = "输入参数不正确";
 9         return false;
10     }
11     //查询订单,判断订单真实性
12     if(!$this->Queryorder($data["transaction_id"])){
13         $msg = "订单查询失败";
14         return false;
15     }
16 
17     $out_trade_no = $data["out_trade_no"]; //订单号
18 
19     //判断该笔订单是否在商户网站中已经做过处理
20     $trade = db(\'订单表\')->where(\'orderNo\',$out_trade_no)->find();
21     //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
22     if ($data[\'mch_id\'] == \'商户号\' && $data[\'total_fee\'] == $trade[\'fee\'])
23     {
24         db(\'订单表\')->where(\'id\',$trade[\'id\'])->update([\'feeStatus\'=>1]);
25 
26     }
27     else
28     {
29        return false;
30     }
31 
32     return true;
33 }        
View Code

  5.编写支付接口回调接口(有重复代码,懒得去改了)

 1  /*微信客户端支付*/
 2     public function pay()
 3     {
 4         if(input(\'param.total\') > 0)
 5         {
 6             //添加一个订单
 7            当用户点击支付按钮时添加一条订单记录
 8            ...
 9 
10             $wx_root = \'./Wxpay\';
11             $file = \'./Wxpay/example/jsapi.php\';
12             require_once $file;
13         }
14     }
15     /*H5支付*/
16     public function h5Pay()
17     {
18         if(input(\'param.total\') > 0)
19         {
20             //添加一个订单
21            当用户点击支付按钮时添加一条订单记录
22            ...
23 
24             $wx_root = \'./Wxpay\';
25             $file = \'./Wxpay/example/mweb.php\';
26             require_once $file;
27         }
28 
29     }
30     /*微信支付回调*/
31     public function notify()
32     {
33         $wx_root = \'./Wxpay\';
34         $file = \'./Wxpay/example/notify.php\';
35         require_once $file;
36     }
View Code

页面测试出现的问题:

  1.文件加载错误,所以支付接口里面已写成了绝对路径。(在控制器里面,include文件是相对于网站的根目录的);

  2.出现’-1页面未注册‘的报错,查各种资料,说是支付授权目录的问题,填写规则上面已有说明;

  3.Notice: Use of undefined constant CURLOP_TIMEOUT - assumed \'CURLOP_TIMEOUT 报错 ,解决如下:

  (在example的JsApi.php的大概99行,修改如下:)

//        curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);

 

  4.H5支付出现curl出错,错误码60,解决如下:

    在lib--->wxpay.api.php大概538行处,修改如下代码

 1 //        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
 2 //        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
 3         if(stripos($url,"https://")!==FALSE){
 4             curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
 5             curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
 6             curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
 7         }
 8         else
 9         {
10             curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
11             curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
12         }
View Code

 

 

H5支付微信H5支付申请相关问题

H5微信支付

java微信支付--------公众号内H5调起支付

H5在微信公众号里调用微信支付总结(前端)

***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结

微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结