- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,168 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\ServiceContainer;
use EasyWeChat\Kernel\Support;
use EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException;
/**
* Class Application.
*
* @author liuml <liumenglei0211@gmail.com>
*
* @property \EasyWeChat\MicroMerchant\Certficates\Client $certficates
* @property \EasyWeChat\MicroMerchant\Material\Client $material
* @property \EasyWeChat\MicroMerchant\MerchantConfig\Client $merchantConfig
* @property \EasyWeChat\MicroMerchant\Withdraw\Client $withdraw
* @property \EasyWeChat\MicroMerchant\Media\Client $media
*
* @method mixed submitApplication(?array $params)
* @method mixed getStatus(?string $applymentId, ?string $businessCode = '')
* @method mixed upgrade(?array $params)
* @method mixed getUpgradeStatus(?string $subMchId = '')
*/
class Application extends ServiceContainer
{
/**
* @var array
*/
protected $providers = [
// Base services
Base\ServiceProvider::class,
Certficates\ServiceProvider::class,
MerchantConfig\ServiceProvider::class,
Material\ServiceProvider::class,
Withdraw\ServiceProvider::class,
Media\ServiceProvider::class,
];
/**
* @var array
*/
protected $defaultConfig = [
'http' => [
'base_uri' => 'https://api.mch.weixin.qq.com/',
],
'log' => [
'default' => 'dev', // 默认使用的 channel生产环境可以改为下面的 prod
'channels' => [
// 测试环境
'dev' => [
'driver' => 'single',
'path' => '/tmp/easywechat.log',
'level' => 'debug',
],
// 生产环境
'prod' => [
'driver' => 'daily',
'path' => '/tmp/easywechat.log',
'level' => 'info',
],
],
],
];
/**
* @return string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
*/
public function getKey()
{
$key = $this['config']->key;
if (empty($key)) {
throw new InvalidArgumentException('config key connot be empty.');
}
if (32 !== strlen($key)) {
throw new InvalidArgumentException(sprintf("'%s' should be 32 chars length.", $key));
}
return $key;
}
/**
* set sub-mch-id and appid.
*
* @param string $subMchId Identification Number of Small and Micro Businessmen Reported by Service Providers
* @param string $appId Public Account ID of Service Provider
*
* @return $this
*/
public function setSubMchId(?string $subMchId, ?string $appId = '')
{
$this['config']->set('sub_mch_id', $subMchId);
if ($appId) {
$this['config']->set('appid', $appId);
}
return $this;
}
/**
* setCertificate.
*
* @return $this
*/
public function setCertificate(?string $certificate, ?string $serialNo)
{
$this['config']->set('certificate', $certificate);
$this['config']->set('serial_no', $serialNo);
return $this;
}
/**
* Returning true indicates that the verification is successful,
* returning false indicates that the signature field does not exist or is empty,
* and if the signature verification is wrong, the InvalidSignException will be thrown directly.
*
* @return bool
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
*/
public function verifySignature(?array $data)
{
if (!isset($data['sign']) || empty($data['sign'])) {
return false;
}
$sign = $data['sign'];
unset($data['sign']);
$signType = strlen($sign) > 32 ? 'HMAC-SHA256' : 'MD5';
$secretKey = $this->getKey();
$encryptMethod = Support\get_encrypt_method($signType, $secretKey);
if (Support\generate_sign($data, $secretKey, $encryptMethod) === $sign) {
return true;
}
throw new InvalidSignException('return value signature verification error');
}
/**
* @param string $name
* @param array $arguments
*
* @return mixed
*/
public function __call($name, $arguments)
{
return call_user_func_array([$this['base'], $name], $arguments);
}
}

View File

@@ -0,0 +1,117 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Base;
use EasyWeChat\MicroMerchant\Kernel\BaseClient;
/**
* Class Client.
*
* @author liuml <liumenglei0211@163.com>
* @DateTime 2019-05-30 14:19
*/
class Client extends BaseClient
{
/**
* apply to settle in to become a small micro merchant.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function submitApplication(?array $params)
{
$params = $this->processParams(array_merge($params, [
'version' => '3.0',
'cert_sn' => '',
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
]));
return $this->safeRequest('applyment/micro/submit', $params);
}
/**
* query application status.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getStatus(?string $applymentId, ?string $businessCode = '')
{
if (!empty($applymentId)) {
$params = [
'applyment_id' => $applymentId,
];
} else {
$params = [
'business_code' => $businessCode,
];
}
$params = array_merge($params, [
'version' => '1.0',
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
]);
return $this->safeRequest('applyment/micro/getstate', $params);
}
/**
* merchant upgrade api.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function upgrade(?array $params)
{
$params['sub_mch_id'] = $params['sub_mch_id'] ?? $this->app['config']->sub_mch_id;
$params = $this->processParams(array_merge($params, [
'version' => '1.0',
'cert_sn' => '',
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
]));
return $this->safeRequest('applyment/micro/submitupgrade', $params);
}
/**
* get upgrade status.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getUpgradeStatus(?string $subMchId = '')
{
return $this->safeRequest('applyment/micro/getupgradestate', [
'version' => '1.0',
'sign_type' => 'HMAC-SHA256',
'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
'nonce_str' => uniqid('micro'),
]);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Base;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
/**
* Class ServiceProvider.
*
* @author overtrue <i@overtrue.me>
*/
class ServiceProvider implements ServiceProviderInterface
{
/**
* {@inheritdoc}.
*/
public function register(Container $app)
{
$app['base'] = function ($app) {
return new Client($app);
};
}
}

View File

@@ -0,0 +1,89 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Certficates;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\MicroMerchant\Kernel\BaseClient;
use EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException;
/**
* Class Client.
*
* @author liuml <liumenglei0211@163.com>
* @DateTime 2019-05-30 14:19
*/
class Client extends BaseClient
{
/**
* get certficates.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function get(bool $returnRaw = false)
{
$params = [
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
];
if (true === $returnRaw) {
return $this->requestRaw('risk/getcertficates', $params);
}
/** @var array $response */
$response = $this->requestArray('risk/getcertficates', $params);
if ('SUCCESS' !== $response['return_code']) {
throw new InvalidArgumentException(sprintf('Failed to get certificate. return_code_msg: "%s" .', $response['return_code'].'('.$response['return_msg'].')'));
}
if ('SUCCESS' !== $response['result_code']) {
throw new InvalidArgumentException(sprintf('Failed to get certificate. result_err_code_desc: "%s" .', $response['result_code'].'('.$response['err_code'].'['.$response['err_code_desc'].'])'));
}
$certificates = \GuzzleHttp\json_decode($response['certificates'], true)['data'][0];
$ciphertext = $this->decrypt($certificates['encrypt_certificate']);
unset($certificates['encrypt_certificate']);
$certificates['certificates'] = $ciphertext;
return $certificates;
}
/**
* decrypt ciphertext.
*
* @return string
*
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException
*/
public function decrypt(?array $encryptCertificate)
{
if (false === extension_loaded('sodium')) {
throw new InvalidExtensionException('sodium extension is not installedReference link https://php.net/manual/zh/book.sodium.php');
}
if (false === sodium_crypto_aead_aes256gcm_is_available()) {
throw new InvalidExtensionException('aes256gcm is not currently supported');
}
// sodium_crypto_aead_aes256gcm_decrypt function needs to open libsodium extension.
// https://www.php.net/manual/zh/function.sodium-crypto-aead-aes256gcm-decrypt.php
return sodium_crypto_aead_aes256gcm_decrypt(
base64_decode($encryptCertificate['ciphertext'], true),
$encryptCertificate['associated_data'],
$encryptCertificate['nonce'],
$this->app['config']->apiv3_key
);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Certficates;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
/**
* Class ServiceProvider.
*
* @author overtrue <i@overtrue.me>
*/
class ServiceProvider implements ServiceProviderInterface
{
/**
* {@inheritdoc}.
*/
public function register(Container $app)
{
$app['certficates'] = function ($app) {
return new Client($app);
};
}
}

View File

@@ -0,0 +1,241 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Kernel;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\Support;
use EasyWeChat\MicroMerchant\Application;
use EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException;
use EasyWeChat\Payment\Kernel\BaseClient as PaymentBaseClient;
/**
* Class BaseClient.
*
* @author liuml <liumenglei0211@163.com>
* @DateTime 2019-07-10 12:06
*/
class BaseClient extends PaymentBaseClient
{
/**
* @var string
*/
protected $certificates;
/**
* BaseClient constructor.
*/
public function __construct(Application $app)
{
$this->app = $app;
$this->setHttpClient($this->app['http_client']);
}
/**
* Extra request params.
*
* @return array
*/
protected function prepends()
{
return [];
}
/**
* httpUpload.
*
* @param bool $returnResponse
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function httpUpload(?string $url, ?array $files = [], ?array $form = [], ?array $query = [], $returnResponse = false)
{
$multipart = [];
foreach ($files as $name => $path) {
$multipart[] = [
'name' => $name,
'contents' => fopen($path, 'r'),
];
}
$base = [
'mch_id' => $this->app['config']['mch_id'],
];
$form = array_merge($base, $form);
$form['sign'] = $this->getSign($form);
foreach ($form as $name => $contents) {
$multipart[] = compact('name', 'contents');
}
$options = [
'query' => $query,
'multipart' => $multipart,
'connect_timeout' => 30,
'timeout' => 30,
'read_timeout' => 30,
'cert' => $this->app['config']->get('cert_path'),
'ssl_key' => $this->app['config']->get('key_path'),
];
$this->pushMiddleware($this->logMiddleware(), 'log');
$response = $this->performRequest($url, 'POST', $options);
$result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
// auto verify signature
if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
$this->app->verifySignature($this->castResponseToType($response, 'array'));
} else {
$this->app->verifySignature($result);
}
return $result;
}
/**
* request.
*
* @param string $method
* @param bool $returnResponse
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function request(?string $endpoint, ?array $params = [], $method = 'post', ?array $options = [], $returnResponse = false)
{
$base = [
'mch_id' => $this->app['config']['mch_id'],
];
$params = array_merge($base, $this->prepends(), $params);
$params['sign'] = $this->getSign($params);
$options = array_merge([
'body' => Support\XML::build($params),
], $options);
$this->pushMiddleware($this->logMiddleware(), 'log');
$response = $this->performRequest($endpoint, $method, $options);
$result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
// auto verify signature
if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
$this->app->verifySignature($this->castResponseToType($response, 'array'));
} else {
$this->app->verifySignature($result);
}
return $result;
}
/**
* processing parameters contain fields that require sensitive information encryption.
*
* @return array
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
*/
protected function processParams(?array $params)
{
$serial_no = $this->app['config']->get('serial_no');
if (null === $serial_no) {
throw new InvalidArgumentException('config serial_no connot be empty.');
}
$params['cert_sn'] = $serial_no;
$sensitive_fields = $this->getSensitiveFieldsName();
foreach ($params as $k => $v) {
if (in_array($k, $sensitive_fields, true)) {
$params[$k] = $this->encryptSensitiveInformation($v);
}
}
return $params;
}
/**
* To id card, mobile phone number and other fields sensitive information encryption.
*
* @return string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
*/
protected function encryptSensitiveInformation(?string $string)
{
$certificates = $this->app['config']->get('certificate');
if (null === $certificates) {
throw new InvalidArgumentException('config certificate connot be empty.');
}
$encrypted = '';
$publicKeyResource = openssl_get_publickey($certificates);
$f = openssl_public_encrypt($string, $encrypted, $publicKeyResource);
openssl_free_key($publicKeyResource);
if ($f) {
return base64_encode($encrypted);
}
throw new EncryptException('Encryption of sensitive information failed');
}
/**
* get sensitive fields name.
*
* @return array
*/
protected function getSensitiveFieldsName()
{
return [
'id_card_name',
'id_card_number',
'account_name',
'account_number',
'contact',
'contact_phone',
'contact_email',
'legal_person',
'mobile_phone',
'email',
];
}
/**
* getSign.
*
* @return string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
*/
protected function getSign(?array $params)
{
$params = array_filter($params);
$key = $this->app->getKey();
$encryptMethod = Support\get_encrypt_method(Support\Arr::get($params, 'sign_type', 'MD5'), $key);
return Support\generate_sign($params, $key, $encryptMethod);
}
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Kernel\Exceptions;
use EasyWeChat\Kernel\Exceptions\Exception;
/**
* Class EncryptException.
*
* @author liuml <liumenglei0211@163.com>
*/
class EncryptException extends Exception
{
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Kernel\Exceptions;
use EasyWeChat\Kernel\Exceptions\Exception;
/**
* Class InvalidExtensionException.
*
* @author liuml <liumenglei0211@163.com>
*/
class InvalidExtensionException extends Exception
{
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Kernel\Exceptions;
use EasyWeChat\Kernel\Exceptions\Exception;
/**
* Class InvalidSignException.
*
* @author liuml <liumenglei0211@163.com>
*/
class InvalidSignException extends Exception
{
}

View File

@@ -0,0 +1,69 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Material;
use EasyWeChat\MicroMerchant\Kernel\BaseClient;
/**
* Class Client.
*
* @author liuml <liumenglei0211@163.com>
* @DateTime 2019-05-30 14:19
*/
class Client extends BaseClient
{
/**
* update settlement card.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function setSettlementCard(?array $params)
{
$params['sub_mch_id'] = $params['sub_mch_id'] ?? $this->app['config']->sub_mch_id;
$params = $this->processParams(array_merge($params, [
'version' => '1.0',
'cert_sn' => '',
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
]));
return $this->safeRequest('applyment/micro/modifyarchives', $params);
}
/**
* update contact info.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function updateContact(?array $params)
{
$params['sub_mch_id'] = $params['sub_mch_id'] ?? $this->app['config']->sub_mch_id;
$params = $this->processParams(array_merge($params, [
'version' => '1.0',
'cert_sn' => '',
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
]));
return $this->safeRequest('applyment/micro/modifycontactinfo', $params);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Material;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
/**
* Class ServiceProvider.
*
* @author overtrue <i@overtrue.me>
*/
class ServiceProvider implements ServiceProviderInterface
{
/**
* {@inheritdoc}.
*/
public function register(Container $app)
{
$app['material'] = function ($app) {
return new Client($app);
};
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Media;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\MicroMerchant\Kernel\BaseClient;
/**
* Class Client.
*
* @author liuml <liumenglei0211@163.com>
* @DateTime 2019-06-10 14:50
*/
class Client extends BaseClient
{
/**
* Upload material.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
*/
public function upload(?string $path)
{
if (!file_exists($path) || !is_readable($path)) {
throw new InvalidArgumentException(sprintf("File does not exist, or the file is unreadable: '%s'", $path));
}
$form = [
'media_hash' => strtolower(md5_file($path)),
'sign_type' => 'HMAC-SHA256',
];
return $this->httpUpload('secapi/mch/uploadmedia', ['media' => $path], $form);
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* ServiceProvider.php.
*
* This file is part of the wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Media;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
/**
* Class ServiceProvider.
*
* @author overtrue <i@overtrue.me>
*/
class ServiceProvider implements ServiceProviderInterface
{
/**
* {@inheritdoc}.
*/
public function register(Container $app)
{
$app['media'] = function ($app) {
return new Client($app);
};
}
}

View File

@@ -0,0 +1,116 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\MerchantConfig;
use EasyWeChat\MicroMerchant\Kernel\BaseClient;
/**
* Class Client.
*
* @author liuml <liumenglei0211@163.com>
* @DateTime 2019-05-30 14:19
*/
class Client extends BaseClient
{
/**
* Service providers configure recommendation functions for small and micro businesses.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function setFollowConfig(?string $subAppId, ?string $subscribeAppId, ?string $receiptAppId = '', ?string $subMchId = '')
{
$params = [
'sub_appid' => $subAppId,
'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
];
if (!empty($subscribeAppId)) {
$params['subscribe_appid'] = $subscribeAppId;
} else {
$params['receipt_appid'] = $receiptAppId;
}
return $this->safeRequest('secapi/mkt/addrecommendconf', array_merge($params, [
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
]));
}
/**
* Configure the new payment directory.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
*/
public function addPath(?string $jsapiPath, ?string $appId = '', ?string $subMchId = '')
{
return $this->addConfig([
'appid' => $appId ?: $this->app['config']->appid,
'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
'jsapi_path' => $jsapiPath,
]);
}
/**
* bind appid.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
*/
public function bindAppId(?string $subAppId, ?string $appId = '', ?string $subMchId = '')
{
return $this->addConfig([
'appid' => $appId ?: $this->app['config']->appid,
'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
'sub_appid' => $subAppId,
]);
}
/**
* add sub dev config.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function addConfig(?array $params)
{
return $this->safeRequest('secapi/mch/addsubdevconfig', $params);
}
/**
* query Sub Dev Config.
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getConfig(?string $subMchId = '', ?string $appId = '')
{
return $this->safeRequest('secapi/mch/querysubdevconfig', [
'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
'appid' => $appId ?: $this->app['config']->appid,
]);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\MerchantConfig;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
/**
* Class ServiceProvider.
*
* @author overtrue <i@overtrue.me>
*/
class ServiceProvider implements ServiceProviderInterface
{
/**
* {@inheritdoc}.
*/
public function register(Container $app)
{
$app['merchantConfig'] = function ($app) {
return new Client($app);
};
}
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Withdraw;
use EasyWeChat\MicroMerchant\Kernel\BaseClient;
/**
* Class Client.
*
* @author liuml <liumenglei0211@163.com>
* @DateTime 2019-05-30 14:19
*/
class Client extends BaseClient
{
/**
* Query withdrawal status.
*
* @param string $date
* @param string $subMchId
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function queryWithdrawalStatus($date, $subMchId = '')
{
return $this->safeRequest('fund/queryautowithdrawbydate', [
'date' => $date,
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
]);
}
/**
* Re-initiation of withdrawal.
*
* @param string $date
* @param string $subMchId
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function requestWithdraw($date, $subMchId = '')
{
return $this->safeRequest('fund/reautowithdrawbydate', [
'date' => $date,
'sign_type' => 'HMAC-SHA256',
'nonce_str' => uniqid('micro'),
'sub_mch_id' => $subMchId ?: $this->app['config']->sub_mch_id,
]);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of the overtrue/wechat.
*
* (c) overtrue <i@overtrue.me>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChat\MicroMerchant\Withdraw;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
/**
* Class ServiceProvider.
*
* @author overtrue <i@overtrue.me>
*/
class ServiceProvider implements ServiceProviderInterface
{
/**
* {@inheritdoc}.
*/
public function register(Container $app)
{
$app['withdraw'] = function ($app) {
return new Client($app);
};
}
}