IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> Thinkphp6微信App支付APIV3对接流程 -> 正文阅读

[PHP知识库]Thinkphp6微信App支付APIV3对接流程

  1. 安装微信支付sdk我这里使用的是wechatpay-php。
    直接使用命令:composer require wechatpay/wechatpay
    安装php微信支付sdk
  2. 生成平台证书,这里取参考微信支付github文档说明
    下载证书工具
    在这里插入图片描述
    生成平台证书
    生成文件
  3. 创建唤起微信支付数据以api接口方式返回给app端。
    public function wechatArousePay()
    {
        $order_id     = $this->request->post('order_id/d', null);
        $order_number = $this->request->post('order_number/s', null);
        if (!$order_id and !$order_number) {
            return self::fail('订单ID或订单号必须存在其中一个');
        }
        $order_map = array(
            ['uid', '=', $this->userinfo['account']],
            ['pay_state', '<>', 20]
        );
        if ($order_id) {//订单ID
            $order_map[] = ['order_id', '=', $order_id];
        }
        if ($order_number) {//订单号
            $order_map[] = ['order_number', '=', $order_number];
        }
        $order_info = Order::where($order_map)->find();
        if (!$order_info) {
            return self::fail('该项目不存在或已支付');
        }
        if ($order_info['total_price'] <= 0) {
            return self::fail('订单支付金额不合法!');
        }
        $PaymentAmount = bcmul($order_info['total_price'], 100, 0);
        // 商户号,假定为`1000100`
        $merchantId = config('wechatpay.mch_id');
        // 商户私钥,文件路径假定为 `/path/to/merchant/apiclient_key.pem`
        // 这里是微信商户端生成的私钥将整个文件放在wechatpay文件夹下
        $merchantPrivateKeyFilePath = public_path() . 'wechatpay/apiclient_key.pem';
        // 加载商户私钥
        $merchantPrivateKeyInstance = PemUtil::loadPrivateKey($merchantPrivateKeyFilePath);
        // 商户证书,文件路径假定为 `/path/to/merchant/apiclient_cert.pem`
        // 这里是微信商户端生成的公钥将整个文件放在wechatpay文件夹下
        $merchantCertificateFilePath = public_path() . 'wechatpay/apiclient_cert.pem';
        // 加载商户证书
        $merchantCertificateInstance = PemUtil::loadCertificate($merchantCertificateFilePath);
        // 解析商户证书序列号
        $merchantCertificateSerial = PemUtil::parseCertificateSerialNo($merchantCertificateInstance);
        // 平台证书,可由下载器 `./bin/CertificateDownloader.php` 生成并假定保存为 `/path/to/wechatpay/cert.pem`
        $platformCertificateFilePath = public_path() . 'wechatpay/cert.pem';
        // 加载平台证书
        $platformCertificateInstance = PemUtil::loadCertificate($platformCertificateFilePath);
        // 解析平台证书序列号
        $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateInstance);
        // 工厂方法构造一个实例
        $instance = Builder::factory([
            'mchid'      => $merchantId,
            'serial'     => $merchantCertificateSerial,
            'privateKey' => $merchantPrivateKeyInstance,
            'certs'      => [
                $platformCertificateSerial => $platformCertificateInstance,
            ],
        ]);
        try {
            $resp        = $instance
                ->v3->pay->transactions->app
                ->post(['json' => [
                    'appid'        => config('wechatpay.wchat_app_id'),
                    'mchid'        => $merchantId,
                    'description'  => $order_info['remark'],
                    'out_trade_no' => $order_info['order_number'],
                    'notify_url'   => config('wechatpay.notify_url') . '/client/xxxx.ClientPay/weiChatNotify',
                    'amount'       => [
                        'total'    => (int)$PaymentAmount,
                        'currency' => 'CNY'
                    ],
                ]]);
            $result_code = $resp->getStatusCode();
            if ($result_code == 200) {
                $result_data         = json_decode($resp->getBody(), true);
                $arouse_data         = [
                    'appid'     => config('wechatpay.wchat_app_id'),
                    'partnerid' => $merchantId,
                    'prepayid'  => $result_data['prepay_id'],
                    'package'   => "Sign=WXPay",
                    'noncestr'  => MD5($order_info['order_number']),
                    'timestamp' => get_now_time(),
                ];
                $arouse_data['sign'] = Rsa::sign(
                    Formatter::joinedByLineFeed(...array_values($arouse_data)),
                    $merchantPrivateKeyInstance
                );
                return self::successful('success', $arouse_data);
            }
        } catch (\Exception $exception) {
            // 进行错误处理
            if ($exception instanceof \GuzzleHttp\Exception\RequestException && $exception->hasResponse()) {
                $r = $exception->getResponse();
                return self::result($r->getStatusCode(), $r->getReasonPhrase());
            }
        }
    }
  1. ApiPost模拟数据。
    在这里插入图片描述
  2. 数据回调。
    public function weiChatNotify()
    {
        //接收返回参数json数据转数组
        $get_content = json_decode(file_get_contents('php://input'), true);
        //将接收到的数据存入文件中
        $file_directory3 = public_path() . '/wei_chat_notify.txt';
        file_put_contents($file_directory3, file_get_contents('php://input'));
        //将接收到的数据解密
        $result_content = AesGcm::decrypt($get_content['resource']['ciphertext'], config('wechatpay.apiv3'), $get_content['resource']['nonce'], $get_content['resource']['associated_data']);
        //将json数据转数组
        $content = json_decode($result_content, true);
        //验签订单
        $result_data = $this->authWeiChatOrder($content);
        if (!$result_data) {
            exit('FAIL');
        }
        $Order = new Order();
        $Order::startTrans();
        $order_info   = $result_data['order'];//订单信息
        $payment_info = $result_data['body'];//订单支付信息
        try {
            $chang_data               = array(
                'pay_state'      => 20,//支付状态
                'pay_style'      => 20,//支付方式
                'pay_time'       => strtotime($payment_info['time_end']),//支付完成时间
                'payment_price'  => bcdiv($payment_info['total_fee'], 100, 2),//支付金额
                'transaction_id' => $payment_info['transaction_id'],//微信支付订单号
                'openid'         => $payment_info['openid'],//微信用户openid
                'notify_json'    => $payment_info
            );
            $chang_data['need_price'] = bcsub($order_info['total_price'], $chang_data['payment_price'], 2);
            $result                   = $Order->where([['order_id', '=', $order_info['order_id']]])->update($chang_data);
            if ($result) {
                $Order::commitTrans();
                exit("SUCCESS");
            }
            throw new Exception('操作失败');
        } catch (\Exception $exception) {
            $Order::rollbackTrans();
            exit("FAIL");
        }
    }
  1. 订单校验。
    public function authWeiChatOrder(array $arr)
    {
        if (!$arr) {
            return null;
        }
        $order_info = Order::where([['order_number', '=', $arr['out_trade_no']]])->find();
        if (!$order_info) {
            return null;
        }
        $OrderQueryUrl  = 'https://api.mch.weixin.qq.com/pay/orderquery';
        $OrderQueryBody = array_filter([
            'appid'          => config('wechatpay.wchat_app_id'),//String(32) # 必填 # 微信分配的小程序ID',
            'mch_id'         => config('wechatpay.mch_id'),//String(32) # 必填 # 微信支付分配的商户号',
            'transaction_id' => $arr['transaction_id'], // String(32) # 与 out_trade_no 二选一 # 微信的订单号,优先使用',
            'out_trade_no'   => $arr['out_trade_no'],//String(32)#与transaction_id二选一#商户系统内部订单号详见商户订单号',
            'nonce_str'      => MD5($arr['out_trade_no']), // String(32) # 必填 # 随机字符串,不长于32位。推荐随机数生成算法',
            'sign_type'      => 'MD5', // String(32) # 选填 # 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5',
        ]);
        // 生成验证签名
        $OrderQueryBody['sign'] = $this->genSign($OrderQueryBody, config('wechatpay.key'));
        //将数组转xml数据
        $xmlContext = $this->ArrayToXml($OrderQueryBody);
        //post发送请求
        $request = $this->ConnCurlSend($OrderQueryUrl, '', $xmlContext, 'POST');
        //将xml数据转数组
        $reqContext = $this->XmlToArray($request);
        if ($reqContext['return_code'] == 'SUCCESS' && $reqContext['result_code'] == 'SUCCESS' && $reqContext['return_msg'] == 'OK') {
            return [
                'order' => $order_info,
                'body'  => $reqContext,
            ];
        }
        return null;
    }
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 11:49:47  更:2021-08-19 11:52:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/15 0:28:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码