thinkphp6(php)框架接入yansongda支付SDK扩展包实现微信支付和支付宝支付的APP支付和退款demo

目录

1.composer安装yansongda SDK

2.支付所需参数配置文件内容参考

3.具体业务代码实现

3.1 下单

3.1.1 控制器

3.1.2 业务层

3.2 APP客户端用3-1-1中返回的参数去调起支付宝和微信支付进行支付

3.3退款

3.3.1 控制器

3.3.2 业务层 

3.4 异步回调处理

3.4.1 控制器代码

3.4.2 业务层代码


1.composer安装yansongda SDK

composer require yansongda/pay:~3.7.0 -vvv
composer require guzzlehttp/guzzle:^7.0
composer require hyperf/pimple:~2.2.0  # 或者 composer require illuminate/container

2.支付所需参数配置文件内容参考

文件位置 "根目录/config/pay.php"

<?php

use think\facade\Request;
use Yansongda\Pay\Pay;

return [
    'wechat'=> [
        'default' => [
            // 必填-商户号,服务商模式下为服务商商户号
            // 可在 https://pay.weixin.qq.com/ 账户中心->商户信息 查看
            'mch_id' => 'zzz',
            // 选填-v2商户私钥
            'mch_secret_key_v2' => '',
            // 必填-v3 商户秘钥
            // 即 API v3 密钥(32字节,形如md5值),可在 账户中心->API安全 中设置
            'mch_secret_key' => '',
            // 必填-商户私钥 字符串或路径
            // 即 API证书 PRIVATE KEY,可在 账户中心->API安全->申请API证书 里获得
            // 文件名形如:apiclient_key.pem
            'mch_secret_cert' => realpath(app()->getRootPath().'public/cert/alipayCertPublicKey_RSA2.crt'),
            // 必填-商户公钥证书路径
            // 即 API证书 CERTIFICATE,可在 账户中心->API安全->申请API证书 里获得
            // 文件名形如:apiclient_cert.pem
            'mch_public_cert_path' => '',
            // 必填-微信回调url
            // 不能有参数,如?号,空格等,否则会无法正确回调
            'notify_url' => Request::domain(). '/api/pay/notifyWxPay',
            // 选填-公众号 的 app_id
            // 可在 mp.weixin.qq.com 设置与开发->基本配置->开发者ID(AppID) 查看
            'mp_app_id' => '2016082000291234',
            // 选填-小程序 的 app_id
            'mini_app_id' => '',
            // 选填-app 的 app_id
            'app_id' => '',
            // 选填-服务商模式下,子公众号 的 app_id
            'sub_mp_app_id' => '',
            // 选填-服务商模式下,子 app 的 app_id
            'sub_app_id' => '',
            // 选填-服务商模式下,子小程序 的 app_id
            'sub_mini_app_id' => '',
            // 选填-服务商模式下,子商户id
            'sub_mch_id' => '',
            // 选填-微信平台公钥证书路径, optional,强烈建议 php-fpm 模式下配置此参数
            'wechat_public_cert_path' => [
                '45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__.'/Cert/wechatPublicKey.crt',
            ],
            // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
            'mode' => Pay::MODE_NORMAL,
        ]
    ],
    'alipay'=>[
        'default' => [
            // 必填-支付宝分配的 app_id
            'app_id' => '你的实际app_id',
            // 必填-应用私钥 字符串或路径
            // 在 https://open.alipay.com/develop/manage 《应用详情->开发设置->接口加签方式》中设置
            'app_secret_cert' => 'MIIEvQIBADANBgkqhkiaaG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCCFUrQVV244Zfygo8FqMMCc7on6o585o98CephLgNWlBrXwbn1nIILNPfCsm+j6zmV9hhdlbuDXvVHyLFLx/MexzOap5RcKhOg2xURE/Rmze3GrOFjGlmxldkt4QVbS2C3P8Kqes5cGHpYaHxmq7AkQ1gILVhOTE8aBMlBh7Zt8CDuBO17kEBPJLpl/Dr+//khOOvB0pxX4hJk6KBR8aiBq66K2GZ3Z8EcAwnUaYdBkEqc7rWGLNUk+Zk9l4PfFdJRJLz5h8bPpTIzo1bNTSUw4bDVwhCT5AprLw7vt3Gl9RxcgvHP37tsdz0FsXGtNlmNArvavrSC94OQx8tQF7s9AgMBAAECggEAF9SavgvFfacmVPECDoFaKErXIZTgwZTjWE/gtijdx7CeMkR1Mr+XO0Ja2TojJZ5kEErjL9HMZkaxHJNxl3Zr3YmUtJJapX+31NINy/Eh5ut20dy99Y/QOq4++R6uAomOkEOH//87are5QhTyJUTyodIMgIL+GGn2W8fgrraT/xOpnBBvCLPlV2RNy6tF3DDSfAgS4yYlcRmoaCyXSEMMCUWhrQJxAKZ6pR1UmgMXh/y+YiymomyOyrZMmtjaISbzsB4H1UHVIM68bN3j8tKM79cvtZ0gyR23bSGMsjOYH6MgO8G7YTpv8H8ws7a6SXVlnCn2/NKlWMatCIh/nIjFaQKBgQDBOL1efuYqCyAKwsLQ5wQzLDVTC4bL2IJFdbphzUzzNumY/pO7CRagIOLnL1MdkuM9aUNbaW26Va1Zjv8OwgMEpj8PMtWvXPmxopsgdXyWDAniyXCPlB2PaQiV4bhlX0+uXa94Gbf968RRRRa1tHivJYutSfENhyufmgkeW9IzB+PwKBgQCsWP570KJz2ELWcggKiXK9SCka1vDBCIp01SVM3x/TuLyQ7VMd890e9RGkqZBxYY9xbRUMTkMMeKKQHUJrGl2k5XdfXC2yvu4dXkrTHjmWCIishoeYI5GQVo7whF5+sF0WAWLtmQRBZ6D8g4iSRRIrsF8WYATUf1e+l+eNtKKfgwKBgHlT55UumdhMpBIdubbzWO/JErLSyhG2Ihb7lc1T1sPcKUGK+ZRVvHSrNgRBCN66LkNidwTDZ1FiTmZcIekUaaHX6trQAwoZmpQT9ghpqxdIOzebquhuFGUt3Knr8I2j/jFAuWGrKXGO7vMxNl/2H7cXmetH6KIhpV3uPxRExG6BAoGAdQW8Ta+9DnGR+G/W++iV6uXbWykEsd0tveSX/hkmUCkIiFNMc3MI+iMmxqqHtCStNDP/7aoaJpamsrnbRkPRv8w7AJnjQZIYtgI3RiAos7G5s4NpACluhhXv2mnWi6kOm4l3daLHW+2URsC886xIiTepaNTrkqmgl34nMHWtUicCgYEAnVP9FogNzu+M3Kw5PvUKbnyn5g5asKICsybEa4eCFJjre90EMZO2/sPWNF7W2m6xJXSo6MwM2N3asVNyvpXcHnYb/c/OjRnYsdV2umWDrofxpboqeQMMHF+xHPyAxlt87kV1oLj9Omp6STb3gU+sl6VwPQQbWIJOkHJGhYJm1LQ=',
            // 设置应用私钥后,即可下载得到以下3个证书
            // 必填-应用公钥证书 路径
            'app_public_cert_path' => realpath(app()->getRootPath().'/public/cert/appCertPublicKey_2021004144642003.crt'),
            // 必填-支付宝公钥证书 路径
            'alipay_public_cert_path' => realpath(app()->getRootPath().'public/cert/alipayCertPublicKey_RSA2.crt'),
            // 必填-支付宝根证书 路径
            'alipay_root_cert_path' => realpath(app()->getRootPath().'public/cert/alipayRootCert.crt'),

            'return_url' => '',
            'notify_url' => Request::domain().'/api/pay/notifyAliPay',
            // 选填-第三方应用授权token
            'app_auth_token' => '',
            // 选填-服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
            'service_provider_id' => '',
            // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
            'mode' => Pay::MODE_NORMAL,
        ]

//        'default' => [
//            // 必填-支付宝分配的 app_id
//            'app_id' => '9021000139627530', //沙箱
//            // 必填-应用私钥 字符串或路径
//            // 在 https://open.alipay.com/develop/manage 《应用详情->开发设置->接口加签方式》中设置
//            'app_secret_cert' => 'MIIEowIBAAKCAQEAl4ZZMKaXHGtKbvk1q80op/kw9vC8kXGmnNwkXdEVJIxiVE6GDD6qGHiKRrctGRvsr3qZ4YgFUAHRyefiZ04LDB8CFrUTcfWnzP+uGvQ93AB18OOGVeWUPzN2Q0eHsb3l9ZF5Fx6u7voKVnWf1Eh7oYMx7/5i/V6SBqBZ0H8HvpGoXXx+ejIL69IuudzsHTqlmsj3Za8+1h83Z/VFWPNP4rGRfAhqv+YEgDKFg0q6GSMRp+PoAwBzVEdkzPIju+gHLtJXdeuXNIFNdYRLI2UlkKf8PYbMo15JQh+6OBGGYj8ivIKfreptDbYvqTVWozP6G7Zy4s16TW90O+P5Uma/9wIDAQABAoIBABkqEr3lrMrndqEfei5iEBJ1bBBWwrpU6Zq7ZL6/7ob3WY0uzUxTS+RsgGpmGXNGE/TAo7W05Uz4QGMLw6nsaCFHNQ2YXPZcGdYN0Fhhn7RdzziGUNULH6evYECkLID0TLCPzFBupBbEJ9tcBYM31nBoXW7CDKaPgijfkIrzzdF0FCefRYD/lYUiXRtQHdGO8dMU+MAfClqxXGpn8naorCo6m/hAGQS2BBJBsBNvbBw8Oj6I5w8wTkOOcDx539CHUwMK7lCY4+AF2OwAAfIzImR8Ikb0TkrxUtwUeBzZ2Av2aJE/mHct1OoJMQkRGVIZg6eb8SVLXNHoxgqDjaney0ECgYEA90UMG/lkQksqd5EaLtJ950l1r0kxE5NcKUyCGYqK95qdA8A+ry34m3u5LiRVGGZKdVMmsUDY5NnzMHYSum7ZKcaY04URSX5M8jx2rMHllULcsVGoYo0ywho2RyR1kATr1uPVBRA4ywN2wlaD7Y8oOaRzLFrmnr7wBbPAVKGAh1kCgYEAnN/omLBKS1noTD3OeSLsFOumXGhUJlPkSZK9GZZCpSxayC+aSPU1LVzGz5Upw6uwGLzovKLvEpLeOqsfGUYdvaU9JxeKIjlQ11559OKmH7IG+G6VYGnpuLRkybIv7xPiAf/QF5ZNJmsCe6oj2nec+YxAt68HRD28rlY82nkY588CgYEA12sRBKH9hX/EjIweOmJpC4FFBKOIHNzJcrVTtnqrXNEXL3hhY+5x4ssj5h4DAJHFFneNgujSzHVQV4zV/hOqH6oD5GrOR6+/y11/qjv2DlZEvDo+rzUB3nZFiS8rOIABEqJEJ/gc8kifQulqYCDS030AVckPl4cSxnT1/wUAW2kCgYBr7lm3g8L56Ne8bOG70l0fX6pL9bO/0wRD4mOcURd1UPj8tlOuUpbNqQFYHMZpS5ySyJZQAsH9w3KGZum0l9sqeZ+DX9y4AzstkmDSLYYiVHgbQOohNX2KiQK3CpOUJ9fdjEV9lPlrr0A8GSklzBoCT47PUerr9pX0VHz1y09pXQKBgEs8F5zBFE746UARvfVuw8bRhVbpgexAjQtr2h2pqtmgp+hpfWJ/AF7LKJe1LXpAO8F53/BkDmtgeCsxFMtj4PrcZ3GmjSV2rij5O7YPhyrypBn8z8RuQ+u1G/GW05K0PCaTKOKzvSJwP+m/LcLLQKR6plY8Ouq/FZThNfyrgz9u',
//            // 设置应用私钥后,即可下载得到以下3个证书
//            // 必填-应用公钥证书 路径
//            'app_public_cert_path' => realpath(app()->getRootPath().'/public/certsx/appPublicCert.crt'),
//            // 必填-支付宝公钥证书 路径
//            'alipay_public_cert_path' => realpath(app()->getRootPath().'public/certsx/alipayPublicCert.crt'),
//            // 必填-支付宝根证书 路径
//            'alipay_root_cert_path' => realpath(app()->getRootPath().'public/certsx/alipayRootCert.crt'),
//
//            'return_url' => 'https://yansongda.cn/alipay/return',
//            'notify_url' => 'http://'.$_SERVER['HTTP_HOST'].'/api/pay/notifyAliPay',
//            // 选填-第三方应用授权token
//            'app_auth_token' => '',
//            // 选填-服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
//            'service_provider_id' => '',
//            // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
//            'mode' => Pay::MODE_SANDBOX,
//        ]

    ],
    'http' => [ // optional
        'timeout' => 5.0,
        'connect_timeout' => 5.0,
        // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
    ],
];

3.具体业务代码实现

3.1 下单
3.1.1 控制器
    /**
     * @return \think\response\Json
     * @notes 下单
     * @author ssx
     */
    public function pay()
    {
        $param = request()->param();
        $result = PayLogic::pay($this->userId,$this->userInfo,$param);
        if (false === $result) {
            return $this->fail(PayLogic::getError());
        }
        return $this->success('下单成功。', $result->getBody()->getContents());
    }
3.1.2 业务层
    public static function pay(int $userId,array $userInfo,array $param)
    {
        Db::startTrans();
        try {
            $payType =  $param['pay_type']??1;
            $money = $param['money'];
            //根据自己的实际项目需求去生成订单以及处理一些其它相关业务
            $sn = "c".date('mdHis').$userId.rand(100,999);
            $id = Db::table('ap_charge')->insertGetId([
                "sn"=>$sn,
                //。。。
            ]);
            if ($id) {
                switch ($payType) {
                    case 1: //微信
                        $res = self::wxPay($sn,$money);
                        break;
                    case 2: //支付宝
                        $res = self::aliPay($sn,$money);
                        break;
                    default:
                        self::$error = "变量payType值有误。";
                        // 回滚事务
                        Db::rollback();
                        return false;
                }
                // 提交事务
                Db::commit();
                return $res;
            }
            self::$error = "订单生成失败。";
            // 回滚事务
            Db::rollback();
            return false;
        } catch (\Exception $e) {
            self::setError($e->getMessage());
            // 回滚事务
            Db::rollback();
            return false;
        }
    }


    protected static function wxPay($sn,$money){
        Pay::config(Config::get("pay"));
        $order = [
            'out_trade_no' => $sn,
            'description' => '充值',
            'amount' => [
                'total' => $money * 100,
            ],
        ];
        // 将返回 json 格式,供后续 APP 调用,调用方式不在本文档讨论范围内,请参考官方文档。
        return Pay::wechat()->app($order);
    }

    protected static function aliPay($sn,$money){
        Pay::config(Config::get("pay"));
        // 注意返回类型为 Response,具体见详细文档
        return Pay::alipay()->app([
            'out_trade_no' => $sn,
            'total_amount' => $money,
            'subject' => '充值',
        ]);
    }

3.2 APP客户端用3-1-1中返回的参数去调起支付宝和微信支付进行支付
3.3退款
3.3.1 控制器
    /**
     * @return \think\response\Json
     * @notes 退款
     * @author ssx
     */
    public function refund(){
        $param = request()->param();
        $result = RechargeLogic::refund($this->adminId,$param);
        if (false === $result) {
            return $this->fail(RechargeLogic::getError());
        }
        return $this->success('请求成功', $result);
    }
3.3.2 业务层 
    public static function refund(int $adminId,array $param){
        // 启动事务
        Db::startTrans();
        try {
            if(empty($param['id'])){
                throw new \Exception("id参数不能为空。");
            }
            $orderInfo = Recharge::where(['ap_charge.id'=>$param['id'],'status'=>2])
                ->leftJoin('ap_mini_program amp','ap_charge.source = amp.code')
                ->field("ap_charge.id,sn,money,pay_type,amp.type")->find();
            if(!$orderInfo){
                throw new \Exception("id参数有误。");
            }

            $outsn = "o" . date('YmdHis') . $adminId . rand(100,999);
            Recharge::where('id',$orderInfo['id'])->update(['outsn' => $outsn,'out_status'=>1]); //out_status 1退款中 2已退款

            switch ($orderInfo['pay_type']) {
                case 1: //微信
                    throw new \Exception("app微信退款-待开发");
                case 2: //支付宝
                    self::aliPayRefund($orderInfo,$outsn);
                    break;
                default:
                    throw new \Exception("pay_type值有误");
            }

            // 提交事务
            Db::commit();
            return true;
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            self::$error = $e->getMessage();
            return false;
        }
    }

    protected static function aliPayRefund($orderInfo,$outsn):void
    {
        Pay::config(Config::get("pay"));
        $result = Pay::alipay()->refund([
            'out_trade_no' => $orderInfo['sn'],
            'refund_amount' => $orderInfo['money'],
            'out_request_no' => $outsn,
            '_action' => 'app', // 退款 APP 订单
        ])->toArray();
        if($result['code'] != 10000 || $result['msg'] != "Success"){
            throw new \Exception($result['sub_msg']);
        }
    }

3.4 异步回调处理
3.4.1 控制器代码
    /**
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Yansongda\Artful\Exception\ContainerException
     * @notes 微信回调
     * @author ssx
     */
    public function notifyWxPay()
    {
        Pay::config(Config::get("pay"));
        PayLogic::notifyWxPay();
        return Pay::wechat()->success();
    }

    /**
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Yansongda\Artful\Exception\ContainerException
     * @notes 支付宝回调
     * @author ssx
     */
    public function notifyAliPay()
    {
        try {
            Pay::config(Config::get("pay"));
            PayLogic::notifyAliPay();
            echo 'success';die;
        } catch (\Exception $e) {
            Log::channel('pay')->write("支付宝异步回调发生错误: " . $e->getMessage(),'error');
            return false;
        }
    }
3.4.2 业务层代码
    public static function notifyAliPay(): bool
    {
        try {
            Pay::config(Config::get("pay"));
            $data = Pay::alipay()->callback()->toArray();
            if ($data['trade_status'] == 'TRADE_SUCCESS') {//交易成功
                Log::channel('pay')->write("支付宝支付-支付成功-回调数据: " . json_encode($data,JSON_UNESCAPED_UNICODE));
                return self::extracted($data); //处理具体的业务
            }elseif($data['trade_status'] == 'TRADE_CLOSED'){//交易关闭
                Log::channel('pay')->write("支付宝支付-退款成功-回调数据: " . json_encode($data,JSON_UNESCAPED_UNICODE));
                if(isset($data['refund_fee']) && isset($data['gmt_refund'])){//退款
                    //含有refund_fee(总退款金额)、gmt_refund(交易退款时间)参数
                    return self::notifyAliPayRefund($data); //处理具体的业务
                }
            }
            Log::channel('pay')->write("支付宝支付-其它-回调数据: " . json_encode($data,JSON_UNESCAPED_UNICODE));
            Db::table('ap_charge')->where(['sn' => $data['out_trade_no']])->update(['status' => 0]);
//            CouponLogic::setUsedCouponLog($data['out_trade_no'], 0);
            return true;
        }catch (\Exception $e) {
            Log::channel('pay')->write("支付宝异步回调发生错误: " . $e->getMessage(),'error');
            return false;
        }
    }

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值