mirror of
https://gitee.com/yansongda/pay.git
synced 2024-12-02 04:08:21 +08:00
update
This commit is contained in:
parent
1134c1a447
commit
b49fafb976
@ -21,15 +21,17 @@
|
||||
"ext-libxml": "*",
|
||||
"ext-json": "*",
|
||||
"php-di/php-di": "~6.3.0",
|
||||
"yansongda/supports": "~3.0.0",
|
||||
"symfony/event-dispatcher": "~5.2.0",
|
||||
"symfony/http-foundation": "~5.2.0"
|
||||
"yansongda/supports": "~3.1.0",
|
||||
"symfony/event-dispatcher": "^5.2.0",
|
||||
"guzzlehttp/guzzle": "^7.0",
|
||||
"monolog/monolog": "^2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"mockery/mockery": "^1.4",
|
||||
"friendsofphp/php-cs-fixer": "^2.15",
|
||||
"symfony/var-dumper": "^5.1"
|
||||
"symfony/var-dumper": "^5.1",
|
||||
"symfony/http-foundation": "~5.2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@ -5,9 +5,14 @@ declare(strict_types=1);
|
||||
namespace Yansongda\Pay\Contract;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
interface PluginInterface
|
||||
{
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection;
|
||||
/**
|
||||
* @author yansongda <me@yansongda.cn>
|
||||
*
|
||||
* @return \Yansongda\Supports\Collection|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next);
|
||||
}
|
||||
|
15
src/Contract/ShortcutInterface.php
Normal file
15
src/Contract/ShortcutInterface.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Contract;
|
||||
|
||||
interface ShortcutInterface
|
||||
{
|
||||
/**
|
||||
* @author yansongda <me@yansongda.cn>
|
||||
*
|
||||
* @return \Yansongda\Pay\Contract\PluginInterface[]
|
||||
*/
|
||||
public function getPlugins(): array;
|
||||
}
|
@ -8,7 +8,7 @@ use Throwable;
|
||||
|
||||
class InvalidParamsException extends Exception
|
||||
{
|
||||
public function __construct(string $message = 'Params Error', int $code = self::PARAMS_ERROR, array $extra = [], Throwable $previous = null)
|
||||
public function __construct(int $code = self::PARAMS_ERROR, string $message = 'Params Error', array $extra = [], Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $extra, $previous);
|
||||
}
|
||||
|
@ -224,7 +224,8 @@ class Pay
|
||||
|
||||
try {
|
||||
$container = $builder->build();
|
||||
$container->set(ContainerInterface::class, $this);
|
||||
$container->set(ContainerInterface::class, $container);
|
||||
$container->set(\Psr\Container\ContainerInterface::class, $container);
|
||||
$container->set(Pay::class, $this);
|
||||
|
||||
self::$container = $container;
|
||||
|
@ -5,16 +5,23 @@ declare(strict_types=1);
|
||||
namespace Yansongda\Pay\Plugin\Alipay;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Str;
|
||||
|
||||
class FilterPlugin
|
||||
class FilterPlugin implements PluginInterface
|
||||
{
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection
|
||||
/**
|
||||
* @return \Yansongda\Supports\Collection|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next)
|
||||
{
|
||||
$payload = $payload->filter(function ($v, $k) {
|
||||
return '' !== $v && !is_null($v) && 'sign' != $k && '_config' != $k;
|
||||
$payload = $rocket->getPayload()->filter(function ($v, $k) {
|
||||
return '' !== $v && !is_null($v) && 'sign' != $k && Str::startsWith($k, '_');
|
||||
});
|
||||
|
||||
return $next($params, $payload);
|
||||
$payload->set('biz_content', json_encode($payload->get('biz_content')));
|
||||
|
||||
return $next($rocket->setPayload($payload));
|
||||
}
|
||||
}
|
||||
|
@ -5,18 +5,31 @@ declare(strict_types=1);
|
||||
namespace Yansongda\Pay\Plugin\Alipay;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
class IgnitePlugin
|
||||
class PreparePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
|
||||
* @throws \Yansongda\Pay\Exception\ContainerException
|
||||
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
|
||||
*/
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection
|
||||
public function assembly(Rocket $rocket, Closure $next)
|
||||
{
|
||||
$payload->merge([
|
||||
return $next(
|
||||
$rocket->mergePayload($this->getPayload($rocket->getParams()))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
|
||||
* @throws \Yansongda\Pay\Exception\ContainerException
|
||||
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
|
||||
*/
|
||||
protected function getPayload(array $params): array
|
||||
{
|
||||
return [
|
||||
'app_id' => get_alipay_config($params)['app_id'] ?? '',
|
||||
'method' => '',
|
||||
'format' => 'JSON',
|
||||
@ -28,9 +41,7 @@ class IgnitePlugin
|
||||
'version' => '1.0',
|
||||
'notify_url' => get_alipay_config($params)['notify_url'] ?? '',
|
||||
'app_auth_token' => '',
|
||||
'biz_content' => '',
|
||||
]);
|
||||
|
||||
return $next($params, $payload);
|
||||
'biz_content' => [],
|
||||
];
|
||||
}
|
||||
}
|
28
src/Plugin/Alipay/RadarPlugin.php
Normal file
28
src/Plugin/Alipay/RadarPlugin.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Provider\Alipay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
class RadarPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
|
||||
* @throws \Yansongda\Pay\Exception\ContainerException
|
||||
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next)
|
||||
{
|
||||
$config = get_alipay_config($rocket->getParams());
|
||||
|
||||
return $next($rocket->setRadar(
|
||||
$config['mode'] ?? Alipay::URL[Pay::MODE_NORMAL]
|
||||
));
|
||||
}
|
||||
}
|
@ -10,8 +10,8 @@ use Yansongda\Supports\Collection;
|
||||
|
||||
class AppPlugin extends AppPayPlugin
|
||||
{
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection
|
||||
public function assembly(array $params, Collection $payload, Closure $next): Collection
|
||||
{
|
||||
return parent::apply(...func_get_args());
|
||||
return parent::assembly(...func_get_args());
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,12 @@ namespace Yansongda\Pay\Plugin\Alipay\Shortcut;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Plugin\Alipay\Trade\PagePayPlugin;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
class WebPlugin extends PagePayPlugin
|
||||
{
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
return parent::apply(...func_get_args());
|
||||
return parent::assembly(...func_get_args());
|
||||
}
|
||||
}
|
||||
|
@ -6,14 +6,16 @@ namespace Yansongda\Pay\Plugin\Alipay;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\ConfigInterface;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Arr;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Supports\Str;
|
||||
|
||||
class SignPlugin
|
||||
class SignPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
|
||||
@ -21,8 +23,9 @@ class SignPlugin
|
||||
* @throws \Yansongda\Pay\Exception\InvalidConfigException
|
||||
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
|
||||
*/
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection
|
||||
public function assembly(Rocket $rocket, Closure $next)
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$privateKey = $this->getPrivateKey();
|
||||
|
||||
openssl_sign($this->getSignContent($payload), $sign, $privateKey, OPENSSL_ALGO_SHA256);
|
||||
@ -33,9 +36,9 @@ class SignPlugin
|
||||
|
||||
!is_resource($privateKey) ?: openssl_free_key($privateKey);
|
||||
|
||||
$payload = $payload->merge(['sign' => $sign]);
|
||||
|
||||
return $next($params, $payload);
|
||||
return $next($rocket->mergePayload([
|
||||
'sign' => $sign,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,22 +5,19 @@ declare(strict_types=1);
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Trade;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
class AppPayPlugin
|
||||
class AppPayPlugin implements PluginInterface
|
||||
{
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $payload->merge([
|
||||
return $next($rocket->mergePayload([
|
||||
'method' => 'alipay.trade.app.pay',
|
||||
'biz_content' => json_encode(array_merge(
|
||||
[
|
||||
'product_code' => 'QUICK_MSECURITY_PAY',
|
||||
],
|
||||
$params
|
||||
)),
|
||||
]);
|
||||
|
||||
return $next($params, $payload);
|
||||
'biz_content' => array_merge(
|
||||
['product_code' => 'QUICK_MSECURITY_PAY'],
|
||||
$rocket->getParams(),
|
||||
),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
@ -5,22 +5,22 @@ declare(strict_types=1);
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Trade;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
class PagePayPlugin
|
||||
class PagePayPlugin implements PluginInterface
|
||||
{
|
||||
public function apply(array $params, Collection $payload, Closure $next): Collection
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $payload->merge([
|
||||
return $next(
|
||||
$rocket->setType(Response::class)
|
||||
->mergePayload([
|
||||
'method' => 'alipay.trade.page.pay',
|
||||
'biz_content' => json_encode(array_merge(
|
||||
[
|
||||
'product_code' => 'FAST_INSTANT_TRADE_PAY',
|
||||
],
|
||||
$params
|
||||
)),
|
||||
]);
|
||||
|
||||
return $next($params, $payload);
|
||||
'biz_content' => array_merge(
|
||||
['product_code' => 'FAST_INSTANT_TRADE_PAY'],
|
||||
$rocket->getParams()
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
11
src/Provider/AbstractProvider.php
Normal file
11
src/Provider/AbstractProvider.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Provider;
|
||||
|
||||
use Yansongda\Pay\Contract\ProviderInterface;
|
||||
|
||||
abstract class AbstractProvider implements ProviderInterface
|
||||
{
|
||||
}
|
@ -4,14 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Provider;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Yansongda\Pay\Contract\ShortcutInterface;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Alipay\FilterPlugin;
|
||||
use Yansongda\Pay\Plugin\Alipay\IgnitePlugin;
|
||||
use Yansongda\Pay\Plugin\Alipay\PreparePlugin;
|
||||
use Yansongda\Pay\Plugin\Alipay\RadarPlugin;
|
||||
use Yansongda\Pay\Plugin\Alipay\SignPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Supports\Pipeline;
|
||||
use Yansongda\Supports\Str;
|
||||
|
||||
class Alipay
|
||||
@ -23,64 +27,76 @@ class Alipay
|
||||
];
|
||||
|
||||
/**
|
||||
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
|
||||
* @throws \Yansongda\Pay\Exception\ContainerException
|
||||
* @throws \Yansongda\Pay\Exception\InvalidParamsException
|
||||
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
|
||||
*
|
||||
* @return \Yansongda\Supports\Collection
|
||||
*/
|
||||
public function __call(string $method, array $params)
|
||||
public function __call(string $shortcut, array $params)
|
||||
{
|
||||
$plugin = '\\Yansongda\\Pay\\Plugin\\Alipay\\Shortcut\\'.
|
||||
Str::studly($method).'Plugin';
|
||||
Str::studly($shortcut).'Shortcut';
|
||||
|
||||
if (!class_exists($plugin) || !in_array(PluginInterface::class, class_implements($plugin))) {
|
||||
throw new InvalidParamsException('Shortcut not found', InvalidParamsException::SHORTCUT_NOT_FOUND);
|
||||
if (!class_exists($plugin) || !in_array(ShortcutInterface::class, class_implements($plugin))) {
|
||||
throw new InvalidParamsException(InvalidParamsException::SHORTCUT_NOT_FOUND, "[$plugin] not found");
|
||||
}
|
||||
|
||||
return $this->pay([$plugin], ...$params);
|
||||
/* @var ShortcutInterface $money */
|
||||
$money = Pay::get($plugin);
|
||||
|
||||
return $this->pay($money->getPlugins(), ...$params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Yansongda\Supports\Collection
|
||||
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
|
||||
* @throws \Yansongda\Pay\Exception\ContainerException
|
||||
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
|
||||
*
|
||||
* @return \Yansongda\Supports\Collection|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function pay(array $plugins, array $order)
|
||||
public function pay(array $plugins, array $params)
|
||||
{
|
||||
$plugins = array_merge(
|
||||
[IgnitePlugin::class],
|
||||
[PreparePlugin::class],
|
||||
$plugins,
|
||||
[FilterPlugin::class, SignPlugin::class]
|
||||
[FilterPlugin::class, SignPlugin::class, RadarPlugin::class]
|
||||
);
|
||||
|
||||
// todo
|
||||
$payload = [];
|
||||
/* @var Pipeline $pipeline */
|
||||
$pipeline = Pay::get(Pipeline::class);
|
||||
|
||||
return $this->launch($payload);
|
||||
return $pipeline
|
||||
->send((new Rocket())->setParams($params)->setPayload(new Collection()))
|
||||
->through($plugins)
|
||||
->via('assembly')
|
||||
->then(function ($rocket) {
|
||||
return $this->ignite($rocket);
|
||||
});
|
||||
}
|
||||
|
||||
public function find($order): Collection
|
||||
public function ignite(Rocket $rocket)
|
||||
{
|
||||
}
|
||||
|
||||
public function refund(array $order): Collection
|
||||
protected function launchResponse(RequestInterface $radar, Collection $payload): Response
|
||||
{
|
||||
$method = $radar->getMethod();
|
||||
$endpoint = $radar->getUri()->getScheme().'://'.$radar->getUri()->getHost();
|
||||
|
||||
if ('GET' === $method) {
|
||||
return new RedirectResponse($radar->getUri()->__toString());
|
||||
}
|
||||
|
||||
public function cancel($order): Collection
|
||||
{
|
||||
$sHtml = "<form id='alipay_submit' name='alipay_submit' action='".$endpoint."' method='".$method."'>";
|
||||
foreach ($payload->all() as $key => $val) {
|
||||
$val = str_replace("'", ''', $val);
|
||||
$sHtml .= "<input type='hidden' name='".$key."' value='".$val."'/>";
|
||||
}
|
||||
$sHtml .= "<input type='submit' value='ok' style='display:none;'></form>";
|
||||
$sHtml .= "<script>document.forms['alipay_submit'].submit();</script>";
|
||||
|
||||
public function close($order): Collection
|
||||
{
|
||||
}
|
||||
|
||||
public function verify($content): Collection
|
||||
{
|
||||
}
|
||||
|
||||
public function success(): Response
|
||||
{
|
||||
}
|
||||
|
||||
public function launch(array $payload): Collection
|
||||
{
|
||||
return new Response($sHtml);
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,10 @@ declare(strict_types=1);
|
||||
namespace Yansongda\Pay\Provider;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Contract\ProviderInterface;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
class Wechat implements ProviderInterface
|
||||
class Wechat
|
||||
{
|
||||
const URL = [
|
||||
Pay::MODE_NORMAL => 'https://api.mch.weixin.qq.com/',
|
||||
@ -18,11 +16,6 @@ class Wechat implements ProviderInterface
|
||||
Pay::MODE_SERVICE => 'https://api.mch.weixin.qq.com/',
|
||||
];
|
||||
|
||||
public function addMiddleware(PluginInterface $middleware): ProviderInterface
|
||||
{
|
||||
// TODO: Implement addMiddleware() method.
|
||||
}
|
||||
|
||||
public function pay($order, ?array $middleware = [])
|
||||
{
|
||||
// TODO: Implement pay() method.
|
||||
|
97
src/Rocket.php
Normal file
97
src/Rocket.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay;
|
||||
|
||||
use ArrayAccess;
|
||||
use JsonSerializable as JsonSerializableInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Serializable as SerializableInterface;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Supports\Traits\Accessable;
|
||||
use Yansongda\Supports\Traits\Arrayable;
|
||||
use Yansongda\Supports\Traits\Serializable;
|
||||
|
||||
class Rocket implements JsonSerializableInterface, SerializableInterface, ArrayAccess
|
||||
{
|
||||
use Accessable;
|
||||
use Arrayable;
|
||||
use Serializable;
|
||||
|
||||
/**
|
||||
* @var \Psr\Http\Message\RequestInterface
|
||||
*/
|
||||
private $radar;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $params;
|
||||
|
||||
/**
|
||||
* @var \Yansongda\Supports\Collection
|
||||
*/
|
||||
private $payload;
|
||||
|
||||
/**
|
||||
* @var \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
private $destination;
|
||||
|
||||
public function getRadar(): RequestInterface
|
||||
{
|
||||
return $this->radar;
|
||||
}
|
||||
|
||||
public function setRadar(RequestInterface $radar): Rocket
|
||||
{
|
||||
$this->radar = $radar;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getParams(): array
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
public function setParams(array $params): Rocket
|
||||
{
|
||||
$this->params = $params;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPayload(): Collection
|
||||
{
|
||||
return $this->payload;
|
||||
}
|
||||
|
||||
public function setPayload(Collection $payload): Rocket
|
||||
{
|
||||
$this->payload = $payload;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function mergePayload(array $payload): Rocket
|
||||
{
|
||||
$this->payload = $this->payload->merge($payload);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDestination(): ResponseInterface
|
||||
{
|
||||
return $this->destination;
|
||||
}
|
||||
|
||||
public function setDestination(ResponseInterface $destination): Rocket
|
||||
{
|
||||
$this->destination = $destination;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user