mirror of
http://124.126.16.154:8888/singularity/hdk-pay.git
synced 2026-01-15 07:15:06 +08:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e92a6f46a4 | ||
|
|
e0748e444b | ||
|
|
244dd1220a | ||
|
|
8a9971bc59 | ||
|
|
4c5dde9020 | ||
|
|
1cb20a7c7e | ||
|
|
028721feb1 | ||
|
|
bd00102081 | ||
|
|
7763b088df | ||
|
|
cd56a6214b | ||
|
|
31559fdf5d | ||
|
|
41d768ba82 | ||
|
|
c552dd8ed0 | ||
|
|
e7e1c7f6c9 | ||
|
|
7e0d711e99 | ||
|
|
eb44b6e3b6 | ||
|
|
3af39e4254 | ||
|
|
8bbc8ed629 |
62
CHANGELOG.md
62
CHANGELOG.md
@@ -1,4 +1,66 @@
|
||||
# 版本更新日志
|
||||
### [1.11.1](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.11.0...v1.11.1) (2025-11-27)
|
||||
|
||||
## [1.11.0](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.10.0...v1.11.0) (2025-11-27)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **invoice:** 添加发票金额和货币支持 ([244dd12](http://124.126.16.154:8888/singularity/hdk-pay/commit/244dd1220a2c19197ef08f41a82bcb273d0900e8))
|
||||
|
||||
## [1.10.0](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.9.7...v1.10.0) (2025-11-25)
|
||||
|
||||
|
||||
### 🚀 Chore | 构建/工程依赖/工具
|
||||
|
||||
* **deps:** 移除 Carbon 依赖包 ([028721f](http://124.126.16.154:8888/singularity/hdk-pay/commit/028721feb1079eaa4fe80f20066912d46634f3df))
|
||||
|
||||
|
||||
### ✅ Tests | 测试
|
||||
|
||||
* **product:** 移除测试中的 only 标记 ([1cb20a7](http://124.126.16.154:8888/singularity/hdk-pay/commit/1cb20a7c7e2c1a26c7b72669e6885d39f8d16005))
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **invoice:** 引入点数价格值对象并更新发票产品结构 ([4c5dde9](http://124.126.16.154:8888/singularity/hdk-pay/commit/4c5dde9020364573d0e9673138620d967149e9f0))
|
||||
|
||||
### [1.9.7](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.9.6...v1.9.7) (2025-10-30)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **account:** 添加4D X无限奖励积分类型 ([7763b08](http://124.126.16.154:8888/singularity/hdk-pay/commit/7763b088dff711f2d95e65ec8437000322931f50))
|
||||
|
||||
### [1.9.6](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.9.5...v1.9.6) (2025-09-19)
|
||||
|
||||
|
||||
### ♻️ Code Refactoring | 代码重构
|
||||
|
||||
* **Domain:** 重构 ExchangeRepoInterface 接口 ([31559fd](http://124.126.16.154:8888/singularity/hdk-pay/commit/31559fdf5ddec048680f520563fa7de56eae3e90))
|
||||
|
||||
### [1.9.5](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.9.4...v1.9.5) (2025-09-19)
|
||||
|
||||
|
||||
### ♻️ Code Refactoring | 代码重构
|
||||
|
||||
* **domain:** 更新汇率接口并添加 UID 参数 ([e7e1c7f](http://124.126.16.154:8888/singularity/hdk-pay/commit/e7e1c7f6c946fa171cdbf8049f1d90864a043685))
|
||||
* **ProductRepo:** 优化 getRate 方法参数处理 ([c552dd8](http://124.126.16.154:8888/singularity/hdk-pay/commit/c552dd8ed0b00f58fefa47c02219ce4de972e85c))
|
||||
|
||||
### [1.9.4](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.9.3...v1.9.4) (2025-09-19)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* **product:** 修复产品列表中点数显示问题 ([eb44b6e](http://124.126.16.154:8888/singularity/hdk-pay/commit/eb44b6e3b6e9a2e3f757076d0d4438163e7d1f51))
|
||||
|
||||
### [1.9.3](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.9.2...v1.9.3) (2025-09-19)
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **PointType:** 添加 ScanToModel 作为点类型 ([8bbc8ed](http://124.126.16.154:8888/singularity/hdk-pay/commit/8bbc8ed629e5c15e42db0adf758505e531ff3dca))
|
||||
|
||||
### [1.9.2](http://124.126.16.154:8888/singularity/hdk-pay/compare/v1.9.1...v1.9.2) (2025-09-19)
|
||||
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
"firebase/php-jwt": "^6.8.0",
|
||||
"hyperf/testing": "^3.1",
|
||||
"friendsofhyperf/pest-plugin-hyperf": "3.1.*",
|
||||
"swoole/ide-helper": "^4.8.13",
|
||||
"nesbot/carbon": "^2.0"
|
||||
"swoole/ide-helper": "^4.8.13"
|
||||
},
|
||||
"minimum-stability": "beta",
|
||||
"prefer-stable": true,
|
||||
@@ -70,5 +69,5 @@
|
||||
"url": "https://mirrors.aliyun.com/composer/"
|
||||
}
|
||||
},
|
||||
"version": "1.9.2"
|
||||
"version": "1.11.1"
|
||||
}
|
||||
|
||||
987
composer.lock
generated
987
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -11,16 +11,21 @@ declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Application\Command;
|
||||
|
||||
final readonly class CreateInvoiceCmd {
|
||||
use Money\Money;
|
||||
|
||||
final readonly class CreateInvoiceCmd
|
||||
{
|
||||
public function __construct(
|
||||
public string $caseId,
|
||||
public bool $setFreqInvAddr,
|
||||
public string $receiver,
|
||||
public string $patientName,
|
||||
public string $address,
|
||||
public string $city,
|
||||
public string $state,
|
||||
public string $country,
|
||||
public string $zipCode,
|
||||
public string $caseId,
|
||||
public bool $setFreqInvAddr,
|
||||
public string $receiver,
|
||||
public string $patientName,
|
||||
public string $address,
|
||||
public string $city,
|
||||
public string $state,
|
||||
public string $country,
|
||||
public string $zipCode,
|
||||
public Money $price,
|
||||
public string $currencySymbol,
|
||||
) {}
|
||||
}
|
||||
@@ -54,17 +54,19 @@ final class RechargeProductsDto extends AbstractDto
|
||||
if (!$is_ftai) {
|
||||
$result += [
|
||||
'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,
|
||||
)),
|
||||
'bonus_rate_pct' => round(
|
||||
(float)(bcmul(
|
||||
num1: $effect->getPointTotal() == 0
|
||||
? '0'
|
||||
: bcdiv(
|
||||
(string)$effect->pointBonus,
|
||||
(string)$effect->getPointTotal(),
|
||||
3,
|
||||
),
|
||||
num2: '100',
|
||||
scale: 3,
|
||||
)),
|
||||
),
|
||||
'point' => [
|
||||
'total' => $effect->getPointTotal(),
|
||||
'number' => $effect->pointBasic,
|
||||
|
||||
@@ -16,15 +16,15 @@ enum PointType: string
|
||||
case EMA = 'ema';
|
||||
|
||||
case FtaiAligner = 'aligner';
|
||||
|
||||
case FtaiRetainer = 'retainer';
|
||||
|
||||
case Aligner4D = 'aligner-4d';
|
||||
|
||||
case NightguardAi = 'nightguard-ai';
|
||||
|
||||
case ScanToModel = 'scan-to-model';
|
||||
|
||||
case FourDXUnlimitedBonusCredits = 'aligner-4d-u';
|
||||
|
||||
public static function values(): array
|
||||
{
|
||||
return [
|
||||
@@ -34,6 +34,8 @@ enum PointType: string
|
||||
self::FtaiRetainer->value,
|
||||
self::Aligner4D->value,
|
||||
self::NightguardAi->value,
|
||||
self::ScanToModel->value,
|
||||
self::FourDXUnlimitedBonusCredits->value,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice;
|
||||
|
||||
use Money\Money;
|
||||
use Singularity\HDK\Pay\Domain\AggregateRoot;
|
||||
|
||||
final class Invoice extends AggregateRoot
|
||||
@@ -22,8 +23,25 @@ final class Invoice extends AggregateRoot
|
||||
private readonly Address $address,
|
||||
private readonly bool $setFreqInvAddr,
|
||||
private readonly string $receiver,
|
||||
private readonly Money $price,
|
||||
private readonly string $currencySymbol,
|
||||
) {}
|
||||
|
||||
public function getAmount(): float
|
||||
{
|
||||
return (float)bcdiv($this->price->getAmount(), '100', 2);
|
||||
}
|
||||
|
||||
public function getCurrencyCode(): string
|
||||
{
|
||||
return $this->price->getCurrency()->getCode();
|
||||
}
|
||||
|
||||
public function getCurrencySymbol(): string
|
||||
{
|
||||
return $this->currencySymbol;
|
||||
}
|
||||
|
||||
public function getInvoiceNo(): string
|
||||
{
|
||||
return $this->invoiceNo;
|
||||
|
||||
@@ -11,12 +11,23 @@ declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice;
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice\ValueObject\PointPrice;
|
||||
|
||||
final readonly class InvoiceProduct {
|
||||
/**
|
||||
* @param string $caseId
|
||||
* @param string $uid
|
||||
* @param string $name
|
||||
* @param string $sku
|
||||
* @param string $description
|
||||
* @param PointPrice[] $prices
|
||||
*/
|
||||
public function __construct(
|
||||
public string $caseId,
|
||||
public string $uid,
|
||||
public string $name,
|
||||
public string $sku,
|
||||
public string $description,
|
||||
public array $prices,
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PointPrice.php@Pay
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2025/11/25
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice\ValueObject;
|
||||
|
||||
use Money\Money;
|
||||
use Singularity\HDK\Pay\Domain\Account\Enum\PointType;
|
||||
|
||||
final readonly class PointPrice
|
||||
{
|
||||
public function __construct(
|
||||
public Money $price,
|
||||
public string $currencySymbol,
|
||||
) {}
|
||||
}
|
||||
@@ -16,7 +16,8 @@ interface ExchangeRepoInterface
|
||||
/**
|
||||
* @param PointType $source
|
||||
* @param PointType $target
|
||||
* @param string|null $uid
|
||||
* @return float
|
||||
*/
|
||||
public function getRate(PointType $source, PointType $target): float;
|
||||
public function getRate(PointType $source, PointType $target, ?string $uid = null): float;
|
||||
}
|
||||
@@ -12,7 +12,10 @@ declare(strict_types=1);
|
||||
namespace Singularity\HDK\Pay\Infrastructure\Repository;
|
||||
|
||||
use Hyperf\Codec\Json;
|
||||
use Money\Currency;
|
||||
use Money\Money;
|
||||
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice\InvoiceProduct;
|
||||
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice\ValueObject\PointPrice;
|
||||
use Singularity\HDK\Pay\Domain\Invoice\Repository\InvoiceProductRepoInterface;
|
||||
|
||||
final class InvoiceProductRepo extends AbstractRepo implements InvoiceProductRepoInterface
|
||||
@@ -33,6 +36,16 @@ final class InvoiceProductRepo extends AbstractRepo implements InvoiceProductRep
|
||||
name: $result['name'],
|
||||
sku: $result['sku'],
|
||||
description: $result['description'],
|
||||
prices: array_map(
|
||||
callback: fn(array $price) => new PointPrice(
|
||||
price: new Money(
|
||||
amount: bcmul((string)$price['amount'], '100', 2),
|
||||
currency: new Currency($price['currency']),
|
||||
),
|
||||
currencySymbol: $price['symbol'],
|
||||
),
|
||||
array: $result['prices'],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@ namespace Singularity\HDK\Pay\Infrastructure\Repository;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Hyperf\Codec\Json;
|
||||
use Money\Currency;
|
||||
use Money\Money;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Singularity\HDK\Core\Exceptions\ValidateException;
|
||||
use Singularity\HDK\Pay\Application\Command\CreateInvoiceCmd;
|
||||
@@ -30,6 +32,7 @@ final class InvoiceRepo extends AbstractRepo implements InvoiceRepoInterface
|
||||
*/
|
||||
public function create(CreateInvoiceCmd $cmd): Invoice
|
||||
{
|
||||
$money = $cmd->price;
|
||||
$response = $this->requestService->requestPost(
|
||||
url: "/rpc/v2/account/logs/points/$cmd->caseId/invoices",
|
||||
data: [
|
||||
@@ -41,12 +44,20 @@ final class InvoiceRepo extends AbstractRepo implements InvoiceRepoInterface
|
||||
'state' => $cmd->state,
|
||||
'country' => $cmd->country,
|
||||
'zip' => $cmd->zipCode,
|
||||
'price' => [
|
||||
'amount' => (float)bcmul($money->getAmount(), '100', 2),
|
||||
'currency' => [
|
||||
'code' => $money->getCurrency()->getCode(),
|
||||
'symbol' => $cmd->currencySymbol,
|
||||
],
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
$result = Json::decode($content);
|
||||
|
||||
$price = $result['price'];
|
||||
return new Invoice(
|
||||
invoiceNo: $result['invoice_no'],
|
||||
uid: $result['uid'],
|
||||
@@ -61,6 +72,11 @@ final class InvoiceRepo extends AbstractRepo implements InvoiceRepoInterface
|
||||
),
|
||||
setFreqInvAddr: $result['set_freq_addr'],
|
||||
receiver: $result['receiver'],
|
||||
price: new Money(
|
||||
bcmul((string)$price['amount'], '100', 2),
|
||||
new Currency($price['code']),
|
||||
),
|
||||
currencySymbol: $price['symbol'],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -206,10 +206,11 @@ final class ProductRepo extends AbstractRepo implements RechargeProductRepoInter
|
||||
* @return float
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function getRate(PointType $source, PointType $target): float
|
||||
public function getRate(PointType $source, PointType $target, ?string $uid = null): float
|
||||
{
|
||||
$response = $this->requestService->requestGet(
|
||||
url: "/rpc/v2/products/$target->value/exchange-rate/$source->value",
|
||||
params: array_filter(['uid' => $uid]),
|
||||
);
|
||||
|
||||
$content = $response->getBody()->getContents();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* Created on 2025/8/29
|
||||
*/
|
||||
|
||||
use Money\Money;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Singularity\HDK\Pay\Application\Command\CreateInvoiceCmd;
|
||||
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice\Invoice;
|
||||
@@ -29,6 +30,8 @@ it('should can create invoice', function () {
|
||||
state: "Illinois",
|
||||
country: "United States",
|
||||
zipCode: "67890-1234",
|
||||
price: Money::EUR('19900'),
|
||||
currencySymbol: '€'
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -10,16 +10,20 @@
|
||||
|
||||
|
||||
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice\InvoiceProduct;
|
||||
use Singularity\HDK\Pay\Domain\Invoice\Aggregate\Invoice\ValueObject\PointPrice;
|
||||
use Singularity\HDK\Pay\Infrastructure\Repository\InvoiceProductRepo;
|
||||
|
||||
use function Hyperf\Support\make;
|
||||
|
||||
it('should can query case invoice product', function () {
|
||||
/** @var InvoiceProductRepo $invoiceProductRepo */
|
||||
$invoiceProductRepo = make(InvoiceProductRepo::class);
|
||||
|
||||
$caseId = '68affb136c01d';
|
||||
|
||||
$result = $invoiceProductRepo->getCaseProduct(caseId: $caseId);
|
||||
|
||||
expect($result)->toBeInstanceOf(InvoiceProduct::class);
|
||||
expect($result)->toBeInstanceOf(InvoiceProduct::class)
|
||||
->prices->toBeArray()
|
||||
->each->toBeInstanceOf(PointPrice::class);
|
||||
});
|
||||
|
||||
@@ -19,6 +19,20 @@ it('can query point rate', function () {
|
||||
$from = PointType::FtaiAligner;
|
||||
$to = PointType::LuxPoint;
|
||||
|
||||
$rate = $repo->getRate($from, $to);
|
||||
$uid = 'cn3321';
|
||||
|
||||
$rate = $repo->getRate($from, $to, $uid);
|
||||
expect($rate)->toBeFloat();
|
||||
});
|
||||
|
||||
it('can query point rate with uid', function () {
|
||||
$repo = make(ProductRepo::class);
|
||||
|
||||
$from = PointType::FtaiAligner;
|
||||
$to = PointType::LuxPoint;
|
||||
|
||||
$uid = 'cn3321';
|
||||
|
||||
$rate = $repo->getRate($from, $to, $uid);
|
||||
expect($rate)->toBeFloat();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user