支付通路

This commit is contained in:
tianmo committed 2026-09-30 15:08:16 +08:00
1 parent c7f43e30a9
commit 85b0e70907
26 files changed
+1324 -74

No files matched your search

@@ -0,0 +1,3 @@
-- 下单设备:由小程序上报 wx.getDeviceInfo().platform。
-- 用途是判断这笔单的支付渠道(iOS 走 Apple 支付,只能用户自己找 App Store 退)。
ALTER TABLE `orders` ADD COLUMN `terminal` VARCHAR(16) NULL;
@@ -0,0 +1,19 @@
-- 退款申请:iOS 用户向 Apple 申请退款后,平台发来的退款问询落库,供后台查看
CREATE TABLE `refund_requests` (
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`pay_order_id` VARCHAR(64) NOT NULL,
`order_id` INTEGER UNSIGNED NULL,
`reason` VARCHAR(255) NULL,
`provide_status` VARCHAR(4) NULL,
`our_result` TINYINT NOT NULL,
`our_evidence` VARCHAR(255) NULL,
`query_count` INTEGER UNSIGNED NOT NULL DEFAULT 1,
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`updated_at` DATETIME(3) NOT NULL,
UNIQUE INDEX `refund_requests_pay_order_id_key`(`pay_order_id`),
INDEX `refund_requests_created_at_idx`(`created_at`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `refund_requests` ADD CONSTRAINT `refund_requests_order_id_fkey` FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
@@ -0,0 +1,3 @@
-- 管理员「同意退款」标记。iOS 退款问询时,标了的订单直接放过。
-- 是事前授权:标记必须发生在苹果下一次问询之前。
ALTER TABLE `orders` ADD COLUMN `refund_consent_at` DATETIME(3) NULL;
@@ -0,0 +1,3 @@
-- 已向微信发起退款的时间。退款是异步的,微信退完才推 xpay_refund_notify 回写「已退款」,
-- 中间靠这一列显示「退款中」,避免管理员重复点退款。
ALTER TABLE `orders` ADD COLUMN `refund_requested_at` DATETIME(3) NULL;
+42 -1
View File
@@ -241,6 +241,15 @@ model Order {
status Int @db.TinyInt
/// 固定 0(正式环境)
env Int @default(0) @db.TinyInt
/// 下单设备,由小程序上报 wx.getDeviceInfo().platform:ios / android / windows / devtools...
/// 平台按设备路由支付渠道(iOS 走 Apple 支付),所以它决定这笔单能不能主动退款
terminal String? @db.VarChar(16)
/// 管理员已同意退款的时间。iOS 用户申请退款时苹果会发问询,看到这一列非空就直接放过。
/// 这是「事前授权」:必须在下一次问询到达前标记,标记之后用户再去 App Store 申请才有效。
refund_consent_at DateTime? @map("refund_consent_at")
/// 已向微信发起退款的时间。退款是异步的——微信退完才推 xpay_refund_notify 回写「已退款」,
/// 中间这段时间靠它显示「退款中」,避免重复点退款。
refund_requested_at DateTime? @map("refund_requested_at")
/// 微信平台单号,发货幂等依据
wx_order_id String? @unique @map("wx_order_id") @db.VarChar(64)
/// 下单时透传字段,发货通知原样带回
@@ -253,11 +262,44 @@ model Order {
user User @relation(fields: [user_id], references: [id])
course Course @relation(fields: [course_id], references: [id])
refund_requests RefundRequest[]
@@index([user_id, created_at])
@@index([status, created_at])
@@map("orders")
}
/// 退款申请。
///
/// Apple 支付不允许开发者主动退款,用户得去 App Store 申请;申请后 Apple 会向我们发
/// 退款问询(xpay_subscribe_ios_refund_query_notify),必须 3 秒内表态,所以决策是自动的。
/// 这张表把每次问询和我们的答复记下来,供后台查看。
/// 微信支付渠道(安卓等)没有用户申请入口,所以这里基本只有 iOS 会产生记录。
model RefundRequest {
id Int @id @default(autoincrement()) @db.UnsignedInt
/// 问询里的支付订单号。平台会重复问询,用它做幂等
pay_order_id String @unique @map("pay_order_id") @db.VarChar(64)
/// 匹配到的本地订单;查不到时为空
order_id Int? @map("order_id") @db.UnsignedInt
/// 用户申请退款的原因
reason String? @db.VarChar(255)
/// 推送里的发货状态:0 未发货 / 1 已发货 / 2 发货中
provide_status String? @map("provide_status") @db.VarChar(4)
/// 我们的答复:0 建议退款 / 1 拒绝退款
our_result Int @map("our_result") @db.TinyInt
/// 答复依据,写给人看
our_evidence String? @map("our_evidence") @db.VarChar(255)
/// 平台重复问询的次数
query_count Int @default(1) @map("query_count") @db.UnsignedInt
created_at DateTime @default(now()) @map("created_at")
updated_at DateTime @updatedAt @map("updated_at")
order Order? @relation(fields: [order_id], references: [id])
@@index([created_at])
@@map("refund_requests")
}
/// 发货推送原始记录,用于幂等、重放与排查
model PaymentNotifyLog {
id Int @id @default(autoincrement()) @db.UnsignedInt
@@ -306,4 +348,3 @@ model AdminUser {
@@map("admin_users")
}