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 相关文章推荐
如何在PHP中进行身份认证
Oct 09 PHP
PHP中file_exists与is_file,is_dir的区别介绍
Sep 12 PHP
谈谈关于php的优点与缺点
Apr 11 PHP
PHP stripos()函数及注意事项的分析
Jun 08 PHP
FireFox浏览器使用Javascript上传大文件
Oct 30 PHP
jQuery中的RadioButton,input,CheckBox取值赋值实现代码
Feb 18 PHP
JavaScript创建命名空间的5种写法
Jun 24 PHP
PHP中余数、取余的妙用
Jun 29 PHP
smarty简单应用实例
Nov 03 PHP
网页的分页下标生成代码(PHP后端方法)
Feb 03 PHP
PHP简单实现二维数组赋值与遍历功能示例
Oct 19 PHP
Laravel中服务提供者和门面模式的入门介绍
Nov 06 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
聊天室php&amp;mysql(四)
2006/10/09 PHP
PHP实现图片不变型裁剪及图片按比例裁剪的方法
2016/01/14 PHP
PHP上传图片、删除图片简单实例
2016/11/12 PHP
关于Laravel Route重定向的一个注意点
2017/01/16 PHP
JQuery 插件模板 制作jquery插件的朋友可以参考下
2010/03/17 Javascript
jquery 模拟雅虎首页的点击对话框效果
2010/04/11 Javascript
javascript alert乱码的解决方法
2013/11/05 Javascript
createTextRange()的使用示例含文本框选中部分文字内容
2014/02/24 Javascript
一张表格告诉你windows.onload()与$(document).ready()的区别
2014/05/16 Javascript
基于replaceChild制作简单的吞噬特效
2015/09/21 Javascript
jQuery1.9.1源码分析系列(十六)ajax之ajax框架
2015/12/04 Javascript
AngularJs expression详解及简单示例
2016/09/01 Javascript
vue.js入门教程之绑定class和style样式
2016/09/02 Javascript
jQuery监听文件上传实现进度条效果的方法
2016/10/16 Javascript
基于JS快速实现导航下拉菜单动画效果附源码下载
2016/10/27 Javascript
webpack常用配置项配置文件介绍
2016/11/07 Javascript
ES6新特性五:Set与Map的数据结构实例分析
2017/04/21 Javascript
js实现本地时间同步功能
2017/08/26 Javascript
JS几个常用的函数和对象定义与用法示例
2020/01/15 Javascript
JS 数组基本用法入门示例解析
2020/01/16 Javascript
JS Generator 函数的含义与用法实例总结
2020/04/08 Javascript
Element Cascader 级联选择器的使用示例
2020/07/27 Javascript
[03:53]2016国际邀请赛中国区预选赛第三日TOP10精彩集锦
2016/06/29 DOTA
解决pandas中读取中文名称的csv文件报错的问题
2018/07/04 Python
python 读取目录下csv文件并绘制曲线v111的方法
2018/07/06 Python
python查看模块,对象的函数方法
2018/10/16 Python
Python hashlib模块实例使用详解
2019/12/24 Python
CSS3实现点击放大的动画实例代码
2017/02/27 HTML / CSS
全球独特生活方式产品和礼品购物网站:AHAlife
2018/09/18 全球购物
生产部管理制度
2014/01/31 职场文书
初三新学期计划书
2014/05/03 职场文书
寻找最美家庭活动方案
2014/08/20 职场文书
2014矛盾纠纷排查调处工作总结
2014/12/09 职场文书
亮剑观后感600字
2015/06/05 职场文书
学术研讨会主持词
2015/07/04 职场文书
《分一些蚊子进来》读后感3篇
2020/01/09 职场文书