tp5支付宝和微信支付
一、生成二维码给用户进行扫码支付
1、先在vendor目录下加入支付宝和微信支付的引用
2、付款处调用
/** * 订单支付接口 * * @api {post} {:url('order/pay')} 前台订单支付二维码接口 * @apiName pay * @apiGroup Order * @apiParam {String} type 支付类型 alipay,wxpay * @apiParam {String} sn 订单号 * @apiSuccess (200) {String} /uploads/tmp/testbfb0f121f0114a8238a8888ed116af50.png 支付二维码地址 * */ public function pay() { $type = input('type', 'alipay', 'trim'); $order_sn = input('sn', '', 'trim'); if (!$order_sn) { return json(['msg' => '订单号错误'], 400); } $pay = new Pay(); $order = db('orders')->where(['order_sn' => $order_sn, 'pay_status' => 0])->find(); if (!$order) { return json(['msg' => '订单没有找到'], 400); } if ($order['pay_status'] == 1) { return json(['msg' => '订单已经支付, 请勿重复支付!'], 400); } try { switch ($type) { case 'alipay': $data = [ 'out_trade_no' => $order['order_sn'], 'subject' => $order['cust_name'] . "扫码支付", 'total_amount' => $order['payment_amount'], 'timeout_express' => "30m", ]; $pay->ali_pay($data); // echo "uploads/tmp/testbfb0f121f0114a8238a8888ed116af50.png"; break; case 'wxpay': $data = [ 'body' => $order['cust_name'], 'total_fee' => $order['payment_amount'] * 100, 'out_trade_no' => $order['order_sn'], 'product_id' => $order['order_sn'], 'trade_type' => 'NATIVE' ]; $pay->wx_pay($data); // echo "uploads/tmp/testbfb0f121f0114a8238a8888ed116af50.png"; break; case 'under_pay'://线下汇款 $bool = db('orders')->where('order_sn',$order_sn)->update(['pay_status'=>1]); if($bool){ return json(['msg'=>"订单完成"],200); }else{ return json(['msg'=>"订单支付异常"],400); } } } catch (\Exception $e) { return json(['msg' => $e->getMessage()], 400); } }
Pay.php文件
<?php namespace app\index\pay; use think\Exception; if (!defined("AOP_SDK_WORK_DIR")) { define("AOP_SDK_WORK_DIR", TEMP_PATH); } class Pay { private $config = []; public function ali_pay($order) { vendor('alipay.AopSdk'); $info = db('pay_config') ->field('fpay_value,public_key,private_key') ->where(['ftype' => 'alipay','fstatus'=>1]) ->find(); $this->config = array( //签名方式,默认为RSA2(RSA2048) 'sign_type' => "RSA2", //支付宝公钥 'alipay_public_key' => $info['public_key'], //商户私钥 'merchant_private_key' => $info['private_key'], //应用ID 'app_id' => $info['fpay_value'], //异步通知地址,只有扫码支付预下单可用 'notify_url' => url('index/alipay/notify', '', '', true),//支付后回调接口 //'notify_url' => "http://requestbin.net/r/1bjk7931", //最大查询重试次数 'MaxQueryRetry' => "10", //查询间隔 'QueryDuration' => "3", ); try { $alipay = new AlipayTradeService($this->config); $response = $alipay->qrPay($order); $alipay->create_erweima($response->qr_code); } catch (\Exception $e) { throw new Exception($e->getMessage()); } } public function wx_pay($order) { $info = db('pay_config')->where(['ftype' => 'wxpay'])->value('fpay_value'); vendor('Weixinpay.Weixinpay'); $info = json_decode($info, true); $this->config = [ 'APPID' => $info['fappid'], // 微信支付APPID 'MCHID' => $info['fmchid'], // 微信支付MCHID 商户收款账号 'KEY' => $info['fappkey'], // 微信支付KEY 'APPSECRET' => $info['fappsecret'], //公众帐号secert 'NOTIFY_URL' => url('index/wxpay/notify', '', '', true), // 接收支付状态的连接 改成自己的域名 ]; $wxpay = new \Weixinpay($this->config); $wxpay->pay($order); } }
(1)支付宝相关接口代码
AlipayTradeService.php
<?php namespace app\index\pay; use think\Exception; class AlipayTradeService { //支付宝网关地址 public $gateway_url = "https://openapi.alipay.com/gateway.do"; //异步通知回调地址 public $notify_url; //签名类型 public $sign_type; //支付宝公钥地址 public $alipay_public_key; //商户私钥地址 public $private_key; //应用id public $appid; //编码格式 public $charset = "UTF-8"; public $token = NULL; //重试次数 private $MaxQueryRetry; //重试间隔 private $QueryDuration; //返回数据格式 public $format = "json"; function __construct($alipay_config) { $this->appid = $alipay_config['app_id']; $this->sign_type = $alipay_config['sign_type']; $this->private_key = $alipay_config['merchant_private_key']; $this->alipay_public_key = $alipay_config['alipay_public_key']; $this->MaxQueryRetry = $alipay_config['MaxQueryRetry']; $this->QueryDuration = $alipay_config['QueryDuration']; $this->notify_url = $alipay_config['notify_url']; if (empty($this->appid) || trim($this->appid) == "") { throw new Exception("appid should not be NULL!"); } if (empty($this->private_key) || trim($this->private_key) == "") { throw new Exception("private_key should not be NULL!"); } if (empty($this->alipay_public_key) || trim($this->alipay_public_key) == "") { throw new Exception("alipay_public_key should not be NULL!"); } if (empty($this->charset) || trim($this->charset) == "") { throw new Exception("charset should not be NULL!"); } if (empty($this->QueryDuration) || trim($this->QueryDuration) == "") { throw new Exception("QueryDuration should not be NULL!"); } if (empty($this->gateway_url) || trim($this->gateway_url) == "") { throw new Exception("gateway_url should not be NULL!"); } if (empty($this->MaxQueryRetry) || trim($this->MaxQueryRetry) == "") { throw new Exception("MaxQueryRetry should not be NULL!"); } if (empty($this->sign_type) || trim($this->sign_type) == "") { throw new Exception("sign_type should not be NULL"); } } //当面付2.0预下单(生成二维码,带轮询) public function qrPay($order) { vendor('alipay.AopSdk'); $order = json_encode($order,JSON_UNESCAPED_UNICODE); $this->writeLog($order); $request = new \AlipayTradePrecreateRequest(); $request->setBizContent($order); $request->setNotifyUrl($this->notify_url); // 首先调用支付api $response = $this->aopclientRequestExecute($request, NULL, NULL); $response = $response->alipay_trade_precreate_response; if (!empty($response) && ("10000" == $response->code)) { return $response; } elseif ($this->tradeError($response)) { throw new Exception($response->code.":".$response->msg); } else { throw new Exception($response->code.":".$response->msg."(".$response->sub_msg.")"); } } /** * 使用SDK执行提交页面接口请求 * @param unknown $request * @param string $token * @param string $appAuthToken * @return string $$result */ private function aopclientRequestExecute($request, $token = NULL, $appAuthToken = NULL) { $aop = new \AopClient (); $aop->gatewayUrl = $this->gateway_url; $aop->appId = $this->appid; $aop->signType = $this->sign_type; $aop->rsaPrivateKey = $this->private_key; $aop->alipayrsaPublicKey = $this->alipay_public_key; $aop->apiVersion = "1.0"; $aop->postCharset = $this->charset; $aop->format = $this->format; // 开启页面信息输出 $aop->debugInfo = true; $response = $aop->execute($request, $token, $appAuthToken); //打开后,将url形式请求报文写入log文件 $this->writeLog("response: " . var_export($response, true)); return $response; } // 交易异常,或发生系统错误 protected function tradeError($response) { return empty($response) || $response->code == "20000"; } function writeLog($text) { // $text=iconv("GBK", "UTF-8//IGNORE", $text); //$text = characet ( $text ); file_put_contents(RUNTIME_PATH."log/log.txt", date("Y-m-d H:i:s") . " " . $text . "\r\n", FILE_APPEND); } function create_erweima($content) { //$content = urlencode($content); qrcode($content); } /** * 验签方法 * @param $arr 验签支付宝返回的信息,使用支付宝公钥。 * @return boolean */ function check($arr){ $aop = new \AopClient(); $aop->alipayrsaPublicKey = $this->alipay_public_key; $result = $aop->rsaCheckV1($arr, $this->alipay_public_key, $this->sign_type); return $result; } }
index/alipay/notify.php---扫码支付后调用接口
<?php namespace app\index\controller; use app\index\pay\AlipayTradeService as JKAlipayTradeService; use think\Controller; class Alipay extends Controller { /** * notify_url接收页面 */ public function notify() { // 引入支付宝 vendor('Alipay.AopSdk'); $info = db('pay_config') ->field('fpay_value,public_key,private_key') ->where(['ftype' => 'alipay','fstatus'=>1]) ->find(); $config = array( //签名方式,默认为RSA2(RSA2048) 'sign_type' => "RSA2", //支付宝公钥 'alipay_public_key' => $info['public_key'], //商户私钥 'merchant_private_key' => $info['private_key'], //应用ID 'app_id' => $info['fpay_value'], //异步通知地址,只有扫码支付预下单可用 'notify_url' => url('index/alipay/notify', '', '', true), //最大查询重试次数 'MaxQueryRetry' => "10", //查询间隔 'QueryDuration' => "3", ); $alipaySevice = new JKAlipayTradeService($config); $alipaySevice->writeLog(var_export($_POST,true)); //$result = $alipaySevice->check($_POST); $out_trade_no = $_POST['out_trade_no']; if ($_POST['trade_status'] == 'TRADE_FINISHED' || $_POST['trade_status'] == 'TRADE_SUCCESS') { if ($order = db('orders')->where("order_sn", $out_trade_no)->find()) { if ($order['pay_status'] != 1) { db("orders") ->where("order_sn", $out_trade_no) ->update(['pay_status' => 1,'status'=>2]); // 付款单创建 db('payment_bills')->insert([ 'cust_code'=>$order['cust_code'], 'cust_name'=>$order['cust_name'], 'payment_type'=>'alipay', 'amount'=>$order['payment_amount'], 'payment_time'=>date('Y-m-d H:i:s'), 'trade_no'=>$_POST['trade_no'], 'status'=>1, 'created_at'=>date('Y-m-d H:i:s'), 'updated_at'=>date('Y-m-d H:i:s'), ]); } } } echo "success"; } }
(2)微信相关接口代码
index/wxpay/notify
<?php namespace app\index\controller; use think\Controller; class Wxpay extends Controller { /** * notify_url接收页面 */ public function notify() { // 获取xml $xml=file_get_contents('php://input', 'r'); //转成php数组 禁止引用外部xml实体 libxml_disable_entity_loader(true); $data= json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)); file_put_contents('./notify.text', $data); // 导入微信支付sdk Vendor('Weixinpay.Weixinpay'); $info = db('pay_config')->where(['ftype' => 'wxpay'])->value('fpay_value'); $info = json_decode($info, true); $config = [ 'APPID' => $info['fappid'], // 微信支付APPID 'MCHID' => $info['fmchid'], // 微信支付MCHID 商户收款账号 'KEY' => $info['fappkey'], // 微信支付KEY 'APPSECRET' => $info['fappsecret'], //公众帐号secert 'NOTIFY_URL' => url('index/wxpay/notify', '', '', true), // 接收支付状态的连接 改成自己的域名 ]; $wxpay = new \Weixinpay($config); $result = $wxpay->notify(); if ($result) { // 验证成功 修改数据库的订单状态等 $result['out_trade_no']为订单id $map = [ 'order_sn' => $result['out_trade_on'], 'status' => 2 ]; if ($order = db('orders')->where($map)->find()) { if ($order['pay_status'] != 1) { db("orders")->where("order_sn", $result['out_trade_on'])->update(['pay_status' => 1]); } // 付款单创建 db('payment_bills')->insert([ 'cust_code'=>$order['cust_code'], 'cust_name'=>$order['cust_name'], 'payment_type'=>'wxpay', 'amount'=>$order['payment_amount'], 'account'=>isset($data['openid'])?$data['openid']:"", 'payment_time'=>date('Y-m-d H:i:s'), 'trade_no'=>isset($result['transaction_id'])?$result['transaction_id']:'', 'status'=>1, 'created_at'=>date('Y-m-d H:i:s'), 'updated_at'=>date('Y-m-d H:i:s'), ]); } } } }
二、用户提供二维码进行支付