mirror of
http://124.126.16.154:8888/singularity/hdk-pay.git
synced 2026-01-15 07:15:06 +08:00
Compare commits
19 Commits
v1.0.0-bet
...
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca6000a5c8 | ||
|
|
1814adc30e | ||
|
|
06dc4a2e65 | ||
|
|
a2fc4cecf8 | ||
|
|
1bb8666b5e | ||
|
|
5559f2c2a5 | ||
|
|
4f0d402538 | ||
|
|
336cb3a9b9 | ||
|
|
3d91f76dc0 | ||
|
|
7f7fe100e7 | ||
|
|
a0baa27c08 | ||
|
|
14fc65dc34 | ||
|
|
678881241f | ||
|
|
8cbc81d3b7 | ||
|
|
b669931e78 | ||
|
|
ce1ad9561e | ||
|
|
427b6cd7af | ||
|
|
047b0ce67a | ||
|
|
7216e2c207 |
56
CHANGELOG.md
56
CHANGELOG.md
@@ -1,4 +1,60 @@
|
||||
# 版本更新日志
|
||||
## [1.0.0](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.0.0-beta.5...v1.0.0) (2025-08-18)
|
||||
|
||||
|
||||
### 📦 Build System | 打包构建
|
||||
|
||||
* **deps:** 更新 Hyperf 和 Symfony 组件 ([7f7fe10](http://124.126.16.154:8888/singularity/hdk-pay/commit/7f7fe100e71e98557de0399702ef2e3cb17d3b42))
|
||||
|
||||
|
||||
### ✅ Tests | 测试
|
||||
|
||||
* **pay:** 添加账户信息查询功能测试 ([336cb3a](http://124.126.16.154:8888/singularity/hdk-pay/commit/336cb3a9b9baa0b9e47ca7cf5bb5a6bc04d48c90))
|
||||
|
||||
|
||||
### ♻️ Code Refactoring | 代码重构
|
||||
|
||||
* **pay:** 调整请求头构建逻辑 ([1bb8666](http://124.126.16.154:8888/singularity/hdk-pay/commit/1bb8666b5e4432d720d9b8256baa06d4f570718a))
|
||||
* **pay:** 重构账户余额查询功能 ([5559f2c](http://124.126.16.154:8888/singularity/hdk-pay/commit/5559f2c2a59326a8aa209ffb00693523d39fc319))
|
||||
* **pay:** 重构账户余额查询接口并添加单元测试 ([4f0d402](http://124.126.16.154:8888/singularity/hdk-pay/commit/4f0d402538410020c89910b48bb418f2d306b1a0))
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **domain:** 新增账户余额和积分相关实体及接口 ([3d91f76](http://124.126.16.154:8888/singularity/hdk-pay/commit/3d91f76dc0657bd24643ee18a3192ad631001530))
|
||||
* **pay:** 添加产品类型枚举和兑换率接口 ([a2fc4ce](http://124.126.16.154:8888/singularity/hdk-pay/commit/a2fc4cecf8105616b440add0bfaab93b91abce09))
|
||||
* **product:** 增加 EMA 产品查询功能 ([1814adc](http://124.126.16.154:8888/singularity/hdk-pay/commit/1814adc30e0c3801c11bfb270a666ebd9348d115))
|
||||
* **product:** 新增充值产品相关数据结构和接口 ([06dc4a2](http://124.126.16.154:8888/singularity/hdk-pay/commit/06dc4a2e6555f92aab09271a3f8cd09fc8960e95))
|
||||
|
||||
## [1.0.0-beta.5](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2025-07-17)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **Goods:** 添加 Stripe 信息并优化金额处理 ([14fc65d](http://124.126.16.154:8888/singularity/hdk-pay/commit/14fc65dc3446d6dce489edf2613c1967a50274bf))
|
||||
|
||||
## [1.0.0-beta.4](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2025-07-11)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **OrderRpc:** 增加站点和环境参数并优化请求头 ([8cbc81d](http://124.126.16.154:8888/singularity/hdk-pay/commit/8cbc81d3b70ca408fbe8e905200d6a89f22cda40))
|
||||
|
||||
## [1.0.0-beta.3](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2025-07-08)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **order:** 兼容 v2 创建订单 ([ce1ad95](http://124.126.16.154:8888/singularity/hdk-pay/commit/ce1ad9561e0a780f670d766b8d4c841130a18697))
|
||||
* **Order:** 增加订单商品名称和数量字段 ([427b6cd](http://124.126.16.154:8888/singularity/hdk-pay/commit/427b6cd7af1800c4c4d5ba685686c61cc6fbef52))
|
||||
|
||||
## [1.0.0-beta.2](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2024-12-06)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **order:** 增加订单商品数量参数并优化代码格式 ([7216e2c](http://124.126.16.154:8888/singularity/hdk-pay/commit/7216e2c20763801d9d3532aad4b4463afb6fcc7e))
|
||||
|
||||
## [1.0.0-beta.1](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.0.0-beta.0...v1.0.0-beta.1) (2024-02-27)
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
"Singularity\\HDK\\Pay\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Singularity\\HDK\\Test\\Pay\\": "tests/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"hyperf": {
|
||||
"config": "Singularity\\HDK\\Pay\\ConfigProvider"
|
||||
@@ -15,21 +20,24 @@
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"composer/composer": ">=2.5.8",
|
||||
"ext-bcmath": "*",
|
||||
"composer/composer": ">=2.7.7",
|
||||
"hyperf/config": "~3.1.0",
|
||||
"hyperf/constants": "3.1.*",
|
||||
"hyperf/contract": "~3.1.0",
|
||||
"hyperf/di": "~3.1.0",
|
||||
"hyperf/guzzle": "3.1.*",
|
||||
"hyperf/http-server": "3.1.*",
|
||||
"hyperf/http-server": "^3.1",
|
||||
"moneyphp/money": "^4.1",
|
||||
"nesbot/carbon": "*",
|
||||
"singularity/hdk-core": "^1.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"firebase/php-jwt": "^6.8.0",
|
||||
"hyperf/testing": "^3.1",
|
||||
"friendsofhyperf/pest-plugin-hyperf": "3.1.*",
|
||||
"swoole/ide-helper": "^4.8.13"
|
||||
"swoole/ide-helper": "^4.8.13",
|
||||
"nesbot/carbon": "^2.0"
|
||||
},
|
||||
"minimum-stability": "beta",
|
||||
"prefer-stable": true,
|
||||
@@ -62,5 +70,5 @@
|
||||
"url": "https://mirrors.aliyun.com/composer/"
|
||||
}
|
||||
},
|
||||
"version": "1.0.0-beta.1"
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
2413
composer.lock
generated
2413
composer.lock
generated
File diff suppressed because it is too large
Load Diff
29
src/Application/Dto/AbstractDto.php
Normal file
29
src/Application/Dto/AbstractDto.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AbstractDto.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Application\Dto;
|
||||
|
||||
use Hyperf\Codec\Json;
|
||||
use Hyperf\Contract\Jsonable;
|
||||
use Swoole\ArrayObject;
|
||||
|
||||
abstract class AbstractDto extends ArrayObject implements Jsonable
|
||||
{
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
|
||||
public function toJson(): string
|
||||
{
|
||||
return Json::encode($this->toArray());
|
||||
}
|
||||
}
|
||||
70
src/Application/Dto/Product/RechargeProductsDto.php
Normal file
70
src/Application/Dto/Product/RechargeProductsDto.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RechargeProductsDto.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Application\Dto\Product;
|
||||
|
||||
|
||||
use Singularity\HDK\Pay\Application\Dto\AbstractDto;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\Entities\ProductItem;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\RechargeProduct;
|
||||
|
||||
final class RechargeProductsDto extends AbstractDto
|
||||
{
|
||||
public function __construct(RechargeProduct $product)
|
||||
{
|
||||
parent::__construct(array_filter([
|
||||
'one_time' => $this->parseProductItem($product->getOneTime()),
|
||||
'renew' => $this->parseProductItem($product->getRenew()),
|
||||
'plan' => array_map(
|
||||
fn(ProductItem $item) => $this->parseProductItem($item),
|
||||
$product->getPlans(),
|
||||
),
|
||||
'package' => array_map(
|
||||
fn(ProductItem $item) => $this->parseProductItem($item),
|
||||
$product->getPackages(),
|
||||
),
|
||||
]));
|
||||
}
|
||||
|
||||
private function parseProductItem(?ProductItem $product): array
|
||||
{
|
||||
if (is_null($product)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$effect = $product->effect;
|
||||
$price = $product->unitPrice;
|
||||
|
||||
return [
|
||||
'id' => $product->id,
|
||||
'name' => $product->description,
|
||||
'currency' => $price->getCurrency()->getCode(),
|
||||
'price' => (float)$price->getAmount(),
|
||||
'total_points' => $effect->getPointTotal(),
|
||||
'bonus_rate_pct' => (float)(bcmul(
|
||||
num1: $effect->getPointTotal() == 0
|
||||
? '0'
|
||||
: bcdiv(
|
||||
(string)$effect->pointBonus,
|
||||
(string)$effect->getPointTotal(),
|
||||
3,
|
||||
),
|
||||
num2: '100',
|
||||
scale: 0,
|
||||
)),
|
||||
'point' => [
|
||||
'total' => $effect->getPointTotal(),
|
||||
'number' => $effect->pointBasic,
|
||||
'bonus' => $effect->pointBonus,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,11 @@ namespace Singularity\HDK\Pay;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Framework\Logger\StdoutLogger;
|
||||
use Singularity\HDK\Pay\Domain\Account\Repository\AccountRepoInterface;
|
||||
use Singularity\HDK\Pay\Domain\Product\Repository\ExchangeRepoInterface;
|
||||
use Singularity\HDK\Pay\Domain\Product\Repository\RechargeProductRepoInterface;
|
||||
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
|
||||
use Singularity\HDK\Pay\Infrastructure\Repository\ProductRepo;
|
||||
|
||||
/**
|
||||
* ConfigProvider.php@HyperfAuth
|
||||
@@ -18,11 +23,15 @@ class ConfigProvider
|
||||
{
|
||||
public function __invoke(): array
|
||||
{
|
||||
/** @noinspection PhpUndefinedConstantInspection */
|
||||
return [
|
||||
// 合并到 config/autoload/dependencies.php 文件
|
||||
'dependencies' => [
|
||||
StdoutLoggerInterface::class => StdoutLogger::class,
|
||||
|
||||
// Repository
|
||||
AccountRepoInterface::class => AccountBalanceRepo::class,
|
||||
ExchangeRepoInterface::class => ProductRepo::class,
|
||||
RechargeProductRepoInterface::class => ProductRepo::class,
|
||||
],
|
||||
// 合并到 config/autoload/annotations.php 文件
|
||||
'annotations' => [
|
||||
|
||||
46
src/Domain/Account/Aggregate/AccountBalance.php
Normal file
46
src/Domain/Account/Aggregate/AccountBalance.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountBalance.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/17
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Account\Aggregate;
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Account\Aggregate\ValueObject\PointsBalance;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Pay\Domain\Account\Aggregate\AccountBalance@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/17
|
||||
*
|
||||
* @template TPointType of string
|
||||
* @template TPointsBalances of array<TPointType, PointsBalance>
|
||||
*/
|
||||
final readonly class AccountBalance
|
||||
{
|
||||
/**
|
||||
* @param string $uid
|
||||
* @param TPointsBalances $pointsBalances
|
||||
*/
|
||||
public function __construct(
|
||||
private string $uid,
|
||||
private array $pointsBalances = [],
|
||||
) {}
|
||||
|
||||
public function getUid(): string
|
||||
{
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
public function getPointsBalances(): array
|
||||
{
|
||||
return $this->pointsBalances;
|
||||
}
|
||||
}
|
||||
58
src/Domain/Account/Aggregate/ValueObject/PointsBalance.php
Normal file
58
src/Domain/Account/Aggregate/ValueObject/PointsBalance.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PointsBalance.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Account\Aggregate\ValueObject;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
|
||||
final readonly class PointsBalance
|
||||
{
|
||||
public function __construct(
|
||||
private PointType $type,
|
||||
private float $total,
|
||||
private float $cost,
|
||||
public float $amount,
|
||||
private string|null $version,
|
||||
private Carbon|null $expiredAt,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getType(): PointType
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getTotal(): float
|
||||
{
|
||||
return $this->total;
|
||||
}
|
||||
|
||||
public function getCost(): float
|
||||
{
|
||||
return $this->cost;
|
||||
}
|
||||
|
||||
public function getVersion(): ?string
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function getExpiredAt(): ?Carbon
|
||||
{
|
||||
return $this->expiredAt;
|
||||
}
|
||||
|
||||
public function getAmount(): float
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
}
|
||||
35
src/Domain/Account/Enum/PointType.php
Normal file
35
src/Domain/Account/Enum/PointType.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* PointType.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Account\Enum;
|
||||
|
||||
enum PointType: string
|
||||
{
|
||||
case LuxPoint = 'lux-point';
|
||||
|
||||
case EMA = 'ema';
|
||||
|
||||
case FtaiAligner = 'aligner';
|
||||
case FtaiRetainer = 'retainer';
|
||||
|
||||
case Aligner4D = 'aligner-4d';
|
||||
case NightguardAi = 'nightguard-ai';
|
||||
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
self::LuxPoint->value,
|
||||
self::EMA->value,
|
||||
self::FtaiAligner->value,
|
||||
self::FtaiRetainer->value,
|
||||
self::Aligner4D->value,
|
||||
self::NightguardAi->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
23
src/Domain/Account/Repository/AccountRepoInterface.php
Normal file
23
src/Domain/Account/Repository/AccountRepoInterface.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountBalanceRpc.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/17
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Account\Repository;
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Account\Aggregate\AccountBalance;
|
||||
use Singularity\HDK\Pay\Domain\Account\Aggregate\ValueObject\PointsBalance;
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
|
||||
interface AccountRepoInterface
|
||||
{
|
||||
public function getAccount(string $uid): AccountBalance;
|
||||
|
||||
public function getPointBalance(string $uid, PointType $pointType): PointsBalance;
|
||||
}
|
||||
32
src/Domain/AggregateRoot.php
Normal file
32
src/Domain/AggregateRoot.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AggregateRoot.php@LuxDesign
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/7/31
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain;
|
||||
|
||||
abstract class AggregateRoot implements AggregateRootInterface {
|
||||
/**
|
||||
* @var array{}|DomainEvent[]
|
||||
*/
|
||||
protected array $domainEvents = [];
|
||||
|
||||
public function recordEvent(DomainEvent $event): void
|
||||
{
|
||||
$this->domainEvents[] = $event;
|
||||
}
|
||||
|
||||
public function flushAllEvent(): array
|
||||
{
|
||||
$events = $this->domainEvents;
|
||||
$this->domainEvents = [];
|
||||
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
14
src/Domain/AggregateRootInterface.php
Normal file
14
src/Domain/AggregateRootInterface.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AbstractAggregateRoot.php@LuxDesign
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/7/25
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain;
|
||||
|
||||
interface AggregateRootInterface {}
|
||||
12
src/Domain/DomainEvent.php
Normal file
12
src/Domain/DomainEvent.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* DomainEvent.php@LuxDesign
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/7/31
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain;
|
||||
|
||||
interface DomainEvent {}
|
||||
14
src/Domain/DomainException.php
Normal file
14
src/Domain/DomainException.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DomainException.php@LuxDesign
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/7/8
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain;
|
||||
|
||||
class DomainException extends \RuntimeException {}
|
||||
27
src/Domain/Product/Aggregate/Entities/ProductItem.php
Normal file
27
src/Domain/Product/Aggregate/Entities/ProductItem.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RechargeProduct.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Product\Aggregate\Entities;
|
||||
|
||||
use Money\Money;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\ValueObject\RechargeEffect;
|
||||
use Singularity\HDK\Pay\Domain\Product\Enum\ProductType;
|
||||
|
||||
final class ProductItem
|
||||
{
|
||||
public function __construct(
|
||||
public int $id,
|
||||
public string $description,
|
||||
public Money $unitPrice,
|
||||
public ProductType $productType,
|
||||
public RechargeEffect $effect,
|
||||
) {}
|
||||
}
|
||||
80
src/Domain/Product/Aggregate/RechargeProduct.php
Normal file
80
src/Domain/Product/Aggregate/RechargeProduct.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RechargeProduct.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Product\Aggregate;
|
||||
|
||||
use Singularity\HDK\Pay\Domain\AggregateRoot;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\Entities\ProductItem;
|
||||
|
||||
/**
|
||||
* App\Domain\Product\Aggregate\RechargeProduct@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*
|
||||
* @property-read ProductItem[] $plans
|
||||
* @property-read ProductItem[] $packages
|
||||
* @property-read ProductItem $oneTime
|
||||
*/
|
||||
final class RechargeProduct extends AggregateRoot
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ?ProductItem $oneTime,
|
||||
private readonly ?ProductItem $renew = null,
|
||||
private readonly array $plans = [],
|
||||
private readonly array $packages = [],
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array $idList
|
||||
* @return array{'id': int, 'quantity': int, 'detail': ProductItem}
|
||||
*/
|
||||
public function selectItemList(array $idList): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
/** @var ProductItem $item */
|
||||
foreach ([$this->oneTime, $this->renew, ...$this->plans, ...$this->packages] as $item) {
|
||||
if (in_array($item->id, $idList)) {
|
||||
$result[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ProductItem[]
|
||||
*/
|
||||
public function getPlans(): array
|
||||
{
|
||||
return $this->plans;
|
||||
}
|
||||
|
||||
public function getRenew(): ?ProductItem
|
||||
{
|
||||
return $this->renew;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ProductItem[]
|
||||
*/
|
||||
public function getPackages(): array
|
||||
{
|
||||
return $this->packages;
|
||||
}
|
||||
|
||||
public function getOneTime(): ?ProductItem
|
||||
{
|
||||
return $this->oneTime;
|
||||
}
|
||||
}
|
||||
86
src/Domain/Product/Aggregate/ValueObject/RechargeEffect.php
Normal file
86
src/Domain/Product/Aggregate/ValueObject/RechargeEffect.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RechargeEffect.php@LuxDesign
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Product\Aggregate\ValueObject;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Hyperf\Framework\Exception\NotImplementedException;
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
|
||||
final class RechargeEffect
|
||||
{
|
||||
private float $pointTotal;
|
||||
|
||||
public function __construct(
|
||||
public PointType $pointType,
|
||||
|
||||
public float $pointBasic,
|
||||
public float $pointBonus,
|
||||
|
||||
public ?Carbon $expiredAt = null,
|
||||
|
||||
public ?string $version = null,
|
||||
) {
|
||||
$this->pointTotal = (float)bcadd((string)$pointBasic, (string)$pointBonus, 4);
|
||||
}
|
||||
|
||||
public function getPointTotal(): float
|
||||
{
|
||||
return $this->pointTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template TPoints of array{'total': float, 'basic': float, 'bonus': float}
|
||||
* @return array{'points'?: TPoints, 'version'?: string, 'expired_at'?: Carbon}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_filter([
|
||||
'points' => $this->pointTotal == 0
|
||||
? null
|
||||
: [
|
||||
'total' => $this->pointTotal,
|
||||
'basic' => $this->pointBasic,
|
||||
'bonus' => $this->pointBonus,
|
||||
],
|
||||
'version' => $this->version,
|
||||
'expired_at' => $this->expiredAt,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PointType $pointType
|
||||
* @param string $range
|
||||
* @return Carbon
|
||||
*/
|
||||
private static function parseExpiredAt(PointType $pointType, string $range): Carbon
|
||||
{
|
||||
if ($pointType !== PointType::EMA) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
$now = Carbon::now();
|
||||
|
||||
preg_match('/^(\d+)(\w)$/', $range, $matches);
|
||||
$quantity = $matches[1]; // 数字部分
|
||||
$unit = $matches[2]; // 单位部分
|
||||
|
||||
return match ($unit) {
|
||||
'Y' => $now->addYears($quantity),
|
||||
'm' => $now->addMonths($quantity),
|
||||
'd' => $now->addDays($quantity),
|
||||
'H' => $now->addHours($quantity),
|
||||
'i' => $now->addMinutes($quantity),
|
||||
's' => $now->addSeconds($quantity),
|
||||
default => $now
|
||||
};
|
||||
}
|
||||
}
|
||||
41
src/Domain/Product/Enum/ProductType.php
Normal file
41
src/Domain/Product/Enum/ProductType.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* ProductType.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Product\Enum;
|
||||
|
||||
enum ProductType {
|
||||
case plan;
|
||||
|
||||
case pack;
|
||||
|
||||
case oneTime;
|
||||
|
||||
case renew;
|
||||
|
||||
public static function tryFrom(string $type): ?ProductType
|
||||
{
|
||||
return match ($type) {
|
||||
'plan' => self::plan,
|
||||
'pack' => self::pack,
|
||||
'oneTime' => self::oneTime,
|
||||
'renew' => self::renew,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
public static function names(): array
|
||||
{
|
||||
$result = [];
|
||||
foreach (self::cases() as $case) {
|
||||
$result[] = $case->name;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
22
src/Domain/Product/Repository/ExchangeRepoInterface.php
Normal file
22
src/Domain/Product/Repository/ExchangeRepoInterface.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* ExchangeRepoInterface.php@LuxDesign
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/7/29
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Product\Repository;
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
|
||||
interface ExchangeRepoInterface
|
||||
{
|
||||
/**
|
||||
* @param PointType $source
|
||||
* @param PointType $target
|
||||
* @return float
|
||||
*/
|
||||
public function getRate(PointType $source, PointType $target): float;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* RechargeProductRepoInterface.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/5
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Product\Repository;
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\RechargeProduct;
|
||||
|
||||
interface RechargeProductRepoInterface
|
||||
{
|
||||
/**
|
||||
* @return RechargeProduct
|
||||
*/
|
||||
public function findLuxPointProduct(): RechargeProduct;
|
||||
|
||||
/**
|
||||
* @param string $uid
|
||||
* @return RechargeProduct
|
||||
*/
|
||||
public function findEmaProduct(string $uid): RechargeProduct;
|
||||
}
|
||||
16
src/Domain/ValueObject.php
Normal file
16
src/Domain/ValueObject.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ValueObject.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/12
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain;
|
||||
|
||||
use Swoole\ArrayObject;
|
||||
|
||||
abstract class ValueObject extends ArrayObject {}
|
||||
17
src/Enum/Environment.php
Normal file
17
src/Enum/Environment.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Environment.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/8
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Enum;
|
||||
|
||||
enum Environment: string
|
||||
{
|
||||
case Dev = 'development';
|
||||
|
||||
case Prod = 'production';
|
||||
}
|
||||
@@ -11,9 +11,12 @@ namespace Singularity\HDK\Pay\Enum;
|
||||
|
||||
enum PaymentMethod: string
|
||||
{
|
||||
case Stripe = 'stripe';
|
||||
// case Stripe = 'stripe';
|
||||
// case WechatPay = 'wechat';
|
||||
|
||||
case WechatPay = 'wechat';
|
||||
case StripeCheckout = 'stripe.checkout';
|
||||
case StripeIntent = 'stripe.intent';
|
||||
case WechatNative = 'wechat.native';
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
|
||||
17
src/Enum/Site.php
Normal file
17
src/Enum/Site.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Site.php@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/8
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Enum;
|
||||
|
||||
enum Site: string
|
||||
{
|
||||
case ChinaMainland = 'CN';
|
||||
|
||||
case NorthAmerica = 'NA';
|
||||
}
|
||||
35
src/Infrastructure/Repository/AbstractRepo.php
Normal file
35
src/Infrastructure/Repository/AbstractRepo.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AbstractRepo.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/18
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Infrastructure\Repository;
|
||||
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Singularity\HDK\Core\Http\RequestService;
|
||||
use Singularity\HDK\Core\Http\RequestServiceFactory;
|
||||
|
||||
use Singularity\HDK\Pay\Trait\RequestHeaderBuilder;
|
||||
|
||||
use function Hyperf\Config\config;
|
||||
|
||||
abstract class AbstractRepo
|
||||
{
|
||||
use RequestHeaderBuilder;
|
||||
|
||||
protected RequestService $requestService;
|
||||
|
||||
public function __construct(?string $baseUrl = null)
|
||||
{
|
||||
$this->requestService = RequestServiceFactory::make([
|
||||
'base_uri' => $baseUrl ?? config('payment.base_uri'),
|
||||
RequestOptions::ALLOW_REDIRECTS => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
75
src/Infrastructure/Repository/AccountBalanceRepo.php
Normal file
75
src/Infrastructure/Repository/AccountBalanceRepo.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AccountBalanceRpc.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/17
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Infrastructure\Repository;
|
||||
|
||||
use Hyperf\Codec\Json;
|
||||
use Singularity\HDK\Pay\Domain\Account\Aggregate\AccountBalance;
|
||||
use Singularity\HDK\Pay\Domain\Account\Aggregate\ValueObject\PointsBalance;
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
use Singularity\HDK\Pay\Domain\Account\Repository\AccountRepoInterface;
|
||||
|
||||
final class AccountBalanceRepo extends AbstractRepo implements AccountRepoInterface
|
||||
{
|
||||
public function getAccount(string $uid): AccountBalance
|
||||
{
|
||||
$response = $this->requestService->requestGet(
|
||||
url: "/rpc/v2/account/$uid/balance",
|
||||
params: [
|
||||
'type' => join(',', PointType::values()),
|
||||
],
|
||||
options: [
|
||||
'headers' => $this->headerBuilder(),
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
$result = Json::decode($content);
|
||||
|
||||
return new AccountBalance(
|
||||
uid: $result['uid'],
|
||||
pointsBalances: array_map(
|
||||
callback: fn($pointBalance)
|
||||
=> new PointsBalance(
|
||||
type: PointType::from($pointBalance['name']),
|
||||
total: $pointBalance['total'],
|
||||
cost: $pointBalance['cost'],
|
||||
amount: $pointBalance['amount'],
|
||||
version: $pointBalance['version'],
|
||||
expiredAt: $pointBalance['expired_at'],
|
||||
),
|
||||
array: $result['point_balance'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function getPointBalance(string $uid, PointType $pointType): PointsBalance
|
||||
{
|
||||
$response = $this->requestService->requestGet(
|
||||
url: "/rpc/v2/account/$uid/balance/$pointType->value",
|
||||
options: [
|
||||
'headers' => $this->headerBuilder(),
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
$result = Json::decode($content);
|
||||
|
||||
return new PointsBalance(
|
||||
type: PointType::from($result['name']),
|
||||
total: $result['total'],
|
||||
cost: $result['cost'],
|
||||
amount: $result['amount'],
|
||||
version: $result['version'],
|
||||
expiredAt: $result['expired_at'],
|
||||
);
|
||||
}
|
||||
}
|
||||
161
src/Infrastructure/Repository/ProductRepo.php
Normal file
161
src/Infrastructure/Repository/ProductRepo.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ProductRepo.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/18
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Infrastructure\Repository;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Hyperf\Codec\Json;
|
||||
use Money\Currency;
|
||||
use Money\Money;
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\Entities\ProductItem;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\RechargeProduct;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\ValueObject\RechargeEffect;
|
||||
use Singularity\HDK\Pay\Domain\Product\Enum\ProductType;
|
||||
use Singularity\HDK\Pay\Domain\Product\Repository\ExchangeRepoInterface;
|
||||
use Singularity\HDK\Pay\Domain\Product\Repository\RechargeProductRepoInterface;
|
||||
|
||||
final class ProductRepo extends AbstractRepo implements RechargeProductRepoInterface, ExchangeRepoInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function findLuxPointProduct(): RechargeProduct
|
||||
{
|
||||
$response = $this->requestService->requestGet(
|
||||
url: '/rpc/v2/products/lux-point',
|
||||
options: [
|
||||
'headers' => $this->headerBuilder(),
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
$result = Json::decode($content);
|
||||
|
||||
return new RechargeProduct(
|
||||
oneTime: new ProductItem(
|
||||
id: $result['one_time']['id'],
|
||||
description: $result['one_time']['name'],
|
||||
unitPrice: new Money(
|
||||
amount: $result['one_time']['price'],
|
||||
currency: new Currency($result['one_time']['currency']),
|
||||
),
|
||||
productType: ProductType::oneTime,
|
||||
effect: new RechargeEffect(
|
||||
pointType: PointType::LuxPoint,
|
||||
pointBasic: $result['one_time']['point']['number'],
|
||||
pointBonus: $result['one_time']['point']['bonus'],
|
||||
),
|
||||
),
|
||||
packages: array_map(fn(array $item) => new ProductItem(
|
||||
id: $item['id'],
|
||||
description: $item['name'],
|
||||
unitPrice: new Money(
|
||||
amount: $item['price'],
|
||||
currency: new Currency($item['currency']),
|
||||
),
|
||||
productType: ProductType::pack,
|
||||
effect: new RechargeEffect(
|
||||
pointType: PointType::LuxPoint,
|
||||
pointBasic: $item['point']['number'],
|
||||
pointBonus: $item['point']['bonus'],
|
||||
),
|
||||
), $result['package']),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function findEmaProduct(string $uid): RechargeProduct
|
||||
{
|
||||
$response = $this->requestService->requestGet(
|
||||
url: '/rpc/v2/products/ema',
|
||||
params: ['uid' => $uid],
|
||||
options: [
|
||||
'headers' => $this->headerBuilder(),
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
$result = Json::decode($content);
|
||||
|
||||
return new RechargeProduct(
|
||||
oneTime: isset($result['one_time'])
|
||||
? new ProductItem(
|
||||
id: $result['one_time']['id'],
|
||||
description: $result['one_time']['name'],
|
||||
unitPrice: new Money(
|
||||
amount: $result['one_time']['price'],
|
||||
currency: new Currency($result['one_time']['currency']),
|
||||
),
|
||||
productType: ProductType::oneTime,
|
||||
effect: new RechargeEffect(
|
||||
pointType: PointType::EMA,
|
||||
pointBasic: $result['one_time']['point']['number'],
|
||||
pointBonus: $result['one_time']['point']['bonus'],
|
||||
),
|
||||
)
|
||||
: null,
|
||||
renew: isset($result['renew'])
|
||||
? new ProductItem(
|
||||
id: $result['renew']['id'],
|
||||
description: $result['renew']['name'],
|
||||
unitPrice: new Money(
|
||||
amount: $result['renew']['price'],
|
||||
currency: new Currency($result['renew']['currency']),
|
||||
),
|
||||
productType: ProductType::renew,
|
||||
effect: new RechargeEffect(
|
||||
pointType: PointType::EMA,
|
||||
pointBasic: $result['renew']['point']['number'],
|
||||
pointBonus: $result['renew']['point']['bonus'],
|
||||
),
|
||||
)
|
||||
: null,
|
||||
plans: array_map(fn(array $item) => new ProductItem(
|
||||
id: $item['id'],
|
||||
description: $item['name'],
|
||||
unitPrice: new Money(
|
||||
amount: $item['price'],
|
||||
currency: new Currency($item['currency']),
|
||||
),
|
||||
productType: ProductType::plan,
|
||||
effect: new RechargeEffect(
|
||||
pointType: PointType::LuxPoint,
|
||||
pointBasic: $item['point']['number'],
|
||||
pointBonus: $item['point']['bonus'],
|
||||
),
|
||||
), $result['plan']),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PointType $source
|
||||
* @param PointType $target
|
||||
* @return float
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function getRate(PointType $source, PointType $target): float
|
||||
{
|
||||
$response = $this->requestService->requestGet(
|
||||
url: "/rpc/v2/products/$target->value/exchange-rate/$source->value",
|
||||
options: [
|
||||
'headers' => $this->headerBuilder(),
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
$result = Json::decode($content);
|
||||
|
||||
return $result['rate'];
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,8 @@ use Money\Money;
|
||||
* @property-read int $id
|
||||
* @property-read string $goodsName
|
||||
* @property-read array<string, mixed>|array{} $goodsSpec
|
||||
* @property-read Money $amount
|
||||
* @property-read Money|array{'price': int, 'currency': string} $amount
|
||||
* @property-read array{'id': int, 'product_id': string, 'price_id': string} $stripe
|
||||
*/
|
||||
final class Goods extends JsonResource
|
||||
{
|
||||
@@ -40,7 +41,19 @@ final class Goods extends JsonResource
|
||||
'id' => $this->id,
|
||||
'goodsName' => $this->goodsName,
|
||||
'goodsSpec' => $this->goodsSpec,
|
||||
'amount' => new Money($this->amount['price'], new Currency($this->amount['currency']))
|
||||
'amount' => new Money(
|
||||
amount: $this->amount['price'],
|
||||
currency: new Currency($this->amount['currency']),
|
||||
),
|
||||
'stripe' => $this->when(
|
||||
condition: isset($this->resource->stripeProduct),
|
||||
value: fn()
|
||||
=> [
|
||||
'id' => $this->stripe['id'],
|
||||
'product_id' => $this->stripe['product_id'],
|
||||
'price_id' => $this->stripe['price_id'],
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,15 @@ use Singularity\HDK\Pay\Enum\OrderStatus;
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/9/19
|
||||
*
|
||||
* @property-read string $orderNo
|
||||
* @property-read string transactionId
|
||||
* @property-read Money amount
|
||||
* @property-read OrderStatus state
|
||||
* @property-read string uid
|
||||
* @property-read string payment
|
||||
* @property-read string remark
|
||||
* @property-read string $orderNo
|
||||
* @property-read string $transactionId
|
||||
* @property-read string $goodsName
|
||||
* @property-read Money|array{'amount': int, 'currency': string} $amount
|
||||
* @property-read OrderStatus $state
|
||||
* @property-read string $uid
|
||||
* @property-read string $payment
|
||||
* @property-read string $remark
|
||||
* @property-read int $number
|
||||
*/
|
||||
class Order extends JsonResource
|
||||
{
|
||||
@@ -32,11 +34,13 @@ class Order extends JsonResource
|
||||
* @return array{
|
||||
* orderNo: string,
|
||||
* transactionId: string,
|
||||
* goodsName: string,
|
||||
* amount: Money,
|
||||
* state: OrderStatus,
|
||||
* uid: string,
|
||||
* payment: string,
|
||||
* remark: string
|
||||
* remark: string,
|
||||
* number: int
|
||||
* }
|
||||
*/
|
||||
public function toArray(): array
|
||||
@@ -48,12 +52,13 @@ class Order extends JsonResource
|
||||
'goodsName' => $this->resource['goodsName'],
|
||||
'amount' => new Money(
|
||||
$this->resource['amount']['amount'],
|
||||
new Currency($this->resource['amount']['currency'])
|
||||
new Currency($this->resource['amount']['currency']),
|
||||
),
|
||||
'state' => OrderStatus::from($this->resource['state']),
|
||||
'uid' => $this->resource['uid'],
|
||||
'payment' => $this->resource['payment'],
|
||||
'remark' => $this->resource['remark'],
|
||||
'number' => $this->resource['number'] ?? 1,
|
||||
// extends
|
||||
// 'spId' => $this->spId,
|
||||
// 'goodsDetail' => GoodsCollection::make([$this->goodsDetail])->resolve(),
|
||||
|
||||
72
src/Resource/V2/Order.php
Normal file
72
src/Resource/V2/Order.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Singularity\HDK\Pay\Resource\V2;
|
||||
|
||||
use App\Model\ServiceProvider;
|
||||
use Carbon\Carbon;
|
||||
use Hyperf\Resource\Json\JsonResource;
|
||||
use Singularity\HDK\Pay\Enum\OrderStatus;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* App\Resource\ Order@LuxPay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/9/19
|
||||
*
|
||||
* @property string $order_no 订单号
|
||||
* @property OrderStatus $state 订单状态
|
||||
* @property string $transaction_id 订单号
|
||||
* @property string $uid 购买用户的 uid
|
||||
* @property string $method 支付方式
|
||||
* @property string $description 订单描述
|
||||
* @property int $total_amount 金额,单位:分
|
||||
* @property string $currency 币种,三个大写字母
|
||||
* @property array $items 订单详情
|
||||
* @property array $external 额外订单信息
|
||||
* @property string $remark 订单备注
|
||||
* @property array $notification 原始通知
|
||||
* @property array more_details 支付信息
|
||||
*/
|
||||
class Order extends JsonResource
|
||||
{
|
||||
public ?string $wrap = null;
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array{
|
||||
* orderNo: string,
|
||||
* transactionId: string,
|
||||
* amount: array{amount: numeric, currency: string},
|
||||
* state: string,
|
||||
* uid: string,
|
||||
* payment: string,
|
||||
* remark: string
|
||||
* }
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'order_no' => $this->order_no,
|
||||
'state' => $this->state,
|
||||
'transaction_id' => $this->transaction_id,
|
||||
'uid' => $this->uid,
|
||||
'method' => $this->method,
|
||||
'description' => $this->description,
|
||||
'total_amount' => $this->total_amount,
|
||||
'currency' => $this->currency,
|
||||
'items' => $this->items,
|
||||
'external' => $this->external,
|
||||
'remark' => $this->remark,
|
||||
'notification' => $this->notification ?? new StdClass(),
|
||||
'more_details' => $this->more_details,
|
||||
];
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->resource->{$key} ?? $this->resource[$key];
|
||||
}
|
||||
}
|
||||
83
src/Sdk/OrderRpc.php
Normal file
83
src/Sdk/OrderRpc.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* OrderRpc.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/7/9
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Sdk;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Hyperf\Codec\Json;
|
||||
use Hyperf\Context\Context;
|
||||
use Lmc\HttpConstants\Header;
|
||||
use Singularity\HDK\Core\Enumerations\Sp\ServiceProviderConfiguration;
|
||||
use Singularity\HDK\Core\Http\RequestService;
|
||||
use Singularity\HDK\Core\Http\RequestServiceFactory;
|
||||
use Singularity\HDK\Core\I18n\Enum\Languages;
|
||||
use Singularity\HDK\Pay\Resource\V2\Order;
|
||||
use Singularity\HDK\Pay\Trait\WebhooksNotificationHandler;
|
||||
|
||||
use function Hyperf\Config\config;
|
||||
|
||||
final class OrderRpc implements ServiceProviderConfiguration
|
||||
{
|
||||
use WebhooksNotificationHandler;
|
||||
|
||||
private RequestService $requestService;
|
||||
|
||||
public function __construct(?string $baseUrl = null)
|
||||
{
|
||||
$this->requestService = RequestServiceFactory::make([
|
||||
'base_uri' => $baseUrl ?? config('payment.base_uri'),
|
||||
RequestOptions::ALLOW_REDIRECTS => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param string|null $serviceProvider
|
||||
* @param Languages|null $locale
|
||||
* @param string|null $site
|
||||
* @param string|null $env
|
||||
* @return Order
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function create(
|
||||
array $data,
|
||||
?string $serviceProvider = null,
|
||||
?Languages $locale = null,
|
||||
?string $site = null,
|
||||
?string $env = null,
|
||||
): Order {
|
||||
$data['method'] = 'stripe.checkout';
|
||||
$response = $this->requestService->requestPost(
|
||||
url: '/rpc/v2/orders',
|
||||
data: $data,
|
||||
options: [
|
||||
'headers' => [
|
||||
Header::CONTENT_TYPE => 'application/json',
|
||||
Header::ACCEPT_LANGUAGE => $locale?->value ?? config('translation.locale', Languages::EN),
|
||||
'X-SP-ID' => $serviceProvider ?? Context::get('sp') ?? config('app_name'),
|
||||
'X-SITE' => match (strtoupper(trim($site ?? config('site', self::NA)))) {
|
||||
'CN' => self::CN,
|
||||
default => self::NA,
|
||||
},
|
||||
'X-ENV' => match (strtolower(trim($env ?? config('app_env', self::DEVELOPMENT)))) {
|
||||
'prod', 'production' => self::PRODUCTION,
|
||||
default => self::DEVELOPMENT
|
||||
},
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
$result = Json::decode($content);
|
||||
return new Order($result);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ namespace Singularity\HDK\Pay\Sdk;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Hyperf\Codec\Json;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
use Lmc\HttpConstants\Header;
|
||||
use Money\Money;
|
||||
use Singularity\HDK\Core\Http\RequestService;
|
||||
@@ -22,7 +21,6 @@ use Singularity\HDK\Core\Http\RequestServiceFactory;
|
||||
use Singularity\HDK\Core\I18n\Enum\Languages;
|
||||
use Singularity\HDK\Pay\Resource\Order;
|
||||
use Singularity\HDK\Pay\Resource\StripeConfiguration;
|
||||
|
||||
use Singularity\HDK\Pay\Trait\WebhooksNotificationHandler;
|
||||
|
||||
use function Hyperf\Config\config;
|
||||
@@ -58,11 +56,15 @@ final class StripeRpc
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Money $money
|
||||
* @param string $uid
|
||||
* @param int $goodsId
|
||||
* @param string $goodsName
|
||||
* @param array $goodsDetail
|
||||
* @param Money $money 总金额
|
||||
* @param string $uid
|
||||
* @param int $goodsId
|
||||
* @param string $goodsName
|
||||
* @param array $goodsDetail
|
||||
* @param int $number
|
||||
* @param Languages|null $locale
|
||||
* @param int|null $service
|
||||
*
|
||||
* @return Order
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
@@ -72,6 +74,7 @@ final class StripeRpc
|
||||
int $goodsId,
|
||||
string $goodsName,
|
||||
array $goodsDetail,
|
||||
int $number = 1,
|
||||
?Languages $locale = null,
|
||||
?int $service = null,
|
||||
): Order {
|
||||
@@ -87,15 +90,16 @@ final class StripeRpc
|
||||
[
|
||||
'id' => $goodsId,
|
||||
'goodsName' => $goodsName,
|
||||
]
|
||||
],
|
||||
),
|
||||
'number' => $number,
|
||||
],
|
||||
options: [
|
||||
'headers' => [
|
||||
Header::CONTENT_TYPE => 'application/json',
|
||||
Header::ACCEPT_LANGUAGE => $locale?->value ?? config('translation.locale')
|
||||
]
|
||||
]
|
||||
Header::ACCEPT_LANGUAGE => $locale?->value ?? config('translation.locale'),
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
|
||||
@@ -46,10 +46,12 @@ final class WechatRpc
|
||||
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param string $type
|
||||
* @param string $goodsName
|
||||
* @param Money $money
|
||||
* @param string $uid
|
||||
* @param string $type
|
||||
* @param string $goodsName
|
||||
* @param Money $money
|
||||
* @param string $uid
|
||||
* @param int $number
|
||||
*
|
||||
* @return array{uri: string, orderNo: string}
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
@@ -58,7 +60,8 @@ final class WechatRpc
|
||||
string $type,
|
||||
string $goodsName,
|
||||
Money $money,
|
||||
string $uid
|
||||
string $uid,
|
||||
int $number = 1,
|
||||
): array {
|
||||
$response = $this->requestService
|
||||
->setOptions([
|
||||
@@ -76,7 +79,8 @@ final class WechatRpc
|
||||
'goods_detail' => [
|
||||
'goods_name' => $goodsName,
|
||||
],
|
||||
]
|
||||
'number' => $number,
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* WechatService.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/7/17
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Service;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Pay\Service\WechatService@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/7/17
|
||||
*/
|
||||
final class WechatService
|
||||
{
|
||||
|
||||
}
|
||||
36
src/Trait/RequestHeaderBuilder.php
Normal file
36
src/Trait/RequestHeaderBuilder.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* RequestHeaderBuilder.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/18
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Pay\Trait;
|
||||
|
||||
use Lmc\HttpConstants\Header;
|
||||
use Singularity\HDK\Core\I18n\Enum\Languages;
|
||||
use Singularity\HDK\Pay\Enum\Environment;
|
||||
use Singularity\HDK\Pay\Enum\Site;
|
||||
|
||||
use function Hyperf\Config\config;
|
||||
|
||||
trait RequestHeaderBuilder {
|
||||
public function headerBuilder(): array
|
||||
{
|
||||
return [
|
||||
Header::CONTENT_TYPE => 'application/json',
|
||||
Header::ACCEPT_LANGUAGE => $locale?->value ?? config('translation.locale', Languages::EN->value),
|
||||
'X-SP-ID' => config('app_name'),
|
||||
'X-SITE' => (match (strtoupper(config('site', Site::NorthAmerica->value))) {
|
||||
'CN' => Site::ChinaMainland,
|
||||
default => Site::NorthAmerica,
|
||||
})->value,
|
||||
'X-ENV' => (match (strtolower(config('app_env', Environment::Dev->value))) {
|
||||
'prod', 'production' => Environment::Prod,
|
||||
default => Environment::Dev,
|
||||
})->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace Singularity\HDK\Pay\Trait;
|
||||
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
use Singularity\HDK\Pay\Resource\Order;
|
||||
use Singularity\HDK\Pay\Resource\V2\Order;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Pay\Trait\Webhooks@Pay
|
||||
|
||||
23
tests/Feature/Account/QueryAccountInformationTest.php
Normal file
23
tests/Feature/Account/QueryAccountInformationTest.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* QueryAccountInformationTest.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/18
|
||||
*/
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Account\Aggregate\AccountBalance;
|
||||
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
|
||||
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
it('should be able to query account information', function () {
|
||||
$uid = '123456';
|
||||
$repo = make(AccountBalanceRepo::class);
|
||||
$result = $repo->getAccount($uid);
|
||||
expect($result)
|
||||
->toBeInstanceOf(AccountBalance::class)
|
||||
->and($result->getUid())->tobe($uid);
|
||||
});
|
||||
24
tests/Feature/Account/QueryPointBalanceTest.php
Normal file
24
tests/Feature/Account/QueryPointBalanceTest.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* QueryPointBalanceTest.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/18
|
||||
*/
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Account\Aggregate\ValueObject\PointsBalance;
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
use Singularity\HDK\Pay\Infrastructure\Repository\AccountBalanceRepo;
|
||||
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
it('should query point balance', function () {
|
||||
$uid = 'cn3221';
|
||||
$repo = make(AccountBalanceRepo::class);
|
||||
$point_balance = $repo->getPointBalance($uid, PointType::EMA);
|
||||
expect($point_balance)
|
||||
->toBeInstanceOf(PointsBalance::class)
|
||||
->and($point_balance->getType())->toBe(PointType::EMA);
|
||||
});
|
||||
24
tests/Feature/Product/QueryPointRateTest.php
Normal file
24
tests/Feature/Product/QueryPointRateTest.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* QueryPointRateTest.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/18
|
||||
*/
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
use Singularity\HDK\Pay\Infrastructure\Repository\ProductRepo;
|
||||
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
it('can query point rate', function () {
|
||||
$repo = make(ProductRepo::class);
|
||||
|
||||
$from = PointType::FtaiAligner;
|
||||
$to = PointType::LuxPoint;
|
||||
|
||||
$rate = $repo->getRate($from, $to);
|
||||
expect($rate)->toBeFloat();
|
||||
});
|
||||
46
tests/Feature/Product/QueryProductsTest.php
Normal file
46
tests/Feature/Product/QueryProductsTest.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* QueryProductsTest.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/8/18
|
||||
*/
|
||||
|
||||
use Pest\Expectation;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\Entities\ProductItem;
|
||||
use Singularity\HDK\Pay\Domain\Product\Aggregate\RechargeProduct;
|
||||
use Singularity\HDK\Pay\Infrastructure\Repository\ProductRepo;
|
||||
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
it('should can query LuxPoint products', function () {
|
||||
$repo = make(ProductRepo::class);
|
||||
|
||||
$products = $repo->findLuxPointProduct();
|
||||
expect($products)
|
||||
->toBeInstanceOf(RechargeProduct::class)
|
||||
->and($products->getOneTime())->toBeInstanceOf(ProductItem::class)
|
||||
->and($products->getPackages())->each->toBeInstanceOf(ProductItem::class);
|
||||
});
|
||||
|
||||
it('should can query EMA products', function () {
|
||||
$repo = make(ProductRepo::class);
|
||||
|
||||
$uid = 'cn3321';
|
||||
$products = $repo->findEmaProduct($uid);
|
||||
expect($products)
|
||||
->toBeInstanceOf(RechargeProduct::class)
|
||||
->when(
|
||||
$products->getOneTime() !== null,
|
||||
fn(Expectation $expectation) => $expectation
|
||||
->and($products->getOneTime())->toBeInstanceOf(ProductItem::class),
|
||||
)
|
||||
->when(
|
||||
$products->getRenew() !== null,
|
||||
fn(Expectation $expectation) => $expectation
|
||||
->and($products->getRenew())->toBeInstanceOf(ProductItem::class),
|
||||
)
|
||||
->and($products->getPlans())->each->toBeInstanceOf(ProductItem::class);
|
||||
})->only();
|
||||
53
tests/HttpTestCase.php
Normal file
53
tests/HttpTestCase.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Test\Pay;
|
||||
|
||||
use Hyperf\Testing\Client;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
/**
|
||||
* Class HttpTestCase.
|
||||
* @method get($uri, $data = [], $headers = [])
|
||||
* @method post($uri, $data = [], $headers = [])
|
||||
* @method json($uri, $data = [], $headers = [])
|
||||
* @method file($uri, $data = [], $headers = [])
|
||||
* @method request($method, $path, $options = [])
|
||||
*/
|
||||
abstract class HttpTestCase extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected Client $client;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct(?string $name = null)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->client = make(Client::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array<string, mixed> $arguments
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function __call(string $name, array $arguments): array
|
||||
{
|
||||
return $this->client->{$name}(...$arguments);
|
||||
}
|
||||
}
|
||||
32
tests/Pest.php
Normal file
32
tests/Pest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Singularity\HDK\Test\Pay\HttpTestCase;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Test Case
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The closure you provide to your tests functions is always bound to a specific PHPUnit tests
|
||||
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
|
||||
| need to change it using the "uses()" function to bind a different classes or traits.
|
||||
|
|
||||
*/
|
||||
|
||||
// uses(HttpTestCase::class)->in('Feature');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Functions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
|
||||
| project that you don't want to repeat in every file. Here you can also expose helpers as
|
||||
| global functions to help you to reduce the number of lines of code in your tests files.
|
||||
|
|
||||
*/
|
||||
|
||||
/*function something()
|
||||
{
|
||||
// ..
|
||||
}*/
|
||||
@@ -2,19 +2,16 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
use Hyperf\Config\Config;
|
||||
use Hyperf\Context\ApplicationContext;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Di\ClassLoader;
|
||||
use Hyperf\Di\Container;
|
||||
use Hyperf\Di\Definition\DefinitionSource;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Swoole\Runtime;
|
||||
|
||||
use function Hyperf\Support\env;
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
ini_set('display_startup_errors', 'on');
|
||||
@@ -22,16 +19,25 @@ ini_set('display_startup_errors', 'on');
|
||||
error_reporting(E_ALL);
|
||||
date_default_timezone_set('Asia/Shanghai');
|
||||
|
||||
|
||||
!defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
|
||||
!defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
|
||||
|
||||
Swoole\Runtime::enableCoroutine(true);
|
||||
Runtime::enableCoroutine(SWOOLE_HOOK_FLAGS);
|
||||
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
Hyperf\Di\ClassLoader::init();
|
||||
ClassLoader::init();
|
||||
|
||||
$container = new Container(new DefinitionSource([]));
|
||||
if (!$container instanceof ContainerInterface) {
|
||||
throw new RuntimeException('The dependency injection container is invalid.');
|
||||
}
|
||||
$container = ApplicationContext::setContainer($container);
|
||||
$container = ApplicationContext::setContainer($container);
|
||||
|
||||
/** @var Config $config */
|
||||
$config = make(Config::class, [
|
||||
[
|
||||
'dependencies' => [],
|
||||
'payment' => [
|
||||
'base_uri' => env('LUX_PAY_BASE_URI', 'http://test-pay.luxcreo.com'),
|
||||
],
|
||||
],
|
||||
]);
|
||||
ApplicationContext::getContainer()->set(ConfigInterface::class, $config);
|
||||
|
||||
Reference in New Issue
Block a user