@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.
- package/LICENSE +21 -0
- package/dist/app/api/stripe/checkout/route.d.ts +19 -0
- package/dist/app/api/stripe/checkout/route.d.ts.map +1 -0
- package/dist/app/api/stripe/checkout/route.js +120 -0
- package/dist/app/api/stripe/checkout/route.mjs +118 -0
- package/dist/app/api/stripe/customer-portal/route.d.ts +11 -0
- package/dist/app/api/stripe/customer-portal/route.d.ts.map +1 -0
- package/dist/app/api/stripe/customer-portal/route.js +73 -0
- package/dist/app/api/stripe/customer-portal/route.mjs +71 -0
- package/dist/app/api/user/anonymous/init/route.d.ts +7 -0
- package/dist/app/api/user/anonymous/init/route.d.ts.map +1 -0
- package/dist/app/api/user/anonymous/init/route.js +210 -0
- package/dist/app/api/user/anonymous/init/route.mjs +208 -0
- package/dist/app/api/webhook/clerk/user/route.d.ts +7 -0
- package/dist/app/api/webhook/clerk/user/route.d.ts.map +1 -0
- package/dist/app/api/webhook/clerk/user/route.js +202 -0
- package/dist/app/api/webhook/clerk/user/route.mjs +200 -0
- package/dist/app/api/webhook/stripe/route.d.ts +8 -0
- package/dist/app/api/webhook/stripe/route.d.ts.map +1 -0
- package/dist/app/api/webhook/stripe/route.js +70 -0
- package/dist/app/api/webhook/stripe/route.mjs +67 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +83 -0
- package/dist/index.mjs +18 -0
- package/dist/lib/auth-utils.d.ts +46 -0
- package/dist/lib/auth-utils.d.ts.map +1 -0
- package/dist/lib/auth-utils.js +107 -0
- package/dist/lib/auth-utils.mjs +102 -0
- package/dist/lib/credit-init.d.ts +8 -0
- package/dist/lib/credit-init.d.ts.map +1 -0
- package/dist/lib/credit-init.js +16 -0
- package/dist/lib/credit-init.mjs +10 -0
- package/dist/lib/index.d.ts +5 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +31 -0
- package/dist/lib/index.mjs +4 -0
- package/dist/lib/money-price-config.d.ts +51 -0
- package/dist/lib/money-price-config.d.ts.map +1 -0
- package/dist/lib/money-price-config.js +156 -0
- package/dist/lib/money-price-config.mjs +151 -0
- package/dist/lib/stripe-config.d.ts +31 -0
- package/dist/lib/stripe-config.d.ts.map +1 -0
- package/dist/lib/stripe-config.js +278 -0
- package/dist/lib/stripe-config.mjs +268 -0
- 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
- 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
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.js +54 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.mjs +51 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.js +44 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.mjs +35 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.js +31 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.mjs +18 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.js +587 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.mjs +527 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.js +447 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.mjs +399 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.js +245 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.mjs +232 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.js +68 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.mjs +62 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.js +39 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.mjs +37 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.js +80 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.mjs +75 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.js +101 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.mjs +86 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.js +102 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.mjs +76 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.js +56 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.mjs +52 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.js +1205 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.mjs +1157 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.js +407 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.mjs +374 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.js +9 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.mjs +7 -0
- package/dist/prisma/client.d.ts +2 -0
- package/dist/prisma/client.d.ts.map +1 -0
- package/dist/prisma/client.js +12 -0
- package/dist/prisma/client.mjs +1 -0
- package/dist/prisma/index.d.ts +4 -0
- package/dist/prisma/index.d.ts.map +1 -0
- package/dist/prisma/index.js +10 -0
- package/dist/prisma/index.mjs +2 -0
- package/dist/prisma/prisma-transaction-util.d.ts +3 -0
- package/dist/prisma/prisma-transaction-util.d.ts.map +1 -0
- package/dist/prisma/prisma-transaction-util.js +29 -0
- package/dist/prisma/prisma-transaction-util.mjs +27 -0
- package/dist/prisma/prisma.d.ts +4 -0
- package/dist/prisma/prisma.d.ts.map +1 -0
- package/dist/prisma/prisma.js +109 -0
- package/dist/prisma/prisma.mjs +106 -0
- package/dist/services/aggregate/billing.aggregate.service.d.ts +83 -0
- package/dist/services/aggregate/billing.aggregate.service.d.ts.map +1 -0
- package/dist/services/aggregate/billing.aggregate.service.js +308 -0
- package/dist/services/aggregate/billing.aggregate.service.mjs +306 -0
- package/dist/services/aggregate/index.d.ts +3 -0
- package/dist/services/aggregate/index.d.ts.map +1 -0
- package/dist/services/aggregate/index.js +9 -0
- package/dist/services/aggregate/index.mjs +2 -0
- package/dist/services/aggregate/user.aggregate.service.d.ts +34 -0
- package/dist/services/aggregate/user.aggregate.service.d.ts.map +1 -0
- package/dist/services/aggregate/user.aggregate.service.js +136 -0
- package/dist/services/aggregate/user.aggregate.service.mjs +133 -0
- package/dist/services/context/index.d.ts +2 -0
- package/dist/services/context/index.d.ts.map +1 -0
- package/dist/services/context/index.js +13 -0
- package/dist/services/context/index.mjs +1 -0
- package/dist/services/context/user-context-service.d.ts +30 -0
- package/dist/services/context/user-context-service.d.ts.map +1 -0
- package/dist/services/context/user-context-service.js +170 -0
- package/dist/services/context/user-context-service.mjs +162 -0
- package/dist/services/database/apilog.service.d.ts +39 -0
- package/dist/services/database/apilog.service.d.ts.map +1 -0
- package/dist/services/database/apilog.service.js +174 -0
- package/dist/services/database/apilog.service.mjs +170 -0
- package/dist/services/database/constants.d.ts +73 -0
- package/dist/services/database/constants.d.ts.map +1 -0
- package/dist/services/database/constants.js +135 -0
- package/dist/services/database/constants.mjs +117 -0
- package/dist/services/database/credit.service.d.ts +107 -0
- package/dist/services/database/credit.service.d.ts.map +1 -0
- package/dist/services/database/credit.service.js +515 -0
- package/dist/services/database/credit.service.mjs +512 -0
- package/dist/services/database/creditAuditLog.service.d.ts +73 -0
- package/dist/services/database/creditAuditLog.service.d.ts.map +1 -0
- package/dist/services/database/creditAuditLog.service.js +305 -0
- package/dist/services/database/creditAuditLog.service.mjs +302 -0
- package/dist/services/database/index.d.ts +10 -0
- package/dist/services/database/index.d.ts.map +1 -0
- package/dist/services/database/index.js +38 -0
- package/dist/services/database/index.mjs +8 -0
- package/dist/services/database/prisma-model-type.d.ts +3 -0
- package/dist/services/database/prisma-model-type.d.ts.map +1 -0
- package/dist/services/database/subscription.service.d.ts +48 -0
- package/dist/services/database/subscription.service.d.ts.map +1 -0
- package/dist/services/database/subscription.service.js +267 -0
- package/dist/services/database/subscription.service.mjs +264 -0
- package/dist/services/database/transaction.service.d.ts +92 -0
- package/dist/services/database/transaction.service.d.ts.map +1 -0
- package/dist/services/database/transaction.service.js +326 -0
- package/dist/services/database/transaction.service.mjs +323 -0
- package/dist/services/database/user.service.d.ts +45 -0
- package/dist/services/database/user.service.d.ts.map +1 -0
- package/dist/services/database/user.service.js +180 -0
- package/dist/services/database/user.service.mjs +177 -0
- package/dist/services/database/userBackup.service.d.ts +45 -0
- package/dist/services/database/userBackup.service.d.ts.map +1 -0
- package/dist/services/database/userBackup.service.js +249 -0
- package/dist/services/database/userBackup.service.mjs +246 -0
- package/dist/services/stripe/index.d.ts +2 -0
- package/dist/services/stripe/index.d.ts.map +1 -0
- package/dist/services/stripe/index.js +7 -0
- package/dist/services/stripe/index.mjs +1 -0
- package/dist/services/stripe/webhook-handler.d.ts +6 -0
- package/dist/services/stripe/webhook-handler.d.ts.map +1 -0
- package/dist/services/stripe/webhook-handler.js +537 -0
- package/dist/services/stripe/webhook-handler.mjs +535 -0
- package/migrations/create.sql +176 -0
- package/migrations/db.init.sql +13 -0
- package/migrations/init-schema.sql +19 -0
- package/migrations/purge.sql +27 -0
- package/migrations/test-check.sql +167 -0
- package/package.json +123 -0
- package/prisma/schema.prisma +191 -0
- package/src/app/api/stripe/checkout/route.ts +145 -0
- package/src/app/api/stripe/customer-portal/route.ts +83 -0
- package/src/app/api/user/anonymous/init/route.ts +284 -0
- package/src/app/api/webhook/clerk/user/route.ts +249 -0
- package/src/app/api/webhook/stripe/route.ts +93 -0
- package/src/index.ts +6 -0
- package/src/lib/auth-utils.ts +101 -0
- package/src/lib/credit-init.ts +9 -0
- package/src/lib/index.ts +4 -0
- package/src/lib/money-price-config.ts +168 -0
- package/src/lib/stripe-config.ts +333 -0
- package/src/prisma/client.ts +2 -0
- package/src/prisma/index.ts +3 -0
- package/src/prisma/prisma-transaction-util.ts +24 -0
- package/src/prisma/prisma.ts +122 -0
- package/src/services/aggregate/billing.aggregate.service.ts +498 -0
- package/src/services/aggregate/index.ts +2 -0
- package/src/services/aggregate/user.aggregate.service.ts +168 -0
- package/src/services/context/index.ts +1 -0
- package/src/services/context/user-context-service.ts +200 -0
- package/src/services/database/apilog.service.ts +185 -0
- package/src/services/database/constants.ts +148 -0
- package/src/services/database/credit.service.ts +747 -0
- package/src/services/database/creditAuditLog.service.ts +402 -0
- package/src/services/database/index.ts +41 -0
- package/src/services/database/prisma-model-type.ts +13 -0
- package/src/services/database/subscription.service.ts +319 -0
- package/src/services/database/transaction.service.ts +447 -0
- package/src/services/database/user.service.ts +218 -0
- package/src/services/database/userBackup.service.ts +290 -0
- package/src/services/stripe/index.ts +1 -0
- package/src/services/stripe/webhook-handler.ts +648 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import { __awaiter } from '../../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';
|
|
2
|
+
import { OrderStatus, TransactionType, BillingReason, PaymentStatus } from '../database/constants.mjs';
|
|
3
|
+
import '../../prisma/prisma.mjs';
|
|
4
|
+
import { subscriptionService } from '../database/subscription.service.mjs';
|
|
5
|
+
import '../database/credit.service.mjs';
|
|
6
|
+
import { transactionService } from '../database/transaction.service.mjs';
|
|
7
|
+
import '@prisma/client';
|
|
8
|
+
import { Apilogger } from '../database/apilog.service.mjs';
|
|
9
|
+
import { oneTimeExpiredDays } from '../../lib/credit-init.mjs';
|
|
10
|
+
import { billingAggregateService } from '../aggregate/billing.aggregate.service.mjs';
|
|
11
|
+
import { getCreditsFromPriceId } from '../../lib/money-price-config.mjs';
|
|
12
|
+
import { stripe, fetchPaymentId } from '../../lib/stripe-config.mjs';
|
|
13
|
+
import { viewLocalTime } from '@windrun-huaiin/lib/utils';
|
|
14
|
+
|
|
15
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
16
|
+
const mapPaymentStatus = (status) => {
|
|
17
|
+
switch (status) {
|
|
18
|
+
case 'paid':
|
|
19
|
+
return PaymentStatus.PAID;
|
|
20
|
+
case 'no_payment_required':
|
|
21
|
+
return PaymentStatus.NO_PAYMENT_REQUIRED;
|
|
22
|
+
case 'unpaid':
|
|
23
|
+
default:
|
|
24
|
+
return PaymentStatus.UN_PAID;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const isPaymentSettled = (paymentStatus) => paymentStatus === PaymentStatus.PAID || paymentStatus === PaymentStatus.NO_PAYMENT_REQUIRED;
|
|
28
|
+
/**
|
|
29
|
+
* Main event handler - routes events to specific handlers
|
|
30
|
+
*/
|
|
31
|
+
function handleStripeEvent(event) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
console.log(`Processing Stripe event: ${event.type}`);
|
|
34
|
+
try {
|
|
35
|
+
switch (event.type) {
|
|
36
|
+
// ===== Checkout Events =====
|
|
37
|
+
case 'checkout.session.completed':
|
|
38
|
+
return yield handleCheckoutCompleted(event.data.object);
|
|
39
|
+
case 'checkout.session.async_payment_succeeded':
|
|
40
|
+
return yield handleAsyncPaymentSucceeded(event.data.object);
|
|
41
|
+
case 'checkout.session.async_payment_failed':
|
|
42
|
+
return yield handleAsyncPaymentFailed(event.data.object);
|
|
43
|
+
// ===== Invoice Events (Subscription renewals) =====
|
|
44
|
+
case 'invoice.paid':
|
|
45
|
+
return yield handleInvoicePaid(event.data.object);
|
|
46
|
+
case 'invoice.payment_failed':
|
|
47
|
+
return yield handleInvoicePaymentFailed(event.data.object);
|
|
48
|
+
// ===== Subscription Events =====
|
|
49
|
+
case 'customer.subscription.created':
|
|
50
|
+
return yield handleSubscriptionCreated(event.data.object);
|
|
51
|
+
case 'customer.subscription.updated':
|
|
52
|
+
return yield handleSubscriptionUpdated(event.data.object);
|
|
53
|
+
case 'customer.subscription.deleted':
|
|
54
|
+
return yield handleSubscriptionDeleted(event.data.object);
|
|
55
|
+
// ===== Payment Intent Events (One-time payments) =====
|
|
56
|
+
case 'payment_intent.succeeded':
|
|
57
|
+
console.log(`Payment Intent succeeded: ${event.data.object.id}`);
|
|
58
|
+
// Usually handled by checkout.session.completed
|
|
59
|
+
return;
|
|
60
|
+
case 'payment_intent.payment_failed':
|
|
61
|
+
console.log(`Payment Intent failed: ${event.data.object.id}`);
|
|
62
|
+
return;
|
|
63
|
+
// ===== Refund Events =====
|
|
64
|
+
case 'charge.refunded':
|
|
65
|
+
return yield handleChargeRefunded(event.data.object);
|
|
66
|
+
default:
|
|
67
|
+
console.log(`Unhandled event type: ${event.type}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error(`Error processing event ${event.type}:`, error);
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function handleCheckoutCompleted(session) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
var _a;
|
|
79
|
+
console.log(`Checkout session completed: ${session.id}`);
|
|
80
|
+
// 1. Get transaction by session ID or order ID
|
|
81
|
+
const orderId = (_a = session.metadata) === null || _a === void 0 ? void 0 : _a.order_id;
|
|
82
|
+
if (!orderId) {
|
|
83
|
+
throw new Error('Missing order_id in session metadata');
|
|
84
|
+
}
|
|
85
|
+
const transaction = yield transactionService.findByOrderId(orderId);
|
|
86
|
+
if (!transaction) {
|
|
87
|
+
throw new Error(`Transaction not found: ${orderId}`);
|
|
88
|
+
}
|
|
89
|
+
if (transaction.orderStatus === OrderStatus.SUCCESS) {
|
|
90
|
+
throw new Error(`Transaction already processed successfully: ${transaction.orderId}, skipping.`);
|
|
91
|
+
}
|
|
92
|
+
// Stripe docs: checkout.session.completed fires even when payment is pending for async methods
|
|
93
|
+
// https://stripe.com/docs/payments/checkout/one-time#webhooks
|
|
94
|
+
const paymentStatus = mapPaymentStatus(session.payment_status);
|
|
95
|
+
if (!isPaymentSettled(paymentStatus)) {
|
|
96
|
+
console.log(`Checkout session ${session.id} payment incomplete (status=${session.payment_status}), awaiting async confirmation.`);
|
|
97
|
+
if (transaction.orderStatus === OrderStatus.CREATED ||
|
|
98
|
+
transaction.orderStatus === OrderStatus.PENDING_UNPAID) {
|
|
99
|
+
yield transactionService.updateStatus(orderId, OrderStatus.PENDING_UNPAID, {
|
|
100
|
+
payUpdatedAt: new Date(),
|
|
101
|
+
paymentStatus,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// 2. Route based on transaction type
|
|
107
|
+
if (transaction.type === TransactionType.SUBSCRIPTION) {
|
|
108
|
+
// For subscriptions, store session info and wait for invoice.paid
|
|
109
|
+
return yield handleSubscriptionCheckoutInit(session, transaction);
|
|
110
|
+
}
|
|
111
|
+
return yield handleOneTimeCheckout(session, transaction, paymentStatus);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function handleSubscriptionCheckoutInit(session, transaction) {
|
|
115
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
116
|
+
var _a, _b, _c, _d;
|
|
117
|
+
console.log(`Processing subscription checkout: ${session.id}`);
|
|
118
|
+
// 1. Get subscription ID from session
|
|
119
|
+
if (!session.subscription) {
|
|
120
|
+
throw new Error('No subscription ID in checkout session');
|
|
121
|
+
}
|
|
122
|
+
const subscriptionId = session.subscription;
|
|
123
|
+
// ===== STEP 1: FETCH EXTERNAL API DATA (BEFORE TRANSACTION) =====
|
|
124
|
+
// 2. Get COMPLETE Stripe subscription details including billing period
|
|
125
|
+
const stripeSubscription = yield stripe.subscriptions.retrieve(subscriptionId);
|
|
126
|
+
// Extract billing period from subscription items (NOT from top-level subscription object)
|
|
127
|
+
// The current_period_start/end are on SubscriptionItem, not on Subscription
|
|
128
|
+
const subscriptionItem = (_b = (_a = stripeSubscription.items) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b[0];
|
|
129
|
+
if (!subscriptionItem) {
|
|
130
|
+
throw new Error(`No subscription items found for subscription ${subscriptionId}`);
|
|
131
|
+
}
|
|
132
|
+
const currentPeriodStart = subscriptionItem.current_period_start;
|
|
133
|
+
const currentPeriodEnd = subscriptionItem.current_period_end;
|
|
134
|
+
if (!currentPeriodStart || !currentPeriodEnd) {
|
|
135
|
+
throw new Error(`Invalid subscription period from Stripe API: start=${currentPeriodStart}, end=${currentPeriodEnd}`);
|
|
136
|
+
}
|
|
137
|
+
const subPeriodStart = new Date(currentPeriodStart * 1000);
|
|
138
|
+
const subPeriodEnd = new Date(currentPeriodEnd * 1000);
|
|
139
|
+
// Log the Stripe API response with correct data structure
|
|
140
|
+
const logId = yield Apilogger.logStripeOutgoing('stripe.subscriptions.retrieve', { subscriptionId }, {
|
|
141
|
+
id: stripeSubscription.id,
|
|
142
|
+
status: stripeSubscription.status,
|
|
143
|
+
subPeriodStart: subPeriodStart,
|
|
144
|
+
subPeriodEnd: subPeriodEnd,
|
|
145
|
+
subscriptionItemCount: ((_d = (_c = stripeSubscription.items) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.length) || 0,
|
|
146
|
+
});
|
|
147
|
+
Apilogger.updateResponse(logId, stripeSubscription);
|
|
148
|
+
console.log('Subscription checkout completed, just log:', {
|
|
149
|
+
id: subscriptionId,
|
|
150
|
+
orderId: transaction.orderId,
|
|
151
|
+
status: stripeSubscription.status,
|
|
152
|
+
periodStart: viewLocalTime(subPeriodStart),
|
|
153
|
+
periodEnd: viewLocalTime(subPeriodEnd),
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function handleOneTimeCheckout(session, transaction, paymentStatus) {
|
|
158
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
159
|
+
var _a;
|
|
160
|
+
console.log(`Processing one-time payment checkout: ${session.id}`);
|
|
161
|
+
// 1. Calculate one-time credit expiration
|
|
162
|
+
const now = new Date();
|
|
163
|
+
const oneTimePaidStart = now;
|
|
164
|
+
const oneTimePaidEnd = new Date(now);
|
|
165
|
+
oneTimePaidEnd.setDate(oneTimePaidEnd.getDate() + oneTimeExpiredDays);
|
|
166
|
+
oneTimePaidEnd.setHours(23, 59, 59, 999);
|
|
167
|
+
yield billingAggregateService.completeOneTimeCheckout({
|
|
168
|
+
userId: transaction.userId,
|
|
169
|
+
orderId: transaction.orderId,
|
|
170
|
+
creditsGranted: transaction.creditsGranted || 0,
|
|
171
|
+
paymentStatus,
|
|
172
|
+
payTransactionId: session.payment_intent,
|
|
173
|
+
paidEmail: (_a = session.customer_details) === null || _a === void 0 ? void 0 : _a.email,
|
|
174
|
+
paidAt: oneTimePaidStart,
|
|
175
|
+
oneTimePaidStart,
|
|
176
|
+
oneTimePaidEnd,
|
|
177
|
+
});
|
|
178
|
+
console.log(`One-time payment completed: ${transaction.orderId}`);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function handleInvoicePaid(invoice) {
|
|
182
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
183
|
+
var _a, _b, _c, _d, _e, _f;
|
|
184
|
+
console.log(`Invoice paid: ${invoice.id}`);
|
|
185
|
+
// ===== STEP 1: EXTRACT AND VALIDATE DATA FROM INVOICE (BEFORE TRANSACTION) =====
|
|
186
|
+
// 1. Get subscription details from invoice parent
|
|
187
|
+
const parentDetails = (_a = invoice.parent) === null || _a === void 0 ? void 0 : _a.subscription_details;
|
|
188
|
+
if (!(parentDetails === null || parentDetails === void 0 ? void 0 : parentDetails.subscription)) {
|
|
189
|
+
throw new Error('Invoice not associated with subscription, skipping');
|
|
190
|
+
}
|
|
191
|
+
// 2. Check billing reason to determine payment type
|
|
192
|
+
const isInitialPayment = invoice.billing_reason === BillingReason.SUBSCRIPTION_CREATE;
|
|
193
|
+
const isRenewal = invoice.billing_reason === BillingReason.SUBSCRIPTION_CYCLE;
|
|
194
|
+
// Only handle initial payments and renewals
|
|
195
|
+
if (!isInitialPayment && !isRenewal) {
|
|
196
|
+
throw new Error(`Unhandled invoice billing_reason: ${invoice.billing_reason}, skipping`);
|
|
197
|
+
}
|
|
198
|
+
// 3. Extract subscription period from invoice line items
|
|
199
|
+
const lineItem = (_c = (_b = invoice.lines) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c[0];
|
|
200
|
+
if (!lineItem) {
|
|
201
|
+
throw new Error(`No line items found in invoice ${invoice.id}`);
|
|
202
|
+
}
|
|
203
|
+
const periodStart = (_d = lineItem.period) === null || _d === void 0 ? void 0 : _d.start;
|
|
204
|
+
const periodEnd = (_e = lineItem.period) === null || _e === void 0 ? void 0 : _e.end;
|
|
205
|
+
if (!periodStart || !periodEnd) {
|
|
206
|
+
throw new Error(`Invalid period in invoice line: start=${periodStart}, end=${periodEnd}. Invoice ID: ${invoice.id}`);
|
|
207
|
+
}
|
|
208
|
+
const subPeriodStart = new Date(periodStart * 1000);
|
|
209
|
+
const subPeriodEnd = new Date(periodEnd * 1000);
|
|
210
|
+
const subscriptionMetadata = parentDetails.metadata || {};
|
|
211
|
+
const orderId = subscriptionMetadata.order_id;
|
|
212
|
+
if (!orderId) {
|
|
213
|
+
throw new Error(`No order_id in subscription metadata for initial invoice ${invoice.id}. ` + `Skipping invoice URL update.`);
|
|
214
|
+
}
|
|
215
|
+
const transaction = yield transactionService.findByOrderId(orderId);
|
|
216
|
+
if (!transaction) {
|
|
217
|
+
throw new Error(`Transaction not found for order_id: ${orderId}`);
|
|
218
|
+
}
|
|
219
|
+
const subscriptionId = parentDetails.subscription;
|
|
220
|
+
const userId = transaction.userId;
|
|
221
|
+
const paymentIntentId = yield fetchPaymentId(invoice.id);
|
|
222
|
+
const invoicePaidAt = (_f = invoice.status_transitions) === null || _f === void 0 ? void 0 : _f.paid_at;
|
|
223
|
+
const paidAt = invoicePaidAt ? new Date(invoicePaidAt * 1000) : new Date();
|
|
224
|
+
const paidEmail = invoice.customer_email;
|
|
225
|
+
console.log('Invoice paid event key-info:', {
|
|
226
|
+
invoiceId: invoice.id,
|
|
227
|
+
subscriptionId,
|
|
228
|
+
paymentIntentId,
|
|
229
|
+
billingReason: invoice.billing_reason,
|
|
230
|
+
isInitialPayment,
|
|
231
|
+
paidEmail,
|
|
232
|
+
paidAt: viewLocalTime(paidAt),
|
|
233
|
+
periodStart: viewLocalTime(subPeriodStart),
|
|
234
|
+
periodEnd: viewLocalTime(subPeriodEnd),
|
|
235
|
+
});
|
|
236
|
+
if (isInitialPayment) {
|
|
237
|
+
// 首次订阅校验
|
|
238
|
+
const nonActiveSubscription = yield subscriptionService.getNonActiveSubscription(userId);
|
|
239
|
+
if (!nonActiveSubscription) {
|
|
240
|
+
throw new Error(`Subscription status is ACTIVE for user ${userId}, forbidden to re-active!`);
|
|
241
|
+
}
|
|
242
|
+
yield billingAggregateService.recordSubscriptionInitPayment({
|
|
243
|
+
userId,
|
|
244
|
+
subIdKey: nonActiveSubscription.id,
|
|
245
|
+
orderId,
|
|
246
|
+
paySubscriptionId: subscriptionId,
|
|
247
|
+
creditsGranted: transaction.creditsGranted || 0,
|
|
248
|
+
priceId: transaction.priceId,
|
|
249
|
+
priceName: transaction.priceName,
|
|
250
|
+
periodStart: subPeriodStart,
|
|
251
|
+
periodEnd: subPeriodEnd,
|
|
252
|
+
invoiceId: invoice.id,
|
|
253
|
+
hostedInvoiceUrl: invoice.hosted_invoice_url,
|
|
254
|
+
invoicePdf: invoice.invoice_pdf,
|
|
255
|
+
billingReason: invoice.billing_reason,
|
|
256
|
+
paymentIntentId,
|
|
257
|
+
paidAt,
|
|
258
|
+
paidEmail
|
|
259
|
+
});
|
|
260
|
+
console.log(`Initial invoice recorded for transaction: ${orderId}`);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (isRenewal) {
|
|
264
|
+
// 续订时,一定要查到订阅记录
|
|
265
|
+
const subscription = yield subscriptionService.findByPaySubscriptionId(subscriptionId);
|
|
266
|
+
if (!subscription) {
|
|
267
|
+
throw new Error(`Subscription not found for renewal: ${subscriptionId}`);
|
|
268
|
+
}
|
|
269
|
+
const renewalOrderId = `order_renew_${invoice.id}`;
|
|
270
|
+
const existingOrder = yield transactionService.findByOrderId(renewalOrderId);
|
|
271
|
+
if (existingOrder) {
|
|
272
|
+
throw new Error(`Renewal invoice ${invoice.id} already processed as ${existingOrder.orderId}, skipping.`);
|
|
273
|
+
}
|
|
274
|
+
// Get credits from current price configuration (handles plan upgrades/downgrades)
|
|
275
|
+
// 优先从配置中取,取不到就以上个周期的为准作为Fallback,后续有问题再人工补偿,优先保证能用
|
|
276
|
+
// 只要配置正确,这里就不会出错!
|
|
277
|
+
const creditsForRenewal = subscription.priceId
|
|
278
|
+
? getCreditsFromPriceId(subscription.priceId)
|
|
279
|
+
: subscription.creditsAllocated;
|
|
280
|
+
const renewalCredits = creditsForRenewal || subscription.creditsAllocated;
|
|
281
|
+
yield billingAggregateService.recordSubscriptionRenewalPayment({
|
|
282
|
+
userId,
|
|
283
|
+
subIdKey: subscription.id,
|
|
284
|
+
orderId: renewalOrderId,
|
|
285
|
+
paySubscriptionId: subscriptionId,
|
|
286
|
+
creditsGranted: renewalCredits,
|
|
287
|
+
priceId: subscription.priceId,
|
|
288
|
+
priceName: subscription.priceName,
|
|
289
|
+
periodStart: subPeriodStart,
|
|
290
|
+
periodEnd: subPeriodEnd,
|
|
291
|
+
invoiceId: invoice.id,
|
|
292
|
+
hostedInvoiceUrl: invoice.hosted_invoice_url,
|
|
293
|
+
invoicePdf: invoice.invoice_pdf,
|
|
294
|
+
billingReason: invoice.billing_reason,
|
|
295
|
+
paymentIntentId,
|
|
296
|
+
paidAt: paidAt,
|
|
297
|
+
paidEmail,
|
|
298
|
+
amountPaidCents: invoice.amount_paid,
|
|
299
|
+
currency: invoice.currency,
|
|
300
|
+
});
|
|
301
|
+
console.log(`Invoice renewal paid event completed, and invoiceId: ${invoice.id}, subscriptionId: ${subscription.id}, orderId: ${renewalOrderId}`);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Handle customer.subscription.deleted
|
|
308
|
+
*/
|
|
309
|
+
function handleSubscriptionDeleted(stripeSubscription) {
|
|
310
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
311
|
+
const subscriptionId = stripeSubscription.id;
|
|
312
|
+
console.log(`Subscription deleted: ${subscriptionId}`);
|
|
313
|
+
const userCanceledAt = stripeSubscription.canceled_at;
|
|
314
|
+
if (!userCanceledAt) {
|
|
315
|
+
throw new Error(`Invalid period in invoice line: canceldAt=${userCanceledAt}, subscriptionId=${subscriptionId}`);
|
|
316
|
+
}
|
|
317
|
+
const subscription = yield subscriptionService.findByPaySubscriptionId(subscriptionId);
|
|
318
|
+
if (!subscription) {
|
|
319
|
+
throw new Error(`Subscription id invalid: ${subscriptionId}`);
|
|
320
|
+
}
|
|
321
|
+
const orderId = subscription.orderId;
|
|
322
|
+
if (!orderId) {
|
|
323
|
+
throw new Error(`Subscription's orderId is NULL: ${subscriptionId}`);
|
|
324
|
+
}
|
|
325
|
+
const transaction = yield transactionService.findByOrderId(orderId);
|
|
326
|
+
if (!transaction) {
|
|
327
|
+
throw new Error(`Subscription's orderId is illegal: subscriptionId=${subscriptionId}, orderId=${orderId}`);
|
|
328
|
+
}
|
|
329
|
+
const canceledAt = new Date(userCanceledAt * 1000);
|
|
330
|
+
const cancellationDetail = stripeSubscription.cancellation_details ? JSON.stringify(stripeSubscription.cancellation_details) : undefined;
|
|
331
|
+
yield billingAggregateService.processSubscriptionCancel({
|
|
332
|
+
userId: subscription.userId,
|
|
333
|
+
subIdKey: subscription.id,
|
|
334
|
+
orderId,
|
|
335
|
+
canceledAt,
|
|
336
|
+
cancellationDetail
|
|
337
|
+
});
|
|
338
|
+
console.log(`Subscription status updated to canceled: ${subscription.id}`);
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
function handleAsyncPaymentSucceeded(session) {
|
|
342
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
343
|
+
console.log(`Async payment succeeded: ${session.id}`);
|
|
344
|
+
// Retrieve the latest session state to ensure payment_status is up to date
|
|
345
|
+
const latestSession = yield stripe.checkout.sessions.retrieve(session.id);
|
|
346
|
+
return yield handleCheckoutCompleted(latestSession);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
function handleAsyncPaymentFailed(session) {
|
|
350
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
351
|
+
var _a;
|
|
352
|
+
console.log(`Async payment failed: ${session.id}`);
|
|
353
|
+
const orderId = (_a = session.metadata) === null || _a === void 0 ? void 0 : _a.order_id;
|
|
354
|
+
if (!orderId) {
|
|
355
|
+
throw new Error(`Transaction orderId is NULL for async payment failure`);
|
|
356
|
+
}
|
|
357
|
+
const transaction = yield transactionService.findByOrderId(orderId);
|
|
358
|
+
if (!transaction) {
|
|
359
|
+
throw new Error(`Transaction not found for async payment failure, orderId=${orderId}`);
|
|
360
|
+
}
|
|
361
|
+
if (transaction.orderStatus === OrderStatus.SUCCESS) {
|
|
362
|
+
throw new Error(`Received async payment failed for already successful order ${orderId}, skipping.`);
|
|
363
|
+
}
|
|
364
|
+
yield transactionService.updateStatus(orderId, OrderStatus.FAILED, {
|
|
365
|
+
payUpdatedAt: new Date(),
|
|
366
|
+
paymentStatus: PaymentStatus.UN_PAID,
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function handleInvoicePaymentFailed(invoice) {
|
|
371
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
372
|
+
var _a;
|
|
373
|
+
console.log(`Invoice payment-failed event: ${invoice.id}`);
|
|
374
|
+
const parentDetails = (_a = invoice.parent) === null || _a === void 0 ? void 0 : _a.subscription_details;
|
|
375
|
+
if (!(parentDetails === null || parentDetails === void 0 ? void 0 : parentDetails.subscription)) {
|
|
376
|
+
throw new Error('Invoice not associated with subscription, skipping');
|
|
377
|
+
}
|
|
378
|
+
const isInitialPayment = invoice.billing_reason === BillingReason.SUBSCRIPTION_CREATE;
|
|
379
|
+
const isRenewal = invoice.billing_reason === BillingReason.SUBSCRIPTION_CYCLE;
|
|
380
|
+
// Only handle initial payments and renewals
|
|
381
|
+
if (!isInitialPayment && !isRenewal) {
|
|
382
|
+
throw new Error(`Unhandled invoice billing_reason: ${invoice.billing_reason}, skipping`);
|
|
383
|
+
}
|
|
384
|
+
const subscriptionId = parentDetails.subscription;
|
|
385
|
+
const subscriptionMetadata = parentDetails.metadata || {};
|
|
386
|
+
// 支付ID
|
|
387
|
+
const paymentIntentId = yield fetchPaymentId(invoice.id);
|
|
388
|
+
console.log('Invoice payment failed event key-info:', {
|
|
389
|
+
invoiceId: invoice.id,
|
|
390
|
+
subscriptionId,
|
|
391
|
+
paymentIntentId,
|
|
392
|
+
billingReason: invoice.billing_reason,
|
|
393
|
+
isInitialPayment
|
|
394
|
+
});
|
|
395
|
+
const paidEmail = invoice.customer_email;
|
|
396
|
+
const orderId = subscriptionMetadata.order_id;
|
|
397
|
+
if (!orderId) {
|
|
398
|
+
throw new Error(`No order_id in subscription metadata for failed initial invoice ${invoice.id}. ` + `Skipping payment failure update.`);
|
|
399
|
+
}
|
|
400
|
+
const transaction = yield transactionService.findByOrderId(orderId);
|
|
401
|
+
if (!transaction) {
|
|
402
|
+
throw new Error(`Transaction not found for order_id: ${orderId}`);
|
|
403
|
+
}
|
|
404
|
+
// ===== CASE 1: Initial subscription payment failed =====
|
|
405
|
+
if (isInitialPayment) {
|
|
406
|
+
yield billingAggregateService.recordInitialPaymentFailure({
|
|
407
|
+
orderId: transaction.orderId,
|
|
408
|
+
invoiceId: invoice.id,
|
|
409
|
+
paymentIntentId: paymentIntentId,
|
|
410
|
+
detail: 'Initial subscription payment failed',
|
|
411
|
+
});
|
|
412
|
+
console.log(`Initial subscription payment-failed event updated for order: ${orderId}`);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
// ===== CASE 2: Subscription renewal payment failed =====
|
|
416
|
+
if (isRenewal) {
|
|
417
|
+
// For renewals, we need the subscription to get user info
|
|
418
|
+
const subscription = yield subscriptionService.findByPaySubscriptionId(subscriptionId);
|
|
419
|
+
if (!subscription) {
|
|
420
|
+
throw new Error(`Subscription not found for renewal payment-failed event, and invoice ${invoice.id}`);
|
|
421
|
+
}
|
|
422
|
+
const failedOrderId = `order_renew_failed_${invoice.id}`;
|
|
423
|
+
const existingFailureOrder = yield transactionService.findByOrderId(failedOrderId);
|
|
424
|
+
if (existingFailureOrder) {
|
|
425
|
+
throw new Error(`Renewal payment-failure event for invoice ${invoice.id} already recorded as ${failedOrderId}, skipping.`);
|
|
426
|
+
}
|
|
427
|
+
yield billingAggregateService.recordRenewalPaymentFailure({
|
|
428
|
+
userId: subscription.userId,
|
|
429
|
+
subIdKey: subscription.id,
|
|
430
|
+
orderId: failedOrderId,
|
|
431
|
+
paySubscriptionId: subscriptionId,
|
|
432
|
+
creditsGranted: 0,
|
|
433
|
+
priceId: subscription.priceId,
|
|
434
|
+
priceName: subscription.priceName,
|
|
435
|
+
periodStart: null,
|
|
436
|
+
periodEnd: null,
|
|
437
|
+
invoiceId: invoice.id,
|
|
438
|
+
billingReason: invoice.billing_reason,
|
|
439
|
+
paymentIntentId,
|
|
440
|
+
amountPaidCents: invoice.amount_due,
|
|
441
|
+
currency: invoice.currency,
|
|
442
|
+
paidAt: null,
|
|
443
|
+
paidEmail
|
|
444
|
+
});
|
|
445
|
+
console.log(`Invoice renewal payment-failed event completed, and invoiceId: ${invoice.id}, recorded: ${subscription.id}, orderId: ${failedOrderId}`);
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
function handleSubscriptionCreated(stripeSubscription) {
|
|
451
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
452
|
+
console.log(`Subscription created: ${stripeSubscription.id}`);
|
|
453
|
+
// Usually handled by checkout.session.completed
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Handle subscription updated TODO
|
|
458
|
+
*/
|
|
459
|
+
function handleSubscriptionUpdated(stripeSubscription) {
|
|
460
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
461
|
+
var _a, _b, _c, _d;
|
|
462
|
+
console.log(`Subscription updated: ${stripeSubscription.id}`);
|
|
463
|
+
const orderId = (_a = stripeSubscription.metadata) === null || _a === void 0 ? void 0 : _a.order_id;
|
|
464
|
+
if (!orderId) {
|
|
465
|
+
throw new Error('Missing order_id in session metadata');
|
|
466
|
+
}
|
|
467
|
+
// Extract period timestamps from subscription items (NOT from top-level subscription object)
|
|
468
|
+
const subscriptionItem = (_c = (_b = stripeSubscription.items) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c[0];
|
|
469
|
+
if (!subscriptionItem) {
|
|
470
|
+
throw new Error(`No subscription items found for ${stripeSubscription.id}, reject!`);
|
|
471
|
+
}
|
|
472
|
+
const subscription = yield subscriptionService.findByPaySubscriptionId(stripeSubscription.id);
|
|
473
|
+
if (!subscription) {
|
|
474
|
+
throw new Error(`Subscription not found in DB: ${stripeSubscription.id}`);
|
|
475
|
+
}
|
|
476
|
+
const isUserCancel = ((_d = stripeSubscription.cancellation_details) === null || _d === void 0 ? void 0 : _d.reason) === 'cancellation_requested';
|
|
477
|
+
// Use period from subscription item if available
|
|
478
|
+
const currentPeriodStart = subscriptionItem.current_period_start;
|
|
479
|
+
const currentPeriodEnd = subscriptionItem.current_period_end;
|
|
480
|
+
yield billingAggregateService.syncSubscriptionFromStripe({
|
|
481
|
+
subscription,
|
|
482
|
+
status: stripeSubscription.status,
|
|
483
|
+
periodStart: new Date(currentPeriodStart * 1000),
|
|
484
|
+
periodEnd: new Date(currentPeriodEnd * 1000),
|
|
485
|
+
orderId,
|
|
486
|
+
isUserCancel
|
|
487
|
+
});
|
|
488
|
+
console.log(`Subscription updated in DB: ${subscription.id}`);
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
function handleChargeRefunded(charge) {
|
|
492
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
493
|
+
var _a;
|
|
494
|
+
console.log(`Charge refunded: ${charge.id}`);
|
|
495
|
+
// Find transaction by payment intent
|
|
496
|
+
const paymentIntentId = typeof charge.payment_intent === 'string'
|
|
497
|
+
? charge.payment_intent
|
|
498
|
+
: (_a = charge.payment_intent) === null || _a === void 0 ? void 0 : _a.id;
|
|
499
|
+
if (!paymentIntentId) {
|
|
500
|
+
throw new Error("PaymentId is illegal NULL");
|
|
501
|
+
}
|
|
502
|
+
const transaction = yield transactionService.findByPayTransactionId(paymentIntentId);
|
|
503
|
+
if (!transaction) {
|
|
504
|
+
throw new Error(`Transaction not found for paymentId: ${paymentIntentId}`);
|
|
505
|
+
}
|
|
506
|
+
if (transaction.orderStatus === OrderStatus.REFUNDED) {
|
|
507
|
+
throw new Error(`Transaction already marked refunded: ${transaction.orderId}, skipping.`);
|
|
508
|
+
}
|
|
509
|
+
if (transaction.type === TransactionType.SUBSCRIPTION) {
|
|
510
|
+
const subscription = transaction.paySubscriptionId
|
|
511
|
+
? yield subscriptionService.findByPaySubscriptionId(transaction.paySubscriptionId)
|
|
512
|
+
: null;
|
|
513
|
+
yield billingAggregateService.processSubscriptionRefund({
|
|
514
|
+
transaction,
|
|
515
|
+
subscription,
|
|
516
|
+
});
|
|
517
|
+
console.log(`Subscription refund processed for transaction: ${transaction.orderId}`);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (transaction.type === TransactionType.ONE_TIME) {
|
|
521
|
+
yield billingAggregateService.processOneTimeRefund({ transaction });
|
|
522
|
+
console.log(`One-time refund processed for transaction: ${transaction.orderId}`);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
// for other type, not available
|
|
526
|
+
yield transactionService.update(transaction.orderId, {
|
|
527
|
+
orderStatus: OrderStatus.REFUNDED,
|
|
528
|
+
paymentStatus: PaymentStatus.UN_PAID,
|
|
529
|
+
payUpdatedAt: new Date(),
|
|
530
|
+
});
|
|
531
|
+
console.log(`Refund processed for transaction without credit adjustments: ${transaction.orderId}`);
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export { handleStripeEvent };
|