Roka 2016-09-13
引言
秋高气爽,天气转凉,正是学习工作做的好时候。(~ ̄ ̄)~~(~ ̄ ̄)~
我是个phper最近在写微信支付(APP支付),微信给的官方文档并不是很详细也没有dome之类的代码啥的(对于新手来说比较麻烦),本人是新手以前也没写过支付,踩了好多坑,所以想写篇文章给没写过支付的新手几个建议。
准备工作
这首先呢你得注册个开放平台以及商户平台的账号吧,注册完成后呢你会收到一封微信里邮件里面有你的商户号等信息,注册这俩账号完你会拥有商户号,appid,appkey等需要的东西。
开发流程
准备完成后我们来看一下支付的大体流程
商户APP应用与微信支付主要的交互说明:
附:1,4是移动端所要做的事情,2,3,5是我们PHP服务端后台要做的6也是,但我没做,这个根据情况而定如果需要的话就做。
开始干活
步骤1.由移动端完成
步骤2. 调用同一下单接口:
先要做的是流程中的第二步,调用同一下单接口。官方文档里说了请求的地址与参数,其中有一些是必填参数,有
好了就是这些必选参数了,剩下就可以自己选择是否要用的参数了根据自己情况而定。
参数选完了就要发送参数了呗,如何发呢?
我们来调用wechatAppPay类中的unifiedOrder()函数。
啊哈啥!!!!!!??????
(⊙o⊙)?(⊙o⊙)?(⊙o⊙)?(⊙o⊙)?(⊙o⊙)?
wechatAppPay类???unifiedOrder()函数???
对就这这俩东西,不要惊讶,不要着急看最后有代码,有这个类,有代码的O(∩_∩)O哈哈~,
你只需在你的项目中加载这个类就可以调用这个方法了!不要崇拜我( st)(因为这个类不是我写的我也忘了从哪找的了,我从百度搜的然后整理的做了些改动r(st)q -_-|||-_-|||-_-!好吧好吧好吧没做改动,只是加了点注释而已,感谢写这个类的大神谢谢O(∩_∩)O谢谢O(∩_∩)O谢谢)
好了抽完疯了,开是干正事!
我们先来new下wechatAppPay类
$wxappid = 'wx0000000000000';//应用ID 字符串 $mch_id = '1000000000';//商户号 字符串 $notify_url = 'http://www.xxx.com/xxxx.php/xxxx/xxxx';//接收微信支付异步通知回调地址 字符串 $wxkey = '00000000000000000000000';//这个是在商户中心设置的那个值用来生成签名时保证安全的 字符串 $this->wechatAppPay = new wechatAppPay($wxappid, $mch_id, $notify_url, $wxkey);
调用wechatAppPay类中的unifiedOrder()函数。unifiedOrder()需要的参数是个数组我们定义为$params
$params = array(); $params['body'] = 'APP-在线支付'; //必填项 商品描述 $params['out_trade_no'] = time()."$member"; //必填项 自定义的订单号 $params['total_fee'] = ($money*100); //必填项 订单金额 单位为分所以要*100 $params['trade_type'] = 'APP'; //必填项 交易类型固定写 APP $params['根据自己情况定的值'] = "根据自己情况定的值" //非必填项 根据自己情况定的值 这个可有好多个可以参看开发文档中的参数 $result = $this->wechatAppPay->unifiedOrder( $params );
注:如果你加了$params['根据自己情况定的值'] wechatAppPay类里要做相应的改动,文章的最后有代码,你一看代码就明白了
现在$result就是我们调用统一下单接口返回的数据了,这个$resutl通过unifiedOrder()函数的处理已经把xml格式变成数组了。$result 里有return_code,return_msg,appid,mch_id,nonce_str,sign,result_code,prepay_id,trade_type。这里面就用一个prepay_id(预支付交易会话ID),其他都不重要了
步骤2完毕
步骤3. 把数据返回给商户APP应用(移动端)调起支付接口
现在我们要把调用统一下单接口返回的数据$resutl里的几个值返回给移动端那几个值呢?这几个:
$sign_array = array(); $sign_array['appid'] = $wx_result['appid']; //注意 $sign_array['appid'] 里的参数名必须是appid $sign_array['partnerid'] = $wx_result['mch_id']; //注意 $sign_array['partnerid'] 里的参数名必须是partnerid $sign_array['prepayid'] = $wx_result['prepay_id'];//注意 $sign_array['prepayid'] 里的参数名必须是prepayid $sign_array['package'] = 'Sign=WXPay'; //注意 $sign_array['package'] 里的参数名必须是package $sign_array['noncestr'] = $wx_result['nonce_str'];//注意 $sign_array['noncestr'] 里的参数名必须是noncestr $sign_array['timestamp'] = time(); //注意 $sign_array['timestamp'] 里的参数名必须是timestamp $sign_two = $this->wechatAppPay->MakeSign($sign_array);//调用wechatAppPay类里的MakeSign()函数生成sign现在就可以把重新生成的sign($sign_two)以及其他参数返回给移动端了,一共返回七个值,有三个之可以让前端写死(appid,partnerid,package),其余四个必须由服务器返回给移动端。
步骤3完毕
步骤4.由移动端完成
步骤5. 回调接口 支付结果通用通知
还记得步骤2中我们设置的$notify_url吗,对现在就要对这个微信返回到这个接口的数据进行一系列的逻辑处理了官方是这样写的:
支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并返回应答。
对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)
注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,防止数据泄漏导致出现“假通知”,造成资金损失。
首先来接收数据
$data = $this->wechatAppPay->getNotifyData();//获取数据 用wechatAppPay类里的getNotifyData()方法,这里数据也被getNotifyData()由xml转化成了数组。
然后官方说要采用数据锁进行并发控制,这个我不懂所以没写(如果你懂你会的话请给我留言私信告诉我,在这谢谢了),对数据进行状态检查这个写了,如何写的呢?很简单微信返回的值有好多其中就可以判断result_code(业务结果)和return_code(返回状态码)是否为SUCCESS就可以了代码就不写了。
然后验签,这个很重要因为这是保证数据没有被第三方人为篡改的标准!
如何验签呢?
把返回的数据$data里除去sign剩下的值都参与重新签名我们把这次签名叫做验签签名,验签签名生成后再与$data里的sign对比,如果相同验签通过,否则不通过。这次签名的参数名与二次签名时的参数名不同,$data数组里叫什么参数名就验签时叫什么参数名。听乱了吧?(~ ̄ ̄)~(~ ̄ ̄)~没关系请看代码
//假如$data里有如下参数 $w_sign = array(); //参加验签签名的参数数组 $w_sign['appid'] = $data['appid']; $w_sign['bank_type'] = $data['bank_type']; $w_sign['cash_fee'] = $data['cash_fee']; $w_sign['fee_type'] = $data['fee_type']; $w_sign['is_subscribe'] = $data['is_subscribe']; $w_sign['mch_id'] = $data['mch_id']; $w_sign['nonce_str'] = $data['nonce_str']; $w_sign['openid'] = $data['openid']; $w_sign['out_trade_no'] = $data['out_trade_no']; $w_sign['result_code'] = $data['result_code']; $w_sign['return_code'] = $data['return_code']; $w_sign['time_end'] = $data['time_end']; $w_sign['total_fee'] = $data['total_fee']; $w_sign['trade_type'] = $data['trade_type']; $w_sign['transaction_id'] = $data['transaction_id']; $verify_sign = $this->wechatAppPay->MakeSign($w_sign);//生成验签签名
好了现在假设你的验签已经通过了接下里就是你自己的逻辑处理了
///////////////////////////////////////////////////////
商户APP应用(后台)处理逻辑代码
//////////////////////////////////////////////////////
自己的逻辑处理已经处理完之后,还得告诉微信一下,别再一直发结果通用通知啦,我已经收到通知并处理完啦!
$this->wechatAppPay->replyNotify();//商户处理后同步返回给微信参数
步骤5结束步骤6根据自己情况而定
结束语
至此微信支付处理完成~(RQ)/~啦啦啦~(RQ)/~啦啦啦~(RQ)/~啦啦啦~(RQ)/~啦啦啦
写的有不对的方还请大家多多指导指教!!!给我留言!!b( ̄ ̄)db( ̄ ̄)db( ̄ ̄)d
还有感谢在我写微信支付地时候 那些被我问烦了的大神们! !谢谢啦~(RQ)/~啦啦啦~(RQ)/~啦啦啦~(RQ)/~啦啦啦O(∩_∩)O哈哈~O(∩_∩)O哈哈~O(∩_∩)O哈哈~<( ̄ ̄)><( ̄ ̄)><( ̄ ̄)>
代码