微信支付 API v3 的 PHP Library,同时也支持 API v2

Overview

微信支付 WeChatPay OpenAPI SDK

[A]Sync Chainable WeChatPay v2&v3's OpenAPI SDK for PHP

GitHub actions Packagist Stars Packagist Downloads Packagist Version Packagist PHP Version Support Packagist License

概览

微信支付 APIv2&APIv3 的Guzzle HttpClient封装组合, APIv2已内置请求数据签名及XML转换器,应答做了数据签名验签,转换提供有WeChatPay\Transformer::toArray静态方法,按需转换; APIv3已内置 请求签名应答验签 两个middleware中间件,创新性地实现了链式面向对象同步/异步调用远程接口。

如果你是使用 Guzzle 的商户开发者,可以使用 WeChatPay\Builder 工厂方法直接创建一个 GuzzleHttp\Client 的链式调用封装器, 实例在执行请求时将自动携带身份认证信息,并检查应答的微信支付签名。

项目状态

当前版本为1.0.5测试版本。请商户的专业技术人员在使用时注意系统和软件的正确性和兼容性,以及带来的风险。

环境要求

我们开发和测试使用的环境如下:

  • PHP >=7.2
  • guzzlehttp/guzzle ^7.0

注:Guzzle7支持的PHP版本最低为7.2.5,另PHP官方已于30 Nov 2020停止维护PHP7.2,详见附注链接。

安装

推荐使用PHP包管理工具composer引入SDK到项目中:

方式一

在项目目录中,通过composer命令行添加:

composer require wechatpay/wechatpay

方式二

在项目的composer.json中加入以下配置:

"require": {
    "wechatpay/wechatpay": "^1.0.5"
}

添加配置后,执行安装

composer install

约定

本类库是以 OpenAPI 对应的接入点 URL.pathname/做切分,映射成segments,编码书写方式有如下约定:

  1. 请求 pathname 切分后的每个segment,可直接以对象获取形式串接,例如 v3/pay/transactions/native 即串成 v3->pay->transactions->native;
  2. 每个 pathname 所支持的 HTTP METHOD,即作为被串接对象的末尾执行方法,例如: v3->pay->transactions->native->post(['json' => []]);
  3. 每个 pathname 所支持的 HTTP METHOD,同时支持Async语法糖,例如: v3->pay->transactions->native->postAsync(['json' => []]);
  4. 每个 segment 有中线(dash)分隔符的,可以使用驼峰camelCase风格书写,例如: merchant-service可写成 merchantService,或如 {'merchant-service'};
  5. 每个 segment 中,若有uri_template动态参数,例如 business_code/{business_code} 推荐以business_code->{'{business_code}'}形式书写,其格式语义与pathname基本一致,阅读起来比较自然;
  6. SDK内置以 v2 特殊标识为 APIv2 的起始 segmemt,之后串接切分后的 segments,如源 pay/micropay 即串成 v2->pay->micropay->post(['xml' => []]) 即以XML形式请求远端接口;
  7. 在IDE集成环境下,也可以按照内置的chain($segment)接口规范,直接以pathname作为变量$segment,来获取OpenAPI接入点的endpoints串接对象,驱动末尾执行方法(填入对应参数),发起请求,例如 chain('v3/pay/transactions/jsapi')->post(['json' => []])

以下示例用法,以异步(Async/PromiseA+)同步(Sync)结合此种编码模式展开。

Note of the segments: See RFC3986 #section-3.3

A path consists of a sequence of path segments separated by a slash ("/") character.

Note of the uri_template: See RFC6570

开始

首先,通过 WeChatPay\Builder 工厂方法构建一个实例,然后如上述约定,链式同步异步请求远端OpenAPI接口。

use WeChatPay\Builder;
use WeChatPay\Util\PemUtil;

// 工厂方法构造一个实例
$instance = Builder::factory([
    // 商户号
    'mchid' => '1000100',
    // 商户证书序列号
    'serial' => 'XXXXXXXXXX',
    // 商户API私钥 PEM格式的文本字符串或者文件resource
    'privateKey' => PemUtil::loadPrivateKey('/path/to/mch/apiclient_key.pem'),
    'certs' => [
        // 可由内置的平台证书下载器 `./bin/CertificateDownloader.php` 生成
        'YYYYYYYYYY' => PemUtil::loadCertificate('/path/to/wechatpay/cert.pem')
    ],
    // APIv2密钥(32字节)--不使用APIv2可选
    'secret' => 'ZZZZZZZZZZ',
    'merchant' => [// --不使用APIv2可选
        // 商户证书 文件路径 --不使用APIv2可选
        'cert' => '/path/to/mch/apiclient_cert.pem',
        // 商户API私钥 文件路径 --不使用APIv2可选
        'key' => '/path/to/mch/apiclient_key.pem',
    ],
]);

初始化字典说明如下:

  • mchid 为你的商户号,一般是10字节纯数字
  • serial 为你的商户证书序列号,一般是40字节字符串
  • privateKey 为你的商户API私钥,一般是通过官方证书生成工具生成的文件名是apiclient_key.pem文件,支持纯字符串或者文件resource格式
  • certs[$serial_number => #resource] 为通过下载工具下载的平台证书key/value键值对,键为平台证书序列号,值为平台证书pem格式的纯字符串或者文件resource格式
  • secret 为APIv2版的密钥,商户平台上设置的32字节字符串
  • merchant[cert => $path] 为你的商户证书,一般是文件名为apiclient_cert.pem文件路径,接受[$path, $passphrase] 格式,其中$passphrase为证书密码
  • merchant[key => $path] 为你的商户API私钥,一般是通过官方证书生成工具生成的文件名是apiclient_key.pem文件路径,接受[$path, $passphrase] 格式,其中$passphrase为私钥密码

注: APIv3, APIv2 以及 GuzzleHttp\Client$config = [] 初始化参数,均融合在一个型参上; 另外初始化参数说明中的平台证书下载器可阅读使用说明文档

APIv3

Native下单

try {
    $resp = $instance->v3->pay->transactions->native->post(['json' => [
        'mchid' => '1900006XXX',
        'out_trade_no' => 'native12177525012014070332333',
        'appid' => 'wxdace645e0bc2cXXX',
        'description' => 'Image形象店-深圳腾大-QQ公仔',
        'notify_url' => 'https://weixin.qq.com/',
        'amount' => [
            'total' => 1,
            'currency' => 'CNY'
        ],
    ]]);

    echo $resp->getStatusCode() . ' ' . $resp->getReasonPhrase(), PHP_EOL;
    echo $resp->getBody(), PHP_EOL;
} catch (Exception $e) {
    // 进行错误处理
    echo $e->getMessage(), PHP_EOL;
    if ($e instanceof \Psr\Http\Message\ResponseInterface && $e->hasResponse()) {
        echo $e->getResponse()->getStatusCode() . ' ' . $e->getResponse()->getReasonPhrase(), PHP_EOL;
        echo $e->getResponse()->getBody();
    }
}

查单

$res = $instance->v3->pay->transactions->id->{'{transaction_id}'}
->getAsync([
    // 查询参数结构
    'query' => ['mchid' => '1230000109'],
    // uri_template 字面量参数
    'transaction_id' => '1217752501201407033233368018',
])
->then(static function($response) {
    // 正常逻辑回调处理
    echo $response->getBody()->getContents(), PHP_EOL;
    return $response;
})
->otherwise(static function($exception) {
    // 异常错误处理
    if ($exception instanceof \Psr\Http\Message\ResponseInterface) {
        $body = $exception->getResponse()->getBody();
        echo $body->getContents(), PHP_EOL, PHP_EOL, PHP_EOL;
    }
    echo $exception->getTraceAsString(), PHP_EOL;
})
->wait();

关单

$res = $instance->v3->pay->transactions->outTradeNo->{'{out_trade_no}'}->close
->postAsync([
    // 请求参数结构
    'json' => ['mchid' => '1230000109'],
    // uri_template 字面量参数
    'out_trade_no' => '1217752501201407033233368018',
])
->then(static function($response) {
    // 正常逻辑回调处理
    echo $response->getBody()->getContents(), PHP_EOL;
    return $response;
})
->otherwise(static function($exception) {
    // 异常错误处理
    if ($exception instanceof \Psr\Http\Message\ResponseInterface) {
        $body = $exception->getResponse()->getBody();
        echo $body->getContents(), PHP_EOL, PHP_EOL, PHP_EOL;
    }
    echo $exception->getTraceAsString(), PHP_EOL;
})
->wait();

退款

$res = $instance->chain('v3/refund/domestic/refunds')
->postAsync([
    'json' => [
        'transaction_id' => '1217752501201407033233368018',
        'out_refund_no' => '1217752501201407033233368018',
        'amount' => [
            'refund' => 888,
            'total' => 888,
            'currency' => 'CNY',
        ],
    ],
])
->then(static function($response) {
    // 正常逻辑回调处理
    echo $response->getBody()->getContents(), PHP_EOL;
    return $response;
})
->otherwise(static function($exception) {
    // 异常错误处理
    if ($exception instanceof \Psr\Http\Message\ResponseInterface) {
        $body = $exception->getResponse()->getBody();
        echo $body->getContents(), PHP_EOL, PHP_EOL, PHP_EOL;
    }
    echo $exception->getTraceAsString(), PHP_EOL;
})
->wait();

视频文件上传

// 参考上述指引说明,并引入 `MediaUtil` 正常初始化,无额外条件
use WeChatPay\Util\MediaUtil;
// 实例化一个媒体文件流,注意文件后缀名需符合接口要求
$media = new MediaUtil('/your/file/path/video.mp4');

try {
    $resp = $instance['v3/merchant/media/video_upload']->post([
        'body'    => $media->getStream(),
        'headers' => [
            'content-type' => $media->getContentType(),
        ]
    ]);
    echo $resp->getStatusCode() . ' ' . $resp->getReasonPhrase(), PHP_EOL;
    echo $resp->getBody(), PHP_EOL;
} catch (Exception $e) {
    echo $e->getMessage(), PHP_EOL;
    if ($e instanceof \Psr\Http\Message\ResponseInterface && $e->hasResponse()) {
        echo $e->getResponse()->getStatusCode() . ' ' . $e->getResponse()->getReasonPhrase(), PHP_EOL;
        echo $e->getResponse()->getBody();
    }
}

图片上传

use WeChatPay\Util\MediaUtil;
$media = new MediaUtil('/your/file/path/image.jpg');
$resp = $instance->v3->marketing->favor->media->imageUpload
->postAsync([
    'body'    => $media->getStream(),
    'headers' => [
        'content-type' => $media->getContentType(),
    ]
])
->then(static function($response) {
    echo $response->getBody()->getContents(), PHP_EOL;
    return $response;
})
->otherwise(static function($exception) {
    if ($exception instanceof \Psr\Http\Message\ResponseInterface) {
        $body = $exception->getResponse()->getBody();
        echo $body->getContents(), PHP_EOL, PHP_EOL, PHP_EOL;
    }
    echo $exception->getTraceAsString(), PHP_EOL;
})
->wait();

敏感信息加/解密

// 参考上上述说明,引入 `WeChatPay\Crypto\Rsa`
use WeChatPay\Crypto\Rsa;
// 加载最新的平台证书
$publicKey = PemUtil::loadCertificate('/path/to/wechatpay/cert.pem');
// 做一个匿名方法,供后续方便使用
$encryptor = function($msg) use ($publicKey) { return Rsa::encrypt($msg, $publicKey); };

// 正常使用Guzzle发起API请求
try {
    // POST 语法糖
    $resp = $instance->chain('v3/applyment4sub/applyment/')->post([
        'json' => [
            'business_code' => 'APL_98761234',
            'contact_info'  => [
                'contact_name'      => $encryptor('value of `contact_name`'),
                'contact_id_number' => $encryptor('value of `contact_id_number'),
                'mobile_phone'      => $encryptor('value of `mobile_phone`'),
                'contact_email'     => $encryptor('value of `contact_email`'),
            ],
            //...
        ],
        'headers' => [
            // 命令行获取证书序列号
            // openssl x509 -in /path/to/wechatpay/cert.pem -noout -serial | awk -F= '{print $2}'
            // 或者使用工具类获取证书序列号 `PemUtil::parseCertificateSerialNo($certificate)`
            'Wechatpay-Serial' => '下载的平台证书序列号',
        ],
    ]);
    echo $resp->getStatusCode() . ' ' . $resp->getReasonPhrase(), PHP_EOL;
    echo $resp->getBody(), PHP_EOL;
} catch (Exception $e) {
    echo $e->getMessage(), PHP_EOL;
    if ($e instanceof \Psr\Http\Message\ResponseInterface && $e->hasResponse()) {
        echo $e->getResponse()->getStatusCode() . ' ' . $e->getResponse()->getReasonPhrase(), PHP_EOL;
        echo $e->getResponse()->getBody();
    }
    return;
}

APIv2

末尾驱动的 HTTP METHOD(POST) 方法入参 array $options,接受两个自定义参数,释义如下:

  • $options['nonceless'] - 标量 scalar 任意值,语义上即,本次请求不用自动添加nonce_str参数,推荐 boolean(True)
  • $options['security'] - 布尔量True,语义上即,本次请求需要加载ssl证书,对应的是初始化 array $config['merchant'] 结构体

企业付款到零钱

use WeChatPay\Transformer;
$res = $instance->v2->mmpaymkttransfers->promotion->transfers
->postAsync([
    'xml' => [
      'appid' => 'wx8888888888888888',
      'mch_id' => '1900000109',
      'partner_trade_no' => '10000098201411111234567890',
      'openid' => 'oxTWIuGaIt6gTKsQRLau2M0yL16E',
      'check_name' => 'FORCE_CHECK',
      're_user_name' => '王小王',
      'amount' => 10099,
      'desc' => '理赔',
      'spbill_create_ip' => '192.168.0.1',
    ],
    'security' => true,
    'debug' => true //开启调试模式
])
->then(static function($response) { return Transformer::toArray($response->getBody()->getContents()); })
->otherwise(static function($exception) { return Transformer::toArray($exception->getResponse()->getBody()->getContents()); })
->wait();
print_r($res);

常见问题

如何下载平台证书?

使用内置的平台证书下载器 ./bin/CertificateDownloader.php ,验签逻辑与有平台证书请求其他接口一致,即在请求完成后,立即用获得的平台证书对返回的消息进行验签,下载器同时开启了 Guzzledebug => true 参数,方便查询请求/响应消息的基础调试信息。

证书和回调解密需要的AesGcm解密在哪里?

请参考AesGcm.php

配合swoole使用时,上传文件接口报错

建议升级至swoole 4.6+,swoole在 4.6.0 中增加了native-curl(swoole/swoole-src#3863)支持,我们测试能正常使用了。 更详细的信息,请参考#36

联系我们

如果你发现了BUG或者有任何疑问、建议,请通过issue进行反馈。

也欢迎访问我们的开发者社区

链接

License

Apache-2.0 License

Comments
  • Call to undefined method think\\exception\\ErrorException::getResponse()

    Call to undefined method think\\exception\\ErrorException::getResponse()

    ->then(function($response) { // 正常逻辑回调处理 echo $response->getBody()->getContents(); return $response; }) ->otherwise(function($exception) { // 异常错误处理 $body = $exception->getResponse()->getBody(); echo $body->getContents(); // echo $exception->getTraceAsString(), PHP_EOL; })

    每次都进入otherwise

    提示Call to undefined method think\exception\ErrorException::getResponse()

    opened by yinmaosong123 17
  • php 使用 swoole报错。

    php 使用 swoole报错。

    curl-native 已经确认开启了。

    swoole

    Swoole => enabled Author => Swoole Team [email protected] Version => 4.8.9 Built => Apr 19 2022 22:22:56 coroutine => enabled with boost asm context epoll => enabled eventfd => enabled signalfd => enabled cpu_affinity => enabled spinlock => enabled rwlock => enabled sockets => enabled openssl => OpenSSL 1.0.2u 20 Dec 2019 curl-native => enabled pcre => enabled zlib => 1.2.7 mutex_timedlock => enabled pthread_barrier => enabled futex => enabled async_redis => enabled

    Directive => Local Value => Master Value swoole.enable_coroutine => On => On swoole.enable_library => On => On swoole.enable_preemptive_scheduler => Off => Off swoole.display_errors => On => On swoole.use_shortname => On => On swoole.unixsock_buffer_size => 8388608 => 8388608

    调用上传媒体素材报 WARNING ProcessPool::wait(): worker#3 abnormal exit, status=0, signal=11 ....

    GCC_VERSION: 4.8.5 20150623 (Red Hat 4.8.5-44) OPENSSL_VERSION: OpenSSL 1.0.2u 20 Dec 2019 PHP_VERSION : 7.4.28

    opened by zhlhuang 15
  • Cannot load privateKey from(/wechat/apiclient_key.pem).

    Cannot load privateKey from(/wechat/apiclient_key.pem).

    i am trying to implement wechat pay into one of my client website. Cannot load privateKey from(/wechat/apiclient_key.pem).

    but i am getting this error any suggestion

    question 
    opened by nabeelzqadri 9
  • 平台证书正常生成后,Fatal error: Uncaught UnexpectedValueException: Cannot load publicKey from(string), please take care about the \$thing input

    平台证书正常生成后,Fatal error: Uncaught UnexpectedValueException: Cannot load publicKey from(string), please take care about the \$thing input

    运行环境

    No response

    描述你的问题现象

    Fatal error: Uncaught UnexpectedValueException: Cannot load publicKey from(string), please take care about the \$thing input. in vendor\wechatpay\wechatpay\src\Crypto\Rsa.php:165 Stack trace: #0
    

    是否有明确错误提示,这提示不能加载publicKey, image

    用的https://github.com/wechatpay-apiv3/wechatpay-php/blob/main/bin/README.md 生成平台证书。

    opened by sunkangchina 8
  • 关于v2接口中间件强行要求验证sign字段问题

    关于v2接口中间件强行要求验证sign字段问题

    运行环境

    php:7.4
    wechatpay-php:1.4.2
    

    描述你的问题现象

    在使用此组件对接了大部分v3接口后,有些业务依然需要对接v2接口,比如“付款到零钱”接口。(https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2)

    这类接口的响应数据中,并没有sign字段,但ClientXmlTrait.php中设置了一个guzzlehttp的中间件方法static::transformResponse(),该方法必须验证body中的sign字段,当验证不通过或者字段不存在,此时会抛出一个RejectionException的异常。这导致了,即使接口返回业务正常响应(例如已经真实付款到用户零钱),依然抛这个错。目前唯一可以解决的方法,是在RejectionException的抛错中通过getReason()方法来找到返回业务正常的响应。

    提交了一个修改建议 #91

    good first issue 
    opened by dxkrs 8
  • 证书下载错误

    证书下载错误

    • Trying 14.215.140.116...
    • TCP_NODELAY set
    • Expire in 74995 ms for 3 (transfer 0x1ff75985080)
    • Expire in 200 ms for 4 (transfer 0x1ff75985080)
    • Connected to api.mch.weixin.qq.com (14.215.140.116) port 443 (#0)
    • ALPN, offering http/1.1
    • SSL certificate problem: unable to get local issuer certificate
    • Closing connection 0 cURL error 60: (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://api.mch.weixin.qq.com/v3/certificates #0 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php(158): GuzzleHttp\Handler\CurlFactory::createRejection(Object(GuzzleHttp\Handler\EasyHandle ), Array) #1 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php(110): GuzzleHttp\Handler\CurlFactory::finishError(Object(GuzzleHttp\Handler\CurlMultiHandl er), Object(GuzzleHttp\Handler\EasyHandle), Object(GuzzleHttp\Handler\CurlFactory)) #2 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\guzzle\src\Handler\CurlMultiHandler.php(236): GuzzleHttp\Handler\CurlFactory::finish(Object(GuzzleHttp\Handler\CurlMultiHandl er), Object(GuzzleHttp\Handler\EasyHandle), Object(GuzzleHttp\Handler\CurlFactory)) #3 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\guzzle\src\Handler\CurlMultiHandler.php(168): GuzzleHttp\Handler\CurlMultiHandler->processMessages() #4 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\guzzle\src\Handler\CurlMultiHandler.php(183): GuzzleHttp\Handler\CurlMultiHandler->tick() #5 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\promises\src\Promise.php(248): GuzzleHttp\Handler\CurlMultiHandler->execute(true) #6 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\promises\src\Promise.php(224): GuzzleHttp\Promise\Promise->invokeWaitFn() #7 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\promises\src\Promise.php(269): GuzzleHttp\Promise\Promise->waitIfPending() #8 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\promises\src\Promise.php(226): GuzzleHttp\Promise\Promise->invokeWaitList() #9 D:\phpstudy_pro\WWW\video_project\vendor\guzzlehttp\promises\src\Promise.php(62): GuzzleHttp\Promise\Promise->waitIfPending() #10 D:\phpstudy_pro\WWW\video_project\vendor\wechatpay\wechatpay\bin\CertificateDownloader.php(109): GuzzleHttp\Promise\Promise->wait() #11 D:\phpstudy_pro\WWW\video_project\vendor\wechatpay\wechatpay\bin\CertificateDownloader.php(47): CertificateDownloader->job(Array) #12 D:\phpstudy_pro\WWW\video_project\vendor\wechatpay\wechatpay\bin\CertificateDownloader.php(235): CertificateDownloader->run() #13 {main}
    opened by XuanDeMeng 7
  • 只是说这个sdk  微信开发sdk的人是傻逼没人会反驳吧

    只是说这个sdk 微信开发sdk的人是傻逼没人会反驳吧

    例子就行下面这个例子

    获取平台证书需要提供平台证书序列号和平台证书 不提供就报错 问? 老子不是在获取么 你都不给获取的机会就开始报错 这不是sb是什么

    // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名
    $platformCertificateFilePath = 'file:///path/to/wechatpay/cert.pem';
    $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
    
    // 从「微信支付平台证书」中获取「证书序列号」
    $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
    
    // 构造一个 APIv3 客户端实例
    $instance = Builder::factory([
        'mchid'      => $merchantId,
        'serial'     => $merchantCertificateSerial,
        'privateKey' => $merchantPrivateKeyInstance,
        'certs'      => [
            $platformCertificateSerial => $platformPublicKeyInstance,
        ],
    ]);
    
    // 发送请求
    $resp = $instance->chain('v3/certificates')->get(
        ['debug' => true] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug
    );
    
    opened by uvd 5
  • BuilderChainable chain 会把大写转化成小写的问题

    BuilderChainable chain 会把大写转化成小写的问题

    调用 BuilderChainable chain 会把大写转化成小写,例如查询订单需要拼上订单号,单订单号有大写的时候,会被转成小写 例如 N123123 会被转成功 -n123123 image

    使用链式的凡事也会被转化 $resp = $this->instance->v3->pay->partner->transactions->outTradeNo->{$out_trade_no}

    输出的是 n123123 不存在

    question 
    opened by zhlhuang 5
  • 接口URL的变量后面还有路径名称

    接口URL的变量后面还有路径名称

    老师,您好! 请问一下; https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter11_1_4.shtml 查询结算账户API 接口说明 适用对象:服务商 电商平台 请求URL:https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/{sub_mchid}/settlement 请求方式:GET 这样的URL变量后面还有参数,pathname应该怎么处理?

    question 
    opened by simosun 5
  • php7.2.1无法使用?

    php7.2.1无法使用?

    使用的是7.2.1的版本,composer报错如下:

    Your requirements could not be resolved to an installable set of packages.

    Problem 1 - wechatpay/wechatpay 1.0.2 requires guzzlehttp/guzzle ^7.0 -> satisfiable by guzzlehttp/guzzle[7.0.0, 7.0.1, 7.1.0, 7.1.1, 7.2.0, 7.3.0]. - wechatpay/wechatpay 1.0.3 requires guzzlehttp/guzzle ^7.0 -> satisfiable by guzzlehttp/guzzle[7.0.0, 7.0.1, 7.1.0, 7.1.1, 7.2.0, 7.3.0]. - wechatpay/wechatpay 1.0.1 requires php ^7.2.5 || ^8.0 -> your PHP version (7.2.1) does not satisfy that requirement. - wechatpay/wechatpay 1.0.0 requires php ^7.2.5 || ^8.0 -> your PHP version (7.2.1) does not satisfy that requirement. - guzzlehttp/guzzle 7.3.0 requires php ^7.2.5 || ^8.0 -> your PHP version (7.2.1) does not satisfy that requirement. - guzzlehttp/guzzle 7.2.0 requires php ^7.2.5 || ^8.0 -> your PHP version (7.2.1) does not satisfy that requirement. - guzzlehttp/guzzle 7.1.1 requires php ^7.2.5 -> your PHP version (7.2.1) does not satisfy that requirement. - guzzlehttp/guzzle 7.1.0 requires php ^7.2.5 -> your PHP version (7.2.1) does not satisfy that requirement. - guzzlehttp/guzzle 7.0.1 requires php ^7.2.5 -> your PHP version (7.2.1) does not satisfy that requirement. - guzzlehttp/guzzle 7.0.0 requires php ^7.2.5 -> your PHP version (7.2.1) does not satisfy that requirement. - Installation request for wechatpay/wechatpay ^1.0 -> satisfiable by wechatpay/wechatpay[1.0.0, 1.0.1, 1.0.2, 1.0.3].

    opened by henggedaren 5
  • 初始化参数`certs`键值对参数校验时为什么不能含商户证书序列号`merchantCertificateSerial`

    初始化参数`certs`键值对参数校验时为什么不能含商户证书序列号`merchantCertificateSerial`

    运行环境

    - OS:centos
    - PHP:7.4
    - wechatpay-php: src/ClientJsonTrait.php:222
    
    if (array_key_exists($config['serial'], $config['certs'])) {
                throw new Exception\InvalidArgumentException(sprintf(
                    Exception\ERR_INIT_CERTS_EXCLUDE_MCHSERIAL, implode(',', array_keys($config['certs'])), $config['serial']
                ));
            }
    
    这里应该是写反了,导致参数校验不通过。应该在前面加上 !。
    

    描述你的问题现象

    No response

    wontfix 
    opened by guoyuanchang 4
Releases(v1.4.8)
  • v1.4.8(Jan 5, 2023)

  • v1.4.7(Dec 6, 2022)

  • v1.4.6(Aug 19, 2022)

  • v1.4.5(May 23, 2022)

  • v1.4.4(May 19, 2022)

    • PHP内置函数hash方法在PHP8变更了返回值逻辑,代之为抛送ValueError异常,优化MediaUtilTest测试用例,以兼容PHP7;
    • 新增APIv2请求/响应白名单URL及调整验签逻辑,对于白名单内的请求,已知无sign返回,应用侧自动忽略验签;

    详情可查阅 CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.4.3(Jan 4, 2022)

    • 优化,严格限定初始化时 mchid 为字符串;
    • 优化,严格限定 chain() 接口函数入参为字符串;
    • 根据 RFC2616 规范,增加 Accept 头(电子回单/客诉图片 API)声明;

    详情可查阅 CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.4.2(Dec 2, 2021)

    • 优化Rsa::parse代码逻辑,去除is_resource/is_object检测;
    • 调整Rsa::from[Pkcs8|Pkcs1|Spki]加载语法糖实现,以Rsa::from为统一入口;
    • 优化ClientDecorator::request[Async]处理逻辑,优先替换URI Template变量,可支持短链模式调用接口;

    详情可查阅 CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.4.1(Nov 3, 2021)

    • 新增phpstan/phpstan:^1.0支持;
    • 优化代码,消除函数内部不安全的"Unsafe call to private|protected method|property ... through static::" 调用隐患;

    详情可查阅 CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Oct 24, 2021)

    • 调整 Guzzle 最低版本支持至 v6.5.0,相应降低 PHP 版本要求至 7.1.2;
    • 调整 PHPUnit 最低版本至 v7.5.0||v8.5.16||v9.3.5;
    • 新增 PHP8.1 支持;

    详情可查阅 CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.3.2(Sep 30, 2021)

  • v1.3.1(Sep 22, 2021)

  • v1.3.0(Sep 18, 2021)

    • 增加IDE提示OpenAPI\V2&OpenAPI\V3的两个入口,接口描述文件拆分为单独的包发行,生产环境无需安装(没必要),仅面向开发环境;

    详情可查阅 CHANGELOG.md

    Source code(tar.gz)
    Source code(zip)
  • v1.2.2(Sep 9, 2021)

    • at sign形式,温和提示APIv2DEP_XML_PROTOCOL_IS_REACHABLE_EOL,相关#38
    • 优化Transformer::toArray函数,对入参xml非法时,返回空array,并把最后一条错误信息温和地打入E_USER_NOTICE通道;
    • 修正Formatter::ksort排列键值时兼容问题,使用字典序(dictionary order)排序,相关#41, 感谢 @suiaiyun 报告此问题;

    更多详情,请参阅 CHANGELOG.md

    Source code(tar.gz)
    Source code(zip)
  • v1.2.1(Sep 6, 2021)

  • v1.2.0(Sep 2, 2021)

    • 新增 Rsa::from 统一加载函数,以接替 PemUtil::loadPrivateKey 函数功能;
    • 新增 Rsa::fromPkcs1, Rsa::fromPkcs8,Rsa::fromSpki语法糖,以支持从云端加载RSA公/私钥;
    • 新增 RSA 公钥 Rsa::pkcs1ToSpki 格式转换函数,入参是base64字符串;

    更多详情,请参阅 CHANGELOG.md

    Source code(tar.gz)
    Source code(zip)
  • v1.1.4(Aug 26, 2021)

  • v1.1.3(Aug 22, 2021)

  • v1.1.2(Aug 19, 2021)

    • 优化README密钥证书等相关术语保持一致;
    • 优化UPGRADING,增加从php_sdk_v3.0.10迁移指南;
    • 优化测试用例,完整覆盖PHP7.2/7.3/7.4/8.0 + Linux/macOS/Windows运行时;
    • 调整composer.json,去除test, phpstan命令,面向生产环境可用;

    更多详情,请参阅 CHANGELOG.md

    Source code(tar.gz)
    Source code(zip)
  • V1.1.1(Aug 13, 2021)

    • 优化内部中间件始终从\GuzzleHttp\Psr7\Stream::__toString取值,并在取值后,判断如果影响了Stream指针,则回滚至开始位;
    • 修正APIv2上,转账至用户零钱接口,xml入参是mchid引发的不适问题;

    更多的信息,请参阅CHANGELOG.md

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Aug 7, 2021)

    • 调整内部中间件栈顺序,并对APIv3的正常返回内容(20X)做精细判断,逻辑异常时使用\GuzzleHttp\Exception\RequestException抛出,应用端可捕获源返回内容;
    • 对于30X4XX,5XX返回,Guzzle基础中间件默认已处理,具体用法及使用,可参考\GuzzleHttp\RedirectMiddleware\GuzzleHttp\Middleware::httpErrors说明;
    • 详细变化可见1.0至1.1升级指南

    更多的信息,请参阅CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.0.9(Aug 5, 2021)

  • v1.0.8(Jul 26, 2021)

    • 增加WeChatPay\Crypto\Hash::equals方法,用于比较 APIv2 哈希签名值是否相等;
    • 我们建议使用 APIv2 的商户,在回调通知场景中,使用此方法来验签,相关说明见 hash_equals 说明;

    更多的信息,请参阅CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.0.7(Jul 22, 2021)

  • v1.0.6(Jul 21, 2021)

  • v1.0.5(Jul 8, 2021)

    • 核心代码全部转入严格类型 declare(strict_types=1) 校验模式 #13
    • 调整 Authorization 头格式顺序,debug 时优先展示关键信息 #13
    • 调整 媒体文件MediaUtil类读取文件时,严格二进制读,避免跨平台干扰问题 #12

    更多的信息,请参阅 CHANGELOG.md

    Source code(tar.gz)
    Source code(zip)
  • v1.0.4(Jul 5, 2021)

  • v1.0.3(Jun 29, 2021)

    • 初始化jsonBased入参判断,平台证书及序列号结构体内不能含商户序列号,相关问题 #8;
    • 修复文档错误,相关 #7;
    • 修复 PHPStan 所有遗留问题;

    更多的信息,请参看CHANGELOG

    Source code(tar.gz)
    Source code(zip)
  • v1.0.2(Jun 24, 2021)

  • v1.0.1(Jun 21, 2021)

    • 优化了一些性能;
    • 修复了大量 phpstan level6 静态分析遗留问题;
    • 新增\WeChatPay\Exception\WeChatPayException异常类接口;
    • 完善文档及方法类型签名;
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jun 19, 2021)

Owner
null
The efficient and elegant JSON:API 1.1 server library for PHP

Woohoo Labs. Yin Woohoo Labs. Yin is a PHP framework which helps you to build beautifully crafted JSON:APIs. Table of Contents Introduction Features W

Woohoo Labs. 237 Nov 28, 2022
The efficient and elegant, PSR-7 compliant JSON:API 1.1 client library for PHP

Woohoo Labs. Yang Woohoo Labs. Yang is a PHP framework which helps you to communicate with JSON:API servers more easily. Table of Contents Introductio

Woohoo Labs. 160 Oct 16, 2022
A PHP library for the CoinMarketCap API designed to be easy to use.

Help wanted: I don't have enough time to keep updating this library, if you can, don't be shy. Pull requests are welcome. PHP CoinMarketCap API This p

Shahrad Elahi 12 Sep 23, 2022
PHP library for Qvapay API integration.

Php library for Qvapay API This PHP library facilitates the integration of the Qvapay API. Sign up on QvaPay Create your account to process payments t

Omar Villafuerte 9 Aug 20, 2022
A PHP library for the Oxxa API.

Oxxa API (PHP) Use the Oxxa API in PHP. Status Installation composer require ben221199/oxxa-api Use $username = 'myUsername'; // Your API username $pa

Ben 1 Jan 5, 2022
Simple and effective multi-format Web API Server to host your PHP API as Pragmatic REST and / or RESTful API

Luracast Restler ![Gitter](https://badges.gitter.im/Join Chat.svg) Version 3.0 Release Candidate 5 Restler is a simple and effective multi-format Web

Luracast 1.4k Dec 14, 2022
Laravel library to convert your models into API responses.

Laravel Scene Laravel library to convert your models into API responses. Why a transformation library? By default you can use the default implementati

Ahmed Azaan 27 Nov 23, 2022
A small library for usage deepai.org api

deepai a small library for usage deepai.org api install via composer : composer require mkhab7/deepai usage use Solid\Deepai\Deepai; require_once 've

solid 1 Oct 23, 2022
Simple utility and class library for generating php classes from a wsdl file.

wsdl2phpgenerator Simple WSDL to PHP classes converter. Takes a WSDL file and outputs class files ready to use. Uses the MIT license. Announcement: We

null 802 Dec 10, 2022
A PHP library to support implementing representations for HATEOAS REST web services.

Hateoas A PHP library to support implementing representations for HATEOAS REST web services. Installation Working With Symfony Usage Introduction Conf

William Durand 998 Dec 5, 2022
YouTrack RestAPI library for PHP. An implementation for communicating with your YouTrack instance.

YouTrack API PHP This is an implementation for communicating with the JetBrains YouTrack RestAPI. This library covers basic resource calls available i

Samih Soylu 4 May 3, 2022
A simple object-relational mapping library built using PHP.

A simple object-relational mapping library built using PHP.

Maleesha Gimshan 2 Jun 29, 2021
PHP Pi Horizon Client Library

phpi-sdk PHP Pi Horizon Client Library This is part of FASTLANE project for the pi payment gateway, as we are trying to build a pi wallet inside FASTL

EMSec 4 May 23, 2022
A php library for coinex exchange apis .

Coinex API PHP Coinex digital coin exchange API for PHP Requirements PHP>=7.1 CURL PHP module Install composer require roozbeh/coinex_php Acquire acce

Roozbeh Baabakaan 3 Nov 12, 2022
A small library that provides functionality to PHP 8.1 enums to act as BitMask flags

PHP Enum BitMask A small library that provides functionality to PHP 8.1 enums to act as BitMask flags. Why? Sometimes you need some flags on the objec

FramJet 53 Dec 11, 2022
A Ping++ driver for the Omnipay PHP payment processing library

Omnipay: Pingpp Introduction Ping++ driver for the Omnipay PHP payment processing library Ping++ is a Chinese leading payment integration service prov

Phx 241 Dec 14, 2022
A PHP replacement layer for the C intl extension that also provides access to the localization data of the ICU library.

A PHP replacement layer for the C intl extension that also provides access to the localization data of the ICU library.

Symfony 2.5k Dec 29, 2022
PHP library/SDK for Crypto APIs 2.0 using Guzzle version 7

cryptoapis/sdk-guzzle7 Crypto APIs 2.0 is a complex and innovative infrastructure layer that radically simplifies the development of any Blockchain an

Crypto APIs 3 Oct 21, 2022
Simple PHP API client for tube-hosting.com rest API

Tube-Hosting API PHP client Explanation This PHP library is a simple api wrapper/client for the tube-hosting.com api. It is based on the provided docu

null 4 Sep 12, 2022