@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,156 @@
1
+ 'use strict';
2
+
3
+ var server = require('@windrun-huaiin/third-ui/main/server');
4
+
5
+ const moneyPriceConfig = {
6
+ paymentProviders: {
7
+ stripe: {
8
+ provider: 'stripe',
9
+ enabled: true,
10
+ // 订阅模式产品
11
+ subscriptionProducts: {
12
+ F1: {
13
+ key: 'F1',
14
+ plans: {
15
+ monthly: {
16
+ priceId: 'free',
17
+ amount: 0,
18
+ currency: 'usd',
19
+ credits: 0
20
+ },
21
+ yearly: {
22
+ priceId: 'free',
23
+ amount: 0,
24
+ currency: 'usd',
25
+ credits: 0
26
+ }
27
+ }
28
+ },
29
+ P2: {
30
+ key: 'P2',
31
+ plans: {
32
+ monthly: {
33
+ priceId: process.env.STRIPE_PRO_MONTHLY_PRICE_ID,
34
+ amount: Number(process.env.STRIPE_PRO_MONTHLY_AMOUNT), // 10
35
+ currency: process.env.STRIPE_PRO_MONTHLY_CURRENCY,
36
+ credits: Number(process.env.STRIPE_PRO_MONTHLY_CREDITS)
37
+ },
38
+ yearly: {
39
+ priceId: process.env.STRIPE_PRO_YEARLY_PRICE_ID,
40
+ amount: Number(process.env.STRIPE_PRO_YEARLY_AMOUNT),
41
+ originalAmount: Number(process.env.STRIPE_PRO_MONTHLY_AMOUNT), // 10,
42
+ discountPercent: Number(process.env.STRIPE_PRO_DISCOUNT_PERCENT),
43
+ currency: process.env.STRIPE_PRO_YEARLY_CURRENCY,
44
+ credits: Number(process.env.STRIPE_PRO_YEARLY_CREDITS)
45
+ }
46
+ }
47
+ },
48
+ U3: {
49
+ key: 'U3',
50
+ plans: {
51
+ monthly: {
52
+ priceId: process.env.STRIPE_ULTRA_MONTHLY_PRICE_ID,
53
+ amount: Number(process.env.STRIPE_ULTRA_MONTHLY_AMOUNT),
54
+ currency: process.env.STRIPE_ULTRA_MONTHLY_CURRENCY,
55
+ credits: Number(process.env.STRIPE_ULTRA_MONTHLY_CREDITS)
56
+ },
57
+ yearly: {
58
+ priceId: process.env.STRIPE_ULTRA_YEARLY_PRICE_ID,
59
+ amount: Number(process.env.STRIPE_ULTRA_YEARLY_AMOUNT),
60
+ originalAmount: Number(process.env.STRIPE_ULTRA_MONTHLY_AMOUNT),
61
+ discountPercent: Number(process.env.STRIPE_ULTRA_DISCOUNT_PERCENT),
62
+ currency: process.env.STRIPE_ULTRA_YEARLY_CURRENCY,
63
+ credits: Number(process.env.STRIPE_ULTRA_YEARLY_CREDITS)
64
+ }
65
+ }
66
+ }
67
+ },
68
+ // 积分包产品
69
+ creditPackProducts: {
70
+ F1: {
71
+ key: 'F1',
72
+ priceId: process.env.STRIPE_ONE_TIME_LESS_PRICE_ID,
73
+ amount: Number(process.env.STRIPE_ONE_TIME_LESS_AMOUNT),
74
+ currency: process.env.STRIPE_ONE_TIME_LESS_CURRENCY,
75
+ credits: Number(process.env.STRIPE_ONE_TIME_LESS_CREDITS)
76
+ },
77
+ P2: {
78
+ key: 'P2',
79
+ priceId: process.env.STRIPE_ONE_TIME_MID_PRICE_ID,
80
+ amount: Number(process.env.STRIPE_ONE_TIME_MID_AMOUNT),
81
+ currency: process.env.STRIPE_ONE_TIME_MID_CURRENCY,
82
+ credits: Number(process.env.STRIPE_ONE_TIME_MID_CREDITS)
83
+ },
84
+ U3: {
85
+ key: 'U3',
86
+ priceId: process.env.STRIPE_ONE_TIME_MORE_PRICE_ID,
87
+ amount: Number(process.env.STRIPE_ONE_TIME_MORE_AMOUNT),
88
+ currency: process.env.STRIPE_ONE_TIME_MORE_CURRENCY,
89
+ credits: Number(process.env.STRIPE_ONE_TIME_MORE_CREDITS)
90
+ }
91
+ }
92
+ }
93
+ },
94
+ activeProvider: process.env.ACTIVE_PAYMENT_PROVIDER || 'stripe',
95
+ display: {
96
+ currency: '$',
97
+ locale: 'en',
98
+ minFeaturesCount: 4
99
+ }
100
+ };
101
+ // ============ 应用层wrapper - 隐藏moneyPriceConfig细节 ============
102
+ /**
103
+ * 获取当前激活的支付供应商配置
104
+ *
105
+ * 🔒 安全设计:
106
+ * - wrapper函数隐藏moneyPriceConfig
107
+ * - util层负责从config中提取激活的provider配置
108
+ * - 外部只能通过这个wrapper访问,看不到config对象
109
+ *
110
+ * @returns 当前激活的支付供应商配置
111
+ */
112
+ function getActiveProviderConfig() {
113
+ return server.getActiveProviderConfigUtil(moneyPriceConfig);
114
+ }
115
+ /**
116
+ * 根据 priceId 获取对应的积分数量
117
+ *
118
+ * 🔒 安全设计:
119
+ * - wrapper函数隐藏moneyPriceConfig
120
+ * - util层负责解析config并提取结果
121
+ * - 外部只能通过这个wrapper访问,看不到config对象
122
+ *
123
+ * @param priceId - 查询的价格ID
124
+ * @param _provider - 保留参数(向后兼容),暂未使用
125
+ * @returns 对应的积分数量,或null
126
+ */
127
+ function getCreditsFromPriceId(priceId, _provider) {
128
+ return server.getCreditsFromPriceIdUtil(priceId, moneyPriceConfig);
129
+ }
130
+ /**
131
+ * 根据查询参数获取价格配置
132
+ *
133
+ * 支持三种查询方式:
134
+ * 1. 按 priceId 查询:getPriceConfig(priceId='price_xxx')
135
+ * 2. 按 plan 和 billingType 查询:getPriceConfig(undefined, 'P2', 'monthly')
136
+ * 3. 按 plan 查询:getPriceConfig(undefined, 'P2')
137
+ *
138
+ * 🔒 安全设计:
139
+ * - wrapper函数隐藏moneyPriceConfig
140
+ * - util层负责解析config并提取匹配的结果
141
+ * - 外部只能通过这个wrapper访问,看不到config对象
142
+ *
143
+ * @param priceId - 查询的价格ID(可选)
144
+ * @param plan - 查询的套餐名称如'P2'、'U3'(可选)
145
+ * @param billingType - 查询的计费类型如'monthly'、'yearly'(可选)
146
+ * @param _provider - 保留参数(向后兼容),暂未使用
147
+ * @returns 匹配的价格配置,包含计算好的元数据(priceName、description、interval)
148
+ */
149
+ function getPriceConfig(priceId, plan, billingType, _provider) {
150
+ return server.getPriceConfigUtil(priceId, plan, billingType, moneyPriceConfig);
151
+ }
152
+
153
+ exports.getActiveProviderConfig = getActiveProviderConfig;
154
+ exports.getCreditsFromPriceId = getCreditsFromPriceId;
155
+ exports.getPriceConfig = getPriceConfig;
156
+ exports.moneyPriceConfig = moneyPriceConfig;
@@ -0,0 +1,151 @@
1
+ import { getActiveProviderConfigUtil, getCreditsFromPriceIdUtil, getPriceConfigUtil } from '@windrun-huaiin/third-ui/main/server';
2
+
3
+ const moneyPriceConfig = {
4
+ paymentProviders: {
5
+ stripe: {
6
+ provider: 'stripe',
7
+ enabled: true,
8
+ // 订阅模式产品
9
+ subscriptionProducts: {
10
+ F1: {
11
+ key: 'F1',
12
+ plans: {
13
+ monthly: {
14
+ priceId: 'free',
15
+ amount: 0,
16
+ currency: 'usd',
17
+ credits: 0
18
+ },
19
+ yearly: {
20
+ priceId: 'free',
21
+ amount: 0,
22
+ currency: 'usd',
23
+ credits: 0
24
+ }
25
+ }
26
+ },
27
+ P2: {
28
+ key: 'P2',
29
+ plans: {
30
+ monthly: {
31
+ priceId: process.env.STRIPE_PRO_MONTHLY_PRICE_ID,
32
+ amount: Number(process.env.STRIPE_PRO_MONTHLY_AMOUNT), // 10
33
+ currency: process.env.STRIPE_PRO_MONTHLY_CURRENCY,
34
+ credits: Number(process.env.STRIPE_PRO_MONTHLY_CREDITS)
35
+ },
36
+ yearly: {
37
+ priceId: process.env.STRIPE_PRO_YEARLY_PRICE_ID,
38
+ amount: Number(process.env.STRIPE_PRO_YEARLY_AMOUNT),
39
+ originalAmount: Number(process.env.STRIPE_PRO_MONTHLY_AMOUNT), // 10,
40
+ discountPercent: Number(process.env.STRIPE_PRO_DISCOUNT_PERCENT),
41
+ currency: process.env.STRIPE_PRO_YEARLY_CURRENCY,
42
+ credits: Number(process.env.STRIPE_PRO_YEARLY_CREDITS)
43
+ }
44
+ }
45
+ },
46
+ U3: {
47
+ key: 'U3',
48
+ plans: {
49
+ monthly: {
50
+ priceId: process.env.STRIPE_ULTRA_MONTHLY_PRICE_ID,
51
+ amount: Number(process.env.STRIPE_ULTRA_MONTHLY_AMOUNT),
52
+ currency: process.env.STRIPE_ULTRA_MONTHLY_CURRENCY,
53
+ credits: Number(process.env.STRIPE_ULTRA_MONTHLY_CREDITS)
54
+ },
55
+ yearly: {
56
+ priceId: process.env.STRIPE_ULTRA_YEARLY_PRICE_ID,
57
+ amount: Number(process.env.STRIPE_ULTRA_YEARLY_AMOUNT),
58
+ originalAmount: Number(process.env.STRIPE_ULTRA_MONTHLY_AMOUNT),
59
+ discountPercent: Number(process.env.STRIPE_ULTRA_DISCOUNT_PERCENT),
60
+ currency: process.env.STRIPE_ULTRA_YEARLY_CURRENCY,
61
+ credits: Number(process.env.STRIPE_ULTRA_YEARLY_CREDITS)
62
+ }
63
+ }
64
+ }
65
+ },
66
+ // 积分包产品
67
+ creditPackProducts: {
68
+ F1: {
69
+ key: 'F1',
70
+ priceId: process.env.STRIPE_ONE_TIME_LESS_PRICE_ID,
71
+ amount: Number(process.env.STRIPE_ONE_TIME_LESS_AMOUNT),
72
+ currency: process.env.STRIPE_ONE_TIME_LESS_CURRENCY,
73
+ credits: Number(process.env.STRIPE_ONE_TIME_LESS_CREDITS)
74
+ },
75
+ P2: {
76
+ key: 'P2',
77
+ priceId: process.env.STRIPE_ONE_TIME_MID_PRICE_ID,
78
+ amount: Number(process.env.STRIPE_ONE_TIME_MID_AMOUNT),
79
+ currency: process.env.STRIPE_ONE_TIME_MID_CURRENCY,
80
+ credits: Number(process.env.STRIPE_ONE_TIME_MID_CREDITS)
81
+ },
82
+ U3: {
83
+ key: 'U3',
84
+ priceId: process.env.STRIPE_ONE_TIME_MORE_PRICE_ID,
85
+ amount: Number(process.env.STRIPE_ONE_TIME_MORE_AMOUNT),
86
+ currency: process.env.STRIPE_ONE_TIME_MORE_CURRENCY,
87
+ credits: Number(process.env.STRIPE_ONE_TIME_MORE_CREDITS)
88
+ }
89
+ }
90
+ }
91
+ },
92
+ activeProvider: process.env.ACTIVE_PAYMENT_PROVIDER || 'stripe',
93
+ display: {
94
+ currency: '$',
95
+ locale: 'en',
96
+ minFeaturesCount: 4
97
+ }
98
+ };
99
+ // ============ 应用层wrapper - 隐藏moneyPriceConfig细节 ============
100
+ /**
101
+ * 获取当前激活的支付供应商配置
102
+ *
103
+ * 🔒 安全设计:
104
+ * - wrapper函数隐藏moneyPriceConfig
105
+ * - util层负责从config中提取激活的provider配置
106
+ * - 外部只能通过这个wrapper访问,看不到config对象
107
+ *
108
+ * @returns 当前激活的支付供应商配置
109
+ */
110
+ function getActiveProviderConfig() {
111
+ return getActiveProviderConfigUtil(moneyPriceConfig);
112
+ }
113
+ /**
114
+ * 根据 priceId 获取对应的积分数量
115
+ *
116
+ * 🔒 安全设计:
117
+ * - wrapper函数隐藏moneyPriceConfig
118
+ * - util层负责解析config并提取结果
119
+ * - 外部只能通过这个wrapper访问,看不到config对象
120
+ *
121
+ * @param priceId - 查询的价格ID
122
+ * @param _provider - 保留参数(向后兼容),暂未使用
123
+ * @returns 对应的积分数量,或null
124
+ */
125
+ function getCreditsFromPriceId(priceId, _provider) {
126
+ return getCreditsFromPriceIdUtil(priceId, moneyPriceConfig);
127
+ }
128
+ /**
129
+ * 根据查询参数获取价格配置
130
+ *
131
+ * 支持三种查询方式:
132
+ * 1. 按 priceId 查询:getPriceConfig(priceId='price_xxx')
133
+ * 2. 按 plan 和 billingType 查询:getPriceConfig(undefined, 'P2', 'monthly')
134
+ * 3. 按 plan 查询:getPriceConfig(undefined, 'P2')
135
+ *
136
+ * 🔒 安全设计:
137
+ * - wrapper函数隐藏moneyPriceConfig
138
+ * - util层负责解析config并提取匹配的结果
139
+ * - 外部只能通过这个wrapper访问,看不到config对象
140
+ *
141
+ * @param priceId - 查询的价格ID(可选)
142
+ * @param plan - 查询的套餐名称如'P2'、'U3'(可选)
143
+ * @param billingType - 查询的计费类型如'monthly'、'yearly'(可选)
144
+ * @param _provider - 保留参数(向后兼容),暂未使用
145
+ * @returns 匹配的价格配置,包含计算好的元数据(priceName、description、interval)
146
+ */
147
+ function getPriceConfig(priceId, plan, billingType, _provider) {
148
+ return getPriceConfigUtil(priceId, plan, billingType, moneyPriceConfig);
149
+ }
150
+
151
+ export { getActiveProviderConfig, getCreditsFromPriceId, getPriceConfig, moneyPriceConfig };
@@ -0,0 +1,31 @@
1
+ import Stripe from 'stripe';
2
+ export declare const stripe: Stripe;
3
+ export declare const validateStripeWebhook: (payload: string | Buffer, signature: string, secret: string) => Stripe.Event;
4
+ export interface BasicCheckoutSessionParams {
5
+ priceId: string;
6
+ customerId?: string;
7
+ clientReferenceId: string;
8
+ successUrl: string;
9
+ cancelUrl: string;
10
+ metadata?: Record<string, string>;
11
+ interval?: string;
12
+ }
13
+ export declare const createCheckoutSession: (params: BasicCheckoutSessionParams, subscriptionData?: Stripe.Checkout.SessionCreateParams.SubscriptionData) => Promise<Stripe.Checkout.Session>;
14
+ export declare const fetchPaymentId: (invoiceId: string) => Promise<string>;
15
+ export declare const createOrGetCustomer: (params: {
16
+ userId: string;
17
+ }) => Promise<string>;
18
+ export declare const updateSubscription: (params: {
19
+ subscriptionId: string;
20
+ priceId: string;
21
+ prorationBehavior?: "create_prorations" | "none" | "always_invoice";
22
+ }) => Promise<Stripe.Subscription>;
23
+ export declare const createCustomerPortalSession: (params: {
24
+ customerId: string;
25
+ returnUrl: string;
26
+ }) => Promise<Stripe.BillingPortal.Session>;
27
+ export declare const cancelSubscription: (subscriptionId: string, cancelAtPeriodEnd?: boolean) => Promise<Stripe.Subscription>;
28
+ export declare class ActiveSubscriptionExistsError extends Error {
29
+ constructor();
30
+ }
31
+ //# sourceMappingURL=stripe-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe-config.d.ts","sourceRoot":"","sources":["../../src/lib/stripe-config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAI5B,eAAO,MAAM,MAAM,QAEjB,CAAC;AAGH,eAAO,MAAM,qBAAqB,GAChC,SAAS,MAAM,GAAG,MAAM,EACxB,WAAW,MAAM,EACjB,QAAQ,MAAM,KACb,MAAM,CAAC,KAET,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAElC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAGnB;AAGD,eAAO,MAAM,qBAAqB,GAChC,QAAQ,0BAA0B,EAClC,mBAAmB,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,gBAAgB,KACtE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAgFjC,CAAC;AAGF,eAAO,MAAM,cAAc,GAAU,WAAW,MAAM,KAAI,OAAO,CAAC,MAAM,CAQvE,CAAA;AAGD,eAAO,MAAM,mBAAmB,GAAU,QAAQ;IAChD,MAAM,EAAE,MAAM,CAAC;CAChB,KAAG,OAAO,CAAC,MAAM,CA0FjB,CAAC;AAGF,eAAO,MAAM,kBAAkB,GAAU,QAAQ;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,mBAAmB,GAAG,MAAM,GAAG,gBAAgB,CAAC;CACrE,KAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAiC9B,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAU,QAAQ;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,KAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAqBvC,CAAC;AAGF,eAAO,MAAM,kBAAkB,GAC7B,gBAAgB,MAAM,EACtB,oBAAmB,OAAc,KAChC,OAAO,CAAC,MAAM,CAAC,YAAY,CAiC7B,CAAC;AAEF,qBAAa,6BAA8B,SAAQ,KAAK;;CAKvD"}
@@ -0,0 +1,278 @@
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 Stripe = require('stripe');
5
+ var user_service = require('../services/database/user.service.js');
6
+ var subscription_service = require('../services/database/subscription.service.js');
7
+ require('../services/database/credit.service.js');
8
+ require('@prisma/client');
9
+ require('../prisma/prisma.js');
10
+ var apilog_service = require('../services/database/apilog.service.js');
11
+
12
+ // Stripe Configuration
13
+ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
14
+ apiVersion: '2025-10-29.clover',
15
+ });
16
+ // Helper function to validate webhook signature
17
+ const validateStripeWebhook = (payload, signature, secret) => {
18
+ return stripe.webhooks.constructEvent(payload, signature, secret);
19
+ };
20
+ // Helper function to create checkout session
21
+ const createCheckoutSession = (params, subscriptionData) => tslib_es6.__awaiter(void 0, void 0, void 0, function* () {
22
+ const { priceId, customerId, clientReferenceId, successUrl, cancelUrl, metadata, interval } = params;
23
+ // ✅ Dynamic mode determination: subscription if interval is not 'onetime'
24
+ const mode = interval && interval !== 'onetime' ? 'subscription' : 'payment';
25
+ const isSubscriptionMode = mode === 'subscription';
26
+ if (isSubscriptionMode) {
27
+ if (!subscriptionData) {
28
+ throw new Error('Subscription data is required for subscription mode');
29
+ }
30
+ const activeSubscription = yield subscription_service.subscriptionService.getActiveSubscription(clientReferenceId);
31
+ if (activeSubscription) {
32
+ throw new ActiveSubscriptionExistsError();
33
+ }
34
+ }
35
+ const sessionParams = {
36
+ mode, // ✅ Dynamic mode
37
+ payment_method_types: ['card'],
38
+ line_items: [
39
+ {
40
+ price: priceId,
41
+ quantity: 1,
42
+ },
43
+ ],
44
+ success_url: successUrl,
45
+ cancel_url: cancelUrl,
46
+ client_reference_id: clientReferenceId,
47
+ metadata: Object.assign(Object.assign({}, metadata), { mode }),
48
+ };
49
+ // Add customer if provided
50
+ if (customerId) {
51
+ sessionParams.customer = customerId;
52
+ }
53
+ // One-time payment specific configuration
54
+ if (isSubscriptionMode) {
55
+ // 在这里注入订单元数据,以保证后续事件处理能根据订单去匹配处理,只能在订阅模式里设置数据,否则Stripe报错
56
+ sessionParams.subscription_data = subscriptionData;
57
+ }
58
+ else {
59
+ // One-time payments don't create invoices
60
+ sessionParams.invoice_creation = {
61
+ enabled: false,
62
+ };
63
+ }
64
+ // Create log record with request
65
+ const logId = yield apilog_service.Apilogger.logStripeOutgoing('createCheckoutSession', params);
66
+ try {
67
+ const session = yield stripe.checkout.sessions.create(sessionParams);
68
+ // Update log record with response
69
+ apilog_service.Apilogger.updateResponse(logId, {
70
+ session_id: session.id,
71
+ url: session.url,
72
+ mode: session.mode
73
+ });
74
+ return session;
75
+ }
76
+ catch (error) {
77
+ // Update log record with error
78
+ apilog_service.Apilogger.updateResponse(logId, {
79
+ error: error instanceof Error ? error.message : 'Unknown error'
80
+ });
81
+ throw error;
82
+ }
83
+ });
84
+ // 根据发票ID去查支付ID
85
+ const fetchPaymentId = (invoiceId) => tslib_es6.__awaiter(void 0, void 0, void 0, function* () {
86
+ var _a, _b;
87
+ const fullInvoice = yield stripe.invoices.retrieve(invoiceId, {
88
+ expand: ['payments']
89
+ });
90
+ const payment = (_a = fullInvoice.payments) === null || _a === void 0 ? void 0 : _a.data[0];
91
+ const paymentIntentInfo = (_b = payment === null || payment === void 0 ? void 0 : payment.payment) === null || _b === void 0 ? void 0 : _b.payment_intent;
92
+ const paymentIntentId = typeof paymentIntentInfo === 'string' ? paymentIntentInfo : paymentIntentInfo === null || paymentIntentInfo === void 0 ? void 0 : paymentIntentInfo.id;
93
+ return paymentIntentId;
94
+ });
95
+ // Helper function to create or retrieve customer
96
+ const createOrGetCustomer = (params) => tslib_es6.__awaiter(void 0, void 0, void 0, function* () {
97
+ const { userId } = params;
98
+ const user = yield user_service.userService.findByUserId(userId);
99
+ if (!user) {
100
+ throw new Error(`User not found for userId: ${userId}`);
101
+ }
102
+ const setStripeCustomerId = (stripeCusId) => tslib_es6.__awaiter(void 0, void 0, void 0, function* () {
103
+ try {
104
+ yield user_service.userService.updateStripeCustomerId(userId, stripeCusId);
105
+ }
106
+ catch (error) {
107
+ console.error('Failed to update stripe customer id', { userId, stripeCusId, error });
108
+ }
109
+ });
110
+ if (user.stripeCusId) {
111
+ try {
112
+ const customer = yield stripe.customers.retrieve(user.stripeCusId);
113
+ if ('deleted' in customer) {
114
+ yield setStripeCustomerId(null);
115
+ }
116
+ else {
117
+ return customer.id;
118
+ }
119
+ }
120
+ catch (error) {
121
+ yield setStripeCustomerId(null);
122
+ console.warn('Failed to retrieve Stripe customer, fallback to lookup by email', {
123
+ userId,
124
+ stripeCusId: user.stripeCusId,
125
+ error,
126
+ });
127
+ }
128
+ }
129
+ if (user.email) {
130
+ const existingCustomers = yield stripe.customers.list({
131
+ email: user.email,
132
+ limit: 1,
133
+ });
134
+ if (existingCustomers.data.length > 0) {
135
+ const stripeCustomer = existingCustomers.data[0];
136
+ if (!user.stripeCusId || user.stripeCusId !== stripeCustomer.id) {
137
+ yield setStripeCustomerId(stripeCustomer.id);
138
+ }
139
+ return stripeCustomer.id;
140
+ }
141
+ }
142
+ // 创建新客户
143
+ const customerParams = {
144
+ metadata: {
145
+ user_id: userId,
146
+ },
147
+ };
148
+ if (user.email) {
149
+ customerParams.email = user.email;
150
+ }
151
+ const derivedName = user.email ? user.email.split('@')[0] : undefined;
152
+ if (derivedName) {
153
+ customerParams.name = derivedName;
154
+ }
155
+ // Create log record with request
156
+ const logId = yield apilog_service.Apilogger.logStripeOutgoing('createCustomer', {
157
+ userId,
158
+ email: customerParams.email,
159
+ name: customerParams.name,
160
+ });
161
+ try {
162
+ const customer = yield stripe.customers.create(customerParams);
163
+ yield setStripeCustomerId(customer.id);
164
+ // Update log record with response
165
+ apilog_service.Apilogger.updateResponse(logId, {
166
+ customer_id: customer.id,
167
+ email: customer.email
168
+ });
169
+ return customer.id;
170
+ }
171
+ catch (error) {
172
+ // Update log record with error
173
+ apilog_service.Apilogger.updateResponse(logId, {
174
+ error: error instanceof Error ? error.message : 'Unknown error'
175
+ });
176
+ throw error;
177
+ }
178
+ });
179
+ // Helper function to update subscription
180
+ const updateSubscription = (params) => tslib_es6.__awaiter(void 0, void 0, void 0, function* () {
181
+ const { subscriptionId, priceId, prorationBehavior = 'create_prorations' } = params;
182
+ const subscription = yield stripe.subscriptions.retrieve(subscriptionId);
183
+ // Create log record with request
184
+ const logId = yield apilog_service.Apilogger.logStripeOutgoing('updateSubscription', params);
185
+ try {
186
+ const updatedSubscription = yield stripe.subscriptions.update(subscriptionId, {
187
+ items: [
188
+ {
189
+ id: subscription.items.data[0].id,
190
+ price: priceId,
191
+ },
192
+ ],
193
+ proration_behavior: prorationBehavior,
194
+ });
195
+ // Update log record with response
196
+ apilog_service.Apilogger.updateResponse(logId, {
197
+ subscription_id: updatedSubscription.id,
198
+ status: updatedSubscription.status
199
+ });
200
+ return updatedSubscription;
201
+ }
202
+ catch (error) {
203
+ // Update log record with error
204
+ apilog_service.Apilogger.updateResponse(logId, {
205
+ error: error instanceof Error ? error.message : 'Unknown error'
206
+ });
207
+ throw error;
208
+ }
209
+ });
210
+ const createCustomerPortalSession = (params) => tslib_es6.__awaiter(void 0, void 0, void 0, function* () {
211
+ const logId = yield apilog_service.Apilogger.logStripeOutgoing('createCustomerPortalSession', params);
212
+ try {
213
+ const session = yield stripe.billingPortal.sessions.create({
214
+ customer: params.customerId,
215
+ return_url: params.returnUrl,
216
+ });
217
+ apilog_service.Apilogger.updateResponse(logId, {
218
+ session_id: session.id,
219
+ url: session.url,
220
+ });
221
+ return session;
222
+ }
223
+ catch (error) {
224
+ apilog_service.Apilogger.updateResponse(logId, {
225
+ error: error instanceof Error ? error.message : 'Unknown error'
226
+ });
227
+ throw error;
228
+ }
229
+ });
230
+ // Helper function to cancel subscription
231
+ const cancelSubscription = (subscriptionId_1, ...args_1) => tslib_es6.__awaiter(void 0, [subscriptionId_1, ...args_1], void 0, function* (subscriptionId, cancelAtPeriodEnd = true) {
232
+ // Create log record with request
233
+ const logId = yield apilog_service.Apilogger.logStripeOutgoing('cancelSubscription', {
234
+ subscriptionId,
235
+ cancelAtPeriodEnd
236
+ });
237
+ try {
238
+ let result;
239
+ if (cancelAtPeriodEnd) {
240
+ result = yield stripe.subscriptions.update(subscriptionId, {
241
+ cancel_at_period_end: true,
242
+ });
243
+ }
244
+ else {
245
+ result = yield stripe.subscriptions.cancel(subscriptionId);
246
+ }
247
+ // Update log record with response
248
+ apilog_service.Apilogger.updateResponse(logId, {
249
+ subscription_id: result.id,
250
+ status: result.status,
251
+ cancel_at_period_end: result.cancel_at_period_end
252
+ });
253
+ return result;
254
+ }
255
+ catch (error) {
256
+ // Update log record with error
257
+ apilog_service.Apilogger.updateResponse(logId, {
258
+ error: error instanceof Error ? error.message : 'Unknown error'
259
+ });
260
+ throw error;
261
+ }
262
+ });
263
+ class ActiveSubscriptionExistsError extends Error {
264
+ constructor() {
265
+ super('ACTIVE_SUBSCRIPTION_EXISTS');
266
+ this.name = 'ActiveSubscriptionExistsError';
267
+ }
268
+ }
269
+
270
+ exports.ActiveSubscriptionExistsError = ActiveSubscriptionExistsError;
271
+ exports.cancelSubscription = cancelSubscription;
272
+ exports.createCheckoutSession = createCheckoutSession;
273
+ exports.createCustomerPortalSession = createCustomerPortalSession;
274
+ exports.createOrGetCustomer = createOrGetCustomer;
275
+ exports.fetchPaymentId = fetchPaymentId;
276
+ exports.stripe = stripe;
277
+ exports.updateSubscription = updateSubscription;
278
+ exports.validateStripeWebhook = validateStripeWebhook;