本文共 7338 字,大约阅读时间需要 24 分钟。
本文是自己做微信支付的一点心得,对于想做微信支付的开发者应该有些许帮助,有写的不对的地方还请见谅。
与微信建立连接
在日常使用微信的过程中,或多或少会接触到一些在微信公众号里付钱的操作,比如手机充钱,京东微信商城购物等。当点击公众号下面菜单的链接跳转到网上商城时,我们发现其实链接到的是商家自己的h5网站,卖什么东西怎么卖是商家自己进行维护(微信提供了网站的入口与便捷的支付功能)。那么怎么才能实现公众号与h5网站的连接呢?
对于动手党来说,肯定是想立马建立一个属于自己的公众号看看效果,那么你可以先看这篇文章(不包含微信支付),如果实现文章里面的那些案例没有问题,那么可以跳过这部分了。http://www.cnblogs.com/txw1958/p/wechat-tutorial.html
如果有些朋友暂时还不想一下子深入进去,可以接着往下看,下面的内容在上面的文章中大部分都有提及。要实现一个简单的公众号与h5网站的连接大概需要包含以下几个部分。 在微信官方网站(https://mp.weixin.qq.com/)上可以进行申请,个人目前可以申请订阅号(没有支付与自定义菜单等高级权限),但是已经可以满足这里与h5网站连接的需要了。如果是企业用户,有支付需求的话,可以申请一个服务号认证后就可以有支付权限了;当然与此配套的还需要申请一个商户号,用以绑定银行卡。 因为是要供微信调用的,所以网站必须在外网能够进行访问,如果自己没有服务器,那么可以使用免费的新浪云(支持MySql数据库),将自己的网站挂在上面。 最重要的就是这个 网站的默认页 ,因为微信发过来的消息全部会到网站的默认页上,在此页面里需要对微信消息进行相应的处理。 在有了公众号与h5网站的基础上,就可以进行这一步了。 URL:h5网站地址,微信会把消息发送到这个网站上 TOKEN:这是个密钥,每次与微信交互信息时需要进行验证 这个页面负责接受微信消息,验证访问正确性,返回消息给微信。下面使用php代码来说明下怎么做。 /** * 验证访问正确性 */ private function CheckSignature() { //微信调用带过来的3个参数 $signature = $_GET["signature"]; //加密的字符串 $timestamp = $_GET["timestamp"]; //时间戳 $nonce = $_GET["nonce"]; //随机字符串 $echostr = $_GET["echostr"]; //如果是在公众号里设置调用url时,会有个参数 //将$token,$timestamp,$nonce拼接在一起使用sha1加密 $token = TOKEN; //这个是设置的密钥 $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); //如果加密出来的信息与微信过来的信息一致则进行后续处理 if ($tmpStr == $signature) { //如果是设置调用url,则原样返回echostr即可 if ($echostr) { echo $echostr; exit(0); } //如果是用户与公众号正常互动,继续处理 $this->DelMsg(); } else { exit(0); } }
在验证了访问的正确性后,就可以解析微信post过来的参数了,根据不同的消息类别可以进行不同的回复,下面以文本消息来实现一个回复与用户发送相同信息的例子。
首先来看微信post过来的参数说明,更多消息类型请看这里http://mp.weixin.qq.com/wiki/17/f298879f8fb29ab98b2f2971d42552fd.html。 /** * 根据信息类型处理信息 */ private function DelMsg() { //微信post过来的参数 $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; if (!empty($postStr)) { //将格式化的xml字符串转化成对象 self::$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); } //判断对象是否解析成功 if (is_object(self::$postObj)) { //MsgType为消息的类型 //更多类型查看http://mp.weixin.qq.com/wiki/17/f298879f8fb29ab98b2f2971d42552fd.html $msgType = trim(self::$postObj->MsgType); switch ($msgType) { case "text": $content = self::$postObj->Content; break; default: $content = ''; break; } echo $this->transmitText(self::$postObj, $content); } else { echo ''; exit(0); } } /** * 回复文本消息 * @param type $object 微信post对象 * @param type $content 文本消息 * @return type */ private function transmitText($object, $content) { //回复消息的模板 //更多模板查看http://mp.weixin.qq.com/wiki/1/6239b44c206cab9145b1d52c67e6c551.html $xmlTpl = " %s "; $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), $content); return $result; }
如果上面处理的没错的话,那么就可以看到如下的效果了:发送了【今天天气真好】微信回复了【今天天气真好】
到这里为止与微信的一个简单连接就建立好了,还有很多有意思的交互,可以自己参考微信的开发文档自己发掘。
公众号支付
微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1 公众号支付,大概功能是微信用户在商家的h5网站上选购商品,通过微信进行付款,商家最后发货的过程。下面分几个部分做说明,详细的 微信用户可以通过扫码或者公众号内消息进入商户的h5网站,在网站上选购自己所需要的物品,如家电或者手机充值等。 用户选择好需要购买的商品后,就可以在商户h5网站进行下单,下单后商户系统需要生成一个订单,包含订单号(订单号需要唯一)与订单的金额等。 上面2个步骤主要是在商户系统进行处理的,这一步需要将商户的订单转成对应的微信订单,好通过微信支付付钱。 这里需要调用微信的统一下单接口(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1),将需要的参数传进去,必要参数如下。 mch_id:微信支付商户号ID,可以在【微信支付-商户信息】里看到 out_trade_no:商户系统内部的订单号,需要唯一 fee_type:付费的类型,正常使用人民币【CNY】 time_expire:交易结束时间,需要超过交易开始时间至少5分钟 notify_url:微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数 trade_type:公众号支付使用【JSAPI】 open_id:这个是用户的微信号,可以通过接口进行获取,详细看这里http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html sign:将上面的信息合并起来再加上商户支付密钥进行一个md5编码,详细看这里https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3 将上面的参数传递给下单接口,如果没问题的话,可以从微信那里得到 在有了上面获取到的prepay_id后,这里可以调用微信的JSAPI接口,让用户可以在微信上进行付款了。 //调用微信JSApi支付 function WeiXinPay(data) { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": "wx2421b1c4370ec43b", //公众号ID,可以在【基本配置】里看到 "timeStamp": " 1395712654", //时间戳,time() "nonceStr": "e61463f8efa94090b1f366cccfbbb444", //32位随机串 "package": "prepay_id=u802345jgfjsdfgsdg888",//上面步骤获取到的预支付ID "signType": "MD5", //微信签名方式: "paySign": "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名,同统一下单签名规则 }, function(res) { WeixinJSBridge.log(res.err_msg); //如果付款成功的话 if (res.err_msg == 'get_brand_wcpay_request:ok') { hideorshow('paysuccess'); $('title').text('支付成功'); } } ); }
如果在上一个步骤用户成功付款的话,可以得到微信前端返回的支付成功消息,这个时候可以在h5页面提示用户付款成功。但是【get_brand_wcpay_request:ok】不一定 绝对可靠,这时还需要用上在统一下单时,传递给微信的回调url。 微信会异步调用这个回调url,并传递进来transaction_id(同prepay_id),在回调页面里面,可以调用微信的查询订单接口 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2,来查询订单的实际状态,用于确认后续的业务流程怎么处理。 transaction_id:微信订单号,与product_id任意一个即可 product_id:商户订单号,与transaction_id任意一个即可 如果从接口返回过来参数中的return_code与result_code都为SUCCESS的话,则代表支付成功了。如果支付成功的话,微信还会返回过来其他一些有用的信息, 比如【is_subscride-用户是否关注公众号,值为Y或者N】,对于关注的微信用户,可以在公众号里给用户推送一条付款成功的消息。 在验证了用户已经付款的情况下,就可以将用户购买的商品快递给用户了,或者为用户指定的手机号充值等。 扫码支付
有些情况下,可能不需要用户进入到公众号里面选购商品,而是已经存在订单,只需要用户直接付款就行了。比如自动售货机,金额已经固定的 合同等。 微信扫码支付文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 这里以模式一作为案例,实现扫码支付,大致需要以下几步。 如果需要使用扫码支付的话,需要在公众号里面设置扫码回调URL,用于微信扫码后,将参数传递进来,商户进行相关验证后,返回给微信支付参数,
类似于公众号支付中,调用JSAPI支付的那段参数。
weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX 如果上一步的二维码生成正确的话,在使用微信里的扫一扫功能扫码后,微信会将上述链接中的product_id回传给设置的回调url中。 在回调页面里面,商户可以验证该订单号的正确性或者是否已经支付过了。如果订单号是有效的,则可以从商户系统里面查询需要的信息进行下单。 这里还可以不依靠上面的product_id(只是为了生成二维码造的假的),在下单时用别的订单号代替,比如一个guid,可用于事先没有订单号的支付。 调用微信的统一下单接口实现,同公众号支付里面的【3.生成微信订单】,主要是为了得到prepay_id。 这里直接将参数转成xml格式,返回就行,参数如下。 prepay_id:预支付ID,如果下单错误,或者商户校验订单号有问题,这个值可以为空 result_code:如果下单正确为【SUCCESS】,如果下单错误或者商户校验订单号有问题,为【FAIL】 err_code_des:如果有错误,则为错误信息,否则为空即可 微信用户如果成功付款的话,也会回调在下单时设置的回调URL。具体逻辑同公众号支付里面的【5.付款验证】 在验证了用户已经付款的情况下,就可以给用户商品或者给用户某些应用重置等。