php实现小程序支付完整版


Posted in PHP onOctober 09, 2018

本文实例为大家分享了php实现小程序支付的具体代码,供大家参考,具体内容如下

环境: tp3.2  + 小程序 微信支付功能开通

Step1:  下载PHP 支付SDK(下载地址)  放到Library\Vendor下,取名Wxpay           

修改WxPay.Config.php 里的appid appsecret key MCHID

Step2: 小程序 js 代码:

var url = getApp().globalData.httpServer + 'api/buy/pay';
    var userId = getApp().globalData.userId;
    var totalMoney = this.data.totalMoney;
    var cart = this.data.goods;
    var param = {
      cart: JSON.stringify(cart),
      cartamount: totalMoney,
      userid: userId,
      payment: this.data.payment,
      addressid: defaultAddress.id
    };
    var that = this;
    util.http(url, param, function (ret) {
      if (ret.data.code == 1) {
        if (that.data.payment == 'balance') { // 余额支付
          that.afterPaySuccess(ret.data.data);
        } else {                // 微信支付
          wx.requestPayment({
            timeStamp: ret.data.data.timeStamp,
            nonceStr: ret.data.data.nonceStr,
            package: ret.data.data.package,
            signType: ret.data.data.signType,
            paySign: ret.data.data.paySign,
            'success': function (res) {
              that.afterPaySuccess(ret.data.data.orderid);
            },
            'fail': function (res) {
              console.log(res);
            }
          })          
 
 
        }
 
      } else {
        util.showTip(ret.data.msg, '提交订单失败');        
      }
    });
/**
 * 网络请求
 */
function http(url, params, callback) {
  wx.request({
    url: url,
    data: params,
    success: function (res) {
      callback(res);
    },
 
    fail: function (err) {
      console.log(err);
    }
  });
}

Step3: 接口代码:

public function pay()
  {
    $cart = I('cart', '', 'trim');
    $cartAmount = I('cartamount');
    $addressId = I('addressid', 0, 'intval');
    $payment = I('payment', '', 'trim');
    $userId = $this->userid;
 
    $cart = json_decode($cart, true);
    if (empty($cart)) {
      $result['msg'] = '购物车获取失败';
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
 
    $totalMoney = 0;
    foreach ($cart as $goods) {
      $money = $goods['price'];  // price
      $selectCount = $goods['selectcount'];  // price
      $itemAmount = number_format($money * $selectCount, 2, '.', '');
      $totalMoney += $itemAmount;
    }
    // 检查总金额是否一致
    if ($totalMoney != $cartAmount) {
      $result['msg'] = '总金额不匹配:' . $totalMoney;
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
 
    // 获取用户地址
    $address = M('MemberAddress')->where('userid=' . $userId . " and id=" . $addressId)->find();
    if (empty($address)) {
      $result['msg'] = '用户地址不存在';
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
 
    // 用户信息
    $user = M('Member')->where("id=" . $userId)->find();
    if ($payment == 'balance') {
      if ($user['amount'] < $cartAmount) {
        $result['msg'] = '余额不足';
        $result['code'] = 0;
        $this->ajaxReturn($result);
      }
    }
 
    // 生成订单
    $order['ordersn'] = $this->genOrdersn($user['id']);
    $order['price'] = $cartAmount;
    $order['addressid'] = $address['id'];
    $order['addressinfo'] = serialize($address); //json_encode($address);
    $order['longitude'] = $address['longitude'];
    $order['latitude'] = $address['latitude'];
    $order['addtime'] = time();
    $order['status'] = 0;
    $order['userid'] = $user['id'];
    $order['paytype'] = $payment;
    $order['paysn'] = '';
    $order['paytime'] = time();
    $orderId = M("Order")->add($order);
    if ($orderId == 0) {
      $result['msg'] = '创建订单失败';
      $result['code'] = 0;
      $this->ajaxReturn($result);
    }
    foreach ($cart as $goods) {
      $orderGoods['orderid'] = $orderId;
      $orderGoods['goodsid'] = $goods['id'];
      $orderGoods['title'] = $goods['title'];
      $orderGoods['price'] = $goods['price'];
      $orderGoods['attr'] = $goods['attr'];
      $orderGoods['pic'] = $goods['pic'];
      $orderGoods['num'] = $goods['selectcount'];
      M("OrderGoods")->add($orderGoods);
    }
 
    if ($payment == 'balance') {
      // 余额支付
      $this->balancePay($cartAmount, $user['wxopenid'], $orderId);
    } else if ($payment == 'weixin') {
      // 微信支付
      $this->weixinPay($cartAmount, $user['wxopenid'], $orderId, $order['ordersn']);
    }
  }
/**
   * 微信支付
   * @author 大脸猫脸大
   * @param $cart
   * @param $cartAmount
   * @param $address
   * @param $user
   */
  private function weixinPay($cartAmount, $openId, $orderId, $orderSn)
  {
 
    import("Vendor.Wxpay.lib.WxPay#Api", "", ".php");
    //订单号
    $money = $cartAmount * 100;
    $openid = $openId;
    $input = new \WxPayUnifiedOrder();
    $input->SetBody("迪克-商品");
    $input->SetOut_trade_no("$orderSn");
    $input->SetTotal_fee("$money");
    $input->SetNotify_url("https://" . $_SERVER['HTTP_HOST'] . "/api/buy/payNotify");
    $input->SetTrade_type("JSAPI");
    $input->SetOpenid($openid);
    $unifiedOrder = \WxPayApi::unifiedOrder($input);
 
    if ($unifiedOrder['result_code'] == 'SUCCESS' && $unifiedOrder['return_code'] == 'SUCCESS') {
      $time = time();
      $data['timeStamp'] = "$time";              //时间戳
      $data['nonceStr'] = $unifiedOrder['nonce_str'];     //随机字符串
      $data['signType'] = 'MD5';                //签名算法,暂支持 MD5
      $data['package'] = 'prepay_id=' . $unifiedOrder['prepay_id'];  //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
      $data['paySign'] = $this->genPaySign($unifiedOrder, $time);// 之前以为是$unifiedOrder['sign']; 后来发现是调用的这种方法. 签名方案参见微信公众号支付帮助文档;
 
      $data['out_trade_no'] = $orderSn; 
      $data['orderid'] = $orderId; 
      $return['code'] = 1; 
      $return['data'] = $data; 
    } else { 
        Log::write(var_export($unifiedOrder, true), Log::ERR, '', C('LOG_PATH')."wx_pay_".date('y_m_d').'.log'); 
        $return['code'] = 0; 
        $return['msg'] = '微信支付失败';// $unifiedOrder['RETURN_MSG']; 
    } 
    $this->ajaxReturn($return); 
}
/* 生成支付签名*/
private function genPaySign($unifiedOrder, $time)
{
  $appId = \WxPayConfig::APPID;
  $nonceStr = $unifiedOrder['nonce_str'];
  $package = 'prepay_id=' . $unifiedOrder['prepay_id'];
  $signType = "MD5";
  $timeStamp = $time;
  $key = \WxPayConfig::KEY;

  $sign = md5(sprintf("appId=%s&nonceStr=%s&package=%s&signType=%s&timeStamp=%s&key=%s", $appId, $nonceStr, $package, $signType, $timeStamp, $key));
}
/**
   * 支付回调
   * @author:大脸猫脸大
   */
  public function payNotify()
  {
    import("Vendor.Wxpay.lib.WxPay#Data", "", ".php");
    $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
    $val = \WxPayResults::Init($xml);
 
    if ($val['result_code'] == 'SUCCESS' && $val['return_code'] == 'SUCCESS') {
 
      $orderSn = $val['out_trade_no'];
      $transactionId = $val['transaction_id'];
      $data = array('paytype' => 'weixin', 'status' => '1', 'paytime' => time(), 'paysn' => $transactionId);
 
      M("Order")->where("ordersn='$orderSn'")->setField($data);
      exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
    }else {
      Log::write(var_export($val, true), Log::ERR, '', C('LOG_PATH')."wx_pay_notify_".date('y_m_d').'.log');
      exit('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
    }
}

payNotify 回调方法里一定要注意返回

<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>

如果不处理,你会发现payNotify  会被执行很多次参见:官方文档

总结一下:

注意二点,1.签名的问题 2. 回调方法的返回处理。

欢迎大家指正。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
一个从别的网站抓取信息的例子(域名查询)
Oct 09 PHP
Windows下IIS6/Apache2.2.4+MySQL5.2+PHP5.2.1安装配置方法
May 03 PHP
ajax php 实现写入数据库
Sep 02 PHP
php代码审计比较有意思的例子
May 07 PHP
微信公众号开发之微信公共平台消息回复类实例
Nov 14 PHP
Symfony2使用Doctrine进行数据库查询方法实例总结
Mar 18 PHP
Yii2实现上下联动下拉框功能的方法
Aug 10 PHP
php实现图片以base64显示的方法
Oct 13 PHP
thinkPHP5.0框架整体架构总览【应用,模块,MVC,驱动,行为,命名空间等】
Mar 25 PHP
使用PHPExcel实现数据批量导出为excel表格的方法(必看)
Jun 09 PHP
PHP的JSON封装、转变及输出操作示例
Sep 27 PHP
laravel实现查询最后执行的一条sql语句的方法
Oct 09 PHP
php实现微信企业付款到个人零钱功能
Oct 09 #PHP
php实现构建排除当前元素的乘积数组方法
Oct 06 #PHP
php微信公众号开发之微信企业付款给个人
Oct 04 #PHP
PHP获取当前系统时间的方法小结
Oct 03 #PHP
PHP格式化显示时间date()函数代码
Oct 03 #PHP
php实现微信企业转账功能
Oct 02 #PHP
PHP实现微信退款功能
Oct 02 #PHP
You might like
德生S2000南麂列岛台湾FM收听记录
2021/03/02 无线电
PHP 多进程 解决难题
2009/06/22 PHP
在MongoDB中模拟Auto Increment的php代码
2011/03/06 PHP
PHP number_format函数原理及实例解析
2020/07/14 PHP
入门基础学习 ExtJS笔记(一)
2010/11/11 Javascript
nodejs win7下安装方法
2012/05/24 NodeJs
jquery弹窗插件colorbox绑定动态生成元素的方法
2014/06/20 Javascript
JS特效实现图片自动播放并可控的效果
2015/07/31 Javascript
跟我学习javascript的Date对象
2015/11/19 Javascript
JavaScript中定义类的方式详解
2016/01/07 Javascript
解决wx.onMenuShareTimeline出现的问题
2016/08/16 Javascript
jQuery动态增减行的实例代码解析(推荐)
2016/12/05 Javascript
vue.js学习之递归组件
2016/12/13 Javascript
jQuery时间验证和转换为标准格式的时间格式
2017/03/06 Javascript
js学习总结之DOM2兼容处理this问题的解决方法
2017/07/27 Javascript
vue双花括号的使用方法 附练习题
2017/11/07 Javascript
JS简单添加元素新节点的方法示例
2018/02/10 Javascript
Vue实现远程获取路由与页面刷新导致404错误的解决
2019/01/31 Javascript
小程序点击图片实现png转jpg
2019/10/22 Javascript
小程序卡片切换效果组件wxCardSwiper的实现
2020/02/13 Javascript
webpack+vue.js构建前端工程化的详细教程
2020/05/10 Javascript
学习python处理python编码问题
2011/03/13 Python
python实现字符串连接的三种方法及其效率、适用场景详解
2017/01/13 Python
Python实现的建造者模式示例
2018/08/06 Python
在python tkinter中Canvas实现进度条显示的方法
2019/06/14 Python
基于python的Paxos算法实现
2019/07/03 Python
python读取并写入mat文件的方法
2019/07/12 Python
解决django服务器重启端口被占用的问题
2019/07/26 Python
使用Bazel编译TensorBoard教程
2020/02/15 Python
详解Pycharm第三方库的安装及使用方法
2020/12/29 Python
用python查找统一局域网下ip对应的mac地址
2021/01/13 Python
python 装饰器重要在哪
2021/02/14 Python
HTML5的表单(绝对特别强大的功能)使用示例
2013/06/20 HTML / CSS
物流管理系毕业生求职信
2014/06/03 职场文书
MySQL8.0.24版本Release Note的一些改进点
2021/04/22 MySQL
Redis实战之Lettuce的使用技巧详解
2022/12/24 Redis