微信 http client 额外参数配置

This commit is contained in:
yansongda 2018-09-13 18:38:35 +08:00
parent 4acb6568a4
commit 24404ce309
13 changed files with 267 additions and 115 deletions

View File

@ -137,6 +137,8 @@ class Support
$result = mb_convert_encoding(self::getInstance()->post('', $data), 'utf-8', 'gb2312');
$result = json_decode($result, true);
Log::debug('Result Of Alipay Api', $result);
$method = str_replace('.', '_', $data['method']).'_response';
if (!isset($result['sign']) || $result[$method]['code'] != '10000') {
@ -302,12 +304,12 @@ class Support
* @param null|string $key
* @param null|mixed $default
*
* @return mixed|null|Config
* @return mixed|null
*/
public function getConfig($key = null, $default = null)
{
if (is_null($key)) {
return $this->config;
return $this->config->all();
}
if ($this->config->has($key)) {

View File

@ -40,20 +40,6 @@ class Wechat implements GatewayApplicationInterface
// 服务商
const MODE_SERVICE = 'service';
/**
* Config.
*
* @var Config
*/
protected $config;
/**
* Mode.
*
* @var string
*/
protected $mode;
/**
* Wechat payload.
*
@ -79,23 +65,21 @@ class Wechat implements GatewayApplicationInterface
*/
public function __construct(Config $config)
{
$this->config = $config;
$this->mode = $this->config->get('mode', self::MODE_NORMAL);
$this->gateway = Support::baseUri($this->mode);
$this->gateway = Support::getInstance($config)->getBaseUri();
$this->payload = [
'appid' => $this->config->get('app_id', ''),
'mch_id' => $this->config->get('mch_id', ''),
'appid' => $config->get('app_id', ''),
'mch_id' => $config->get('mch_id', ''),
'nonce_str' => Str::random(),
'notify_url' => $this->config->get('notify_url', ''),
'notify_url' => $config->get('notify_url', ''),
'sign' => '',
'trade_type' => '',
'spbill_create_ip' => Request::createFromGlobals()->getClientIp(),
];
if ($this->mode === static::MODE_SERVICE) {
if ($config->get('mode', self::MODE_NORMAL) === static::MODE_SERVICE) {
$this->payload = array_merge($this->payload, [
'sub_mch_id' => $this->config->get('sub_mch_id'),
'sub_appid' => $this->config->get('sub_app_id', ''),
'sub_mch_id' => $config->get('sub_mch_id'),
'sub_appid' => $config->get('sub_app_id', ''),
]);
}
}
@ -165,13 +149,13 @@ class Wechat implements GatewayApplicationInterface
$data = Support::fromXml($content);
if ($refund) {
$decrypt_data = Support::decryptRefundContents($data['req_info'], $this->config->get('key'));
$decrypt_data = Support::decryptRefundContents($data['req_info']);
$data = array_merge(Support::fromXml($decrypt_data), $data);
}
Log::debug('Resolved The Received Wechat Request Data', $data);
if ($refund || Support::generateSign($data, $this->config->get('key')) === $data['sign']) {
if ($refund || Support::generateSign($data) === $data['sign']) {
return new Collection($data);
}
@ -196,14 +180,13 @@ class Wechat implements GatewayApplicationInterface
*/
public function find($order, $refund = false): Collection
{
$this->payload = Support::filterPayload($this->payload, $order, $this->config);
$this->payload = Support::filterPayload($this->payload, $order);
Log::info('Starting To Find An Wechat Order', [$this->gateway, $this->payload]);
return Support::requestApi(
$refund ? 'pay/refundquery' : 'pay/orderquery',
$this->payload,
$this->config->get('key')
$this->payload
);
}
@ -222,15 +205,14 @@ class Wechat implements GatewayApplicationInterface
*/
public function refund($order): Collection
{
$this->payload = Support::filterPayload($this->payload, $order, $this->config, true);
$this->payload = Support::filterPayload($this->payload, $order, true);
Log::info('Starting To Refund An Wechat Order', [$this->gateway, $this->payload]);
return Support::requestApi(
'secapi/pay/refund',
$this->payload,
$this->config->get('key'),
['cert' => $this->config->get('cert_client'), 'ssl_key' => $this->config->get('cert_key')]
true
);
}
@ -269,11 +251,11 @@ class Wechat implements GatewayApplicationInterface
{
unset($this->payload['spbill_create_ip']);
$this->payload = Support::filterPayload($this->payload, $order, $this->config);
$this->payload = Support::filterPayload($this->payload, $order);
Log::info('Starting To Close An Wechat Order', [$this->gateway, $this->payload]);
return Support::requestApi('pay/closeorder', $this->payload, $this->config->get('key'));
return Support::requestApi('pay/closeorder', $this->payload);
}
/**
@ -307,7 +289,7 @@ class Wechat implements GatewayApplicationInterface
*/
protected function makePay($gateway)
{
$app = new $gateway($this->config);
$app = new $gateway();
if ($app instanceof GatewayInterface) {
return $app->pay($this->gateway, $this->payload);

View File

@ -21,25 +21,28 @@ class AppGateway extends Gateway
* @throws \Yansongda\Pay\Exceptions\GatewayException
* @throws \Yansongda\Pay\Exceptions\InvalidArgumentException
* @throws \Yansongda\Pay\Exceptions\InvalidSignException
* @throws \Exception
*
* @return Response
*/
public function pay($endpoint, array $payload): Response
{
$payload['appid'] = $this->config->get('appid');
$payload['appid'] = Support::getInstance()->appid;
$payload['trade_type'] = $this->getTradeType();
$this->mode !== Wechat::MODE_SERVICE ?: $payload['sub_appid'] = $this->config->get('sub_appid');
if ($this->mode !== Wechat::MODE_SERVICE) {
$payload['sub_appid'] = Support::getInstance()->sub_appid;
}
$payRequest = [
'appid' => $this->mode === Wechat::MODE_SERVICE ? $payload['sub_appid'] : $payload['appid'],
'partnerid' => $this->mode === Wechat::MODE_SERVICE ? $payload['sub_mch_id'] : $payload['mch_id'],
'prepayid' => $this->preOrder('pay/unifiedorder', $payload)->prepay_id,
'prepayid' => $this->preOrder($payload)->prepay_id,
'timestamp' => strval(time()),
'noncestr' => Str::random(),
'package' => 'Sign=WXPay',
];
$payRequest['sign'] = Support::generateSign($payRequest, $this->config->get('key'));
$payRequest['sign'] = Support::generateSign($payRequest);
Log::info('Starting To Pay A Wechat App Order', [$endpoint, $payRequest]);

View File

@ -3,20 +3,12 @@
namespace Yansongda\Pay\Gateways\Wechat;
use Yansongda\Pay\Contracts\GatewayInterface;
use Yansongda\Pay\Gateways\Wechat;
use Yansongda\Pay\Log;
use Yansongda\Supports\Collection;
use Yansongda\Supports\Config;
abstract class Gateway implements GatewayInterface
{
/**
* Config.
*
* @var Config
*/
protected $config;
/**
* Mode.
*
@ -29,12 +21,11 @@ abstract class Gateway implements GatewayInterface
*
* @author yansongda <me@yansongda.cn>
*
* @param Config $config
* @throws \Yansongda\Pay\Exceptions\InvalidArgumentException
*/
public function __construct(Config $config)
public function __construct()
{
$this->config = $config;
$this->mode = $this->config->get('mode', Wechat::MODE_NORMAL);
$this->mode = Support::getInstance()->mode;
}
/**
@ -63,7 +54,6 @@ abstract class Gateway implements GatewayInterface
*
* @author yansongda <me@yansongda.cn>
*
* @param string $endpoint
* @param array $payload
*
* @throws \Yansongda\Pay\Exceptions\GatewayException
@ -72,12 +62,12 @@ abstract class Gateway implements GatewayInterface
*
* @return Collection
*/
protected function preOrder($endpoint, $payload): Collection
protected function preOrder($payload): Collection
{
$payload['sign'] = Support::generateSign($payload, $this->config->get('key'));
$payload['sign'] = Support::generateSign($payload);
Log::info('Starting To Schedule A Wechat order', [$endpoint, $payload]);
Log::debug('Schedule A Wechat order', [$payload]);
return Support::requestApi($endpoint, $payload, $this->config->get('key'));
return Support::requestApi('pay/unifiedorder', $payload);
}
}

View File

@ -29,17 +29,17 @@ class GroupRedpackGateway extends Gateway
$this->mode !== Wechat::MODE_SERVICE ?: $payload['msgappid'] = $payload['appid'];
unset($payload['appid'], $payload['trade_type'], $payload['notify_url'], $payload['spbill_create_ip']);
unset($payload['appid'], $payload['trade_type'],
$payload['notify_url'], $payload['spbill_create_ip']);
$payload['sign'] = Support::generateSign($payload, $this->config->get('key'));
$payload['sign'] = Support::generateSign($payload);
Log::info('Starting To Pay A Wechat Group Redpack Order', [$endpoint, $payload]);
return Support::requestApi(
'mmpaymkttransfers/sendgroupredpack',
$payload,
$this->config->get('key'),
['cert' => $this->config->get('cert_client'), 'ssl_key' => $this->config->get('cert_key')]
true
);
}

View File

@ -23,9 +23,11 @@ class MiniappGateway extends MpGateway
*/
public function pay($endpoint, array $payload): Collection
{
$payload['appid'] = $this->config->get('miniapp_id');
$payload['appid'] = Support::getInstance()->miniapp_id;
$this->mode !== Wechat::MODE_SERVICE ?: $payload['sub_appid'] = $this->config->get('sub_miniapp_id');
if ($this->mode !== Wechat::MODE_SERVICE) {
$payload['sub_appid'] = Support::getInstance()->sub_miniapp_id;
}
return parent::pay($endpoint, $payload);
}

View File

@ -31,10 +31,10 @@ class MpGateway extends Gateway
'appId' => $payload['appid'],
'timeStamp' => strval(time()),
'nonceStr' => Str::random(),
'package' => 'prepay_id='.$this->preOrder('pay/unifiedorder', $payload)->prepay_id,
'package' => 'prepay_id='.$this->preOrder($payload)->prepay_id,
'signType' => 'MD5',
];
$payRequest['paySign'] = Support::generateSign($payRequest, $this->config->get('key'));
$payRequest['paySign'] = Support::generateSign($payRequest);
Log::info('Starting To Pay A Wechat JSAPI Order', [$endpoint, $payRequest]);

View File

@ -27,7 +27,11 @@ class PosGateway extends Gateway
Log::info('Starting To Pay A Wechat Pos Order', [$endpoint, $payload]);
return $this->preOrder('pay/micropay', $payload);
$payload['sign'] = Support::generateSign($payload);
Log::info('Starting To Pay A Wechat Pos order', [$payload]);
return Support::requestApi('pay/micropay', $payload);
}
/**

View File

@ -26,21 +26,26 @@ class RedpackGateway extends Gateway
public function pay($endpoint, array $payload): Collection
{
$payload['wxappid'] = $payload['appid'];
php_sapi_name() === 'cli' ?: $payload['client_ip'] = Request::createFromGlobals()->server->get('SERVER_ADDR');
$this->mode !== Wechat::MODE_SERVICE ?: $payload['msgappid'] = $payload['appid'];
if (php_sapi_name() !== 'cli') {
$payload['client_ip'] = Request::createFromGlobals()->server->get('SERVER_ADDR');
}
unset($payload['appid'], $payload['trade_type'], $payload['notify_url'], $payload['spbill_create_ip']);
if ($this->mode !== Wechat::MODE_SERVICE) {
$payload['msgappid'] = $payload['appid'];
}
$payload['sign'] = Support::generateSign($payload, $this->config->get('key'));
unset($payload['appid'], $payload['trade_type'],
$payload['notify_url'], $payload['spbill_create_ip']);
$payload['sign'] = Support::generateSign($payload);
Log::info('Starting To Pay A Wechat Redpack Order', [$endpoint, $payload]);
return Support::requestApi(
'mmpaymkttransfers/sendredpack',
$payload,
$this->config->get('key'),
['cert' => $this->config->get('cert_client'), 'ssl_key' => $this->config->get('cert_key')]
true
);
}

View File

@ -29,7 +29,7 @@ class ScanGateway extends Gateway
Log::info('Starting To Pay A Wechat Scan Order', [$endpoint, $payload]);
return $this->preOrder('pay/unifiedorder', $payload);
return $this->preOrder($payload);
}
/**

View File

@ -8,8 +8,28 @@ use Yansongda\Pay\Exceptions\InvalidSignException;
use Yansongda\Pay\Gateways\Wechat;
use Yansongda\Pay\Log;
use Yansongda\Supports\Collection;
use Yansongda\Supports\Config;
use Yansongda\Supports\Traits\HasHttpRequest;
/**
* @author yansongda <me@yansongda.cn>
*
* @property string appid
* @property string app_id
* @property string miniapp_id
* @property string sub_appid
* @property string sub_app_id
* @property string sub_miniapp_id
* @property string mch_id
* @property string sub_mch_id
* @property string key
* @property string return_url
* @property string cert_client
* @property string cert_key
* @property array log
* @property array http
* @property string mode
*/
class Support
{
use HasHttpRequest;
@ -21,6 +41,13 @@ class Support
*/
protected $baseUri = 'https://api.mch.weixin.qq.com/';
/**
* Config.
*
* @var Config
*/
protected $config;
/**
* Instance.
*
@ -32,9 +59,41 @@ class Support
* Bootstrap.
*
* @author yansongda <me@yansongda.cn>
*
* @param Config $config
*
* @throws InvalidArgumentException
*/
private function __construct()
private function __construct(Config $config)
{
$this->config = $config;
$this->setBaseUri()->setHttpOptions();
}
/**
* __get.
*
* @author yansongda <me@yansongda.cn>
*
* @param $key
*
* @return mixed|null|Config
*/
public function __get($key)
{
return $this->getConfig($key);
}
/**
* Get Base Uri.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
public function getBaseUri()
{
return $this->baseUri;
}
/**
@ -42,12 +101,20 @@ class Support
*
* @author yansongda <me@yansongda.cn>
*
* @param Config|null $config
*
* @throws InvalidArgumentException
*
* @return self
*/
public static function getInstance(): self
public static function getInstance($config = null): self
{
if ((!(self::$instance instanceof self)) && is_null($config)) {
throw new InvalidArgumentException('Must Initialize Support With Config Before Using');
}
if (!(self::$instance instanceof self)) {
self::$instance = new self();
self::$instance = new self($config);
}
return self::$instance;
@ -58,10 +125,9 @@ class Support
*
* @author yansongda <me@yansongda.cn>
*
* @param string $endpoint
* @param array $data
* @param string|null $key
* @param array $cert
* @param string $endpoint
* @param array $data
* @param bool $cert
*
* @throws GatewayException
* @throws InvalidArgumentException
@ -69,17 +135,22 @@ class Support
*
* @return Collection
*/
public static function requestApi($endpoint, $data, $key = null, $cert = []): Collection
public static function requestApi($endpoint, $data, $cert = false): Collection
{
Log::debug('Request To Wechat Api', [self::baseUri().$endpoint, $data]);
Log::debug('Request To Wechat Api', [self::getInstance()->getBaseUri().$endpoint, $data]);
$result = self::getInstance()->post(
$endpoint,
self::toXml($data),
$cert
$cert ? [
'cert' => self::getInstance()->cert_client,
'ssl_key' => self::getInstance()->cert_key
] : []
);
$result = is_array($result) ? $result : self::fromXml($result);
Log::debug('Result Of Wechat Api', $result);
if (!isset($result['return_code']) || $result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS') {
throw new GatewayException(
'Get Wechat API Error:'.$result['return_msg'].($result['err_code_des'] ?? ''),
@ -88,7 +159,7 @@ class Support
);
}
if (strpos($endpoint, 'mmpaymkttransfers') !== false || self::generateSign($result, $key) === $result['sign']) {
if (strpos($endpoint, 'mmpaymkttransfers') !== false || self::generateSign($result) === $result['sign']) {
return new Collection($result);
}
@ -102,24 +173,27 @@ class Support
*
* @author yansongda <me@yansongda.cn>
*
* @param array $payload
* @param array|string $order
* @param \Yansongda\Supports\Config $config
* @param bool $preserveNotifyUrl
* @param array $payload
* @param array|string $params
* @param bool $preserveNotifyUrl
*
* @throws InvalidArgumentException
*
* @return array
*/
public static function filterPayload($payload, $order, $config, $preserveNotifyUrl = false): array
public static function filterPayload($payload, $params, $preserveNotifyUrl = false): array
{
$payload = array_merge($payload, is_array($order) ? $order : ['out_trade_no' => $order]);
$payload = array_merge(
$payload,
is_array($params) ? $params : ['out_trade_no' => $params]
);
$type = isset($order['type']) ? $order['type'].($order['type'] == 'app' ? '' : '_').'id' : 'app_id';
$payload['appid'] = $config->get($type, '');
$type = self::getInstance()->getTypeName($params['type'] ?? '');
if ($config->get('mode', Wechat::MODE_NORMAL) === Wechat::MODE_SERVICE) {
$payload['sub_appid'] = $config->get('sub_'.$type, '');
$payload['appid'] = self::getInstance()->getConfig($type, '');
if (self::getInstance()->getConfig('mode', Wechat::MODE_NORMAL) === Wechat::MODE_SERVICE) {
$payload['sub_appid'] = self::getInstance()->getConfig('sub_'.$type, '');
}
unset($payload['trade_type'], $payload['type']);
@ -128,7 +202,7 @@ class Support
unset($payload['notify_url']);
}
$payload['sign'] = self::generateSign($payload, $config->get('key'));
$payload['sign'] = self::generateSign($payload);
return $payload;
}
@ -138,15 +212,16 @@ class Support
*
* @author yansongda <me@yansongda.cn>
*
* @param array $data
* @param null|string $key
* @param array $data
*
* @throws InvalidArgumentException
*
* @return string
*/
public static function generateSign($data, $key = null): string
public static function generateSign($data): string
{
$key = self::getInstance()->key;
if (is_null($key)) {
throw new InvalidArgumentException('Missing Wechat Config -- [key]');
}
@ -188,13 +263,19 @@ class Support
* @author yansongda <me@yansongda.cn>
*
* @param string $contents
* @param string $key
*
* @throws InvalidArgumentException
*
* @return string
*/
public static function decryptRefundContents($contents, $key): string
public static function decryptRefundContents($contents): string
{
return openssl_decrypt(base64_decode($contents), 'AES-256-ECB', md5($key), OPENSSL_RAW_DATA);
return openssl_decrypt(
base64_decode($contents),
'AES-256-ECB',
self::getInstance()->key,
OPENSSL_RAW_DATA
);
}
/**
@ -247,17 +328,80 @@ class Support
}
/**
* Wechat gateway.
* Initialize.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $mode
* @param Config $config
*
* @throws InvalidArgumentException
*
* @return Support
*/
public static function initialize(Config $config): self
{
return self::getInstance($config);
}
/**
* Get service config.
*
* @author yansongda <me@yansongda.cn>
*
* @param null|string $key
* @param null|mixed $default
*
* @return mixed|null
*/
public function getConfig($key = null, $default = null)
{
if (is_null($key)) {
return $this->config->all();
}
if ($this->config->has($key)) {
return $this->config[$key];
}
return $default;
}
/**
* Get app id according to param type.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $type
*
* @return string
*/
public static function baseUri($mode = null): string
public function getTypeName($type = ''): string
{
switch ($mode) {
$type = $type.'_id';
if ($type == 'app') {
$type = 'appid';
}
if ($type == '') {
$type = 'app_id';
}
return $type;
}
/**
* Set base uri.
*
* @author yansongda <me@yansongda.cn>
*
* @throws InvalidArgumentException
*
* @return self
*/
private function setBaseUri(): self
{
switch ($this->config->get('mode', Wechat::MODE_NORMAL)) {
case Wechat::MODE_DEV:
self::getInstance()->baseUri = 'https://api.mch.weixin.qq.com/sandboxnew/';
break;
@ -270,6 +414,23 @@ class Support
break;
}
return self::getInstance()->baseUri;
return $this;
}
/**
* Set Http options.
*
* @author yansongda <me@yansongda.cn>
*
* @return self
*/
private function setHttpOptions(): self
{
if ($this->config->has('http')) {
$this->config->forget('http.base_uri');
$this->httpOptions = $this->config->get('http');
}
return $this;
}
}

View File

@ -28,24 +28,27 @@ class TransferGateway extends Gateway
if ($this->mode === Wechat::MODE_SERVICE) {
unset($payload['sub_mch_id'], $payload['sub_appid']);
}
$type = isset($payload['type']) ? ($payload['type'].($payload['type'] == 'app' ?: '_').'id') : 'app_id';
$payload['mch_appid'] = $this->config->get($type, '');
$type = Support::getInstance()->getTypeName($payload['type']);
$payload['mch_appid'] = Support::getInstance()->getConfig($type, '');
$payload['mchid'] = $payload['mch_id'];
php_sapi_name() === 'cli' ?: $payload['spbill_create_ip'] = Request::createFromGlobals()->server->get('SERVER_ADDR');
if (php_sapi_name() !== 'cli') {
$payload['spbill_create_ip'] = Request::createFromGlobals()->server->get('SERVER_ADDR');
}
unset($payload['appid'], $payload['mch_id'], $payload['trade_type'],
$payload['notify_url'], $payload['type']);
$payload['sign'] = Support::generateSign($payload, $this->config->get('key'));
$payload['sign'] = Support::generateSign($payload);
Log::info('Starting To Pay A Wechat Transfer Order', [$endpoint, $payload]);
return Support::requestApi(
'mmpaymkttransfers/promotion/transfers',
$payload,
$this->config->get('key'),
['cert' => $this->config->get('cert_client'), 'ssl_key' => $this->config->get('cert_key')]
true
);
}

View File

@ -28,10 +28,10 @@ class WapGateway extends Gateway
Log::info('Starting To Pay A Wechat Wap Order', [$endpoint, $payload]);
$data = $this->preOrder('pay/unifiedorder', $payload);
$data = $this->preOrder($payload);
$url = is_null($this->config->get('return_url')) ? $data->mweb_url : $data->mweb_url.
'&redirect_url='.urlencode($this->config->get('return_url'));
$url = is_null(Support::getInstance()->return_url) ? $data->mweb_url : $data->mweb_url.
'&redirect_url='.urlencode(Support::getInstance()->return_url);
return RedirectResponse::create($url);
}