@windrun-huaiin/backend-core 10.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/dist/app/api/stripe/checkout/route.d.ts +19 -0
  3. package/dist/app/api/stripe/checkout/route.d.ts.map +1 -0
  4. package/dist/app/api/stripe/checkout/route.js +120 -0
  5. package/dist/app/api/stripe/checkout/route.mjs +118 -0
  6. package/dist/app/api/stripe/customer-portal/route.d.ts +11 -0
  7. package/dist/app/api/stripe/customer-portal/route.d.ts.map +1 -0
  8. package/dist/app/api/stripe/customer-portal/route.js +73 -0
  9. package/dist/app/api/stripe/customer-portal/route.mjs +71 -0
  10. package/dist/app/api/user/anonymous/init/route.d.ts +7 -0
  11. package/dist/app/api/user/anonymous/init/route.d.ts.map +1 -0
  12. package/dist/app/api/user/anonymous/init/route.js +210 -0
  13. package/dist/app/api/user/anonymous/init/route.mjs +208 -0
  14. package/dist/app/api/webhook/clerk/user/route.d.ts +7 -0
  15. package/dist/app/api/webhook/clerk/user/route.d.ts.map +1 -0
  16. package/dist/app/api/webhook/clerk/user/route.js +202 -0
  17. package/dist/app/api/webhook/clerk/user/route.mjs +200 -0
  18. package/dist/app/api/webhook/stripe/route.d.ts +8 -0
  19. package/dist/app/api/webhook/stripe/route.d.ts.map +1 -0
  20. package/dist/app/api/webhook/stripe/route.js +70 -0
  21. package/dist/app/api/webhook/stripe/route.mjs +67 -0
  22. package/dist/index.d.ts +7 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +83 -0
  25. package/dist/index.mjs +18 -0
  26. package/dist/lib/auth-utils.d.ts +46 -0
  27. package/dist/lib/auth-utils.d.ts.map +1 -0
  28. package/dist/lib/auth-utils.js +107 -0
  29. package/dist/lib/auth-utils.mjs +102 -0
  30. package/dist/lib/credit-init.d.ts +8 -0
  31. package/dist/lib/credit-init.d.ts.map +1 -0
  32. package/dist/lib/credit-init.js +16 -0
  33. package/dist/lib/credit-init.mjs +10 -0
  34. package/dist/lib/index.d.ts +5 -0
  35. package/dist/lib/index.d.ts.map +1 -0
  36. package/dist/lib/index.js +31 -0
  37. package/dist/lib/index.mjs +4 -0
  38. package/dist/lib/money-price-config.d.ts +51 -0
  39. package/dist/lib/money-price-config.d.ts.map +1 -0
  40. package/dist/lib/money-price-config.js +156 -0
  41. package/dist/lib/money-price-config.mjs +151 -0
  42. package/dist/lib/stripe-config.d.ts +31 -0
  43. package/dist/lib/stripe-config.d.ts.map +1 -0
  44. package/dist/lib/stripe-config.js +278 -0
  45. package/dist/lib/stripe-config.mjs +268 -0
  46. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.js +48 -0
  47. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.mjs +45 -0
  48. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.js +54 -0
  49. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.mjs +51 -0
  50. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.js +44 -0
  51. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.mjs +35 -0
  52. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.js +31 -0
  53. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.mjs +18 -0
  54. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.js +587 -0
  55. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.mjs +527 -0
  56. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.js +447 -0
  57. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.mjs +399 -0
  58. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.js +245 -0
  59. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.mjs +232 -0
  60. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.js +68 -0
  61. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.mjs +62 -0
  62. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.js +39 -0
  63. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.mjs +37 -0
  64. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.js +80 -0
  65. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.mjs +75 -0
  66. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.js +101 -0
  67. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.mjs +86 -0
  68. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.js +102 -0
  69. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.mjs +76 -0
  70. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.js +56 -0
  71. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.mjs +52 -0
  72. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.js +1205 -0
  73. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.mjs +1157 -0
  74. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.js +407 -0
  75. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.mjs +374 -0
  76. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.js +9 -0
  77. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.mjs +7 -0
  78. package/dist/prisma/client.d.ts +2 -0
  79. package/dist/prisma/client.d.ts.map +1 -0
  80. package/dist/prisma/client.js +12 -0
  81. package/dist/prisma/client.mjs +1 -0
  82. package/dist/prisma/index.d.ts +4 -0
  83. package/dist/prisma/index.d.ts.map +1 -0
  84. package/dist/prisma/index.js +10 -0
  85. package/dist/prisma/index.mjs +2 -0
  86. package/dist/prisma/prisma-transaction-util.d.ts +3 -0
  87. package/dist/prisma/prisma-transaction-util.d.ts.map +1 -0
  88. package/dist/prisma/prisma-transaction-util.js +29 -0
  89. package/dist/prisma/prisma-transaction-util.mjs +27 -0
  90. package/dist/prisma/prisma.d.ts +4 -0
  91. package/dist/prisma/prisma.d.ts.map +1 -0
  92. package/dist/prisma/prisma.js +109 -0
  93. package/dist/prisma/prisma.mjs +106 -0
  94. package/dist/services/aggregate/billing.aggregate.service.d.ts +83 -0
  95. package/dist/services/aggregate/billing.aggregate.service.d.ts.map +1 -0
  96. package/dist/services/aggregate/billing.aggregate.service.js +308 -0
  97. package/dist/services/aggregate/billing.aggregate.service.mjs +306 -0
  98. package/dist/services/aggregate/index.d.ts +3 -0
  99. package/dist/services/aggregate/index.d.ts.map +1 -0
  100. package/dist/services/aggregate/index.js +9 -0
  101. package/dist/services/aggregate/index.mjs +2 -0
  102. package/dist/services/aggregate/user.aggregate.service.d.ts +34 -0
  103. package/dist/services/aggregate/user.aggregate.service.d.ts.map +1 -0
  104. package/dist/services/aggregate/user.aggregate.service.js +136 -0
  105. package/dist/services/aggregate/user.aggregate.service.mjs +133 -0
  106. package/dist/services/context/index.d.ts +2 -0
  107. package/dist/services/context/index.d.ts.map +1 -0
  108. package/dist/services/context/index.js +13 -0
  109. package/dist/services/context/index.mjs +1 -0
  110. package/dist/services/context/user-context-service.d.ts +30 -0
  111. package/dist/services/context/user-context-service.d.ts.map +1 -0
  112. package/dist/services/context/user-context-service.js +170 -0
  113. package/dist/services/context/user-context-service.mjs +162 -0
  114. package/dist/services/database/apilog.service.d.ts +39 -0
  115. package/dist/services/database/apilog.service.d.ts.map +1 -0
  116. package/dist/services/database/apilog.service.js +174 -0
  117. package/dist/services/database/apilog.service.mjs +170 -0
  118. package/dist/services/database/constants.d.ts +73 -0
  119. package/dist/services/database/constants.d.ts.map +1 -0
  120. package/dist/services/database/constants.js +135 -0
  121. package/dist/services/database/constants.mjs +117 -0
  122. package/dist/services/database/credit.service.d.ts +107 -0
  123. package/dist/services/database/credit.service.d.ts.map +1 -0
  124. package/dist/services/database/credit.service.js +515 -0
  125. package/dist/services/database/credit.service.mjs +512 -0
  126. package/dist/services/database/creditAuditLog.service.d.ts +73 -0
  127. package/dist/services/database/creditAuditLog.service.d.ts.map +1 -0
  128. package/dist/services/database/creditAuditLog.service.js +305 -0
  129. package/dist/services/database/creditAuditLog.service.mjs +302 -0
  130. package/dist/services/database/index.d.ts +10 -0
  131. package/dist/services/database/index.d.ts.map +1 -0
  132. package/dist/services/database/index.js +38 -0
  133. package/dist/services/database/index.mjs +8 -0
  134. package/dist/services/database/prisma-model-type.d.ts +3 -0
  135. package/dist/services/database/prisma-model-type.d.ts.map +1 -0
  136. package/dist/services/database/subscription.service.d.ts +48 -0
  137. package/dist/services/database/subscription.service.d.ts.map +1 -0
  138. package/dist/services/database/subscription.service.js +267 -0
  139. package/dist/services/database/subscription.service.mjs +264 -0
  140. package/dist/services/database/transaction.service.d.ts +92 -0
  141. package/dist/services/database/transaction.service.d.ts.map +1 -0
  142. package/dist/services/database/transaction.service.js +326 -0
  143. package/dist/services/database/transaction.service.mjs +323 -0
  144. package/dist/services/database/user.service.d.ts +45 -0
  145. package/dist/services/database/user.service.d.ts.map +1 -0
  146. package/dist/services/database/user.service.js +180 -0
  147. package/dist/services/database/user.service.mjs +177 -0
  148. package/dist/services/database/userBackup.service.d.ts +45 -0
  149. package/dist/services/database/userBackup.service.d.ts.map +1 -0
  150. package/dist/services/database/userBackup.service.js +249 -0
  151. package/dist/services/database/userBackup.service.mjs +246 -0
  152. package/dist/services/stripe/index.d.ts +2 -0
  153. package/dist/services/stripe/index.d.ts.map +1 -0
  154. package/dist/services/stripe/index.js +7 -0
  155. package/dist/services/stripe/index.mjs +1 -0
  156. package/dist/services/stripe/webhook-handler.d.ts +6 -0
  157. package/dist/services/stripe/webhook-handler.d.ts.map +1 -0
  158. package/dist/services/stripe/webhook-handler.js +537 -0
  159. package/dist/services/stripe/webhook-handler.mjs +535 -0
  160. package/migrations/create.sql +176 -0
  161. package/migrations/db.init.sql +13 -0
  162. package/migrations/init-schema.sql +19 -0
  163. package/migrations/purge.sql +27 -0
  164. package/migrations/test-check.sql +167 -0
  165. package/package.json +123 -0
  166. package/prisma/schema.prisma +191 -0
  167. package/src/app/api/stripe/checkout/route.ts +145 -0
  168. package/src/app/api/stripe/customer-portal/route.ts +83 -0
  169. package/src/app/api/user/anonymous/init/route.ts +284 -0
  170. package/src/app/api/webhook/clerk/user/route.ts +249 -0
  171. package/src/app/api/webhook/stripe/route.ts +93 -0
  172. package/src/index.ts +6 -0
  173. package/src/lib/auth-utils.ts +101 -0
  174. package/src/lib/credit-init.ts +9 -0
  175. package/src/lib/index.ts +4 -0
  176. package/src/lib/money-price-config.ts +168 -0
  177. package/src/lib/stripe-config.ts +333 -0
  178. package/src/prisma/client.ts +2 -0
  179. package/src/prisma/index.ts +3 -0
  180. package/src/prisma/prisma-transaction-util.ts +24 -0
  181. package/src/prisma/prisma.ts +122 -0
  182. package/src/services/aggregate/billing.aggregate.service.ts +498 -0
  183. package/src/services/aggregate/index.ts +2 -0
  184. package/src/services/aggregate/user.aggregate.service.ts +168 -0
  185. package/src/services/context/index.ts +1 -0
  186. package/src/services/context/user-context-service.ts +200 -0
  187. package/src/services/database/apilog.service.ts +185 -0
  188. package/src/services/database/constants.ts +148 -0
  189. package/src/services/database/credit.service.ts +747 -0
  190. package/src/services/database/creditAuditLog.service.ts +402 -0
  191. package/src/services/database/index.ts +41 -0
  192. package/src/services/database/prisma-model-type.ts +13 -0
  193. package/src/services/database/subscription.service.ts +319 -0
  194. package/src/services/database/transaction.service.ts +447 -0
  195. package/src/services/database/user.service.ts +218 -0
  196. package/src/services/database/userBackup.service.ts +290 -0
  197. package/src/services/stripe/index.ts +1 -0
  198. package/src/services/stripe/webhook-handler.ts +648 -0
@@ -0,0 +1,106 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+
3
+ var _a;
4
+ const globalForPrisma = globalThis;
5
+ // ==================== 日志配置 ====================
6
+ const getLogConfig = () => {
7
+ const env = process.env.NODE_ENV || 'development';
8
+ switch (env) {
9
+ case 'development':
10
+ return [
11
+ { emit: 'event', level: 'query' },
12
+ { emit: 'stdout', level: 'info' },
13
+ { emit: 'stdout', level: 'warn' },
14
+ { emit: 'stdout', level: 'error' },
15
+ ];
16
+ case 'test':
17
+ return [
18
+ { emit: 'stdout', level: 'warn' },
19
+ { emit: 'stdout', level: 'error' },
20
+ ];
21
+ default:
22
+ return [{ emit: 'stdout', level: 'error' }];
23
+ }
24
+ };
25
+ const logConfig = getLogConfig();
26
+ // ==================== 创建 Prisma 全局单例 ====================
27
+ const prisma = (_a = globalForPrisma.prisma) !== null && _a !== void 0 ? _a : new PrismaClient({
28
+ log: logConfig,
29
+ });
30
+ if (process.env.NODE_ENV !== 'production') {
31
+ globalForPrisma.prisma = prisma;
32
+ }
33
+ if (process.env.NODE_ENV === 'development') {
34
+ const REGISTERED_KEY = '__prisma_query_logger_registered';
35
+ const ID_KEY = '__prisma_query_logger_id';
36
+ if (globalForPrisma[REGISTERED_KEY]) {
37
+ console.log(`Prisma Query Logger Already Registered | ID: ${globalForPrisma[ID_KEY]}`);
38
+ }
39
+ else {
40
+ const listenerId = `listener_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
41
+ globalForPrisma[ID_KEY] = listenerId;
42
+ // --- 自定义SQL拼接 ---
43
+ const interpolate = (query, params) => {
44
+ // 1. 【核心修改】:安全检查和参数解析
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ let parameters = [];
47
+ try {
48
+ // 尝试解析 params 字符串
49
+ // 如果 params 是空字符串 "",或者不是有效的 JSON,这里会捕获错误
50
+ parameters = params && params.length > 0 ? JSON.parse(params) : [];
51
+ // eslint-disable-next-line unused-imports/no-unused-vars
52
+ }
53
+ catch (e) {
54
+ // 如果无法解析,则直接返回原始查询,跳过替换
55
+ return query;
56
+ }
57
+ // 确保 parameters 是一个数组
58
+ if (!Array.isArray(parameters)) {
59
+ console.warn('Prisma params解析结果不是数组,跳过参数替换。Result:', parameters);
60
+ return query;
61
+ }
62
+ // 如果没有参数,直接返回查询
63
+ if (parameters.length === 0) {
64
+ return query;
65
+ }
66
+ // 2. 将参数列表的值进行安全的字符串化处理
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ const safeValues = parameters.map((p) => {
69
+ if (p === null)
70
+ return 'NULL';
71
+ // 对字符串类型的值加上单引号并转义(这是SQL安全的关键)
72
+ if (typeof p === 'string')
73
+ return `'${p.replace(/'/g, "''")}'`;
74
+ return p; // 数字、布尔值等直接返回
75
+ });
76
+ // 3. 循环替换 $1, $2, ...
77
+ let sql = query;
78
+ for (let i = 0; i < safeValues.length; i++) {
79
+ const placeholder = new RegExp('\\$' + (i + 1) + '(?!\\d)', 'g');
80
+ sql = sql.replace(placeholder, safeValues[i]);
81
+ }
82
+ return sql;
83
+ };
84
+ const wrappedHandler = (event) => {
85
+ const ms = event.duration;
86
+ const slow = ms >= 200 ? '🐌 SLOW SQL ' : '🚀 SQL';
87
+ const interpolatedSql = interpolate(event.query, event.params);
88
+ const clean = interpolatedSql
89
+ .replace(/"[^"]+"\./g, '') // 去 "表".
90
+ .replace(/= '([^']+)'/g, `= '$1'`) // 已经替换成单引号,此处可以优化
91
+ .replace(/"/g, ''); // 彻底灭双引号
92
+ console.log('─'.repeat(60));
93
+ console.log(`${clean};`);
94
+ console.log(`⏰ 耗时: ${ms}ms, ${slow}`);
95
+ };
96
+ // 注册包装后的 handler
97
+ prisma.$on('query', wrappedHandler);
98
+ globalForPrisma[REGISTERED_KEY] = true;
99
+ }
100
+ }
101
+ // ==================== 便捷方法, 入参事务客户端不存在或者不传, 就返回全局非事务客户端 ====================
102
+ function checkAndFallbackWithNonTCClient(tx) {
103
+ return tx !== null && tx !== void 0 ? tx : prisma;
104
+ }
105
+
106
+ export { checkAndFallbackWithNonTCClient, prisma };
@@ -0,0 +1,83 @@
1
+ import { PaymentStatus } from '../database/index';
2
+ import type { Subscription, Transaction } from '../database/prisma-model-type';
3
+ type NullableString = string | null | undefined;
4
+ type BasicOrderContext = {
5
+ userId: string;
6
+ subIdKey: bigint;
7
+ orderId: string;
8
+ paySubscriptionId: string;
9
+ creditsGranted: number;
10
+ priceId?: NullableString;
11
+ priceName?: NullableString;
12
+ periodStart: Date | null;
13
+ periodEnd: Date | null;
14
+ invoiceId: string;
15
+ hostedInvoiceUrl?: NullableString;
16
+ invoicePdf?: NullableString;
17
+ billingReason?: NullableString;
18
+ paymentIntentId?: string;
19
+ paidAt: Date | null;
20
+ paidEmail: string | null;
21
+ };
22
+ type RenewalOrderContext = BasicOrderContext & {
23
+ amountPaidCents: number;
24
+ currency: string;
25
+ };
26
+ type SubscriptionCancelContext = {
27
+ userId: string;
28
+ subIdKey: bigint;
29
+ orderId: string;
30
+ canceledAt: Date;
31
+ cancellationDetail?: string;
32
+ };
33
+ type SubscriptionRefundContext = {
34
+ transaction: Transaction;
35
+ subscription?: Subscription | null;
36
+ };
37
+ type OneTimeRefundContext = {
38
+ transaction: Transaction;
39
+ };
40
+ declare class BillingAggregateService {
41
+ recordSubscriptionInitPayment(context: BasicOrderContext): Promise<void>;
42
+ completeOneTimeCheckout(params: {
43
+ userId: string;
44
+ orderId: string;
45
+ creditsGranted: number;
46
+ paymentStatus: PaymentStatus;
47
+ payTransactionId: string;
48
+ paidAt: Date;
49
+ paidEmail?: NullableString;
50
+ oneTimePaidStart: Date;
51
+ oneTimePaidEnd: Date;
52
+ }): Promise<void>;
53
+ recordInitialInvoiceDetails(params: {
54
+ orderId: string;
55
+ invoiceId: string;
56
+ paymentIntentId: string;
57
+ hostedInvoiceUrl?: NullableString;
58
+ invoicePdf?: NullableString;
59
+ billingReason?: NullableString;
60
+ }): Promise<void>;
61
+ recordSubscriptionRenewalPayment(context: RenewalOrderContext): Promise<void>;
62
+ recordInitialPaymentFailure(params: {
63
+ orderId: string;
64
+ invoiceId: string;
65
+ paymentIntentId: string;
66
+ detail?: string;
67
+ }): Promise<void>;
68
+ recordRenewalPaymentFailure(context: RenewalOrderContext): Promise<void>;
69
+ syncSubscriptionFromStripe(params: {
70
+ subscription: Subscription;
71
+ status: string;
72
+ periodStart: Date;
73
+ periodEnd: Date;
74
+ orderId: string;
75
+ isUserCancel: boolean;
76
+ }): Promise<void>;
77
+ processSubscriptionCancel(context: SubscriptionCancelContext): Promise<void>;
78
+ processSubscriptionRefund(context: SubscriptionRefundContext): Promise<void>;
79
+ processOneTimeRefund(context: OneTimeRefundContext): Promise<void>;
80
+ }
81
+ export declare const billingAggregateService: BillingAggregateService;
82
+ export {};
83
+ //# sourceMappingURL=billing.aggregate.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.aggregate.service.d.ts","sourceRoot":"","sources":["../../../src/services/aggregate/billing.aggregate.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,308 @@
1
+ 'use strict';
2
+
3
+ var tslib_es6 = require('../../node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.js');
4
+ var constants = require('../database/constants.js');
5
+ require('../../prisma/prisma.js');
6
+ var prismaTransactionUtil = require('../../prisma/prisma-transaction-util.js');
7
+ var subscription_service = require('../database/subscription.service.js');
8
+ var credit_service = require('../database/credit.service.js');
9
+ var transaction_service = require('../database/transaction.service.js');
10
+ require('@prisma/client');
11
+
12
+ class BillingAggregateService {
13
+ recordSubscriptionInitPayment(context) {
14
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
15
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
16
+ var _a, _b, _c, _d, _e, _f, _g, _h;
17
+ const now = new Date();
18
+ // 订阅截止时间统一为到期日最后1s
19
+ const originSubPeriodEnd = context.periodEnd;
20
+ const specialEnd = originSubPeriodEnd ? new Date(originSubPeriodEnd.setHours(23, 59, 59, 999)) : originSubPeriodEnd;
21
+ const updatedSubscription = yield subscription_service.subscriptionService.updateSubscription(context.subIdKey, {
22
+ status: constants.SubscriptionStatus.ACTIVE,
23
+ orderId: (_a = context.orderId) !== null && _a !== void 0 ? _a : undefined,
24
+ paySubscriptionId: context.paySubscriptionId,
25
+ priceId: (_b = context.priceId) !== null && _b !== void 0 ? _b : undefined,
26
+ priceName: (_c = context.priceName) !== null && _c !== void 0 ? _c : undefined,
27
+ creditsAllocated: context.creditsGranted || 0,
28
+ subPeriodStart: context.periodStart,
29
+ subPeriodEnd: specialEnd,
30
+ updatedAt: now,
31
+ }, tx);
32
+ yield transaction_service.transactionService.update(context.orderId, {
33
+ orderStatus: constants.OrderStatus.SUCCESS,
34
+ paymentStatus: constants.PaymentStatus.PAID,
35
+ paySubscriptionId: context.paySubscriptionId,
36
+ subPeriodStart: context.periodStart,
37
+ subPeriodEnd: context.periodEnd,
38
+ payInvoiceId: context.invoiceId,
39
+ hostedInvoiceUrl: (_d = context.hostedInvoiceUrl) !== null && _d !== void 0 ? _d : undefined,
40
+ invoicePdf: (_e = context.invoicePdf) !== null && _e !== void 0 ? _e : undefined,
41
+ billingReason: (_f = context.billingReason) !== null && _f !== void 0 ? _f : undefined,
42
+ payTransactionId: (_g = context.paymentIntentId) !== null && _g !== void 0 ? _g : undefined,
43
+ paidEmail: (_h = context.paidEmail) !== null && _h !== void 0 ? _h : undefined,
44
+ paidAt: context.paidAt,
45
+ payUpdatedAt: now,
46
+ }, tx);
47
+ if (context.creditsGranted > 0) {
48
+ yield credit_service.creditService.rechargeCredit(context.userId, { paid: context.creditsGranted }, {
49
+ feature: constants.TransactionType.SUBSCRIPTION,
50
+ operationReferId: context.orderId,
51
+ }, tx);
52
+ }
53
+ yield tx.credit.update({
54
+ where: { userId: context.userId },
55
+ data: {
56
+ paidStart: context.periodStart,
57
+ paidEnd: context.periodEnd,
58
+ },
59
+ });
60
+ return updatedSubscription;
61
+ }));
62
+ });
63
+ }
64
+ completeOneTimeCheckout(params) {
65
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
66
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
67
+ var _a;
68
+ const now = new Date();
69
+ yield transaction_service.transactionService.update(params.orderId, {
70
+ orderStatus: constants.OrderStatus.SUCCESS,
71
+ paymentStatus: params.paymentStatus,
72
+ payTransactionId: params.payTransactionId,
73
+ paidAt: now,
74
+ paidEmail: (_a = params.paidEmail) !== null && _a !== void 0 ? _a : undefined,
75
+ payUpdatedAt: now,
76
+ }, tx);
77
+ if (params.creditsGranted > 0) {
78
+ yield credit_service.creditService.rechargeCredit(params.userId, { oneTimePaid: params.creditsGranted }, {
79
+ feature: constants.TransactionType.ONE_TIME,
80
+ operationReferId: params.orderId,
81
+ }, tx);
82
+ }
83
+ yield tx.credit.update({
84
+ where: { userId: params.userId },
85
+ data: {
86
+ oneTimePaidStart: params.oneTimePaidStart,
87
+ oneTimePaidEnd: params.oneTimePaidEnd,
88
+ },
89
+ });
90
+ }));
91
+ });
92
+ }
93
+ recordInitialInvoiceDetails(params) {
94
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
95
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
96
+ var _a, _b, _c;
97
+ yield transaction_service.transactionService.update(params.orderId, {
98
+ payInvoiceId: params.invoiceId,
99
+ payTransactionId: params.paymentIntentId,
100
+ hostedInvoiceUrl: (_a = params.hostedInvoiceUrl) !== null && _a !== void 0 ? _a : undefined,
101
+ invoicePdf: (_b = params.invoicePdf) !== null && _b !== void 0 ? _b : undefined,
102
+ billingReason: (_c = params.billingReason) !== null && _c !== void 0 ? _c : undefined,
103
+ payUpdatedAt: new Date(),
104
+ }, tx);
105
+ }));
106
+ });
107
+ }
108
+ recordSubscriptionRenewalPayment(context) {
109
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
110
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
111
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
112
+ yield transaction_service.transactionService.createTransaction({
113
+ userId: context.userId,
114
+ orderId: context.orderId,
115
+ orderStatus: constants.OrderStatus.SUCCESS,
116
+ paymentStatus: constants.PaymentStatus.PAID,
117
+ paySupplier: constants.PaySupplier.STRIPE,
118
+ paySubscriptionId: (_a = context.paySubscriptionId) !== null && _a !== void 0 ? _a : undefined,
119
+ subPeriodStart: (_b = context.periodStart) !== null && _b !== void 0 ? _b : undefined,
120
+ subPeriodEnd: (_c = context.periodEnd) !== null && _c !== void 0 ? _c : undefined,
121
+ payInvoiceId: context.invoiceId,
122
+ hostedInvoiceUrl: (_d = context.hostedInvoiceUrl) !== null && _d !== void 0 ? _d : undefined,
123
+ invoicePdf: (_e = context.invoicePdf) !== null && _e !== void 0 ? _e : undefined,
124
+ billingReason: (_f = context.billingReason) !== null && _f !== void 0 ? _f : undefined,
125
+ payTransactionId: (_g = context.paymentIntentId) !== null && _g !== void 0 ? _g : undefined,
126
+ priceId: (_h = context.priceId) !== null && _h !== void 0 ? _h : undefined,
127
+ priceName: (_j = context.priceName) !== null && _j !== void 0 ? _j : undefined,
128
+ type: constants.TransactionType.SUBSCRIPTION,
129
+ amount: context.amountPaidCents / 100,
130
+ currency: context.currency.toUpperCase(),
131
+ creditsGranted: context.creditsGranted,
132
+ paidAt: (_k = context.paidAt) !== null && _k !== void 0 ? _k : undefined,
133
+ paidEmail: context.paidEmail,
134
+ payUpdatedAt: new Date(),
135
+ }, tx);
136
+ // 订阅截止时间统一为到期日最后1s
137
+ const originSubPeriodEnd = context.periodEnd;
138
+ const specialEnd = originSubPeriodEnd ? new Date(originSubPeriodEnd.setHours(23, 59, 59, 999)) : originSubPeriodEnd;
139
+ yield subscription_service.subscriptionService.updateSubscription(context.subIdKey, {
140
+ status: constants.SubscriptionStatus.ACTIVE,
141
+ orderId: context.orderId,
142
+ subPeriodStart: context.periodStart,
143
+ subPeriodEnd: specialEnd,
144
+ updatedAt: new Date(),
145
+ }, tx);
146
+ if (context.creditsGranted > 0) {
147
+ yield credit_service.creditService.rechargeCredit(context.userId, { paid: context.creditsGranted }, {
148
+ feature: `${constants.TransactionType.SUBSCRIPTION}_renewal`,
149
+ operationReferId: context.orderId,
150
+ }, tx);
151
+ }
152
+ yield tx.credit.update({
153
+ where: { userId: context.userId },
154
+ data: {
155
+ paidStart: context.periodStart,
156
+ paidEnd: context.periodEnd,
157
+ },
158
+ });
159
+ }));
160
+ });
161
+ }
162
+ recordInitialPaymentFailure(params) {
163
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
164
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
165
+ var _a, _b;
166
+ yield transaction_service.transactionService.updateStatus(params.orderId, constants.OrderStatus.FAILED, {
167
+ paymentStatus: constants.PaymentStatus.UN_PAID,
168
+ payInvoiceId: params.invoiceId,
169
+ payTransactionId: params.paymentIntentId,
170
+ payUpdatedAt: new Date(),
171
+ paidDetail: (_a = params.detail) !== null && _a !== void 0 ? _a : undefined,
172
+ orderDetail: (_b = params.detail) !== null && _b !== void 0 ? _b : undefined,
173
+ }, tx);
174
+ }));
175
+ });
176
+ }
177
+ recordRenewalPaymentFailure(context) {
178
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
179
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
180
+ var _a, _b, _c, _d, _e, _f;
181
+ yield transaction_service.transactionService.createTransaction({
182
+ userId: context.userId,
183
+ orderId: context.orderId,
184
+ orderStatus: constants.OrderStatus.FAILED,
185
+ paymentStatus: constants.PaymentStatus.UN_PAID,
186
+ paySupplier: constants.PaySupplier.STRIPE,
187
+ paySubscriptionId: (_a = context.paySubscriptionId) !== null && _a !== void 0 ? _a : undefined,
188
+ payInvoiceId: context.invoiceId,
189
+ billingReason: (_b = context.billingReason) !== null && _b !== void 0 ? _b : undefined,
190
+ payTransactionId: (_c = context.paymentIntentId) !== null && _c !== void 0 ? _c : undefined,
191
+ priceId: (_d = context.priceId) !== null && _d !== void 0 ? _d : undefined,
192
+ priceName: (_e = context.priceName) !== null && _e !== void 0 ? _e : undefined,
193
+ type: constants.TransactionType.SUBSCRIPTION,
194
+ amount: context.amountPaidCents / 100,
195
+ currency: context.currency.toUpperCase(),
196
+ creditsGranted: 0,
197
+ paidAt: (_f = context.paidAt) !== null && _f !== void 0 ? _f : undefined,
198
+ paidEmail: context.paidEmail,
199
+ payUpdatedAt: new Date(),
200
+ orderDetail: 'Subscription renewal payment failed',
201
+ }, tx);
202
+ yield credit_service.creditService.payFailedWatcher({
203
+ userId: context.userId,
204
+ feature: `${constants.TransactionType.SUBSCRIPTION}_renewal_failed`,
205
+ operationReferId: context.orderId,
206
+ creditType: constants.CreditType.PAID,
207
+ operationType: constants.OperationType.RECHARGE,
208
+ creditsChange: 0,
209
+ }, tx);
210
+ yield subscription_service.subscriptionService.updateSubscription(context.subIdKey, {
211
+ status: constants.SubscriptionStatus.PAST_DUE,
212
+ orderId: context.orderId,
213
+ updatedAt: new Date(),
214
+ }, tx);
215
+ }));
216
+ });
217
+ }
218
+ syncSubscriptionFromStripe(params) {
219
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
220
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
221
+ if (params.isUserCancel) {
222
+ // 记录用户取消订阅的时间信息
223
+ yield transaction_service.transactionService.update(params.orderId, {
224
+ subLastTryCancelAt: new Date(),
225
+ }, tx);
226
+ }
227
+ yield subscription_service.subscriptionService.updateSubscription(params.subscription.id, {
228
+ status: params.status,
229
+ subPeriodStart: params.periodStart,
230
+ subPeriodEnd: params.periodEnd,
231
+ updatedAt: new Date(),
232
+ }, tx);
233
+ }));
234
+ });
235
+ }
236
+ processSubscriptionCancel(context) {
237
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
238
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
239
+ var _a;
240
+ // 更新订单, 记录取消信息
241
+ yield transaction_service.transactionService.update(context.orderId, {
242
+ subPeriodCanceledAt: context.canceledAt,
243
+ subCancellationDetail: (_a = context.cancellationDetail) !== null && _a !== void 0 ? _a : undefined
244
+ }, tx);
245
+ // 更新订阅信息
246
+ yield subscription_service.subscriptionService.updateStatus(context.subIdKey, constants.SubscriptionStatus.CANCELED, tx);
247
+ // 清理积分并留痕
248
+ yield credit_service.creditService.purgePaidCredit(context.userId, 'cancel_subscription_purge', context.orderId, tx);
249
+ }));
250
+ });
251
+ }
252
+ processSubscriptionRefund(context) {
253
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
254
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
255
+ var _a, _b;
256
+ const now = new Date();
257
+ yield transaction_service.transactionService.update(context.transaction.orderId, {
258
+ orderStatus: constants.OrderStatus.REFUNDED,
259
+ paymentStatus: constants.PaymentStatus.UN_PAID,
260
+ payUpdatedAt: now,
261
+ }, tx);
262
+ const subscription = (_a = context.subscription) !== null && _a !== void 0 ? _a : (context.transaction.paySubscriptionId
263
+ ? yield subscription_service.subscriptionService.findByPaySubscriptionId(context.transaction.paySubscriptionId, tx)
264
+ : null);
265
+ if (subscription) {
266
+ yield subscription_service.subscriptionService.updateSubscription(subscription.id, {
267
+ status: constants.SubscriptionStatus.CANCELED,
268
+ updatedAt: now,
269
+ }, tx);
270
+ }
271
+ const credit = yield credit_service.creditService.getCredit(context.transaction.userId, tx);
272
+ const paidBalance = Math.max((_b = credit === null || credit === void 0 ? void 0 : credit.balancePaid) !== null && _b !== void 0 ? _b : 0, 0);
273
+ if (paidBalance > 0) {
274
+ yield credit_service.creditService.consumeCredit(context.transaction.userId, { paid: paidBalance }, {
275
+ feature: constants.OrderStatus.REFUNDED,
276
+ operationReferId: context.transaction.orderId,
277
+ }, tx);
278
+ }
279
+ }));
280
+ });
281
+ }
282
+ processOneTimeRefund(context) {
283
+ return tslib_es6.__awaiter(this, void 0, void 0, function* () {
284
+ yield prismaTransactionUtil.runInTransaction((tx) => tslib_es6.__awaiter(this, void 0, void 0, function* () {
285
+ var _a, _b;
286
+ const now = new Date();
287
+ yield transaction_service.transactionService.update(context.transaction.orderId, {
288
+ orderStatus: constants.OrderStatus.REFUNDED,
289
+ paymentStatus: constants.PaymentStatus.UN_PAID,
290
+ payUpdatedAt: now,
291
+ }, tx);
292
+ const credit = yield credit_service.creditService.getCredit(context.transaction.userId, tx);
293
+ const currentBalance = Math.max((_a = credit === null || credit === void 0 ? void 0 : credit.balanceOneTimePaid) !== null && _a !== void 0 ? _a : 0, 0);
294
+ const granted = Math.max((_b = context.transaction.creditsGranted) !== null && _b !== void 0 ? _b : 0, 0);
295
+ const amountToConsume = Math.min(currentBalance, granted);
296
+ if (amountToConsume > 0) {
297
+ yield credit_service.creditService.consumeCredit(context.transaction.userId, { oneTimePaid: amountToConsume }, {
298
+ feature: constants.OrderStatus.REFUNDED,
299
+ operationReferId: context.transaction.orderId,
300
+ }, tx);
301
+ }
302
+ }));
303
+ });
304
+ }
305
+ }
306
+ const billingAggregateService = new BillingAggregateService();
307
+
308
+ exports.billingAggregateService = billingAggregateService;