有关微信公众号和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 ?>
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>
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 }
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 }
页面测试出现的问题:
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 }
把H5支付微信H5支付申请相关问题