mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
feat(payments): 增加兑换码与支付适配框架 (#299)
* feat(payments): 增加兑换码与支付适配框架 * fix(ci): 对齐 Rust 1.95 lint 与格式要求 * fix(payments): harden redeem code wallet credits --------- Co-authored-by: fawney19 <elky0401@gmail.com>
This commit is contained in:
@@ -32,7 +32,9 @@ use aether_data::repository::usage::InMemoryUsageReadRepository;
|
||||
use aether_data::repository::users::{
|
||||
InMemoryUserReadRepository, StoredUserAuthRecord, StoredUserExportRow,
|
||||
};
|
||||
use aether_data::repository::wallet::{InMemoryWalletRepository, StoredWalletSnapshot};
|
||||
use aether_data::repository::wallet::{
|
||||
InMemoryWalletRepository, StoredWalletSnapshot, WalletWriteRepository,
|
||||
};
|
||||
use aether_data_contracts::repository::global_models::StoredProviderActiveGlobalModel;
|
||||
use aether_data_contracts::repository::provider_catalog::ProviderCatalogReadRepository;
|
||||
use aether_data_contracts::repository::usage::{StoredRequestUsageAudit, UsageRepository};
|
||||
@@ -3234,6 +3236,88 @@ async fn gateway_rejects_invalid_nested_announcement_paths_as_local_not_found_wi
|
||||
upstream_handle.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_redeems_wallet_code_locally() {
|
||||
let now = Utc::now();
|
||||
let user = sample_auth_user(now);
|
||||
let access_token = build_test_auth_token(
|
||||
"access",
|
||||
serde_json::Map::from_iter([
|
||||
("user_id".to_string(), json!(user.id.clone())),
|
||||
("role".to_string(), json!(user.role.clone())),
|
||||
(
|
||||
"created_at".to_string(),
|
||||
json!(user.created_at.map(|value| value.to_rfc3339())),
|
||||
),
|
||||
("session_id".to_string(), json!("session-wallet-redeem-1")),
|
||||
]),
|
||||
now + chrono::Duration::hours(1),
|
||||
);
|
||||
|
||||
let wallet_repository = Arc::new(InMemoryWalletRepository::seed(vec![sample_auth_wallet(
|
||||
"user-auth-1",
|
||||
now,
|
||||
)]));
|
||||
let batch = wallet_repository
|
||||
.create_admin_redeem_code_batch(
|
||||
aether_data::repository::wallet::CreateAdminRedeemCodeBatchInput {
|
||||
name: "测试兑换".to_string(),
|
||||
amount_usd: 6.5,
|
||||
currency: "USD".to_string(),
|
||||
balance_bucket: "gift".to_string(),
|
||||
total_count: 1,
|
||||
expires_at_unix_secs: None,
|
||||
description: Some("public support".to_string()),
|
||||
created_by: Some("admin-user-1".to_string()),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.expect("batch should create");
|
||||
let redeem_code = batch.codes[0].code.clone();
|
||||
|
||||
let user_repository = Arc::new(InMemoryUserReadRepository::seed_auth_users(vec![user]));
|
||||
let state = AppState::new()
|
||||
.expect("gateway should build")
|
||||
.with_data_state_for_tests(
|
||||
crate::data::GatewayDataState::with_user_and_wallet_for_tests(
|
||||
user_repository,
|
||||
wallet_repository,
|
||||
),
|
||||
)
|
||||
.with_auth_sessions_for_tests([sample_auth_session(
|
||||
"user-auth-1",
|
||||
"session-wallet-redeem-1",
|
||||
"device-wallet-redeem-1",
|
||||
"refresh-token-wallet-redeem-1",
|
||||
now,
|
||||
)]);
|
||||
let gateway = build_router_with_state(state);
|
||||
let (gateway_url, gateway_handle) = start_server(gateway).await;
|
||||
|
||||
let response = reqwest::Client::new()
|
||||
.post(format!("{gateway_url}/api/wallet/redeem"))
|
||||
.header("authorization", format!("Bearer {access_token}"))
|
||||
.header("x-client-device-id", "device-wallet-redeem-1")
|
||||
.header("user-agent", "AetherTest/1.0")
|
||||
.json(&json!({ "code": redeem_code }))
|
||||
.send()
|
||||
.await
|
||||
.expect("request should succeed");
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let payload: serde_json::Value = response.json().await.expect("json body should parse");
|
||||
assert_eq!(payload["batch_name"], "测试兑换");
|
||||
assert_eq!(payload["amount_usd"], 6.5);
|
||||
assert_eq!(payload["order"]["payment_method"], "gift_code");
|
||||
assert_eq!(payload["order"]["refundable_amount_usd"], 0.0);
|
||||
assert_eq!(payload["wallet"]["total_recharged"], 26.5);
|
||||
assert_eq!(payload["wallet"]["recharge_balance"], 12.5);
|
||||
assert_eq!(payload["wallet"]["gift_balance"], 9.5);
|
||||
assert_eq!(payload["wallet"]["refundable_balance"], 12.5);
|
||||
|
||||
gateway_handle.abort();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gateway_creates_wallet_recharge_orders_locally_without_proxying_upstream() {
|
||||
let now = Utc::now();
|
||||
|
||||
Reference in New Issue
Block a user