标签:开放平台 财付通 alt ref window image host tran php
最近个人负责的一些项目开发,都用到了微信支付(微信公众号支付、微信H5支付、微信扫码支付、APP微信支付)。在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,以备查看使用。
先说注意的第一点,所有支付的第一步都是请求统一下单,统一下单,统一下单,请求URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder。统一下单的目的是拿到预支付交易会话标识prepay_id,这个是必须的。所有的支付调用都是通过prepay_id来识别。
再说一个微信官方提供的一个很重要的工具,微信支付接口签名校验工具(网址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1),此工具旨在帮助开发者检测调用【微信支付接口API】时发送的请求参数中生成的签名是否正确,提交相关信息后可获得签名校验结果。特别实用!特别实用!特别实用!签名只要正确了,一切就OK了!
还有就是官方提供的几种支付方式的对比说明,如下图所示。
第一部分 微信公众号支付
微信公众号支付需要配置的参数有:APPID(微信公众号开发者ID)、APPSECRET(微信公众号开发者密码)、MCHID(商户ID)、KEY(商户密钥)。
微信公众号支付应用的场景是在微信内部的H5环境中是用的支付方式。因为要通过网页授权获取用户的OpenId,所以必须要配置网页授权域名。同时要配置JS接口安全域名,如下图所示:
以PHP为例,使用官方demo一个最常见的问题就是500错误,回调没反应,这个一般情况下是xml数据解析出现的问题(错误在这里WxPay.Data.php中WxPayDataBase类的FromXml()方法),解决方案如下:
public function FromXml($xml) { if(!$xml) { throw new WxPayException("xml数据异常!"); } //将XML转为array //禁止引用外部xml实体 libxml_disable_entity_loader(true); //这句导致出现上述问题 $this->values = json_decode(json_encode(simplexml_load_string($xml, ‘SimpleXMLElement‘, LIBXML_NOCDATA)), true); return $this->values; }
问题就出现在libxml_disable_entity_loader(),它的作用是设置是否禁止从外部加载XML实体,设为true就是禁止。可以使用将代码改成以下内容进行解决:
public function FromXml($xml) { if(!$xml) { throw new WxPayException("xml数据异常!"); } //将XML转为array //禁止引用外部xml实体 $disableLibxmlEntityLoader = libxml_disable_entity_loader(true); //改为这句 $this->values = json_decode(json_encode(simplexml_load_string($xml, ‘SimpleXMLElement‘, LIBXML_NOCDATA)), true); libxml_disable_entity_loader($disableLibxmlEntityLoader); //添加这句 return $this->values; }
本人也尝试过这样一个简单的方案,如下,直接屏蔽(在低版本PHP5.2中测试通过)libxml_disable_entity_loader():
public function FromXml($xml) { if(!$xml) { throw new WxPayException("xml数据异常!"); } //将XML转为array //禁止引用外部xml实体 //libxml_disable_entity_loader(true); //或者是把这句屏蔽 $this->values = json_decode(json_encode(simplexml_load_string($xml, ‘SimpleXMLElement‘, LIBXML_NOCDATA)), true); return $this->values; }
把这个解决之后就OK了。
还有一个问题就是“curl出错,错误码:60”,这个错误是由于服务器和PHP版本导致的,最近一次出现是在一个PHP5.2版本的原生项目上。微信官方对支付的数据传输提出了三点建议:
◆ 使用HTTPS确保网络传输安全性。
◆ 禁用SSL等不安全协议和算法,建议使用TLS1.2。
◆ 不要轻易的尝试设计和实现自己的加密传输算法,几乎都会存在问题。
具体的错误信息在日志里面是这样的:Fatal error: Uncaught exception ‘WxPayException‘ with message ‘curl出错,错误码:60‘ in ,目前的解决方案如下:
最原始的3.0demo里面,找到WxPay.JsApiPay.php文件的99行:
curl_setopt($ch, CURLOP_TIMEOUT, 30);
最早的example代码里少了一个“T”,这个问题官方已经解决,正确代码应该是如下的:
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
还有就是安全校验的问题,在官方demo WxPay.Api.php 文件中找到如下代码:
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
将上述代码做出如下修改:
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出错,错误码:60这个问题就可以解决了。
第二部分 微信H5支付
微信H5支付是微信官方2017年上半年刚刚对外开放的支付模式,它主要应用于在手机网站在移动浏览器(非微信环境)调用微信支付的场景。底层的技术以及支付链接本质上是财付通。
微信H5支付的流程比较简单,就是拼接请求的xml数据,进行统一下单,获取到支付的mweb_url,然后请求这个url网址就行。请求使用curl函数,使用的时候需要注意设置header参数。
$headers = array(); $headers[] = ‘Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8‘; $headers[] = ‘Connection: Keep-Alive‘; $headers[] = ‘Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3‘; $headers[] = ‘Accept-Encoding: gzip, deflate‘; $headers[] = ‘User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0‘;
下面直接奉上整个流程源码。
$userip = $_SERVER["REMOTE_ADDR"]; //获得用户设备IP $appid = "wx24d9dbdf00000";//微信 $mch_id = "888888888";//微信官方的 $key = "FSDFSD2356DSD00";//自己设置的微信商家key $nonce_str=MD5($out_trade_no);//随机字符串 $total_fee = $total_fee*100; //金额 $spbill_create_ip = $userip; //IP $notify_url = "http://www.bojuwang.net/"; //回调地址 $trade_type = ‘MWEB‘;//交易类型 具体看API 里面有详细介绍 $scene_info =‘{"h5_info":{"type":"Wap","wap_url":"http://www.hnyjzpw.com","wap_name":"支付"}}‘;//场景信息 必要参数 $signA ="appid=$appid&body=$body&mch_id=$mch_id&nonce_str=$nonce_str¬ify_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"; $strSignTmp = $signA."&key=$key"; //拼接字符串 注意顺序微信有个测试网址 顺序按照他的来 直接点下面的校正测试 包括下面XML 是否正确 $sign = strtoupper(MD5($strSignTmp)); // MD5 后转换成大写 $post_data="<xml><appid>$appid</appid><body>$body</body><mch_id>$mch_id</mch_id><nonce_str>$nonce_str</nonce_str><notify_url>$notify_url</notify_url><out_trade_no>$out_trade_no</out_trade_no><scene_info>$scene_info</scene_info><spbill_create_ip>$spbill_create_ip</spbill_create_ip><total_fee>$total_fee</total_fee><trade_type>$trade_type</trade_type><sign>$sign</sign> </xml>";//拼接成XML 格式 $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信传参地址 $dataxml = http_post($url,$post_data,$headers); $objectxml = (array)simplexml_load_string($dataxml,‘SimpleXMLElement‘,LIBXML_NOCDATA); //将微信返回的XML 转换成数组 function http_post($url=‘‘,$post_data=array(),$header=array(),$timeout=30) { $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); $response = curl_exec($ch); curl_close($ch); return $response; } if($objectxml[‘return_code‘] == ‘SUCCESS‘){ $mweb_url= $objectxml[‘mweb_url‘]; // header("Location:$mweb_url"); } $redirect_url = urlencode("http://www.bojuwang.net/");
H5支付的回调代码如下,注意xml数据的接收。PHP需要使用 $GLOBALS[‘HTTP_RAW_POST_DATA‘]解析微信支付结果返回的xml。
$xml = $GLOBALS[‘HTTP_RAW_POST_DATA‘]; $dataxml = json_decode(json_encode(simplexml_load_string($xml, ‘SimpleXMLElement‘, LIBXML_NOCDATA)), true);//转成数组, if($dataxml[‘return_code‘] == ‘SUCCESS‘){ //success }
第三部分 微信扫码支付
微信扫码支付一般应用的场景是PC端电脑支付。
第四部分 微信小程序支付
微信小程序支付是在小程序环境中使用的微信支付方式。
第五部分 微信APP支付
微信APP支付是在APP应用中使用的微信支付方式。
最后,总结一下上述几种支付方式需要注意的点。
1. 所有的支付参数都需要到微信支付商户平台(pay.weixin.qq.com)配置参数。
2. 微信公众号支付、微信扫码支付需要在微信公众号里面申请开通;APP支付需要在微信开放平台申请开通(open.weixin.qq.com);小程序支付需要在小程序平台申请开通。
3. 仅有公众号支付和扫码支付需配置支付域名,APP支付、刷卡支付无需配置域名。下图就是在微信支付商户平台配置授权域名的界面。
4. 所有使用JS API方式发起支付请求的链接地址,都必须在当前页面所配置的支付授权目录之下。下单前需要调用【网页授权获取用户信息】接口获取到用户的Openid。
5. 当公众平台接到扫码支付请求时,会回调当前页面所配置的支付回调链接传递订单信息。
微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结
标签:开放平台 财付通 alt ref window image host tran php
原文地址:http://www.cnblogs.com/zhengluwei/p/7746095.html