这两天完成了公司网站手机和PC端的支付对接,就是支付宝和微信.

对接完后有所感触,我们来聊一聊,微信支付的坑,为什么这么说呢,因为我在对接完支付宝后是很愉快的,基本上在demo上稍加修改就ok了,

对于支付宝我觉得基本上都没什么可以说的,而微信支付...

网上搜了一下,基本上没有看到有针对h5支付的成功教程,全都是复制粘贴官方文档,有意思吗.

恰好今天空了,来聊一聊微信支付的坑,当然本文也不是光吐槽了事,我会把完整的代码放到文末尾处,并加以适当的注释.

------------------------------

首先第一步去微信商户平台开通h5支付的.

因为公司的app中的微信支付是我对接的,所以在开始做手机网站的微信支付前,我首先想到去微信开放平台,新建了一个网站应用,

最后审核下来居然没有支付接口,只有获取用户信息的接口,我有点蒙笔,然后我打了一下客服电话,那边客服说h5支付在公众号平台中完成(注意:这里客服mm向我扔了一个巨坑,接着往下看

既然这样,我就去了微信公众号平台,我们有服务号,拿着appid和mch_id就开始搞,一切都很好,但是提示[商户号该产品权限预开通中,请等待产品开通后重试],

我赶紧登录商户平台看一下,确定h5是开通的没问题,这个时候我注意到一个问题,就是我的公众号平台中的商户号和商户平台中的商户号不一致,我检查了公司信息,邮箱,手机号,两者都是完全一样的.

这个时候我把代码中的商户号(微信公众号平台的)改成了商户平台的商户号,请求接口返回[商户号和appid不匹配],我再次坚定,应该用微信公众号平台的商户号,因为appid是用的微信公众号平台的.

这个时候我陷入了焦灼,网上找了很久,没有搜到任何跟[商户号该产品权限预开通中,请等待产品开通后重试] 有关的结果,我给微信支付技术发了一封邮件,阐述了我遇到的问题,

第二天技术回复了我,说 "你开通h5支付的商户号是这个(商户平台的),而不是你现在用这个(微信公众号平台的)",这就是前面那个客服mm给我扔的大坑!!

邮件中还告诉我,我开通h5支付的商户号对应的appid是这个[appid**],而这个appid是我在开放平台中以前建的移动应用,也就是我们之前的app中用的...此时一万只草泥马在开始奔腾.

前后跨度太大,让我一时无法接受这个事实,

你先告诉我,h5支付为什么跟移动应用扯上关系了,其次你文档中提到了一星半点吗,没有!,客服mm也是调皮,动不动就h5支付跟开放平台没关系,只需要公众号平台.

还有 你微信产品真多 微信公众号平台(配置),微信开放平台(文档),微信商户平台(配置),我对接个微信支付要在三大平台之间来回切换,你真的666!!!

---------------------------------

平复一下心情,来看一下h5支付的流程,整个逻辑是这样的,首先用户打开手机网站某个服务页面

点击开通某个产品时,此时通过ajax请求带上产品价格,名称等参数来请求一个php脚本(wxpay_wap.php),

这个脚本根据官方文档要求的参数,组合,生成签名,请求统一下单接口,

返回一个支付url,然后用js生成一个a标签并模拟点击或者直接location.href应该都是可以的,

就会调起微信支付,支付完成后微信会发送一个请求到你设定的回调脚本(wxpay_wap_notify.php),在回调脚本里写业务逻辑

大体就是这样的,以下代码稍加修改就可以直接用了

---------------------------------

wxpay_wap.php

 // 文档中说的,价格 单位是分
$money = $_POST['money']*100; //商品价格
// 前台请求的参数
$title = $_POST['title']; //商品名称
$userid = $_POST['userid']; //用户id $time = time(); $nonce_str = "hcuasduvihasdiovjerjgvujsaru"; //随机字符串
$appid = "wx**************33"; //在微信开放平台中的 appid(先要创建一个移动应用)
$mch_id = "147****642"; //商户号,在商户平台中查看
$key = "51b*************************f15e"; //在微信开放平台中的 
$notify_url = "http://www.xxx.com/xxx/wxnotify.php"; //用户支付完后微信会来触发这个脚本,是处理业务逻辑的地方
//订单号可以灵活使用,比如我这个地方把userid加进去,在异步回调的时候方便直接操作用户
$out_trade_no = $time."__".$userid; // 下面的参数含义直接看文档
$tmpArr = array(
'appid'=>$appid, //不要填成了 公众号原始id
'attach'=>$title, 
'body'=>$title,
'mch_id'=>$mch_id,
'nonce_str'=>$nonce_str,
'notify_url'=>$notify_url,
'out_trade_no'=>$out_trade_no,
'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],
'total_fee'=>$money,
'trade_type'=>'MWEB'
);
// 签名逻辑官网有说明,签名步骤就不解释了
ksort($tmpArr); $buff = "";
foreach ($tmpArr as $k => $v)
{
$buff .= $k . "=" . $v . "&";
}
$buff = trim($buff, "&");
$stringSignTemp=$buff."&key=51b3363e91fe317fc346526f5933f15e";
$sign= strtoupper(md5($stringSignTemp)); //签名 $xml = "<xml>
<appid>".$appid."</appid>
<attach>".$title."</attach>
<body>".$title."</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>
<spbill_create_ip>".$_SERVER['REMOTE_ADDR']."</spbill_create_ip>
<total_fee>".$money."</total_fee>
<trade_type>MWEB</trade_type>
<sign>".$sign."</sign>
</xml> "; $posturl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $ch = curl_init($posturl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$response = curl_exec($ch);
curl_close($ch); $xmlobj = json_decode(json_encode(simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA )));
exit($xmlobj->mweb_url);

------------------------------------------

wxpay_wap_notify.php

 // 本脚本的业务逻辑只是个例子,仅供参考

 // 拿到原始数据并通过xml类解析为对象
$postObj = simplexml_load_string(file_get_contents("php://input"), 'SimpleXMLElement', LIBXML_NOCDATA );
// 你可以通过下面这种方式来看一下微信究竟返回了那些参数,请保证log.php存在并且有写权限
// file_put_contents(dirname(__file__)."/log.php",file_get_contents("php://input"));
$arr = array();
foreach ($postObj as $key => $value) {
$arr[$key] = $value;
}
// 订单状态
$status = $arr['result_code']; if(trim($status) == "SUCCESS") {
// 微信订单
$out_trade_no = $arr['transaction_id']; // 价格
$money = $arr['total_fee']/100;
// 在商户订单号中提取用户id,上一个脚本中我说了这个商户订单号可以灵活使用
$uid = explode("__", $arr['out_trade_no'])[1]; // 在数据库中检查这个订单号是否已经处理过了 以免重复处理,因为很多原因微信可能多次触发本脚本
// checkrepeat(orderid); /////////////////////////////////////////////////////////////
//// /////
//// 这里处理业务逻辑.... /////
//// /////
///////////////////////////////////////////////////////////// // 处理完逻辑 返回这个xml数据,告诉微信服务器,这个订单号已经处理完了 不要在来骚扰我了
$xml = "
<xml>
<return_code><![CDATA[".$status."]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>";
echo $xml; }

如果需要微信扫码支付或者支付宝支付相关文章,请在我的php分类中查看

微信支付之h5方式(非微信内置浏览器中支付)的更多相关文章

  1. 微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone)

    微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone) 前言: 这是小菜博客的第三篇文章.一直认为自己可以表达的东西太过简单,难以上台面,总是吝啬地不肯写.就算是写,也不知道从何开始.在同事的 ...

  2. 微信内置浏览器中的cookie很诡异呀

    微信内置浏览器中的cookie很诡异呀 这是设置和删除COOKIE的代码 function set_cookie($var ,$value = '' ,$expire = 0){ $path = '/ ...

  3. 用js限制网页只能在微信内置浏览器或支付宝内置浏览器中打开

    function is_weixinOrAli(){ var ua = navigator.userAgent.toLowerCase(); //判断浏览器的类型 if (ua.match(/Micr ...

  4. MyEclipse中的内置浏览器中的历史记录怎么清除

    eclipse内置浏览器的访问记录是存储在对应的工程目录下的.metadata配置中,也就是说你新建一个工程的话就没有了. 如果确实要删除那就找到工作空间中的org.eclipse.ui.browse ...

  5. 清除Eclipse中的内置浏览器中的历史记录

    eclipse内置浏览器的访问记录是存储在对应的工程目录下的.metadata配置中, 也就是说你新建一个工程的话就没有了. 如果确实要删除那就找到工作空间中的org.eclipse.ui.brows ...

  6. PHP限制网页只能在微信内置浏览器中查看并显示

    微信现在算是火了,围绕微信开发的应用也越来越多了,前段时间,自己公司需要,用PHP写了一个微信应用,为了防止自己辛苦写成的PHP应用被盗用,于是 通过PHP做了限制,只能在微信自带的浏览器中才能打开本 ...

  7. 解决 iOS 9.1 微信内置浏览器中html audio 不能自动播放的问题

    使用微信现在提供过的微信js-sdk 在ready中进行播放便可. 首先引用js : <script src="http://res.wx.qq.com/open/js/jweixin ...

  8. 微信内置浏览器的JS API

    /**! * 微信内置浏览器的Javascript API,功能包括: * * 1.分享到微信朋友圈 * 2.分享给微信好友 * 3.分享到腾讯微博 * 4.新的分享接口,包含朋友圈.好友.微博的分享 ...

  9. 2017年05月10日记一次微项目投产 | 安卓版微信内置浏览器不能解析gzip压缩过的mp4视频的问题

    前言 今天投产了一个小项目,一个很简单的H5,有播放视频功能,使用了videojs插件. 之前也做过数个视频播放,视频的转压都按照既定流程进行,文件放到FTP后,iphone和安卓机测试下来都没有问题 ...

随机推荐

  1. js,jQuery实现可关闭悬浮框广告特效,兼容(谷歌,火狐,Ie)

    注意不能直接用close()命名关闭广告函数,避免冲突. javascript实现方法: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tr ...

  2. JS中的DOM操作和事件

    [DOM树节点] DOM节点分为三大类: 元素节点. 属性节点. 文本节点: 文本节点.属性节点属于元素节点的子节点.操作时,均需要先取到元素节点,再操作子节点:可以使用getElement系列方法, ...

  3. About the diffrence of wait timed_wait and block in java

    import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * @au ...

  4. MySQL(十一)之触发器

    上一篇介绍的是比较简单的视图,其实用起来是相对比较简单的,以后有什么更多的关于视图的用法,到时候在自己补充.接下来让我们一起了解一下触发器的使用! 一.触发器概述 1.1.什么是触发器 触发器(Tri ...

  5. ios 初体验<真机调试>

    1.很多小伙伴,初学ios后面,都想迫不及待的连接上真机,在真机上调试,本人今天花了许久时间,在网上查了许多资料,一直出现了个问题导致我没法真机调试, 问题一:Your session has exp ...

  6. [转载]历上最强的音乐播放器(jetAudio-8.0.5.320-Plus-VX

    原文地址:历上最强的音乐播放器(jetAudio-8.0.5.320-Plus-VX-完全汉化版)下载作者:盖世天星 历上最强的音乐播放器(jetAudio-8.0.5.320-Plus-VX-完全汉 ...

  7. 201521123083《Java程序设计》第8周学习总结

    1. 本周学习总结 这周因为一些事情耽搁了,几乎没什么打java代码,这几天尽量补过来 2. 书面作业 1.List中指定元素的删除 1.1 实验总结 不贴大段代码了,简要总结一下.切割成数组,主要用 ...

  8. 201521123069 《Java程序设计》 第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. (1)文档注释(类注释.方法注释.属性注释.通用注释.) (2)多态性.instanceof ...

  9. 201521123004 《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  10. 201521123104《java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...