不知道什么时候,微信对外开放了H5支付功能,即微信浏览器外实现微信支付,这对于ecshop的用户来说,也算是件好事。帮人做项目的时候正好用到这个WXH5支付功能,顺便整理了下代码。
H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。
主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。
实际运用中,在支付流程时,WXH5支付调起了一个微信的内部页面MWEB_URL,然后通过该页面发起手机内的微信客户端进行支付,剩下的流程则基本和wxjsapi支付差不多,通过异步通知来确认收款,通过同步通知来进行前端显示。
下面简单地提一下几个关键点代码,所有源码均可在文后链接处下载。
1. 生成微信H5支付链接
前端发起支付请求的flow.php页面通过调用payment_object->get_code()函数来生成按钮。get_code函数关键内容如下:
function get_code($order, $payment){ $wechat = new wechat(); $ip = $wechat->getIPaddress(); $timestamp = time(); $noncestr = $wechat->create_noncestr(); $apikey = $payment['wxh5_apikey']; $appid = $payment['wxh5_appid']; $mchid = $payment['wxh5_mchid']; $body = $order['order_sn']; $total_fee = floor($order['order_amount']*100); $out_trade_no = $order['order_sn'] . 'O' . $order['log_id']; $callback_url = $GLOBALS['ecs']->url() . 'wechat.php'; $wechat->set_para("nonce_str", $noncestr); //随机字符串 $wechat->set_para("appid", $appid); //公众号 $wechat->set_para("mch_id", $mchid); //商户号 $wechat->set_para("device_info", 'WEB'); //终端设备号(商户的门店号或设备ID),注意:PC网页或公众号内支付请传"WEB" $wechat->set_para("body", $body); //商品或支付单简要描述 $wechat->set_para("out_trade_no", $out_trade_no); //商户订单号 $wechat->set_para("total_fee", $total_fee); //付款金额,单位分 $wechat->set_para("spbill_create_ip", $ip); // 终端地址 $wechat->set_para("notify_url", $callback_url); //异步通知地址 $wechat->set_para("trade_type", 'MWEB'); //交易类型H5 $postxml = $wechat->create_xml($apikey,1); $prepayobj = $wechat->request_for_pre_id($postxml); //统一下单接口返回 $url = $prepayobj->mweb_url; //当交易类型为H5时,会返回mweb_url,即h5支付页 $button = '<div style="text-align:center"><a href='.$url.' class="c-btn3" style="font-size:20px;"><img style="width:200px;" /></a></div>'; }
2.同步响应处理
同步响应代码同公众号支付,用于用户在微信客户端调起付款后的操作前端响应,不建议用来做业务逻辑处理。建议同步回来的信息后,发起一次支付订单查询,以得到结果后再跳转页面,不然的话,可能无法获取正确的支付结果而导致用户体验不佳。
$out_trade_no = $_GET['out_trade_no']; $wechat = new wechat(); $noncestr = $wechat->create_noncestr(); //公众号参数 $sql = "SELECT pay_config FROM " .$GLOBALS['ecs']->table('payment'). " WHERE pay_code = 'wxh5'"; $result = $GLOBALS['db']->getOne($sql); $config = unserialize_config($result); $apikey = $config['wxh5_apikey']; $appid = $config['wxh5_appid']; $secret = $config['wxh5_secret']; $mchid = $config['wxh5_mchid']; $wechat->set_para("nonce_str", $noncestr); $wechat->set_para("appid", $appid); $wechat->set_para("mch_id", $mchid); $wechat->set_para("out_trade_no", $out_trade_no); $postxml = $wechat->create_xml($apikey,2); $prepayobj = $wechat->queryorder($postxml); //发起查询 if(isset($prepayobj->trade_state) && $prepayobj->trade_state == 'SUCCESS') { //TODO } else { //TODO }
4.异步响应处理
异步响应代码,用于处理订单状态逻辑,此处需要有金额检查,避免出现1分钱订单。
$xml = file_get_contents('php://input'); if(!isset($xml)) { echo "fail"; exit; } else { //LOG SOMETHING } $responseObj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $json = json_encode($responseObj); $res = json_decode($json, true); if($wechat->check_respond_date($res,$apikey)) { $out_trade_no = $res['out_trade_no']; $out_trade_no = explode('O', $out_trade_no); $order_sn = $out_trade_no[0]; $log_id = $out_trade_no[1]; $total_fee = $res['total_fee']; if (!check_money($log_id, $total_fee/100)) { return false; } if($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS') { order_paid($log_id, 2); echo "success"; exit; } else { echo "fail"; } } else echo "fail";
由于ecshop并没有插件机制,以上代码需要理解后自行修改才能实现功能。
以上代码只适用于官方标准版2.73+php7版本,php5需要自行调整兼容代码,所有源码均可通过下方链接下载。
新春佳节到。祝好!祝好!
暂时用不到这些,