爱编码的Farmer

  • 主页
  • 编程开发
  • 运营维护
  • 随心笔记
  • 留言页面
  • 打赏
爱编码的Farmer
我是Farmer,我为自己代言
  1. 首页
  2. 编程开发
  3. 开发
  4. 正文

微信支付对接

2018年9月16日 5681点热度 4人点赞 3条评论

最近有一个项目,有需要对接微信支付,资质已经都申请好了,原来一直想试一试对接微信支付这些的,但是门槛太高,就没有研究这些支付的接口了,今天有机会,顺便记录下来

配置

根据官方的文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3 配置好url,就不多说了
我的使用场景是微信公众号,所以需要一个h5页面,调起微信支付

公众号支付(JSAPI支付)是指用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块来完成支付。

下单

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

在我们调起支付之前,需要调用这个统一下单的接口,获取我们支付的一些参数

获取openid

在h5中,我们需要获取到用户的openid,才能进行下单操作,一个简单的方法是,在公众号生成链接的时候,给链接带上一些参数,指向用户。这里我们用微信给我们提供的接口来获取openid https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

我们只需要openid,我们使用snsapi_base就好了,关于其他的信息可以通过openid从数据库中读取

直接将此链接发送给用户
https://open.weixin.qq.com/connect/oauth2/authorize?appid=[appid]&redirect_uri=[url]&response_type=code&scope=snsapi_base#wechat_redirect

然后会调用我们的链接,后面带了code参数,到这里就要获取openid了

$http = new \lib\http(
    "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code={$_GET['code']}&grant_type=authorization_code"
);
$data = $http->get();
$json = json_decode($data, true);
$openid = $json['openid'];

获取支付参数

在使用前端调起的时候,需要一个参数才能成功

$http = new \lib\http('https://api.mch.weixin.qq.com/pay/unifiedorder');
$data = [
    'appid' => $appid,//公众号id
    'mch_id' => $mch_id,//商户id
    'nonce_str' => $rand,//随机字符串
    'body' => 'test order',//商品描述
    'out_trade_no' => $trade_no,//商户自己的订单id,可以用来判断订单情况
    'total_fee' => '1',//金额,单位为分 我这样就是0.01元
    'spbill_create_ip' => getip(),//获取客户的ip
    'notify_url' => '',//异步回调链接
    'openid' => '',//必须要有openid
    'trade_type' => 'JSAPI'//JSAPI类型
];
ksort($data);
$sign = '';
foreach ($data as $k => $value) {
    $sign .= "$k=$value&";
}
$sign .= "key=$key";
$data['sign'] = strtoupper(md5($sign));//转换为大写
$xmlData = \controller\baseMsgController::arr2xml($data);//数组转换成xml
$xmlData = $http->post($xmlData);
//转换xml
$xml = simplexml_load_string($xmlData);
$prepay_id = $xml->prepay_id->__toString();//这个值是下面调起支付需要的,其他的到是无所谓

调起支付

直接复制官网的过来https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

那几个监听什么的,主要是监听网页的WeixinJSBridge加载完成事件,不然一开始就调起支付,可能没加载出来,导致失败

function onBridgeReady(){
   WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
         "appId":"wx2421b1c4370ec43b",     //公众号名称,由商户传入     
         "timeStamp":"1395712654",         //时间戳,自1970年以来的秒数     
         "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串     
         "package":"prepay_id=u802345jgfjsdfgsdg888",     //**主要就是这里了**
         "signType":"MD5",         //微信签名方式:     
         "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
      },
      function(res){
      if(res.err_msg == "get_brand_wcpay_request:ok" ){
      // 使用以上方式判断前端返回,微信团队郑重提示:
            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      } 
   }); 
}
if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
   }else if (document.attachEvent){
       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
   }
}else{
   onBridgeReady();
}

异步回调

异步回调算是最重要的一步了,有了它才能让我们知道用户支付完成了,并且给用户增加积分等等

这是我一次成功支付回调的xml

<xml><appid><![CDATA[******]]></appid>
<bank_type><![CDATA[CFT]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[1514896031]]></mch_id>
<nonce_str><![CDATA[****]]></nonce_str>
<openid><![CDATA[****-YRcXk]]></openid>
<out_trade_no><![CDATA[1537084330722301]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[****]]></sign>
<time_end><![CDATA[20180916155215]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[*****]]></transaction_id>
</xml>

对于异步回调我们需要校验sign

<?php
$xmlData = file_get_contents('php://input');

$xml = simplexml_load_string($xmlData);
$xmlArray = xml2arr($xml);
$sign = $xmlArray['sign'];
unset($xmlArray['sign']);
ksort($xmlArray);
//校验sign,appid等
if ($sign == pay_sign($xmlArray, $key) && $xmlArray['appid'] == $appid
    && $xmlArray['mch_id'] == $mch_id) {
//校验成功,查询订单等等,这里主要用 out_trade_no 来判断我们的商品信息等等
}else{
    //失败处理
}

function xml2arr($xml) {
    $ret_array = [];
    foreach ($xml as $key => $value) {
        $ret_array[$key] = $value->__toString();
    }
    return $ret_array;
}


function pay_sign($data, $key) {
    ksort($data);
    $sign = '';
    foreach ($data as $k => $value) {
        $sign .= "$k=$value&";
    }
    $sign .= "key=$key";
    $sign = strtoupper(md5($sign));
    return $sign;
}

标签: 暂无
最后更新:2018年9月16日

Farmer

不敢说什么

点赞
< 上一篇
下一篇 >

文章评论

  • 新的一天

    :cry: 为什么我一直学不会支付接口!!!

    2018年9月21日
    回复
    • Farmer

      @新的一天 就异步和加密那里有一点难度

      2018年9月21日
      回复
  • 取消回复

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据。

    COPYRIGHT © 2021 icodef.com. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang

    湘ICP备19008073号