thinkphp5开发小程序后台(PHP小程序支付功能完整版基于thinkPHP)
类别:编程学习 浏览量:117
时间:2022-04-01 01:39:51 thinkphp5开发小程序后台
PHP小程序支付功能完整版基于thinkPHP本文实例讲述了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 )); return $sign ; } /** * 支付回调 * @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连接数据库拒绝使用域名(访问php时提示内存位置访问无效的解决办法和思路分析)
- php怎么创建一个文件(PHP文件后缀不强制为.php方法)
- phpstudy如何域名访问(phpStudy2016 配置多个域名期间遇到的问题小结)
- vuephp后台开发框架(Vue+thinkphp5.1+axios实现文件上传)
- php验证码思路(PHP实现字母数字混合验证码功能)
- php守护进程(什么是PHP7中的孤儿进程与僵尸进程)
- thinkphp怎么输出二维值(thinkphp 表名 大小写 窍门)
- php执行超时怎么办(PHP错误提示It is not safe to rely on the system……的解决方法)
- thinkphp接口开发实例(ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解)
- php+mysql源码部署教程(在WIN主机IIS上支持PHP和MySQL实现方法)
- php上传大文件教程(PHP实现带进度条的Ajax文件上传功能示例)
- dedecms新字段(DEDECMSv5.6 tags.php标签不能按照时间排序的问题)
- php中如何打开文件读文件(PHP通过文件保存和更新信息的方法分析)
- 本地phpstudy搭建网站教程学习(phpstudy搭建本地网站服务器图文教程)
- thinkphp支付宝支付(thinkPHP和onethink微信支付插件分享)
- php逻辑技巧图解(php版本CKEditor 4和CKFinder安装及配置方法图文教程)
- 新闻周刊 青岛网红 赵厂长 编段子一箩筐输出快乐,陪父亲十二载勇斗病魔(新闻周刊青岛网红)
- 44岁夏雨演谋女郎爸,大其24岁却看不出,互动不怕袁泉吃醋(44岁夏雨演谋女郎爸)
- 全椒人,你还记得吗 那年,那人,那网,那些我们的青春记忆(全椒人你还记得吗)
- 全椒人在苏州10周年联谊会在苏州举办(全椒人在苏州10周年联谊会在苏州举办)
- 这个全椒人被通报表彰,看看你认识吗(这个全椒人被通报表彰)
- 全椒人,38年集体回忆 1980-2018 ,看完不要哭(全椒人38年集体回忆)
热门推荐
- nginx怎么进一步配置(Nginx已编译的nginx-添加新模块)
- 阿里云到期ecs迁移至本地(阿里云ecs 硬盘在线扩容详细教程)
- html5canvas怎么改扇形起始角(HTML5 Canvas实现放大镜效果示例)
- react基础知识入门(浅谈React 的引入)
- cssanimation效果(使用CSS transition和animation改变渐变状态的实现方法)
- wds怎么设置32位(wdcp /dev/vda1 磁盘占满使用100%解决办法)
- wxpython 弹出对话框显示图片(WxPython建立批量录入框窗口)
- docker端口访问不了(docker设置了端口映射,不能访问的解决方案)
- mysqldata数据如何恢复(mysql5.7.33误删除ibdata文件找回数据的方法)
- 安装SQL Server 2016出错提示:需要安装oracle JRE7 更新 51(64位)或更高版本问题的解(安装SQL Server 2016出错提示:需要安装oracle JRE7 更新 5164位或更高版本问题的解)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9