feat(db): add and refresh payment entities (currency_rates, customers, intents, methods, refunds, settlements, webhooks)
zhenyi committed
Added lib/db/payment/currency_rates.rs lib/db/payment/currency_rates.rs +26 −0 View lib/db/payment/currency_rates.rs
@@ -0,0 +1,26 @@
1use sea_orm::entity::prelude::*;
2use time::OffsetDateTime;
3
4use super::payment_orders::PaymentProvider;
5
6#[sea_orm::model]
7#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
8#[sea_orm(table_name = "currency_rate")]
9pub struct Model {
10 #[sea_orm(primary_key)]
11 pub id: Uuid,
12 #[sea_orm(unique_key = "base_quote_provider_date")]
13 pub base_currency: String,
14 #[sea_orm(unique_key = "base_quote_provider_date")]
15 pub quote_currency: String,
16 #[sea_orm(unique_key = "base_quote_provider_date")]
17 pub provider: PaymentProvider,
18 /// 快照日期(写入方归一化到 UTC 当日零点)
19 #[sea_orm(unique_key = "base_quote_provider_date")]
20 pub rate_date: OffsetDateTime,
21 /// 汇率:定点 i64,刻度 1e8(如 0.0723 → 7_230_000)
22 pub rate: i64,
23 pub created_at: OffsetDateTime,
24}
25
26impl ActiveModelBehavior for ActiveModel {}
Modified lib/db/payment/mod.rs lib/db/payment/mod.rs +7 −0 View lib/db/payment/mod.rs
@@ -1,4 +1,11 @@
1pub mod currency_rates;
2pub mod payment_customers;
3pub mod payment_intents;
4pub mod payment_methods;
15pub mod payment_orders;
6pub mod payment_refunds;
7pub mod payment_settlement_accounts;
28pub mod payment_transactions;
39pub mod payment_wallets;
10pub mod payment_webhook_events;
411pub mod subscriptions;
Added lib/db/payment/payment_customers.rs lib/db/payment/payment_customers.rs +24 −0 View lib/db/payment/payment_customers.rs
@@ -0,0 +1,24 @@
1use sea_orm::entity::prelude::*;
2use time::OffsetDateTime;
3
4use super::payment_orders::PaymentProvider;
5
6#[sea_orm::model]
7#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
8#[sea_orm(table_name = "payment_customer")]
9pub struct Model {
10 #[sea_orm(primary_key)]
11 pub id: Uuid,
12 #[sea_orm(unique)]
13 pub user_id: Uuid,
14 pub provider: PaymentProvider,
15 #[sea_orm(unique)]
16 pub provider_customer_id: String,
17 pub email: Option<String>,
18 pub created_at: OffsetDateTime,
19 pub updated_at: OffsetDateTime,
20 #[sea_orm(belongs_to, from = "user_id", to = "uid")]
21 pub user: BelongsTo<super::super::user::users::Entity>,
22}
23
24impl ActiveModelBehavior for ActiveModel {}
Added lib/db/payment/payment_intents.rs lib/db/payment/payment_intents.rs +60 −0 View lib/db/payment/payment_intents.rs
@@ -0,0 +1,60 @@
1use sea_orm::JsonValue;
2use sea_orm::entity::prelude::*;
3use serde::{Deserialize, Serialize};
4use time::OffsetDateTime;
5
6use super::payment_orders::PaymentProvider;
7
8#[derive(
9 Debug, Clone, Copy, PartialEq, Eq, Default, EnumIter, DeriveActiveEnum, Serialize, Deserialize,
10)]
11#[sea_orm(rs_type = "i16", db_type = "SmallInteger")]
12pub enum PaymentIntentStatus {
13 #[default]
14 Created = 0,
15 RequiresPaymentMethod = 1,
16 RequiresAction = 2,
17 Processing = 3,
18 Succeeded = 4,
19 RequiresCapture = 5,
20 Cancelled = 6,
21 Failed = 7,
22}
23
24#[sea_orm::model]
25#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
26#[sea_orm(table_name = "payment_intent")]
27pub struct Model {
28 #[sea_orm(primary_key)]
29 pub id: Uuid,
30 #[sea_orm(indexed)]
31 pub order_id: Uuid,
32 pub provider: PaymentProvider,
33 #[sea_orm(unique)]
34 pub provider_intent_id: Option<String>,
35 #[sea_orm(unique)]
36 pub request_id: String,
37 pub amount: i64,
38 #[sea_orm(default_value = "CNY")]
39 pub currency: String,
40 pub status: PaymentIntentStatus,
41 /// PSP 原始状态字符串(调试/对账用),以业务枚举 status 为准
42 pub provider_status: Option<String>,
43 #[sea_orm(indexed)]
44 pub payment_method_id: Option<Uuid>,
45 #[sea_orm(indexed)]
46 pub customer_id: Option<Uuid>,
47 pub captured_amount: Option<i64>,
48 pub metadata: Option<JsonValue>,
49 pub created_at: OffsetDateTime,
50 pub updated_at: OffsetDateTime,
51 pub expires_at: Option<OffsetDateTime>,
52 #[sea_orm(belongs_to, from = "order_id", to = "id")]
53 pub order: BelongsTo<super::payment_orders::Entity>,
54 #[sea_orm(belongs_to, from = "payment_method_id", to = "id")]
55 pub payment_method: BelongsTo<Option<super::payment_methods::Entity>>,
56 #[sea_orm(belongs_to, from = "customer_id", to = "id")]
57 pub customer: BelongsTo<Option<super::payment_customers::Entity>>,
58}
59
60impl ActiveModelBehavior for ActiveModel {}
Added lib/db/payment/payment_methods.rs lib/db/payment/payment_methods.rs +51 −0 View lib/db/payment/payment_methods.rs
@@ -0,0 +1,51 @@
1use sea_orm::entity::prelude::*;
2use serde::{Deserialize, Serialize};
3use time::OffsetDateTime;
4
5use super::payment_orders::PaymentProvider;
6
7#[derive(
8 Debug, Clone, Copy, PartialEq, Eq, Default, EnumIter, DeriveActiveEnum, Serialize, Deserialize,
9)]
10#[sea_orm(rs_type = "i16", db_type = "SmallInteger")]
11pub enum PaymentMethodType {
12 #[default]
13 Card = 0,
14 Alipay = 1,
15 WechatPay = 2,
16 UnionPay = 3,
17 BankTransfer = 4,
18}
19
20#[sea_orm::model]
21#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
22#[sea_orm(table_name = "payment_method")]
23pub struct Model {
24 #[sea_orm(primary_key)]
25 pub id: Uuid,
26 #[sea_orm(indexed)]
27 pub customer_id: Option<Uuid>,
28 #[sea_orm(indexed)]
29 pub user_id: Uuid,
30 pub provider: PaymentProvider,
31 #[sea_orm(unique)]
32 pub provider_method_id: String,
33 pub method_type: PaymentMethodType,
34 /// PCI 约束:仅存 token/brand/last4/fingerprint,禁止存完整卡号与 CVV
35 pub card_brand: Option<String>,
36 pub card_last4: Option<String>,
37 pub card_exp_month: Option<i32>,
38 pub card_exp_year: Option<i32>,
39 pub card_fingerprint: Option<String>,
40 #[sea_orm(default_value = "false")]
41 pub is_default: bool,
42 #[sea_orm(default_value = "true")]
43 pub is_active: bool,
44 pub created_at: OffsetDateTime,
45 #[sea_orm(belongs_to, from = "customer_id", to = "id")]
46 pub customer: BelongsTo<Option<super::payment_customers::Entity>>,
47 #[sea_orm(belongs_to, from = "user_id", to = "uid")]
48 pub user: BelongsTo<super::super::user::users::Entity>,
49}
50
51impl ActiveModelBehavior for ActiveModel {}
Modified lib/db/payment/payment_orders.rs lib/db/payment/payment_orders.rs +18 −0 View lib/db/payment/payment_orders.rs
@@ -1,3 +1,4 @@
1use sea_orm::JsonValue;
12use sea_orm::entity::prelude::*;
23use serde::{Deserialize, Serialize};
34use time::OffsetDateTime;
@@ -15,13 +16,25 @@
1516 Expired = 4,
1617}
1718
19#[derive(
20 Debug, Clone, Copy, PartialEq, Eq, Default, EnumIter, DeriveActiveEnum, Serialize, Deserialize,
21)]
22#[sea_orm(rs_type = "i16", db_type = "SmallInteger")]
23pub enum PaymentProvider {
24 #[default]
25 Airwallex = 0,
26 Manual = 1,
27}
28
1829#[sea_orm::model]
1930#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
2031#[sea_orm(table_name = "payment_order")]
2132pub struct Model {
2233 #[sea_orm(primary_key)]
2334 pub id: Uuid,
35 #[sea_orm(indexed)]
2436 pub user_id: Uuid,
37 #[sea_orm(indexed)]
2538 pub space_id: Option<Uuid>,
2639 pub product_id: Option<Uuid>,
2740 pub amount: i64,
@@ -31,6 +44,11 @@
3144 pub payment_method: Option<String>,
3245 #[sea_orm(unique)]
3346 pub external_txn_id: Option<String>,
47 pub title: Option<String>,
48 pub metadata: Option<JsonValue>,
49 #[sea_orm(default_value = "0")]
50 pub refunded_amount: i64,
51 pub provider: PaymentProvider,
3452 pub created_at: OffsetDateTime,
3553 pub paid_at: Option<OffsetDateTime>,
3654 pub expires_at: Option<OffsetDateTime>,
Added lib/db/payment/payment_refunds.rs lib/db/payment/payment_refunds.rs +49 −0 View lib/db/payment/payment_refunds.rs
@@ -0,0 +1,49 @@
1use sea_orm::entity::prelude::*;
2use serde::{Deserialize, Serialize};
3use time::OffsetDateTime;
4
5use super::payment_orders::PaymentProvider;
6
7#[derive(
8 Debug, Clone, Copy, PartialEq, Eq, Default, EnumIter, DeriveActiveEnum, Serialize, Deserialize,
9)]
10#[sea_orm(rs_type = "i16", db_type = "SmallInteger")]
11pub enum RefundStatus {
12 #[default]
13 Pending = 0,
14 InProgress = 1,
15 Succeeded = 2,
16 Failed = 3,
17 Cancelled = 4,
18}
19
20#[sea_orm::model]
21#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
22#[sea_orm(table_name = "payment_refund")]
23pub struct Model {
24 #[sea_orm(primary_key)]
25 pub id: Uuid,
26 #[sea_orm(indexed)]
27 pub payment_intent_id: Uuid,
28 #[sea_orm(indexed)]
29 pub order_id: Uuid,
30 pub provider: PaymentProvider,
31 pub amount: i64,
32 #[sea_orm(default_value = "CNY")]
33 pub currency: String,
34 pub reason: Option<String>,
35 pub status: RefundStatus,
36 #[sea_orm(unique)]
37 pub provider_refund_id: Option<String>,
38 #[sea_orm(unique)]
39 pub request_id: String,
40 pub created_at: OffsetDateTime,
41 pub updated_at: OffsetDateTime,
42 pub completed_at: Option<OffsetDateTime>,
43 #[sea_orm(belongs_to, from = "payment_intent_id", to = "id")]
44 pub payment_intent: BelongsTo<super::payment_intents::Entity>,
45 #[sea_orm(belongs_to, from = "order_id", to = "id")]
46 pub order: BelongsTo<super::payment_orders::Entity>,
47}
48
49impl ActiveModelBehavior for ActiveModel {}
Added lib/db/payment/payment_settlement_accounts.rs lib/db/payment/payment_settlement_accounts.rs +27 −0 View lib/db/payment/payment_settlement_accounts.rs
@@ -0,0 +1,27 @@
1use sea_orm::entity::prelude::*;
2use time::OffsetDateTime;
3
4use super::payment_orders::PaymentProvider;
5
6#[sea_orm::model]
7#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
8#[sea_orm(table_name = "payment_settlement_account")]
9pub struct Model {
10 #[sea_orm(primary_key)]
11 pub id: Uuid,
12 pub provider: PaymentProvider,
13 #[sea_orm(unique)]
14 pub provider_account_id: String,
15 #[sea_orm(default_value = "CNY")]
16 pub currency: String,
17 /// Airwallex 账户类型开放(virtual_account / funding_account 等),不枚举
18 pub account_type: String,
19 pub account_name: Option<String>,
20 pub account_number_masked: Option<String>,
21 pub bank_name: Option<String>,
22 pub status: String,
23 pub created_at: OffsetDateTime,
24 pub updated_at: OffsetDateTime,
25}
26
27impl ActiveModelBehavior for ActiveModel {}
Modified lib/db/payment/payment_transactions.rs lib/db/payment/payment_transactions.rs +1 −0 View lib/db/payment/payment_transactions.rs
@@ -40,6 +40,7 @@
4040 pub status: TransactionStatus,
4141 pub ref_type: Option<String>,
4242 pub ref_id: Option<String>,
43 pub currency: Option<String>,
4344 pub created_at: OffsetDateTime,
4445 pub completed_at: Option<OffsetDateTime>,
4546 #[sea_orm(belongs_to, from = "wallet_id", to = "user_id")]
Added lib/db/payment/payment_webhook_events.rs lib/db/payment/payment_webhook_events.rs +41 −0 View lib/db/payment/payment_webhook_events.rs
@@ -0,0 +1,41 @@
1use sea_orm::JsonValue;
2use sea_orm::entity::prelude::*;
3use serde::{Deserialize, Serialize};
4use time::OffsetDateTime;
5
6use super::payment_orders::PaymentProvider;
7
8#[derive(
9 Debug, Clone, Copy, PartialEq, Eq, Default, EnumIter, DeriveActiveEnum, Serialize, Deserialize,
10)]
11#[sea_orm(rs_type = "i16", db_type = "SmallInteger")]
12pub enum WebhookEventStatus {
13 #[default]
14 Received = 0,
15 Processing = 1,
16 Processed = 2,
17 Failed = 3,
18 Ignored = 4,
19}
20
21#[sea_orm::model]
22#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
23#[sea_orm(table_name = "payment_webhook_event")]
24pub struct Model {
25 #[sea_orm(primary_key)]
26 pub id: Uuid,
27 /// (provider, provider_event_id) 复合唯一 = 幂等处理锚点
28 #[sea_orm(unique_key = "provider_event")]
29 pub provider: PaymentProvider,
30 #[sea_orm(unique_key = "provider_event")]
31 pub provider_event_id: String,
32 /// 例如 payment_intent.succeeded / refund.updated
33 pub event_type: String,
34 pub payload: JsonValue,
35 pub status: WebhookEventStatus,
36 pub error: Option<String>,
37 pub processed_at: Option<OffsetDateTime>,
38 pub created_at: OffsetDateTime,
39}
40
41impl ActiveModelBehavior for ActiveModel {}
Modified lib/db/payment/subscriptions.rs lib/db/payment/subscriptions.rs +27 −0 View lib/db/payment/subscriptions.rs
@@ -15,6 +15,20 @@
1515 Expired = 4,
1616}
1717
18#[derive(
19 Debug, Clone, Copy, PartialEq, Eq, Default, EnumIter, DeriveActiveEnum, Serialize, Deserialize,
20)]
21#[sea_orm(rs_type = "i16", db_type = "SmallInteger")]
22pub enum BillingInterval {
23 #[default]
24 OneTime = 0,
25 Monthly = 1,
26 Quarterly = 2,
27 Yearly = 3,
28}
29
30use super::payment_orders::PaymentProvider;
31
1832#[sea_orm::model]
1933#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
2034#[sea_orm(table_name = "subscription")]
@@ -25,12 +39,25 @@
2539 pub space_id: Uuid,
2640 #[sea_orm(unique_key = "space_product")]
2741 pub product_id: Uuid,
42 /// 订阅扣费主体(付费人)
43 pub user_id: Uuid,
44 /// 每期扣费金额(最小单位)
45 pub amount: i64,
46 #[sea_orm(default_value = "CNY")]
47 pub currency: String,
48 pub billing_interval: BillingInterval,
2849 pub plan: Option<String>,
2950 pub status: SubscriptionStatus,
3051 pub current_period_start: Option<OffsetDateTime>,
3152 pub current_period_end: Option<OffsetDateTime>,
3253 pub cancel_at: Option<OffsetDateTime>,
54 pub canceled_at: Option<OffsetDateTime>,
55 pub provider: Option<PaymentProvider>,
56 #[sea_orm(unique)]
57 pub provider_subscription_id: Option<String>,
3358 pub created_at: OffsetDateTime,
59 #[sea_orm(belongs_to, from = "user_id", to = "uid")]
60 pub user: BelongsTo<super::super::user::users::Entity>,
3461 #[sea_orm(belongs_to, from = "space_id", to = "id")]
3562 pub space: BelongsTo<super::super::space::spaces::Entity>,
3663 #[sea_orm(belongs_to, from = "product_id", to = "id")]