@misterhomer1992/miit-bot-payment 1.1.7 → 2.0.4

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 (248) hide show
  1. package/dist/config/ConfigurationManager.d.ts +64 -0
  2. package/dist/config/ConfigurationManager.d.ts.map +1 -0
  3. package/dist/config/ConfigurationManager.js +144 -0
  4. package/dist/config/ConfigurationManager.js.map +1 -0
  5. package/dist/config/defaults.d.ts +18 -0
  6. package/dist/config/defaults.d.ts.map +1 -0
  7. package/dist/config/defaults.js +26 -0
  8. package/dist/config/defaults.js.map +1 -0
  9. package/dist/config/environment.d.ts +38 -0
  10. package/dist/config/environment.d.ts.map +1 -0
  11. package/dist/config/environment.js +91 -0
  12. package/dist/config/environment.js.map +1 -0
  13. package/dist/config/index.d.ts +5 -0
  14. package/dist/config/index.d.ts.map +1 -0
  15. package/dist/config/index.js +18 -0
  16. package/dist/config/index.js.map +1 -0
  17. package/dist/config/types.d.ts +53 -0
  18. package/dist/config/types.d.ts.map +1 -0
  19. package/dist/config/types.js +3 -0
  20. package/dist/config/types.js.map +1 -0
  21. package/dist/index.d.ts +21 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +23 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/modules/cache/InMemoryCache.d.ts +17 -0
  26. package/dist/modules/cache/InMemoryCache.d.ts.map +1 -0
  27. package/dist/modules/cache/InMemoryCache.js +77 -0
  28. package/dist/modules/cache/InMemoryCache.js.map +1 -0
  29. package/dist/modules/cache/index.d.ts +3 -0
  30. package/dist/modules/cache/index.d.ts.map +1 -0
  31. package/dist/modules/cache/index.js +19 -0
  32. package/dist/modules/cache/index.js.map +1 -0
  33. package/dist/modules/cache/types.d.ts +52 -0
  34. package/dist/modules/cache/types.d.ts.map +1 -0
  35. package/dist/modules/cache/types.js +3 -0
  36. package/dist/modules/cache/types.js.map +1 -0
  37. package/dist/modules/errors/index.d.ts +2 -0
  38. package/dist/modules/errors/index.d.ts.map +1 -0
  39. package/dist/modules/errors/index.js +19 -0
  40. package/dist/modules/errors/index.js.map +1 -0
  41. package/dist/modules/errors/types.d.ts +112 -0
  42. package/dist/modules/errors/types.d.ts.map +1 -0
  43. package/dist/modules/errors/types.js +174 -0
  44. package/dist/modules/errors/types.js.map +1 -0
  45. package/dist/modules/payments/api.d.ts +63 -1
  46. package/dist/modules/payments/api.d.ts.map +1 -1
  47. package/dist/modules/payments/api.js +103 -1
  48. package/dist/modules/payments/api.js.map +1 -1
  49. package/dist/modules/payments/const.d.ts.map +1 -1
  50. package/dist/modules/payments/const.js +1 -0
  51. package/dist/modules/payments/const.js.map +1 -1
  52. package/dist/modules/payments/index.d.ts +8 -0
  53. package/dist/modules/payments/index.d.ts.map +1 -1
  54. package/dist/modules/payments/index.js +8 -0
  55. package/dist/modules/payments/index.js.map +1 -1
  56. package/dist/modules/payments/service.d.ts +42 -2
  57. package/dist/modules/payments/service.d.ts.map +1 -1
  58. package/dist/modules/payments/service.js +132 -3
  59. package/dist/modules/payments/service.js.map +1 -1
  60. package/dist/modules/payments/subscription-check-webhook.handler.d.ts +85 -0
  61. package/dist/modules/payments/subscription-check-webhook.handler.d.ts.map +1 -0
  62. package/dist/modules/payments/subscription-check-webhook.handler.js +155 -0
  63. package/dist/modules/payments/subscription-check-webhook.handler.js.map +1 -0
  64. package/dist/modules/payments/subscription-check-webhook.service.d.ts +59 -0
  65. package/dist/modules/payments/subscription-check-webhook.service.d.ts.map +1 -0
  66. package/dist/modules/payments/subscription-check-webhook.service.js +330 -0
  67. package/dist/modules/payments/subscription-check-webhook.service.js.map +1 -0
  68. package/dist/modules/payments/subscription-check-webhook.types.d.ts +25 -0
  69. package/dist/modules/payments/subscription-check-webhook.types.d.ts.map +1 -0
  70. package/dist/modules/payments/subscription-check-webhook.types.js +3 -0
  71. package/dist/modules/payments/subscription-check-webhook.types.js.map +1 -0
  72. package/dist/modules/payments/types.d.ts +69 -2
  73. package/dist/modules/payments/types.d.ts.map +1 -1
  74. package/dist/modules/payments/utils.d.ts +151 -5
  75. package/dist/modules/payments/utils.d.ts.map +1 -1
  76. package/dist/modules/payments/utils.js +253 -9
  77. package/dist/modules/payments/utils.js.map +1 -1
  78. package/dist/modules/payments/wayforpay.service.d.ts +39 -0
  79. package/dist/modules/payments/wayforpay.service.d.ts.map +1 -0
  80. package/dist/modules/payments/wayforpay.service.js +217 -0
  81. package/dist/modules/payments/wayforpay.service.js.map +1 -0
  82. package/dist/modules/payments/wayforpay.types.d.ts +115 -0
  83. package/dist/modules/payments/wayforpay.types.d.ts.map +1 -0
  84. package/dist/modules/payments/wayforpay.types.js +3 -0
  85. package/dist/modules/payments/wayforpay.types.js.map +1 -0
  86. package/dist/modules/payments/webhook.handler.d.ts +98 -0
  87. package/dist/modules/payments/webhook.handler.d.ts.map +1 -0
  88. package/dist/modules/payments/webhook.handler.js +153 -0
  89. package/dist/modules/payments/webhook.handler.js.map +1 -0
  90. package/dist/modules/payments/webhook.service.d.ts +99 -0
  91. package/dist/modules/payments/webhook.service.d.ts.map +1 -0
  92. package/dist/modules/payments/webhook.service.js +672 -0
  93. package/dist/modules/payments/webhook.service.js.map +1 -0
  94. package/dist/modules/payments/webhook.types.d.ts +35 -0
  95. package/dist/modules/payments/webhook.types.d.ts.map +1 -0
  96. package/dist/modules/payments/webhook.types.js +3 -0
  97. package/dist/modules/payments/webhook.types.js.map +1 -0
  98. package/dist/modules/subscription/change.service.d.ts +80 -0
  99. package/dist/modules/subscription/change.service.d.ts.map +1 -0
  100. package/dist/modules/subscription/change.service.js +226 -0
  101. package/dist/modules/subscription/change.service.js.map +1 -0
  102. package/dist/modules/subscription/index.d.ts +2 -0
  103. package/dist/modules/subscription/index.d.ts.map +1 -1
  104. package/dist/modules/subscription/index.js +2 -0
  105. package/dist/modules/subscription/index.js.map +1 -1
  106. package/dist/modules/subscription/service.d.ts +8 -1
  107. package/dist/modules/subscription/service.d.ts.map +1 -1
  108. package/dist/modules/subscription/service.js +58 -1
  109. package/dist/modules/subscription/service.js.map +1 -1
  110. package/dist/modules/subscription/status-check.handler.d.ts +117 -0
  111. package/dist/modules/subscription/status-check.handler.d.ts.map +1 -0
  112. package/dist/modules/subscription/status-check.handler.js +164 -0
  113. package/dist/modules/subscription/status-check.handler.js.map +1 -0
  114. package/dist/modules/subscription/types.d.ts +37 -1
  115. package/dist/modules/subscription/types.d.ts.map +1 -1
  116. package/dist/modules/subscriptionPlan/const.d.ts +5 -0
  117. package/dist/modules/subscriptionPlan/const.d.ts.map +1 -0
  118. package/dist/modules/subscriptionPlan/const.js +106 -0
  119. package/dist/modules/subscriptionPlan/const.js.map +1 -0
  120. package/dist/modules/subscriptionPlan/index.d.ts +5 -0
  121. package/dist/modules/subscriptionPlan/index.d.ts.map +1 -0
  122. package/dist/modules/subscriptionPlan/index.js +21 -0
  123. package/dist/modules/subscriptionPlan/index.js.map +1 -0
  124. package/dist/modules/subscriptionPlan/repository.d.ts +22 -0
  125. package/dist/modules/subscriptionPlan/repository.d.ts.map +1 -0
  126. package/dist/modules/subscriptionPlan/repository.js +95 -0
  127. package/dist/modules/subscriptionPlan/repository.js.map +1 -0
  128. package/dist/modules/subscriptionPlan/service.d.ts +21 -0
  129. package/dist/modules/subscriptionPlan/service.d.ts.map +1 -0
  130. package/dist/modules/subscriptionPlan/service.js +128 -0
  131. package/dist/modules/subscriptionPlan/service.js.map +1 -0
  132. package/dist/modules/subscriptionPlan/types.d.ts +40 -0
  133. package/dist/modules/subscriptionPlan/types.d.ts.map +1 -0
  134. package/dist/modules/subscriptionPlan/types.js +3 -0
  135. package/dist/modules/subscriptionPlan/types.js.map +1 -0
  136. package/dist/modules/token/const.d.ts +7 -0
  137. package/dist/modules/token/const.d.ts.map +1 -0
  138. package/dist/modules/token/const.js +66 -0
  139. package/dist/modules/token/const.js.map +1 -0
  140. package/dist/modules/token/index.d.ts +4 -0
  141. package/dist/modules/token/index.d.ts.map +1 -0
  142. package/dist/modules/token/index.js +20 -0
  143. package/dist/modules/token/index.js.map +1 -0
  144. package/dist/modules/token/service.d.ts +46 -0
  145. package/dist/modules/token/service.d.ts.map +1 -0
  146. package/dist/modules/token/service.js +249 -0
  147. package/dist/modules/token/service.js.map +1 -0
  148. package/dist/modules/token/types.d.ts +109 -0
  149. package/dist/modules/token/types.d.ts.map +1 -0
  150. package/dist/modules/token/types.js +3 -0
  151. package/dist/modules/token/types.js.map +1 -0
  152. package/dist/modules/tokenPack/const.d.ts +4 -0
  153. package/dist/modules/tokenPack/const.d.ts.map +1 -0
  154. package/dist/modules/tokenPack/const.js +10 -0
  155. package/dist/modules/tokenPack/const.js.map +1 -0
  156. package/dist/modules/tokenPack/index.d.ts +5 -0
  157. package/dist/modules/tokenPack/index.d.ts.map +1 -0
  158. package/dist/modules/tokenPack/index.js +21 -0
  159. package/dist/modules/tokenPack/index.js.map +1 -0
  160. package/dist/modules/tokenPack/repository.d.ts +32 -0
  161. package/dist/modules/tokenPack/repository.d.ts.map +1 -0
  162. package/dist/modules/tokenPack/repository.js +103 -0
  163. package/dist/modules/tokenPack/repository.js.map +1 -0
  164. package/dist/modules/tokenPack/service.d.ts +28 -0
  165. package/dist/modules/tokenPack/service.d.ts.map +1 -0
  166. package/dist/modules/tokenPack/service.js +106 -0
  167. package/dist/modules/tokenPack/service.js.map +1 -0
  168. package/dist/modules/tokenPack/types.d.ts +124 -0
  169. package/dist/modules/tokenPack/types.d.ts.map +1 -0
  170. package/dist/modules/tokenPack/types.js +3 -0
  171. package/dist/modules/tokenPack/types.js.map +1 -0
  172. package/package.json +9 -5
  173. package/src/config/ConfigurationManager.ts +159 -0
  174. package/src/config/defaults.ts +27 -0
  175. package/src/config/environment.ts +94 -0
  176. package/src/config/index.ts +22 -0
  177. package/src/config/types.ts +56 -0
  178. package/src/index.ts +29 -0
  179. package/src/modules/cache/InMemoryCache.ts +98 -0
  180. package/src/modules/cache/index.ts +2 -0
  181. package/src/modules/cache/types.ts +60 -0
  182. package/src/modules/cancellableAPI/utils.ts +60 -0
  183. package/src/modules/errors/index.ts +16 -0
  184. package/src/modules/errors/types.ts +201 -0
  185. package/src/modules/invoice/const.ts +7 -0
  186. package/src/modules/invoice/index.ts +4 -0
  187. package/src/modules/invoice/repository.ts +52 -0
  188. package/src/modules/invoice/service.ts +44 -0
  189. package/src/modules/invoice/types.ts +47 -0
  190. package/src/modules/logger/types.ts +8 -0
  191. package/src/modules/network/utils.ts +24 -0
  192. package/src/modules/payments/api.ts +289 -0
  193. package/src/modules/payments/const.ts +11 -0
  194. package/src/modules/payments/index.ts +14 -0
  195. package/src/modules/payments/repository.ts +125 -0
  196. package/src/modules/payments/service.test.ts +400 -0
  197. package/src/modules/payments/service.ts +365 -0
  198. package/src/modules/payments/subscription-check-webhook.handler.integration.test.ts +935 -0
  199. package/src/modules/payments/subscription-check-webhook.handler.ts +211 -0
  200. package/src/modules/payments/subscription-check-webhook.service.ts +398 -0
  201. package/src/modules/payments/subscription-check-webhook.types.ts +29 -0
  202. package/src/modules/payments/types.ts +193 -0
  203. package/src/modules/payments/utils.ts +428 -0
  204. package/src/modules/payments/wayforpay.service.test.ts +375 -0
  205. package/src/modules/payments/wayforpay.service.ts +284 -0
  206. package/src/modules/payments/wayforpay.types.ts +138 -0
  207. package/src/modules/payments/webhook.handler.integration.test.ts +975 -0
  208. package/src/modules/payments/webhook.handler.ts +219 -0
  209. package/src/modules/payments/webhook.service.ts +812 -0
  210. package/src/modules/payments/webhook.types.ts +38 -0
  211. package/src/modules/subscription/change.service.ts +317 -0
  212. package/src/modules/subscription/const.ts +9 -0
  213. package/src/modules/subscription/index.ts +5 -0
  214. package/src/modules/subscription/repository.ts +277 -0
  215. package/src/modules/subscription/service.test.ts +665 -0
  216. package/src/modules/subscription/service.ts +328 -0
  217. package/src/modules/subscription/status-check.handler.ts +254 -0
  218. package/src/modules/subscription/types.ts +267 -0
  219. package/src/modules/subscription/utils.ts +5 -0
  220. package/src/modules/subscriptionPlan/const.ts +106 -0
  221. package/src/modules/subscriptionPlan/index.ts +4 -0
  222. package/src/modules/subscriptionPlan/repository.ts +129 -0
  223. package/src/modules/subscriptionPlan/service.test.ts +401 -0
  224. package/src/modules/subscriptionPlan/service.ts +148 -0
  225. package/src/modules/subscriptionPlan/types.ts +67 -0
  226. package/src/modules/token/const.ts +64 -0
  227. package/src/modules/token/index.ts +3 -0
  228. package/src/modules/token/service.test.ts +499 -0
  229. package/src/modules/token/service.ts +297 -0
  230. package/src/modules/token/types.ts +124 -0
  231. package/src/modules/tokenPack/const.ts +9 -0
  232. package/src/modules/tokenPack/index.ts +4 -0
  233. package/src/modules/tokenPack/repository.ts +144 -0
  234. package/src/modules/tokenPack/service.ts +119 -0
  235. package/src/modules/tokenPack/types.ts +131 -0
  236. package/src/modules/user/index.ts +3 -0
  237. package/src/modules/user/types.ts +143 -0
  238. package/src/modules/user/userRepository.ts +64 -0
  239. package/src/modules/user/userService.ts +68 -0
  240. package/src/types/extend-express.d.ts +16 -0
  241. package/src/types/function.ts +5 -0
  242. package/src/types/utilities.ts +22 -0
  243. package/src/utils.ts +53 -0
  244. package/tsconfig.json +29 -0
  245. package/dist/modules/subscription/subscriptionPlan.d.ts +0 -4
  246. package/dist/modules/subscription/subscriptionPlan.d.ts.map +0 -1
  247. package/dist/modules/subscription/subscriptionPlan.js +0 -67
  248. package/dist/modules/subscription/subscriptionPlan.js.map +0 -1
@@ -0,0 +1,193 @@
1
+ import { NestedPathsAccess } from '../../types/utilities';
2
+
3
+ type PaymentType = 'subscription' | 'token_pack' | 'subscription_upgrade';
4
+
5
+ type PaymentEntity = {
6
+ /** Auto-generated unique ID (document ID) */
7
+ id?: string;
8
+ /** The unique ID you generate and send to Wayforpay. This is the key to match incoming webhooks to a payment attempt. */
9
+ orderReference: string;
10
+ /** The ID of the user initiating the payment */
11
+ userId: string;
12
+ /** The state of this payment attempt */
13
+ status: 'pending' | 'completed' | 'failed' | 'expired';
14
+ /** The URL from Wayforpay that is sent to the user */
15
+ paymentLink: string;
16
+ /** The plan or pack ID the user is attempting to purchase */
17
+ planId: string;
18
+ /** The type of payment (subscription or token_pack) */
19
+ paymentType: PaymentType;
20
+ /** The amount to be charged */
21
+ amount: number;
22
+ /** Currency of the payment */
23
+ currency: 'UAH' | 'USD';
24
+ /** When this payment attempt was created */
25
+ createdAt: string;
26
+ /** Optional. The ID of the corresponding document in the invoices collection, added after the webhook is processed */
27
+ invoiceId?: string;
28
+ /** Platform/app namespace */
29
+ platform: string;
30
+ /** Payment provider */
31
+ provider: 'wayforpay';
32
+ };
33
+
34
+ type PaymentFieldPath = NestedPathsAccess<PaymentEntity>;
35
+
36
+ /**
37
+ * Interface for payment repository operations.
38
+ * Defines the contract for data access layer.
39
+ */
40
+ interface IPaymentRepository {
41
+ /**
42
+ * Retrieves a payment by its order reference.
43
+ */
44
+ getByOrderReference(orderReference: string): Promise<PaymentEntity | null>;
45
+
46
+ /**
47
+ * Retrieves all payments for a specific user.
48
+ */
49
+ getByUser(params: { userId: string; platform: string; status?: PaymentEntity['status'] }): Promise<PaymentEntity[]>;
50
+
51
+ /**
52
+ * Creates a new payment record in the database.
53
+ */
54
+ create(paymentData: Omit<PaymentEntity, 'id'>): Promise<PaymentEntity>;
55
+
56
+ /**
57
+ * Updates specific fields of a payment identified by order reference.
58
+ * @param params - Update parameters
59
+ */
60
+ updateFields(params: { id: string; fields: any }): Promise<void>;
61
+
62
+ /**
63
+ * Retrieves all pending payments that are older than specified hours.
64
+ * @param params - Query parameters
65
+ * @returns Promise resolving to array of expired PaymentEntity
66
+ */
67
+ getExpiredPendingPayments(params?: { hoursOld?: number }): Promise<PaymentEntity[]>;
68
+ }
69
+
70
+ /**
71
+ * Result of signature validation.
72
+ */
73
+ type SignatureValidationResult = {
74
+ isValid: boolean;
75
+ error?: string;
76
+ };
77
+
78
+ /**
79
+ * Interface for payment service operations.
80
+ * Defines the contract for business logic layer.
81
+ */
82
+ interface IPaymentService {
83
+ /**
84
+ * Retrieves a payment by its order reference.
85
+ * @param orderReference - The unique order reference identifier
86
+ * @returns Promise resolving to PaymentEntity or null if not found
87
+ */
88
+ getByOrderReference(orderReference: string): Promise<PaymentEntity | null>;
89
+
90
+ /**
91
+ * Retrieves all payments for a specific user.
92
+ * @param params - Query parameters
93
+ * @returns Promise resolving to array of PaymentEntity
94
+ */
95
+ getByUser(params: { userId: string; platform: string; status?: PaymentEntity['status'] }): Promise<PaymentEntity[]>;
96
+
97
+ /**
98
+ * Creates a new payment record in the database.
99
+ * @param paymentData - Payment data without ID
100
+ * @returns Promise resolving to created PaymentEntity with ID
101
+ */
102
+ create(paymentData: Omit<PaymentEntity, 'id'>): Promise<PaymentEntity>;
103
+
104
+ /**
105
+ * Updates the status of a payment.
106
+ * @param params - Update parameters containing id and new status
107
+ */
108
+ updateStatus(params: { id: string; status: PaymentEntity['status'] }): Promise<void>;
109
+
110
+ /**
111
+ * Updates specific fields of a payment.
112
+ * @param params - Update parameters
113
+ * @deprecated Use updateStatus instead for status changes
114
+ */
115
+ changeStatus(params: { id: string; status: PaymentEntity['status'] }): Promise<void>;
116
+
117
+ /**
118
+ * Retrieves all pending payments that are older than specified hours.
119
+ * @param params - Query parameters
120
+ * @returns Promise resolving to array of expired PaymentEntity
121
+ */
122
+ getExpiredPendingPayments(params?: { hoursOld?: number }): Promise<PaymentEntity[]>;
123
+
124
+ /**
125
+ * Creates a payment intent for a user subscription.
126
+ * @param params - Payment intent parameters
127
+ * @returns Promise resolving to the created PaymentEntity with payment link
128
+ */
129
+ createPaymentIntent(params: {
130
+ userId: string;
131
+ platform: string;
132
+ planId: string;
133
+ productName: string;
134
+ productPrice: number;
135
+ currency: 'UAH' | 'USD';
136
+ regularCount?: number;
137
+ regularMode?: 'daily' | 'weekly' | 'monthly' | 'yearly';
138
+ language?: string;
139
+ }): Promise<PaymentEntity>;
140
+
141
+ /**
142
+ * Creates a payment intent for a token pack purchase.
143
+ * @param params - Payment intent parameters
144
+ * @returns Promise resolving to the created PaymentEntity with payment link
145
+ */
146
+ createTokenPackPaymentIntent(params: {
147
+ userId: string;
148
+ platform: string;
149
+ packId: string;
150
+ productName: string;
151
+ productPrice: number;
152
+ currency: 'UAH' | 'USD';
153
+ language?: string;
154
+ returnUrl?: string;
155
+ }): Promise<PaymentEntity>;
156
+
157
+ /**
158
+ * Validates the signature of payment callback data.
159
+ * @param callbackData - The callback data from the payment provider
160
+ * @returns Validation result indicating if signature is valid
161
+ */
162
+ validateSignature(callbackData: {
163
+ merchantAccount: string;
164
+ orderReference: string;
165
+ amount: number;
166
+ currency: string;
167
+ authCode: string;
168
+ cardPan: string;
169
+ transactionStatus: string;
170
+ reasonCode: string | number;
171
+ merchantSignature: string;
172
+ }): SignatureValidationResult;
173
+
174
+ /**
175
+ * Creates a payment intent for a subscription upgrade.
176
+ * @param params - Payment intent parameters
177
+ * @returns Promise resolving to the created PaymentEntity with payment link
178
+ */
179
+ createUpgradePaymentIntent(params: {
180
+ userId: string;
181
+ platform: string;
182
+ currentPlanId: string;
183
+ newPlanId: string;
184
+ productName: string;
185
+ upgradeCost: number;
186
+ currency: 'UAH' | 'USD';
187
+ regularMode?: 'daily' | 'monthly' | 'yearly';
188
+ regularCount?: number;
189
+ language?: string;
190
+ }): Promise<PaymentEntity>;
191
+ }
192
+
193
+ export type { PaymentEntity, PaymentType, PaymentFieldPath, IPaymentRepository, IPaymentService, SignatureValidationResult };
@@ -0,0 +1,428 @@
1
+ /**
2
+ * Payment type for order references
3
+ */
4
+ type OrderReferencePaymentType = 'sub' | 'tkn' | 'upg';
5
+
6
+ /**
7
+ * Parameters for creating a subscription order reference
8
+ */
9
+ interface CreateSubscriptionOrderReferenceParams {
10
+ userId: string;
11
+ platform: string;
12
+ planId: string;
13
+ utcDate: string;
14
+ }
15
+
16
+ /**
17
+ * Parameters for creating a token pack order reference
18
+ */
19
+ interface CreateTokenPackOrderReferenceParams {
20
+ userId: string;
21
+ platform: string;
22
+ packId: string;
23
+ utcDate: string;
24
+ }
25
+
26
+ /**
27
+ * Parameters for creating an upgrade order reference
28
+ */
29
+ interface CreateUpgradeOrderReferenceParams {
30
+ userId: string;
31
+ platform: string;
32
+ currentPlanId: string;
33
+ newPlanId: string;
34
+ utcDate: string;
35
+ }
36
+
37
+ /**
38
+ * Parsed upgrade order reference
39
+ */
40
+ interface ParsedUpgradeOrderReference {
41
+ appName: string;
42
+ platform: string;
43
+ serviceType: string;
44
+ userId: string;
45
+ paymentType: 'upg';
46
+ currentPlanId: string;
47
+ newPlanId: string;
48
+ version: string;
49
+ timestamp: string;
50
+ }
51
+
52
+ /**
53
+ * Parsed order reference with payment type discrimination
54
+ */
55
+ interface ParsedOrderReference {
56
+ appName: string;
57
+ platform: string;
58
+ serviceType: string;
59
+ userId: string;
60
+ /** Payment type: 'sub' for subscription, 'tkn' for token pack */
61
+ paymentType: OrderReferencePaymentType;
62
+ /** Plan ID for subscriptions, Pack ID for token packs */
63
+ itemId: string;
64
+ version: string;
65
+ timestamp: string;
66
+ chargeId?: string;
67
+ }
68
+
69
+ /**
70
+ * Legacy parsed reference string (backward compatibility)
71
+ */
72
+ interface ParsedReferenceString {
73
+ appName: string;
74
+ platform: string;
75
+ serviceType: string;
76
+ userId: string;
77
+ planId: string;
78
+ version: string;
79
+ timestamp: string;
80
+ chargeId?: string;
81
+ }
82
+
83
+ const ORDER_REFERENCE_VERSION = 'v2';
84
+ const ORDER_REFERENCE_APP_NAME = 'miia';
85
+ const ORDER_REFERENCE_SERVICE_TYPE = 'bot';
86
+
87
+ /**
88
+ * Creates a unique order reference for subscription payments.
89
+ * Format: miia_{platform}_bot_{userId}_sub_{planId}_v2_{utcDate}
90
+ *
91
+ * @param params - Parameters for generating the order reference
92
+ * @returns A unique order reference string
93
+ */
94
+ function createSubscriptionOrderReference({
95
+ userId,
96
+ platform,
97
+ planId,
98
+ utcDate,
99
+ }: CreateSubscriptionOrderReferenceParams): string {
100
+ return `${ORDER_REFERENCE_APP_NAME}_${platform}_${ORDER_REFERENCE_SERVICE_TYPE}_${userId}_sub_${planId}_${ORDER_REFERENCE_VERSION}_${utcDate}`;
101
+ }
102
+
103
+ /**
104
+ * Creates a unique order reference for token pack payments.
105
+ * Format: miia_{platform}_bot_{userId}_tkn_{packId}_v2_{utcDate}
106
+ *
107
+ * @param params - Parameters for generating the order reference
108
+ * @returns A unique order reference string
109
+ */
110
+ function createTokenPackOrderReference({
111
+ userId,
112
+ platform,
113
+ packId,
114
+ utcDate,
115
+ }: CreateTokenPackOrderReferenceParams): string {
116
+ return `${ORDER_REFERENCE_APP_NAME}_${platform}_${ORDER_REFERENCE_SERVICE_TYPE}_${userId}_tkn_${packId}_${ORDER_REFERENCE_VERSION}_${utcDate}`;
117
+ }
118
+
119
+ /**
120
+ * Creates a unique order reference for subscription upgrade payments.
121
+ * Format: miia_{platform}_bot_{userId}_upg_{currentPlanId}_to_{newPlanId}_v2_{utcDate}
122
+ *
123
+ * @param params - Parameters for generating the order reference
124
+ * @returns A unique order reference string
125
+ */
126
+ function createUpgradeOrderReference({
127
+ userId,
128
+ platform,
129
+ currentPlanId,
130
+ newPlanId,
131
+ utcDate,
132
+ }: CreateUpgradeOrderReferenceParams): string {
133
+ return `${ORDER_REFERENCE_APP_NAME}_${platform}_${ORDER_REFERENCE_SERVICE_TYPE}_${userId}_upg_${currentPlanId}_to_${newPlanId}_${ORDER_REFERENCE_VERSION}_${utcDate}`;
134
+ }
135
+
136
+ /**
137
+ * Checks if an order reference is for a subscription payment.
138
+ *
139
+ * @param orderReference - The order reference string to check
140
+ * @returns True if the order reference is for a subscription
141
+ */
142
+ function isSubscriptionOrderReference(orderReference: string): boolean {
143
+ const parsed = parseOrderReference(orderReference);
144
+ if (!parsed) return false;
145
+
146
+ // v2 format with explicit type
147
+ if ('paymentType' in parsed && parsed.paymentType === 'sub') {
148
+ return true;
149
+ }
150
+
151
+ // v1 legacy format (all were subscriptions)
152
+ if (parsed.version === 'v1') {
153
+ return true;
154
+ }
155
+
156
+ return false;
157
+ }
158
+
159
+ /**
160
+ * Checks if an order reference is for a token pack payment.
161
+ *
162
+ * @param orderReference - The order reference string to check
163
+ * @returns True if the order reference is for a token pack
164
+ */
165
+ function isTokenPackOrderReference(orderReference: string): boolean {
166
+ const parsed = parseOrderReference(orderReference);
167
+ if (!parsed) return false;
168
+
169
+ return 'paymentType' in parsed && parsed.paymentType === 'tkn';
170
+ }
171
+
172
+ /**
173
+ * Checks if an order reference is for a subscription upgrade payment.
174
+ *
175
+ * @param orderReference - The order reference string to check
176
+ * @returns True if the order reference is for an upgrade
177
+ */
178
+ function isUpgradeOrderReference(orderReference: string): boolean {
179
+ const parsed = parseOrderReference(orderReference);
180
+ if (!parsed) return false;
181
+
182
+ return 'paymentType' in parsed && parsed.paymentType === 'upg';
183
+ }
184
+
185
+ /**
186
+ * Parses an upgrade order reference to extract both plan IDs.
187
+ *
188
+ * @param orderReference - The order reference string to parse
189
+ * @returns Parsed upgrade reference with currentPlanId and newPlanId, or null if invalid
190
+ */
191
+ function parseUpgradeOrderReference(orderReference: string): ParsedUpgradeOrderReference | null {
192
+ const parts = orderReference.split('_');
193
+
194
+ // Format: miia_{platform}_bot_{userId}_upg_{currentPlanId}_to_{newPlanId}_v2_{timestamp}
195
+ // Minimum parts: appName, platform, serviceType, userId, upg, currentPlanId, to, newPlanId, version, timestamp
196
+ if (parts.length < 10) {
197
+ return null;
198
+ }
199
+
200
+ const [appName, platform, serviceType, userId, paymentType] = parts;
201
+
202
+ if (paymentType !== 'upg') {
203
+ return null;
204
+ }
205
+
206
+ // Find the 'to' separator to extract plan IDs
207
+ const toIndex = parts.indexOf('to', 5);
208
+ if (toIndex === -1) {
209
+ return null;
210
+ }
211
+
212
+ // currentPlanId is between 'upg' (index 4) and 'to'
213
+ const currentPlanId = parts.slice(5, toIndex).join('_');
214
+
215
+ // newPlanId is between 'to' and version (which starts with 'v')
216
+ // Find the version index (starts with 'v' and is followed by a number)
217
+ let versionIndex = -1;
218
+ for (let i = toIndex + 1; i < parts.length; i++) {
219
+ if (parts[i].match(/^v\d+$/)) {
220
+ versionIndex = i;
221
+ break;
222
+ }
223
+ }
224
+
225
+ if (versionIndex === -1) {
226
+ return null;
227
+ }
228
+
229
+ const newPlanId = parts.slice(toIndex + 1, versionIndex).join('_');
230
+ const version = parts[versionIndex];
231
+ const timestamp = parts.slice(versionIndex + 1).join('_');
232
+
233
+ return {
234
+ appName,
235
+ platform,
236
+ serviceType,
237
+ userId,
238
+ paymentType: 'upg',
239
+ currentPlanId,
240
+ newPlanId,
241
+ version,
242
+ timestamp,
243
+ };
244
+ }
245
+
246
+ /**
247
+ * Extracts the payment type from an order reference.
248
+ *
249
+ * @param orderReference - The order reference string
250
+ * @returns The payment type ('sub' or 'tkn'), or null if invalid
251
+ */
252
+ function getOrderReferencePaymentType(orderReference: string): OrderReferencePaymentType | null {
253
+ const parsed = parseOrderReference(orderReference);
254
+ if (!parsed) return null;
255
+
256
+ if ('paymentType' in parsed) {
257
+ return parsed.paymentType;
258
+ }
259
+
260
+ // v1 legacy format was always subscription
261
+ if (parsed.version === 'v1') {
262
+ return 'sub';
263
+ }
264
+
265
+ return null;
266
+ }
267
+
268
+ /**
269
+ * Extracts the item ID (plan ID or pack ID) from an order reference.
270
+ *
271
+ * @param orderReference - The order reference string
272
+ * @returns The item ID, or null if invalid
273
+ */
274
+ function getOrderReferenceItemId(orderReference: string): string | null {
275
+ const parsed = parseOrderReference(orderReference);
276
+ if (!parsed) return null;
277
+
278
+ if ('itemId' in parsed) {
279
+ return parsed.itemId;
280
+ }
281
+
282
+ // v1 legacy format
283
+ if ('planId' in parsed) {
284
+ return parsed.planId;
285
+ }
286
+
287
+ return null;
288
+ }
289
+
290
+ /**
291
+ * Extracts the user ID from an order reference.
292
+ *
293
+ * @param orderReference - The order reference string
294
+ * @returns The user ID, or null if invalid
295
+ */
296
+ function getOrderReferenceUserId(orderReference: string): string | null {
297
+ const parsed = parseOrderReference(orderReference);
298
+ return parsed?.userId ?? null;
299
+ }
300
+
301
+ /**
302
+ * Parses an order reference string into its components.
303
+ * Supports both v1 (legacy) and v2 (new) formats.
304
+ *
305
+ * v1 format: miia_{platform}_bot_{userId}_{planId}_v1_{timestamp}
306
+ * v2 format: miia_{platform}_bot_{userId}_{type}_{itemId}_v2_{timestamp}
307
+ *
308
+ * @param referenceString - The order reference string to parse
309
+ * @returns Parsed reference object or null if invalid
310
+ */
311
+ function parseOrderReference(referenceString: string): (ParsedOrderReference | ParsedReferenceString) | null {
312
+ const parts = referenceString.split('_');
313
+
314
+ // Minimum parts: appName, platform, serviceType, userId, planId/type, version, timestamp
315
+ if (parts.length < 7) {
316
+ return null;
317
+ }
318
+
319
+ const [appName, platform, serviceType, userId] = parts;
320
+
321
+ // Validate required fields
322
+ if (
323
+ typeof appName !== 'string' ||
324
+ typeof platform !== 'string' ||
325
+ typeof serviceType !== 'string' ||
326
+ typeof userId !== 'string'
327
+ ) {
328
+ return null;
329
+ }
330
+
331
+ // Check for v2 format (has payment type indicator)
332
+ const potentialType = parts[4];
333
+ const isV2Format = potentialType === 'sub' || potentialType === 'tkn' || potentialType === 'upg';
334
+
335
+ // Handle upgrade references separately (they have a different structure)
336
+ if (potentialType === 'upg') {
337
+ const upgradeParsed = parseUpgradeOrderReference(referenceString);
338
+ if (upgradeParsed) {
339
+ return {
340
+ appName: upgradeParsed.appName,
341
+ platform: upgradeParsed.platform,
342
+ serviceType: upgradeParsed.serviceType,
343
+ userId: upgradeParsed.userId,
344
+ paymentType: 'upg',
345
+ itemId: upgradeParsed.newPlanId, // Use newPlanId as itemId for compatibility
346
+ version: upgradeParsed.version,
347
+ timestamp: upgradeParsed.timestamp,
348
+ };
349
+ }
350
+ return null;
351
+ }
352
+
353
+ if (isV2Format) {
354
+ // v2 format: miia_{platform}_bot_{userId}_{type}_{itemId}_v2_{timestamp}[_{chargeId}]
355
+ const [, , , , paymentType, itemId, version, timestamp, chargeId] = parts;
356
+
357
+ if (
358
+ typeof paymentType !== 'string' ||
359
+ typeof itemId !== 'string' ||
360
+ typeof version !== 'string' ||
361
+ typeof timestamp !== 'string'
362
+ ) {
363
+ return null;
364
+ }
365
+
366
+ return {
367
+ appName,
368
+ platform,
369
+ serviceType,
370
+ userId,
371
+ paymentType: paymentType as OrderReferencePaymentType,
372
+ itemId,
373
+ version,
374
+ timestamp,
375
+ chargeId,
376
+ };
377
+ }
378
+
379
+ // v1 legacy format: miia_{platform}_bot_{userId}_{planId}_v1_{timestamp}[_{chargeId}]
380
+ const [, , , , planId, version, timestamp, chargeId] = parts;
381
+
382
+ if (typeof planId !== 'string' || typeof version !== 'string' || typeof timestamp !== 'string') {
383
+ return null;
384
+ }
385
+
386
+ return {
387
+ appName,
388
+ platform,
389
+ serviceType,
390
+ userId,
391
+ planId,
392
+ version,
393
+ timestamp,
394
+ chargeId,
395
+ };
396
+ }
397
+
398
+ export type {
399
+ OrderReferencePaymentType,
400
+ CreateSubscriptionOrderReferenceParams,
401
+ CreateTokenPackOrderReferenceParams,
402
+ CreateUpgradeOrderReferenceParams,
403
+ ParsedOrderReference,
404
+ ParsedReferenceString,
405
+ ParsedUpgradeOrderReference,
406
+ };
407
+
408
+ export {
409
+ // Constants
410
+ ORDER_REFERENCE_VERSION,
411
+ ORDER_REFERENCE_APP_NAME,
412
+ ORDER_REFERENCE_SERVICE_TYPE,
413
+ // New v2 functions
414
+ createSubscriptionOrderReference,
415
+ createTokenPackOrderReference,
416
+ createUpgradeOrderReference,
417
+ // Type checking functions
418
+ isSubscriptionOrderReference,
419
+ isTokenPackOrderReference,
420
+ isUpgradeOrderReference,
421
+ getOrderReferencePaymentType,
422
+ getOrderReferenceItemId,
423
+ getOrderReferenceUserId,
424
+ // Upgrade-specific functions
425
+ parseUpgradeOrderReference,
426
+ // Legacy (backward compatible)
427
+ parseOrderReference,
428
+ };