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程序设计有所帮助。