微信支付pc端native支付,
程序员文章站
2022-04-28 16:31:34
...
前言:工作需要,想一个ecshop开发一个支付功能,支付宝功能已经对接好了,开始对接微信pc扫码支付,和手机端支付,然而就弄扫码支付昨天弄了一下午,因为技术不行,eschop的代码可能是很多年前了,所以一个php文件就是一长溜的if判断,没有类,纯php写的if判断,很难受,所以官方的sdk不能使用异步通知信息,主要是手写微信异步回调之后的,前面文件闹得,恶心的一批。
-
官方下载nativesdk,然后配置信息就是appid呀等等信息,该配置文件存放在example/WxPay.Config.php,对应填写微信的信息,
-
然后可以看native.php文件,看他是怎么调用微信支付的sdk的。就是这块的代码,其中现在不在提供模式1的支付,可以直接注释掉,然后就看模式二的传入的参数,这里需要传递的是商品的名称,订单号,时间戳,商品价格,异步回调地址,这些信息是必须要严格填写的。
<?php /** * * example目录下为简单的支付样例,仅能用于搭建快速体验微信支付使用 * 样例的作用仅限于指导如何使用sdk,在安全上面仅做了简单处理, 复制使用样例代码时请慎重 * 请勿直接直接使用样例对外提供服务 **/ require_once "../lib/WxPay.Api.php"; require_once "WxPay.NativePay.php"; require_once 'log.php'; //初始化日志 $logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log'); $log = Log::Init($logHandler, 15); //模式一 //不再提供模式一支付方式 /** * 流程: * 1、组装包含支付信息的url,生成二维码 * 2、用户扫描二维码,进行支付 * 3、确定支付之后,微信服务器会回调预先配置的回调地址,在【微信开放平台-微信支付-支付配置】中进行配置 * 4、在接到回调通知之后,用户进行统一下单支付,并返回支付信息以完成支付(见:native_notify.php) * 5、支付完成之后,微信服务器会通知支付成功 * 6、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php) */ $notify = new NativePay(); # $url1 = $notify->GetPrePayUrl("123456789"); //模式二 /** * 流程: * 1、调用统一下单,取得code_url,生成二维码 * 2、用户扫描二维码,进行支付 * 3、支付完成之后,微信服务器会通知支付成功 * 4、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php) */ $input = new WxPayUnifiedOrder(); $input->SetBody("test"); $input->SetAttach("test"); $input->SetOut_trade_no("sdkphp123456789".date("YmdHis")); $input->SetTotal_fee("1"); $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); $input->SetGoods_tag("test"); $input->SetNotify_url("http://paysdk.weixin.qq.com/notify.php"); $input->SetTrade_type("NATIVE"); $input->SetProduct_id("123456789"); $result = $notify->GetPayUrl($input); $url2 = $result["code_url"]; ?>
-
注意设置的异步回调地址,要在微信开放平台中,对应的产品信息设置这个pc网站页面回调地址。因为今天是记录昨天的信息就没有截图。注意这个设置的异步通知地址要和在上方代码编写的异步通知地址要相同。
-
这些信息配置好了之后,将代码移入到我们的业务逻辑中,看看eschop的代码,感觉到了恶心,真的。不带黑的。
require './payment/wechat/lib/WxPay.Api.php'; require './payment/wechat/example/WxPay.NativePay.php'; include_once './payment/wechat/example/log.php'; //初始化日志 $logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log'); $log = Log::Init($logHandler, 15); $notify = new NativePay(); $input = new WxPayUnifiedOrder(); $input->SetBody("商城"); $input->SetAttach("test"); $input->SetOut_trade_no($order['order_sn']); $input->SetTotal_fee(((int)$order['order_amount']));# 金额注意要以分为单位, // $input->SetTotal_fee(((int)$order['order_amount']) * 100); $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); # 二维码有效期 $input->SetGoods_tag("test"); $input->SetNotify_url(""); # 异步回调地址 $input->SetTrade_type("NATIVE"); $input->SetProduct_id($cart_goods[0]['goods_id']); $result = $notify->GetPayUrl($input); $code_url = $result["code_url"];# 生成的二维码图片 # 微信生成二维码图片路径 $smarty->assign('code_url',$code_url); $smarty->assign('goods_name',$cart_goods[0]['goods_name']); # 表示当前是否是为微信自写支付信息 $smarty->assign('pay_online', 1);
-
注意标记红色的位置,我们还需要用到,然后会生成一个二维码的路径,最终在页面中形成的路径应该是这样的。
<img src="/payment/wechat/example/qrcode.php?data={$code_url}" width="300" height="300"> <!-- 路径解释:/payment/wechat/example/qrcode.php 表示的是sdk的路径,要能是web服务器能访问到的路径 --> <!-- data参数名称。变量就是上方代码生成的二维码图片信息-->
-
此时就可以显示出微信支付了,这是比较简单的, 接下来就是我的噩梦了。
-
支付成功之后大家都知道会有一个验证签名的方式,但因为我的代码不能直接通过类名加方法名去访问到页面,所以就需要手写微信生成签名的方式,来进行验证,这就是弄了我一下午时间才勉强弄好的问题原因所在,
<?php libxml_disable_entity_loader(true); # 小于5.5的版本支持 $xml = $GLOBALS['HTTP_RAW_POST_DATA']; # 解析xml成 数组,这段代码要和sdk中的代码一直 $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); # 生成签名函数 function appgetSign($data){ # 微信秘钥 需要手动填写,必须填写否则签名会验证不通过。 $appwxpay_key = ''; //签名步骤一:按字典序排序参数 ksort($data); # 调用函数 这个时将数组转换成路径的 $String = callbackToUrlParams($data); //签名步骤二:在string后加入KEY if($appwxpay_key){ $String = $String."&key=".$appwxpay_key; } //签名步骤三:MD5加密 $String = md5($String); //签名步骤四:所有字符转为大写 $result_ = strtoupper($String); return $result_; } /** * 格式化参数格式化成url参数 */ function callbackToUrlParams($Parameters){ $buff = ""; foreach ($Parameters as $k => $v){ if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } # 日志写入函数 function logTest($msg){ if(!is_array(($msg))){ $msg = iconv("UTF-8", "GBK", $msg); }else{ foreach($msg as &$v) { $v = iconv("UTF-8", "GBK", $v); } $msg = print_r($msg,1); } file_put_contents ( dirname ( __FILE__ )."/WeChatlog.txt", date ( "Y-m-d H:i:s" ) . " " . $msg . "\r\n", FILE_APPEND ); } # 调用签名函数 $res = appgetSign($data); # 写入日志函数 logTest($data); # 验证签名成功 if($data['sign'] == $res && $data['return_code'] == "SUCCESS" && $data['result_code'] == "SUCCESS") { logTest("验证签名成功"); # 进入到这里就可以开始处理订单业务逻辑了 $results = true; }else{ logTest("验证签名失败"); $results = false; } # 如果为true则通知微信不需要再给我发情求了,此订单已支付成功。但是同志为先的方法有问题。 if ($results) { echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; die; } else { echo "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[NO]]></return_msg></xml>"; die; }
注意微信native方法通知都是异步的,没有同步跳转地址,所以需要在出现二维码这里再加上一个倒计时效果,如果倒计时结束则提示用户二维码失效,且跳转到订单详情页面,外仍需要加上一个ajax请求,在倒计时效果中判断订单是否支付成功,支付成功仍需要跳到订单详情页面(可以写个js定时器,每两秒发一次ajax请求,通过之后直接返回到订单详情页)。
结语:
- 这次的微信支付就算结束了,相对来说微信支付没有支付宝支付好调整,但也还好,主要还是php版本低的问题,需要做兼容,相对来说,微信提供的sdk还可以,主要的是和微信支付平台以及微信公众平台的那些信息对接好,那些信息填好,只是需要发一个请求即可,这次的微信支付,感觉不太好,想要找一个全新的,从来没有注册过微信公众号没有开发过微信号的用户,走一把流程,那样的话记忆就会加深很多,但总体来说还可以。
- 送给自己一句话,长路漫漫,戒骄戒躁,踏实努力,认真生活。