zl程序教程

您现在的位置是:首页 >  其他

当前栏目

基于thinkphp5.0和支付宝面对面扫码支付DEMO制作的扫码支付

2023-04-18 14:47:37 时间

基于thinkphp5.0和支付宝面对面扫码支付DEMO制作的扫码支付 今天接口申请下来,下载了官方demo对着调试了一天,终于实现想要的功能,先看图

选择支付宝支付

跳出二维码弹窗

手机支付宝进行扫码支付

支付完成,点击支付完成按钮跳转到订单列表

实现步骤: 1 支付宝接口申请,这个自行申请哦

2 下载官方扫码支付DEMO aopsdkdownload.cn-hangzhou.alipay-pub.aliyun-inc.com/demo/F2FPay… 将其中的f2fpay,aop两个文件夹复制到extend/alipay目录下. 其中的AlipayTradeService.php 我有稍作修改,到时在附件传上来.

3 点击页面的支付按钮后,异步请求二维码

//发起支付宝支付
    public function alipay()
    {
        if (!request()->isAjax()) {
            $this->error('该操作仅支持异步操作');
        }

        $productId = input('productId',0);
        $product = model('Product')->where('id',$productId)->find();
        if (empty($product)) {
            $this->error('产品不存在');
        }
        if ($product['status'] != 1) {
            $this->error('产品已下架');
        }

        $outTradeNo = out_trade_no();

        $data = [
            'notify_url' => url('api/Notify/alipay','',false,true), //回调链接
            'return_url' => '',
            'out_trade_no' => $outTradeNo, //订单号
            'subject' => '爱站SEO '.$product['title'], //产品标题
            'total_fee' => $product['cash'],//订单金额,单位为元
            'body' => $product['remark'], //产品描述
        ];

        $alipay = new Alipay;
        $result = $alipay->qrpay($data);
        if(!$result['code']){
            return $this->error($result['msg']);
        }

        //录入订单数据
        $orderData = [
            'order_num' => $data['out_trade_no'],
            // 'prepay_id' => $prepayId,
            'product_id' => $productId,
            'uid' => session('uid'),
            'count' => 1,
            'pay_fee' => $data['total_fee'] * 100,
            'create_time' => time(),
            'paied_time' => 0,
            'status' => 1,
        ];
        $res = db('Order')->insert($orderData);

        if (!$res) {
            $this->error('订单未成功生成');
        }

        //二维码生成
        $qrcodeImg = make_qrcode($result['msg'],$data['out_trade_no']);

        return [
            'code' => 1,
            'msg' => '请用支付宝支付',
            'qrcodeImg' => $qrcodeImg, //二维码图片地址
            'productInfo' => $product //产品信息
        ];
    }
复制代码

先检查产品是否可用销售,然后生成订单号,调用Alipay支付请求,订单录入后,生成二维码图片,传给前端. Alipay.php 我是放在common/pay/目录下的

<?php
namespace appcommonpay;

use thinkValidate;
use thinkLog;
/**
* 支付宝扫码支付
*/
class Alipay
{
    public function qrpay($data = [])
    {
        $validate = new Validate([
            ['out_trade_no','require|alphaNum','订单编号输入错误|订单编号输入错误'],
            ['total_fee','require|number|gt:0','金额输入错误|金额输入错误|金额输入错误'],
            ['subject','require','请输入标题'],
            ['body','require','请输入描述'],
            ['notify_url','require','异步通知地址不为空'],
        ]);
        if (!$validate->check($data)) {
            return ['code'=>0,'msg'=>$validate->getError()];
        }


        // 支付超时,线下扫码交易定义为5分钟
        $timeExpress = "5m";

        import('alipay.f2fpay.model.builder.AlipayTradePrecreateContentBuilder', EXTEND_PATH);
        import('alipay.f2fpay.service.AlipayTradeService', EXTEND_PATH);

        // 创建请求builder,设置请求参数
        $qrPayRequestBuilder = new AlipayTradePrecreateContentBuilder();
        $qrPayRequestBuilder->setOutTradeNo($data['out_trade_no']);
        $qrPayRequestBuilder->setTotalAmount($data['total_fee']);
        $qrPayRequestBuilder->setTimeExpress($timeExpress);
        $qrPayRequestBuilder->setSubject($data['subject']);
        $qrPayRequestBuilder->setBody($data['body']);

        // 调用qrPay方法获取当面付应答
        $config = config('alipay');
        if (!empty($data['notify_url'])) {
            $config['notify_url'] = $data['notify_url'];
        }
        $qrPay = new AlipayTradeService($config);
        $qrPayResult = $qrPay->qrPay($qrPayRequestBuilder);

        //  根据状态值进行业务处理
        switch ($qrPayResult->getTradeStatus()){
            case "SUCCESS":
                // echo "支付宝创建订单二维码成功:"."<br>---------------------------------------<br>";
                $response = $qrPayResult->getResponse();
                return ['code'=>1,'msg'=>$response->qr_code];
                break;
            case "FAILED":
                // echo "支付宝创建订单二维码失败!!!"."<br>--------------------------<br>";
                return ['code'=>0,'msg'=>'支付宝创建订单二维码失败!!!'];
                break;
            case "UNKNOWN":
                // echo "系统异常,状态未知!!!"."<br>--------------------------<br>";
                return ['code'=>0,'msg'=>'系统异常,状态未知!!!'];
                break;
            default:
                return ['code'=>0,'msg'=>'不支持的返回状态,创建订单二维码返回异常!!!'];
                break;
        }
        return ;
    }

    public function notify_alipay()
    {
        import('alipay.aop.AopClient');
        $config = config('alipay');
        $out_trade_no = input('post.out_trade_no');
        $transaction_id = input('post.trade_no');
        $aop = new AopClient;
        $aop->appId = $config['app_id'];
        $aop->rsaPrivateKey = $config['merchant_private_key'];
        $aop->alipayrsaPublicKey = $config['alipay_public_key'];
        $aop->signType = $config['sign_type'];
        $result = $aop->rsaCheckV1($_POST,'',$config['sign_type']);

        if ($result) {
            if(input('trade_status') == 'TRADE_FINISHED' || input('trade_status') == 'TRADE_SUCCESS') {
                // 处理支付成功后的逻辑业务
                $order = db('Order')->where(['order_num'=>$out_trade_no])->find();
                if (!$order) {
                    Log::write('order not exists');
                    return 'order not exists';
                }

                //订单状态错误 1 未付款 其他状态均为已处理的状态
                if ($order['status'] != 1) {
                    Log::write('order is completed:'.$order['status']);
                    return true;
                }

                if ($order['pay_fee'] != input('post.total_amount') * 100) {
                    Log::write('total_amount is error:'.$order['pay_fee'].','.input('post.total_amount'));
                    return 'total_amount is error';
                }

                $order['transaction_id'] = $transaction_id;
                $order['paied_time'] = time();
                $order['status'] = 2;
                db('Order')->update($order);
                //支付成功的逻辑
                
                return 'success';
            }
            Log::write('trade_status is error:'.input('trade_status'));
            return 'fail';
        }
        Log::write('sign verify is error:'.var_export($_POST));
        return 'fail';
    }
}
复制代码

主要有qrpay二维码扫描支付的请求,notify_alipay接收异步通知的处理逻辑 这里用到的接口配置,我是放在/application/extra/alipay.php 下面

<?php
return [
        //签名方式,默认为RSA2(RSA2048)
        'sign_type' => "RSA2",

        //支付宝公钥
        'alipay_public_key' => "",

        //商户私钥
        'merchant_private_key' => "",

        //编码格式
        'charset' => "UTF-8",

        //支付宝网关
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

        //应用ID
        'app_id' => "",

        //异步通知地址,只有扫码支付预下单可用
        'notify_url' => "http://www.baidu.com",

        //最大查询重试次数
        'MaxQueryRetry' => "10",

        //查询间隔
        'QueryDuration' => "3",

        //日志文件
        'log_file' => RUNTIME_PATH.'/log/'.date('Ym').'/'.date('d').'.log',
];
复制代码
填写公钥,私钥,异步通知地址,我自己添加了一个日志文件,为了结合请求的日志记录write_log使用.