小程序发起微信支付(使用jiaweixs)

首先引用一下微信官方文档的业务流程时序图,这是最简洁明了的:

商户系统和微信支付系统主要交互:

    1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API

    2、商户server调用支付统一下单,api参见公共api【统一下单API

    3、商户server调用再次签名,api参见公共api【再次签名

    4、商户server接收支付通知,api参见公共api【支付结果通知API

    5、商户server查询支付结果,api参见公共api【查询订单API



其次,我们需要使用小程序提供的API,发起微信支付。以下是详细的接口文档:

wx.requestPayment(OBJECT)

Object参数说明:

参数 类型 必填 说明
timeStamp String 时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间
nonceStr String 随机字符串,长度为32个字符以下。
package String 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
signType String 签名算法,暂支持 MD5
paySign String 签名,具体签名方案参见小程序支付接口文档;
success Function 接口调用成功的回调函数
fail Function 接口调用失败的回调函数
complete Function 接口调用结束的回调函数(调用成功、失败都会执行)

了解更多信息,请查看微信支付接口文档

回调结果:

回调类型 errMsg 说明
success requestPayment:ok 调用支付成功
fail requestPayment:fail cancel 用户取消支付
fail requestPayment:fail (detail message) 调用支付失败,其中 detail message 为后台返回的详细失败原因

示例代码:

wx.requestPayment({
   'timeStamp': '',
   'nonceStr': '',
   'package': '',
   'signType': 'MD5',
   'paySign': '',
   'success':function(res){
   },
   'fail':function(res){
   }
})

Bug & Tip

  1. bug: 6.5.2 及之前版本中,用户取消支付不会触发 fail 回调,只会触发 complete 回调,回调 errMsg 为 'requestPayment:cancel'

现在给出实际开发代码的一个例子:

①:小程序发起微信支付与回调处理的代码:

//购买
  pay: function (e) {
    var id = e.currentTarget.dataset.id;
    var that = this;
    request.post({
      url: '/api/mime/createOrder',
      data: {
        id: id,
      },
      success: function (res) {
        console.log(res);
        var result = res.data.result;
        wx.requestPayment({
          timeStamp: result.time.toString(),
          nonceStr: result.nonce_str,
          package: 'prepay_id=' + result.prepay_id,
          signType: 'MD5',
          paySign: result.sign,
          success: function (res) {
            that.confirmOrder(result.orderNo);
          },
          fail: function (res) {
            console.log(res);
          }
        })
      },
      fail: function (e) {
        wx.showToast({
          title: '请求失败!',
          duration: 2000
        });
      },
    });
  },
  //付款成功
  confirmOrder: function () {
    var that = this;
    request.post({
      url: '/api/mime/confirmOrder',
      data: {},
      success: function (res) {
        wx.showToast({
          title: '成功开通会员',
          duration: 2000
        });
        setTimeout(function(){
          wx.switchTab({
            url: '../mine/mine'
          })
        },2000);
      },
      fail: function (e) {
        wx.showToast({
          title: '请求失败!',
          duration: 2000
        });
      },
    });
  },

②:然后是用php写的处理生成订单的接口,这里我使用的是jiaweixs的组件

    在composer的配置文件中加入配置,也可以直接用composer命令直接添加

    

/**
     * 微信统一下单
     *
     */
    public function createOrder()
    {
        $id = trim($_POST['id']);
        $config = MemberCostConfig::get($id);
        $userId = $this->user->id;
        //生成订单
        $memberRecord = new MemberRecord();
        $data = array();
        $orderNo = 'W'.date('YmdHis',time()).mt_rand(10000, 99999);
        $data['orderNo'] = $orderNo;
        $data['status'] = 0;
        $data['user_id'] = $userId;
        $data['star_id'] = 0;
        $data['money'] = $config['price'];
        $data['duration'] = $config['duration'];
        $data['vip_day'] = $config['days'];
        $data['create_time'] = date("Y-m-d H:i:s");
        $data['update_time'] = date("Y-m-d H:i:s");
        $memberRecord->save($data);

        $money = (float)$config['price']*100;
        $unifiedorder = new Unifiedorder(APPID, MCHID, KEY);    //Unifiedorder是jiaweixs封装可以直接使用的
        $openid = $this->user->openid;
        // 必填
        $unifiedorder->set('body',          '充值会员');
        $unifiedorder->set('total_fee',     $money);
        $unifiedorder->set('openid',        $openid);
        $unifiedorder->set('trade_type',    'JSAPI');
        $unifiedorder->set('out_trade_no',  date('YmdHis').mt_rand(10000, 99999));
        $unifiedorder->set('notify_url',    BUY_MEMBER_URL);    //这里是微信支付回调地址

        // 选填
        $unifiedorder->set('attach',        $orderNo);
        $unifiedorder->set('time_start',    date("YmdHis")); //订单生成时间
        $unifiedorder->set('time_expire',   date("YmdHis", time() + 600)); //订单失效时间

        $response = $unifiedorder->getResponse();
        $res =  $response->toArray();
        $time = Time();
        $str = 'appId='.$res['appid'].'&nonceStr='.$res['nonce_str'].'&package=prepay_id='.$res['prepay_id'].'&signType=MD5&timeStamp='.$time;
        //重新生成签名
        $res['sign']=strtoupper(md5($str.'&key='.KEY));
        $res['time'] = $time;
        $res['orderNo'] =$orderNo;

        // 下单结果
        return $this->api_success('success', 200, $res);
    }

    /**
     * 修改订单状态
     *
     */
    public function confirmOrder()
    {
        $orderNo = trim($_POST['orderNo']);
        //修改订单状态
        $rechargeRecord = new RechargeRecord();
        $order = $rechargeRecord->where('orderNo', 'eq', $orderNo)->find();
        if ($order) {
            $data['number'] = $order['love_number'];
            return $this->api_success('success', 200, $data);
        } else {
            return $this->api_error('订单不存在',100);
        }
    }

③:最后就是微信支付的回调通知:

/**
     * 开通会员成功支付回调 接口
     */
    public function member()
    {
        $post = file_get_contents("php://input");
        $post_data = $this->xml_to_array($post);   //微信支付成功,返回回调地址url的数据:XML转数组Array

        $postSign = $post_data['sign'];
        unset($post_data['sign']);
        $record = new MemberRecord();
        $order = $record->where('orderNo', 'eq', $post_data['attach'])->find();

        if ($post_data['return_code'] == 'SUCCESS' && $postSign) {
            if ($order['status'] == '0') {
                $record->save(array('status' => 1,'update_time'=>date('Y-m-d H:i:s')), array('orderNo' => $post_data['attach']));

                $user = User::get($order['user_id']);
                $user['recharge_times'] = $user['recharge_times'] + 1;
                $user['recharge_money'] = $user['recharge_money'] + $order['money'];
                $user->save();

                $memberRecord = new MemberRecord();
                $record = $memberRecord->field('')
                    ->where('user_id','eq',$user->id)
                    ->where('end_time','>',date('Y-m-d H:i:s'))
                    ->order('end_time desc')
                    ->limit(1)
                    ->select();
                $order['start_time'] = count($record) > 0 ? $record[0]['end_time'] : date("Y-m-d H:i:s");
                $order['end_time'] = date("Y-m-d H:i:s",(strtotime($order['start_time']) + 3600*24*$order['vip_day']));    //天数
                $order['update_time'] = date("Y-m-d H:i:s");
                $order['status'] = '1';
                $order->save();

                // 对应的渠道增加佣金
                $channel = Channel::get(['id'=> $user['channel_id']]);
                if ($channel) {
                    $brokerage = $channel['brokerage'];
                    $channel['total_brokerage'] = $channel['total_brokerage'] + ( $order['money'] * ($brokerage / 100));
                    $channel->save();
                }
            }
            $this->return_success();
        } else {
            echo '微信支付失败';
        }
    }
/**
     * 将xml转为array
     */
    public function xml_to_array($xml)
    {
        if (!$xml) {
            return false;
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

    /**
     * 给微信发送确认订单金额和签名正确,SUCCESS信息 -xzz0521
     */
    private function return_success()
    {
        $return['return_code'] = 'SUCCESS';
        $return['return_msg'] = 'OK';
        $xml_post = '<xml>
                    <return_code>' . $return['return_code'] . '</return_code>
                    <return_msg>' . $return['return_msg'] . '</return_msg>
                    </xml>';
        echo $xml_post;
        exit;
    }












猜你喜欢

转载自blog.csdn.net/qq_20745827/article/details/80347611
今日推荐