不知道什么时候,微信对外开放了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需要自行调整兼容代码,所有源码均可通过下方链接下载。

新春佳节到。祝好!祝好!
暂时用不到这些,