公众号支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。 但是,微信官方的SDK “WxpayAPI_php_v3” V3版存在诸多问题,现从微信支付的接口原则和逻辑说说怎么解决。
官方文档中接口调用规则:
1、认证方式:HTTPS 认证,退款和冲正接口调用需要商户证书;
2、请求采用 POST 方式;
3、提交和返回结果采用 XML 格式;
4、字符集默认使用 UTF-8,请勿使用其它字符集;
5、商户与微信之间的交互(特别是 Native 回调和支付通知回调),都需验证签名;
6、处理返回时先判断协议返回错误码,再判断业务返回错误码,最后判断交易状态。
微信支付的流程与逻辑:
1、授权,抓取openid;
2、订单信息+openid得到支付页面;
3、支付,程序结束;
4、异步,腾讯服务器执行回调;回调目的是腾讯告诉我们订单是否支付成功。
问题一:curl错误码6
/** * * 通过code从工作平台获取openid机器access_token * @param string $code 微信跳转回来带上的code * * @return openid */ public function GetOpenidFromMp($code) { $url = $this->__CreateOauthUrlForOpenid($code); //初始化curl $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE); curl_setopt($ch, CURLOPT_HEADER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" && WxPayConfig::CURL_PROXY_PORT != 0){ curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST); curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT); } //运行curl,结果以jason形式返回 $res = curl_exec($ch); curl_close($ch); //取出openid $data = json_decode($res,true); $this->data = $data; $openid = $data['openid']; return $openid; }
问题原因:
如果开启了IPv6,curl默认会优先解析 IPv6,在对应域名没有 IPv6 的情况下,会等待 IPv6 dns解析失败 timeout 之后才按以前的正常流程去找 IPv4。在程序中我对curl获取内容都作了较为严格的超时限制,所以就会造成无法获取内容的问题。
解决办法: 强制curl走ipv4;或者centos系统中禁用ipv6; 或者添加微信相关域名解析。
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
修改/etc/sysctl.conf文件: net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.all.disable_ipv6 = 1 # /sbin/sysctl -p 使禁用IPv6生效
vi etc/hosts 添加以下内容: 101.227.143.34 open.weixin.qq.com 101.226.90.149 api.mch.weixin.qq.com 101.226.90.58 api.weixin.qq.com
问题二:PHP7 接入微信支付存在的错误
/** * * 支付结果通用通知 * @param function $callback * 直接回调函数使用方法: notify(you_function); * 回调类成员函数方法:notify(array($this, you_function)); * $callback 原型为:function function_name($data){} */ public static function notify($callback, &$msg) { //获取通知的数据 $xml = $GLOBALS['HTTP_RAW_POST_DATA']; //如果返回成功则验证签名 try { $result = WxPayResults::Init($xml); } catch (WxPayException $e){ $msg = $e->errorMessage(); return false; } return call_user_func($callback, $result); }
问题原因:
PHP7 不支持 $GLOBALS[‘HTTP_RAW_POST_DATA’]; 已移除该全局变量。
解决办法:
$xml = $GLOBALS['HTTP_RAW_POST_DATA']; 修改成: $xml = file_get_contents("php://input");