chengkun
2025-09-15 cff43dbd99d99189864acd591f856a38e87c5b09
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<?php
 
namespace pay;
 
use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;
use think\facade\Config;
 
 
class Weixin {
    private $config;
    /**
     * 获取缓存配置
     * @access public
     * @param null|string $name    名称
     * @param mixed       $default 默认值
     * @return mixed
     */
    public function getConfig(string $name = null, $default = null)
    {
        if (!is_null($name)) {
            return Config::get('pay.' . $name, $default);
        }
        return Config::get('pay');
    }
 
    /**
     * 获取支付宝配置
     */
    private function getOptions() {
        $this->config = $this->getConfig('payment.weixin');
        echo $this->config['platformCertificateFilePath']."\n<br>\n";
//        exit();
        $merchantPrivateKeyInstance = Rsa::from($this->config['merchantPrivateKeyFilePath'], Rsa::KEY_TYPE_PRIVATE);
 
        $platformPublicKeyInstance = Rsa::from($this->config['platformCertificateFilePath'], Rsa::KEY_TYPE_PUBLIC);
        // 从「微信支付平台证书」中获取「证书序列号」
        $platformCertificateSerial = PemUtil::parseCertificateSerialNo($this->config['platformCertificateFilePath']);
        // 构造一个 APIv3 客户端实例
        $instance = Builder::factory([
            'mchid'      => $this->config['merchantId'],
            'serial'     => $this->config['merchantCertificateSerial'],
            'privateKey' => $merchantPrivateKeyInstance,
            'certs'      => [
                $platformCertificateSerial => $platformPublicKeyInstance,
            ],
        ]);
        return $instance;
    }
 
    /**
     * pc Native支付下单, 生成二维码地址
     */
    public function pcPay(int $payOrderNo, float $amount, string $currencyType, int $payTimeUnix, string $description)  {
        try {
            $payTime = date('Y-m-d', $payTimeUnix).'T'.date('H:i:s', $payTimeUnix).'+08:00';
            $instance = $this->getOptions();
            // 发送请求
//            $resp = $instance->chain('v3/certificates')->get(
//                ['debug' => true] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug
//            );
//            echo $resp->getBody(), PHP_EOL;
//            echo $description;
//            exit();
            //同步请求 Native支付下单
            $total = $amount*100;
            $resp = $instance
                ->chain('v3/pay/transactions/native')
                ->post(['json' => [
                    'mchid'        => $this->config['merchantId'], // 直连商户号
                    'out_trade_no' => (string)$payOrderNo, //商户订单号 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
                    'appid'        => $this->config['appId'], // 应用ID
                    'description'  => $description, //商品描述
                    // 通知URL必须为直接可访问的URL,不允许携带查询串,要求必须为https地址。 格式:URL
                    // 示例值:https://www.weixin.qq.com/wxpay/pay.php
                    'notify_url'   => $this->config['notifyUrl'],
                    // 订单失效时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
                    // 示例值:2018-06-08T10:34:56+08:00
                    'time_expire'   => $payTime,
                    'amount'       => [
                        //订单总金额,单位为分。示例值:100
                        'total'    => (int)$total,
                        // CNY:人民币,境内商户号仅支持人民币。示例值:CNY
                        'currency' => $currencyType
                    ],
                ]]);
 
            echo $resp->getStatusCode(), PHP_EOL;
            echo $resp->getBody(), PHP_EOL;
 
        } catch (\Exception $e) {
            // 进行错误处理
            echo $e->getMessage(), PHP_EOL;
            if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
                $r = $e->getResponse();
                echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
                echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
            }
            echo $e->getTraceAsString(), PHP_EOL;
        }
 
    }
}