@open-mercato/core 0.4.7-develop-0a657b411f → 0.4.7-develop-e249d3e7d0
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/dist/generated/entities/carrier_shipment/index.js +37 -0
- package/dist/generated/entities/carrier_shipment/index.js.map +7 -0
- package/dist/generated/entities/gateway_transaction/index.js +47 -0
- package/dist/generated/entities/gateway_transaction/index.js.map +7 -0
- package/dist/generated/entities/webhook_processed_event/index.js +17 -0
- package/dist/generated/entities/webhook_processed_event/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +10 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +6 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +14 -5
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.meta.js +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.meta.js.map +1 -1
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +37 -12
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
- package/dist/modules/directory/api/get/tenants/lookup.js +1 -0
- package/dist/modules/directory/api/get/tenants/lookup.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +38 -11
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +52 -26
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +37 -7
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +121 -0
- package/dist/modules/integrations/api/umes-read.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js +715 -183
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +30 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/detail-page-widgets.js +46 -0
- package/dist/modules/integrations/backend/integrations/detail-page-widgets.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/page.js +78 -62
- package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/page.meta.js +2 -2
- package/dist/modules/integrations/backend/integrations/page.meta.js.map +1 -1
- package/dist/modules/integrations/setup.js +2 -2
- package/dist/modules/integrations/setup.js.map +2 -2
- package/dist/modules/payment_gateways/acl.js +12 -0
- package/dist/modules/payment_gateways/acl.js.map +7 -0
- package/dist/modules/payment_gateways/api/cancel/route.js +55 -0
- package/dist/modules/payment_gateways/api/cancel/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/capture/route.js +55 -0
- package/dist/modules/payment_gateways/api/capture/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/interceptors.js +24 -0
- package/dist/modules/payment_gateways/api/interceptors.js.map +7 -0
- package/dist/modules/payment_gateways/api/openapi.js +5 -0
- package/dist/modules/payment_gateways/api/openapi.js.map +7 -0
- package/dist/modules/payment_gateways/api/refund/route.js +56 -0
- package/dist/modules/payment_gateways/api/refund/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/sessions/route.js +74 -0
- package/dist/modules/payment_gateways/api/sessions/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/status/route.js +66 -0
- package/dist/modules/payment_gateways/api/status/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/transactions/[id]/route.js +118 -0
- package/dist/modules/payment_gateways/api/transactions/[id]/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/transactions/route.js +113 -0
- package/dist/modules/payment_gateways/api/transactions/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +136 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +496 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +7 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js +23 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js.map +7 -0
- package/dist/modules/payment_gateways/data/enrichers.js +5 -0
- package/dist/modules/payment_gateways/data/enrichers.js.map +7 -0
- package/dist/modules/payment_gateways/data/entities.js +131 -0
- package/dist/modules/payment_gateways/data/entities.js.map +7 -0
- package/dist/modules/payment_gateways/data/validators.js +57 -0
- package/dist/modules/payment_gateways/data/validators.js.map +7 -0
- package/dist/modules/payment_gateways/di.js +16 -0
- package/dist/modules/payment_gateways/di.js.map +7 -0
- package/dist/modules/payment_gateways/events.js +21 -0
- package/dist/modules/payment_gateways/events.js.map +7 -0
- package/dist/modules/payment_gateways/i18n/en.js +6 -0
- package/dist/modules/payment_gateways/i18n/en.js.map +7 -0
- package/dist/modules/payment_gateways/i18n/pl.js +6 -0
- package/dist/modules/payment_gateways/i18n/pl.js.map +7 -0
- package/dist/modules/payment_gateways/index.js +9 -0
- package/dist/modules/payment_gateways/index.js.map +7 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js +378 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +7 -0
- package/dist/modules/payment_gateways/lib/queue.js +17 -0
- package/dist/modules/payment_gateways/lib/queue.js.map +7 -0
- package/dist/modules/payment_gateways/lib/status-machine.js +29 -0
- package/dist/modules/payment_gateways/lib/status-machine.js.map +7 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js +88 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js.map +7 -0
- package/dist/modules/payment_gateways/lib/webhook-utils.js +42 -0
- package/dist/modules/payment_gateways/lib/webhook-utils.js.map +7 -0
- package/dist/modules/payment_gateways/migrations/Migration20260305122155.js +19 -0
- package/dist/modules/payment_gateways/migrations/Migration20260305122155.js.map +7 -0
- package/dist/modules/payment_gateways/setup.js +13 -0
- package/dist/modules/payment_gateways/setup.js.map +7 -0
- package/dist/modules/payment_gateways/widgets/injection-table.js +7 -0
- package/dist/modules/payment_gateways/widgets/injection-table.js.map +7 -0
- package/dist/modules/payment_gateways/workers/status-poller.js +44 -0
- package/dist/modules/payment_gateways/workers/status-poller.js.map +7 -0
- package/dist/modules/payment_gateways/workers/webhook-processor.js +20 -0
- package/dist/modules/payment_gateways/workers/webhook-processor.js.map +7 -0
- package/dist/modules/sales/data/enrichers.js +72 -0
- package/dist/modules/sales/data/enrichers.js.map +7 -0
- package/dist/modules/sales/lib/makeSalesLineRoute.js +3 -0
- package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js +29 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js.map +7 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +23 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +7 -0
- package/dist/modules/sales/widgets/injection-table.js +13 -1
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/dist/modules/shipping_carriers/acl.js +10 -0
- package/dist/modules/shipping_carriers/acl.js.map +7 -0
- package/dist/modules/shipping_carriers/api/cancel/route.js +55 -0
- package/dist/modules/shipping_carriers/api/cancel/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/interceptors.js +21 -0
- package/dist/modules/shipping_carriers/api/interceptors.js.map +7 -0
- package/dist/modules/shipping_carriers/api/openapi.js +5 -0
- package/dist/modules/shipping_carriers/api/openapi.js.map +7 -0
- package/dist/modules/shipping_carriers/api/rates/route.js +55 -0
- package/dist/modules/shipping_carriers/api/rates/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js +61 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/tracking/route.js +58 -0
- package/dist/modules/shipping_carriers/api/tracking/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +119 -0
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/shipping_carriers/data/enrichers.js +82 -0
- package/dist/modules/shipping_carriers/data/enrichers.js.map +7 -0
- package/dist/modules/shipping_carriers/data/entities.js +80 -0
- package/dist/modules/shipping_carriers/data/entities.js.map +7 -0
- package/dist/modules/shipping_carriers/data/validators.js +49 -0
- package/dist/modules/shipping_carriers/data/validators.js.map +7 -0
- package/dist/modules/shipping_carriers/di.js +15 -0
- package/dist/modules/shipping_carriers/di.js.map +7 -0
- package/dist/modules/shipping_carriers/events.js +19 -0
- package/dist/modules/shipping_carriers/events.js.map +7 -0
- package/dist/modules/shipping_carriers/i18n/en.js +11 -0
- package/dist/modules/shipping_carriers/i18n/en.js.map +7 -0
- package/dist/modules/shipping_carriers/i18n/pl.js +11 -0
- package/dist/modules/shipping_carriers/i18n/pl.js.map +7 -0
- package/dist/modules/shipping_carriers/index.js +9 -0
- package/dist/modules/shipping_carriers/index.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/adapter-registry.js +29 -0
- package/dist/modules/shipping_carriers/lib/adapter-registry.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/adapter.js +1 -0
- package/dist/modules/shipping_carriers/lib/adapter.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/queue.js +17 -0
- package/dist/modules/shipping_carriers/lib/queue.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/shipping-service.js +155 -0
- package/dist/modules/shipping_carriers/lib/shipping-service.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/status-sync.js +37 -0
- package/dist/modules/shipping_carriers/lib/status-sync.js.map +7 -0
- package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js +16 -0
- package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js.map +7 -0
- package/dist/modules/shipping_carriers/setup.js +13 -0
- package/dist/modules/shipping_carriers/setup.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js +25 -0
- package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js +23 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js +40 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection-table.js +24 -0
- package/dist/modules/shipping_carriers/widgets/injection-table.js.map +7 -0
- package/dist/modules/shipping_carriers/workers/status-poller.js +21 -0
- package/dist/modules/shipping_carriers/workers/status-poller.js.map +7 -0
- package/dist/modules/shipping_carriers/workers/webhook-processor.js +54 -0
- package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +7 -0
- package/dist/modules/translations/api/get/locales.js +1 -0
- package/dist/modules/translations/api/get/locales.js.map +2 -2
- package/dist/modules/translations/api/put/locales.js +1 -0
- package/dist/modules/translations/api/put/locales.js.map +2 -2
- package/generated/entities/carrier_shipment/index.ts +17 -0
- package/generated/entities/gateway_transaction/index.ts +22 -0
- package/generated/entities/webhook_processed_event/index.ts +7 -0
- package/generated/entities.ids.generated.ts +10 -1
- package/generated/entity-fields-registry.ts +6 -0
- package/jest.config.cjs +1 -0
- package/package.json +5 -2
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +18 -5
- package/src/modules/data_sync/backend/data-sync/page.meta.ts +2 -2
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +50 -12
- package/src/modules/directory/api/get/tenants/lookup.ts +1 -0
- package/src/modules/integrations/AGENTS.md +31 -0
- package/src/modules/integrations/api/[id]/route.ts +38 -11
- package/src/modules/integrations/api/logs/route.ts +53 -27
- package/src/modules/integrations/api/route.ts +31 -1
- package/src/modules/integrations/api/umes-read.ts +177 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +902 -202
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +43 -9
- package/src/modules/integrations/backend/integrations/detail-page-widgets.ts +74 -0
- package/src/modules/integrations/backend/integrations/page.meta.ts +2 -2
- package/src/modules/integrations/backend/integrations/page.tsx +65 -54
- package/src/modules/integrations/i18n/de.json +15 -0
- package/src/modules/integrations/i18n/en.json +15 -0
- package/src/modules/integrations/i18n/es.json +15 -0
- package/src/modules/integrations/i18n/pl.json +15 -0
- package/src/modules/integrations/setup.ts +2 -2
- package/src/modules/payment_gateways/acl.ts +8 -0
- package/src/modules/payment_gateways/api/cancel/route.ts +56 -0
- package/src/modules/payment_gateways/api/capture/route.ts +56 -0
- package/src/modules/payment_gateways/api/interceptors.ts +22 -0
- package/src/modules/payment_gateways/api/openapi.ts +1 -0
- package/src/modules/payment_gateways/api/refund/route.ts +57 -0
- package/src/modules/payment_gateways/api/sessions/route.ts +76 -0
- package/src/modules/payment_gateways/api/status/route.ts +69 -0
- package/src/modules/payment_gateways/api/transactions/[id]/route.ts +123 -0
- package/src/modules/payment_gateways/api/transactions/route.ts +120 -0
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +161 -0
- package/src/modules/payment_gateways/backend/payment-gateways/page.meta.ts +19 -0
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +660 -0
- package/src/modules/payment_gateways/data/enrichers.ts +8 -0
- package/src/modules/payment_gateways/data/entities.ts +106 -0
- package/src/modules/payment_gateways/data/validators.ts +67 -0
- package/src/modules/payment_gateways/di.ts +26 -0
- package/src/modules/payment_gateways/events.ts +17 -0
- package/src/modules/payment_gateways/i18n/de.json +77 -0
- package/src/modules/payment_gateways/i18n/en.json +77 -0
- package/src/modules/payment_gateways/i18n/en.ts +4 -0
- package/src/modules/payment_gateways/i18n/es.json +77 -0
- package/src/modules/payment_gateways/i18n/pl.json +77 -0
- package/src/modules/payment_gateways/i18n/pl.ts +4 -0
- package/src/modules/payment_gateways/index.ts +5 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +486 -0
- package/src/modules/payment_gateways/lib/queue.ts +19 -0
- package/src/modules/payment_gateways/lib/status-machine.ts +28 -0
- package/src/modules/payment_gateways/lib/webhook-processor.ts +133 -0
- package/src/modules/payment_gateways/lib/webhook-utils.ts +52 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +373 -0
- package/src/modules/payment_gateways/migrations/Migration20260305122155.ts +20 -0
- package/src/modules/payment_gateways/setup.ts +11 -0
- package/src/modules/payment_gateways/widgets/injection-table.ts +9 -0
- package/src/modules/payment_gateways/workers/status-poller.ts +58 -0
- package/src/modules/payment_gateways/workers/webhook-processor.ts +30 -0
- package/src/modules/sales/data/enrichers.ts +120 -0
- package/src/modules/sales/lib/makeSalesLineRoute.ts +3 -0
- package/src/modules/sales/widgets/injection/payment-gateway-config-field/widget.ts +28 -0
- package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +22 -0
- package/src/modules/sales/widgets/injection-table.ts +12 -0
- package/src/modules/shipping_carriers/acl.ts +6 -0
- package/src/modules/shipping_carriers/api/cancel/route.ts +53 -0
- package/src/modules/shipping_carriers/api/interceptors.ts +19 -0
- package/src/modules/shipping_carriers/api/openapi.ts +1 -0
- package/src/modules/shipping_carriers/api/rates/route.ts +53 -0
- package/src/modules/shipping_carriers/api/shipments/route.ts +59 -0
- package/src/modules/shipping_carriers/api/tracking/route.ts +56 -0
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +134 -0
- package/src/modules/shipping_carriers/data/enrichers.ts +89 -0
- package/src/modules/shipping_carriers/data/entities.ts +60 -0
- package/src/modules/shipping_carriers/data/validators.ts +48 -0
- package/src/modules/shipping_carriers/di.ts +20 -0
- package/src/modules/shipping_carriers/events.ts +16 -0
- package/src/modules/shipping_carriers/i18n/de.json +7 -0
- package/src/modules/shipping_carriers/i18n/en.json +7 -0
- package/src/modules/shipping_carriers/i18n/en.ts +7 -0
- package/src/modules/shipping_carriers/i18n/es.json +7 -0
- package/src/modules/shipping_carriers/i18n/pl.json +7 -0
- package/src/modules/shipping_carriers/i18n/pl.ts +7 -0
- package/src/modules/shipping_carriers/index.ts +5 -0
- package/src/modules/shipping_carriers/lib/adapter-registry.ts +33 -0
- package/src/modules/shipping_carriers/lib/adapter.ts +93 -0
- package/src/modules/shipping_carriers/lib/queue.ts +19 -0
- package/src/modules/shipping_carriers/lib/shipping-service.ts +204 -0
- package/src/modules/shipping_carriers/lib/status-sync.ts +38 -0
- package/src/modules/shipping_carriers/migrations/Migration20260305170000.ts +14 -0
- package/src/modules/shipping_carriers/setup.ts +11 -0
- package/src/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.ts +24 -0
- package/src/modules/shipping_carriers/widgets/injection/tracking-column/widget.ts +22 -0
- package/src/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.tsx +44 -0
- package/src/modules/shipping_carriers/widgets/injection-table.ts +22 -0
- package/src/modules/shipping_carriers/workers/status-poller.ts +33 -0
- package/src/modules/shipping_carriers/workers/webhook-processor.ts +79 -0
- package/src/modules/translations/api/get/locales.ts +1 -0
- package/src/modules/translations/api/put/locales.ts +1 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
2
|
+
import {
|
|
3
|
+
getGatewayAdapter
|
|
4
|
+
} from "@open-mercato/shared/modules/payment_gateways/types";
|
|
5
|
+
import { GatewayTransaction } from "../data/entities.js";
|
|
6
|
+
import { isValidTransition } from "./status-machine.js";
|
|
7
|
+
import { emitPaymentGatewayEvent } from "../events.js";
|
|
8
|
+
function createPaymentGatewayService(deps) {
|
|
9
|
+
const { em, integrationCredentialsService, integrationLogService } = deps;
|
|
10
|
+
async function findTransactionOrThrow(transactionId, scope) {
|
|
11
|
+
const transaction = await findOneWithDecryption(
|
|
12
|
+
em,
|
|
13
|
+
GatewayTransaction,
|
|
14
|
+
{
|
|
15
|
+
id: transactionId,
|
|
16
|
+
organizationId: scope.organizationId,
|
|
17
|
+
tenantId: scope.tenantId,
|
|
18
|
+
deletedAt: null
|
|
19
|
+
},
|
|
20
|
+
void 0,
|
|
21
|
+
scope
|
|
22
|
+
);
|
|
23
|
+
if (!transaction) {
|
|
24
|
+
throw new Error("Transaction not found");
|
|
25
|
+
}
|
|
26
|
+
return transaction;
|
|
27
|
+
}
|
|
28
|
+
function readProviderSessionId(transaction) {
|
|
29
|
+
if (typeof transaction.providerSessionId === "string" && transaction.providerSessionId.trim().length > 0) {
|
|
30
|
+
return transaction.providerSessionId;
|
|
31
|
+
}
|
|
32
|
+
throw new Error("Transaction is missing provider session id");
|
|
33
|
+
}
|
|
34
|
+
async function emitStatusEvent(status, payload) {
|
|
35
|
+
const eventMap = {
|
|
36
|
+
authorized: "payment_gateways.payment.authorized",
|
|
37
|
+
captured: "payment_gateways.payment.captured",
|
|
38
|
+
failed: "payment_gateways.payment.failed",
|
|
39
|
+
refunded: "payment_gateways.payment.refunded",
|
|
40
|
+
cancelled: "payment_gateways.payment.cancelled"
|
|
41
|
+
};
|
|
42
|
+
const eventId = eventMap[status];
|
|
43
|
+
if (!eventId) return;
|
|
44
|
+
await emitPaymentGatewayEvent(eventId, payload);
|
|
45
|
+
}
|
|
46
|
+
async function writeTransactionLog(providerKey, scope, transactionId, level, message, payload, code) {
|
|
47
|
+
if (!integrationLogService) return;
|
|
48
|
+
await integrationLogService.write({
|
|
49
|
+
integrationId: `gateway_${providerKey}`,
|
|
50
|
+
scopeEntityType: "payment_transaction",
|
|
51
|
+
scopeEntityId: transactionId,
|
|
52
|
+
level,
|
|
53
|
+
message,
|
|
54
|
+
code,
|
|
55
|
+
payload: payload ?? null
|
|
56
|
+
}, scope);
|
|
57
|
+
}
|
|
58
|
+
async function resolveAdapterAndCredentials(providerKey, scope) {
|
|
59
|
+
const integrationId = `gateway_${providerKey}`;
|
|
60
|
+
const selectedVersion = deps.integrationStateService ? await deps.integrationStateService.resolveApiVersion(integrationId, scope) : void 0;
|
|
61
|
+
const adapter = getGatewayAdapter(providerKey, selectedVersion);
|
|
62
|
+
if (!adapter) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
selectedVersion ? `No gateway adapter registered for provider: ${providerKey} (version: ${selectedVersion})` : `No gateway adapter registered for provider: ${providerKey}`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
const credentials = await integrationCredentialsService.resolve(integrationId, scope) ?? {};
|
|
68
|
+
return { adapter, credentials };
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
async createPaymentSession(input) {
|
|
72
|
+
const scope = { organizationId: input.organizationId, tenantId: input.tenantId };
|
|
73
|
+
const { adapter, credentials } = await resolveAdapterAndCredentials(input.providerKey, scope);
|
|
74
|
+
const sessionInput = {
|
|
75
|
+
paymentId: input.paymentId,
|
|
76
|
+
orderId: input.orderId,
|
|
77
|
+
tenantId: input.tenantId,
|
|
78
|
+
organizationId: input.organizationId,
|
|
79
|
+
amount: input.amount,
|
|
80
|
+
currencyCode: input.currencyCode,
|
|
81
|
+
captureMethod: input.captureMethod,
|
|
82
|
+
description: input.description,
|
|
83
|
+
successUrl: input.successUrl,
|
|
84
|
+
cancelUrl: input.cancelUrl,
|
|
85
|
+
metadata: input.metadata,
|
|
86
|
+
credentials
|
|
87
|
+
};
|
|
88
|
+
const session = await adapter.createSession(sessionInput);
|
|
89
|
+
const transaction = em.create(GatewayTransaction, {
|
|
90
|
+
paymentId: input.paymentId,
|
|
91
|
+
providerKey: input.providerKey,
|
|
92
|
+
providerSessionId: session.sessionId,
|
|
93
|
+
unifiedStatus: session.status,
|
|
94
|
+
redirectUrl: session.redirectUrl ?? null,
|
|
95
|
+
clientSecret: null,
|
|
96
|
+
amount: String(input.amount),
|
|
97
|
+
currencyCode: input.currencyCode,
|
|
98
|
+
gatewayMetadata: session.providerData ?? null,
|
|
99
|
+
organizationId: input.organizationId,
|
|
100
|
+
tenantId: input.tenantId
|
|
101
|
+
});
|
|
102
|
+
await em.persistAndFlush(transaction);
|
|
103
|
+
await emitPaymentGatewayEvent("payment_gateways.session.created", {
|
|
104
|
+
transactionId: transaction.id,
|
|
105
|
+
paymentId: transaction.paymentId,
|
|
106
|
+
providerKey: transaction.providerKey,
|
|
107
|
+
status: transaction.unifiedStatus,
|
|
108
|
+
organizationId: transaction.organizationId,
|
|
109
|
+
tenantId: transaction.tenantId
|
|
110
|
+
});
|
|
111
|
+
await writeTransactionLog(
|
|
112
|
+
transaction.providerKey,
|
|
113
|
+
scope,
|
|
114
|
+
transaction.id,
|
|
115
|
+
"info",
|
|
116
|
+
"Payment session created",
|
|
117
|
+
{
|
|
118
|
+
paymentId: transaction.paymentId,
|
|
119
|
+
providerSessionId: transaction.providerSessionId,
|
|
120
|
+
status: transaction.unifiedStatus,
|
|
121
|
+
amount: input.amount,
|
|
122
|
+
currencyCode: input.currencyCode
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
return { transaction, session };
|
|
126
|
+
},
|
|
127
|
+
async capturePayment(transactionId, amount, scope) {
|
|
128
|
+
const transaction = await findTransactionOrThrow(transactionId, scope);
|
|
129
|
+
const { adapter, credentials } = await resolveAdapterAndCredentials(
|
|
130
|
+
transaction.providerKey,
|
|
131
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId }
|
|
132
|
+
);
|
|
133
|
+
const result = await adapter.capture({
|
|
134
|
+
sessionId: readProviderSessionId(transaction),
|
|
135
|
+
amount,
|
|
136
|
+
credentials
|
|
137
|
+
});
|
|
138
|
+
transaction.unifiedStatus = result.status;
|
|
139
|
+
transaction.gatewayMetadata = { ...transaction.gatewayMetadata, captureResult: result.providerData };
|
|
140
|
+
await em.flush();
|
|
141
|
+
await emitStatusEvent(result.status, {
|
|
142
|
+
transactionId: transaction.id,
|
|
143
|
+
paymentId: transaction.paymentId,
|
|
144
|
+
providerKey: transaction.providerKey,
|
|
145
|
+
organizationId: transaction.organizationId,
|
|
146
|
+
tenantId: transaction.tenantId
|
|
147
|
+
});
|
|
148
|
+
await writeTransactionLog(
|
|
149
|
+
transaction.providerKey,
|
|
150
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId },
|
|
151
|
+
transaction.id,
|
|
152
|
+
"info",
|
|
153
|
+
"Payment captured",
|
|
154
|
+
{
|
|
155
|
+
amount: amount ?? null,
|
|
156
|
+
status: result.status,
|
|
157
|
+
capturedAmount: result.capturedAmount
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
return result;
|
|
161
|
+
},
|
|
162
|
+
async refundPayment(transactionId, amount, reason, scope) {
|
|
163
|
+
const transaction = await findTransactionOrThrow(transactionId, scope);
|
|
164
|
+
const { adapter, credentials } = await resolveAdapterAndCredentials(
|
|
165
|
+
transaction.providerKey,
|
|
166
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId }
|
|
167
|
+
);
|
|
168
|
+
const result = await adapter.refund({
|
|
169
|
+
sessionId: readProviderSessionId(transaction),
|
|
170
|
+
amount,
|
|
171
|
+
reason,
|
|
172
|
+
credentials
|
|
173
|
+
});
|
|
174
|
+
transaction.unifiedStatus = result.status;
|
|
175
|
+
transaction.gatewayRefundId = result.refundId;
|
|
176
|
+
transaction.gatewayMetadata = { ...transaction.gatewayMetadata, refundResult: result.providerData };
|
|
177
|
+
await em.flush();
|
|
178
|
+
await emitStatusEvent(result.status, {
|
|
179
|
+
transactionId: transaction.id,
|
|
180
|
+
paymentId: transaction.paymentId,
|
|
181
|
+
providerKey: transaction.providerKey,
|
|
182
|
+
organizationId: transaction.organizationId,
|
|
183
|
+
tenantId: transaction.tenantId
|
|
184
|
+
});
|
|
185
|
+
await writeTransactionLog(
|
|
186
|
+
transaction.providerKey,
|
|
187
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId },
|
|
188
|
+
transaction.id,
|
|
189
|
+
"info",
|
|
190
|
+
"Payment refunded",
|
|
191
|
+
{
|
|
192
|
+
amount: amount ?? null,
|
|
193
|
+
reason: reason ?? null,
|
|
194
|
+
status: result.status,
|
|
195
|
+
refundId: result.refundId
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
return result;
|
|
199
|
+
},
|
|
200
|
+
async cancelPayment(transactionId, reason, scope) {
|
|
201
|
+
const transaction = await findTransactionOrThrow(transactionId, scope);
|
|
202
|
+
const { adapter, credentials } = await resolveAdapterAndCredentials(
|
|
203
|
+
transaction.providerKey,
|
|
204
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId }
|
|
205
|
+
);
|
|
206
|
+
const result = await adapter.cancel({
|
|
207
|
+
sessionId: readProviderSessionId(transaction),
|
|
208
|
+
reason,
|
|
209
|
+
credentials
|
|
210
|
+
});
|
|
211
|
+
transaction.unifiedStatus = result.status;
|
|
212
|
+
await em.flush();
|
|
213
|
+
await emitStatusEvent(result.status, {
|
|
214
|
+
transactionId: transaction.id,
|
|
215
|
+
paymentId: transaction.paymentId,
|
|
216
|
+
providerKey: transaction.providerKey,
|
|
217
|
+
organizationId: transaction.organizationId,
|
|
218
|
+
tenantId: transaction.tenantId
|
|
219
|
+
});
|
|
220
|
+
await writeTransactionLog(
|
|
221
|
+
transaction.providerKey,
|
|
222
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId },
|
|
223
|
+
transaction.id,
|
|
224
|
+
"info",
|
|
225
|
+
"Payment cancelled",
|
|
226
|
+
{
|
|
227
|
+
reason: reason ?? null,
|
|
228
|
+
status: result.status
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
return result;
|
|
232
|
+
},
|
|
233
|
+
async getPaymentStatus(transactionId, scope) {
|
|
234
|
+
const transaction = await findTransactionOrThrow(transactionId, scope);
|
|
235
|
+
const { adapter, credentials } = await resolveAdapterAndCredentials(
|
|
236
|
+
transaction.providerKey,
|
|
237
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId }
|
|
238
|
+
);
|
|
239
|
+
const status = await adapter.getStatus({
|
|
240
|
+
sessionId: readProviderSessionId(transaction),
|
|
241
|
+
credentials
|
|
242
|
+
});
|
|
243
|
+
if (status.status !== transaction.unifiedStatus && isValidTransition(transaction.unifiedStatus, status.status)) {
|
|
244
|
+
const previousStatus = transaction.unifiedStatus;
|
|
245
|
+
transaction.unifiedStatus = status.status;
|
|
246
|
+
transaction.gatewayStatus = status.status;
|
|
247
|
+
transaction.gatewayMetadata = { ...transaction.gatewayMetadata, statusResult: status.providerData ?? null };
|
|
248
|
+
transaction.lastPolledAt = /* @__PURE__ */ new Date();
|
|
249
|
+
await em.flush();
|
|
250
|
+
await emitStatusEvent(status.status, {
|
|
251
|
+
transactionId: transaction.id,
|
|
252
|
+
paymentId: transaction.paymentId,
|
|
253
|
+
providerKey: transaction.providerKey,
|
|
254
|
+
previousStatus,
|
|
255
|
+
organizationId: transaction.organizationId,
|
|
256
|
+
tenantId: transaction.tenantId
|
|
257
|
+
});
|
|
258
|
+
await writeTransactionLog(
|
|
259
|
+
transaction.providerKey,
|
|
260
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId },
|
|
261
|
+
transaction.id,
|
|
262
|
+
"info",
|
|
263
|
+
"Payment status updated by poller",
|
|
264
|
+
{
|
|
265
|
+
previousStatus,
|
|
266
|
+
nextStatus: status.status
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
return status;
|
|
271
|
+
},
|
|
272
|
+
async syncTransactionStatus(transactionId, update, scope) {
|
|
273
|
+
const transaction = await findTransactionOrThrow(transactionId, scope);
|
|
274
|
+
const currentStatus = transaction.unifiedStatus;
|
|
275
|
+
const canTransition = isValidTransition(currentStatus, update.unifiedStatus);
|
|
276
|
+
const shouldApplyStatus = canTransition && update.unifiedStatus !== currentStatus;
|
|
277
|
+
const previousStatus = transaction.unifiedStatus;
|
|
278
|
+
if (shouldApplyStatus) {
|
|
279
|
+
transaction.unifiedStatus = update.unifiedStatus;
|
|
280
|
+
}
|
|
281
|
+
if (update.providerStatus) {
|
|
282
|
+
transaction.gatewayStatus = update.providerStatus;
|
|
283
|
+
}
|
|
284
|
+
if (update.providerData) {
|
|
285
|
+
transaction.gatewayMetadata = { ...transaction.gatewayMetadata, ...update.providerData };
|
|
286
|
+
}
|
|
287
|
+
if (update.webhookEvent) {
|
|
288
|
+
const webhookLog = Array.isArray(transaction.webhookLog) ? transaction.webhookLog : [];
|
|
289
|
+
webhookLog.push({
|
|
290
|
+
eventType: update.webhookEvent.eventType,
|
|
291
|
+
receivedAt: update.webhookEvent.receivedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
292
|
+
idempotencyKey: update.webhookEvent.idempotencyKey,
|
|
293
|
+
unifiedStatus: update.unifiedStatus,
|
|
294
|
+
processed: update.webhookEvent.processed
|
|
295
|
+
});
|
|
296
|
+
transaction.webhookLog = webhookLog;
|
|
297
|
+
}
|
|
298
|
+
transaction.lastWebhookAt = /* @__PURE__ */ new Date();
|
|
299
|
+
await em.flush();
|
|
300
|
+
if (shouldApplyStatus) {
|
|
301
|
+
await emitStatusEvent(update.unifiedStatus, {
|
|
302
|
+
transactionId: transaction.id,
|
|
303
|
+
paymentId: transaction.paymentId,
|
|
304
|
+
providerKey: transaction.providerKey,
|
|
305
|
+
previousStatus,
|
|
306
|
+
organizationId: transaction.organizationId,
|
|
307
|
+
tenantId: transaction.tenantId
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
await writeTransactionLog(
|
|
311
|
+
transaction.providerKey,
|
|
312
|
+
{ organizationId: transaction.organizationId, tenantId: transaction.tenantId },
|
|
313
|
+
transaction.id,
|
|
314
|
+
shouldApplyStatus ? "info" : "warn",
|
|
315
|
+
shouldApplyStatus ? "Payment status synchronized from webhook" : "Webhook received with no status transition",
|
|
316
|
+
{
|
|
317
|
+
previousStatus,
|
|
318
|
+
nextStatus: update.unifiedStatus,
|
|
319
|
+
providerStatus: update.providerStatus ?? null,
|
|
320
|
+
eventType: update.webhookEvent?.eventType ?? null,
|
|
321
|
+
idempotencyKey: update.webhookEvent?.idempotencyKey ?? null
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
},
|
|
325
|
+
async findTransaction(id, scope) {
|
|
326
|
+
return findOneWithDecryption(
|
|
327
|
+
em,
|
|
328
|
+
GatewayTransaction,
|
|
329
|
+
{
|
|
330
|
+
id,
|
|
331
|
+
organizationId: scope.organizationId,
|
|
332
|
+
tenantId: scope.tenantId,
|
|
333
|
+
deletedAt: null
|
|
334
|
+
},
|
|
335
|
+
void 0,
|
|
336
|
+
scope
|
|
337
|
+
);
|
|
338
|
+
},
|
|
339
|
+
async findTransactionBySessionId(providerSessionId, scope, providerKey) {
|
|
340
|
+
return findOneWithDecryption(
|
|
341
|
+
em,
|
|
342
|
+
GatewayTransaction,
|
|
343
|
+
{
|
|
344
|
+
providerSessionId,
|
|
345
|
+
organizationId: scope.organizationId,
|
|
346
|
+
tenantId: scope.tenantId,
|
|
347
|
+
deletedAt: null,
|
|
348
|
+
...providerKey ? { providerKey } : {}
|
|
349
|
+
},
|
|
350
|
+
void 0,
|
|
351
|
+
scope
|
|
352
|
+
);
|
|
353
|
+
},
|
|
354
|
+
async listTransactionsForStatusPolling(scope) {
|
|
355
|
+
const where = {
|
|
356
|
+
unifiedStatus: { $in: ["pending", "authorized", "partially_captured"] },
|
|
357
|
+
deletedAt: null
|
|
358
|
+
};
|
|
359
|
+
if (scope?.organizationId) where.organizationId = scope.organizationId;
|
|
360
|
+
if (scope?.tenantId) where.tenantId = scope.tenantId;
|
|
361
|
+
if (scope?.providerKey) where.providerKey = scope.providerKey;
|
|
362
|
+
return findWithDecryption(
|
|
363
|
+
em,
|
|
364
|
+
GatewayTransaction,
|
|
365
|
+
where,
|
|
366
|
+
{
|
|
367
|
+
orderBy: { updatedAt: "asc" },
|
|
368
|
+
limit: scope?.limit ?? 100
|
|
369
|
+
},
|
|
370
|
+
scope
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
export {
|
|
376
|
+
createPaymentGatewayService
|
|
377
|
+
};
|
|
378
|
+
//# sourceMappingURL=gateway-service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/payment_gateways/lib/gateway-service.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport {\n getGatewayAdapter,\n type CreateSessionInput,\n type CreateSessionResult,\n type CaptureResult,\n type RefundResult,\n type CancelResult,\n type GatewayPaymentStatus,\n type UnifiedPaymentStatus,\n} from '@open-mercato/shared/modules/payment_gateways/types'\nimport type { CredentialsService } from '../../integrations/lib/credentials-service'\nimport type { IntegrationStateService } from '../../integrations/lib/state-service'\nimport type { IntegrationLogService } from '../../integrations/lib/log-service'\nimport { GatewayTransaction } from '../data/entities'\nimport { isValidTransition } from './status-machine'\nimport { emitPaymentGatewayEvent } from '../events'\n\nexport interface PaymentGatewayServiceDeps {\n em: EntityManager\n integrationCredentialsService: CredentialsService\n integrationStateService?: IntegrationStateService\n integrationLogService?: IntegrationLogService\n}\n\nexport interface CreatePaymentSessionInput {\n providerKey: string\n paymentId: string\n orderId?: string\n amount: number\n currencyCode: string\n captureMethod?: 'automatic' | 'manual'\n description?: string\n successUrl?: string\n cancelUrl?: string\n metadata?: Record<string, unknown>\n organizationId: string\n tenantId: string\n}\n\nexport function createPaymentGatewayService(deps: PaymentGatewayServiceDeps) {\n const { em, integrationCredentialsService, integrationLogService } = deps\n\n async function findTransactionOrThrow(\n transactionId: string,\n scope: { organizationId: string; tenantId: string },\n ): Promise<GatewayTransaction> {\n const transaction = await findOneWithDecryption(\n em,\n GatewayTransaction,\n {\n id: transactionId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!transaction) {\n throw new Error('Transaction not found')\n }\n return transaction\n }\n\n function readProviderSessionId(transaction: GatewayTransaction): string {\n if (typeof transaction.providerSessionId === 'string' && transaction.providerSessionId.trim().length > 0) {\n return transaction.providerSessionId\n }\n throw new Error('Transaction is missing provider session id')\n }\n\n async function emitStatusEvent(status: UnifiedPaymentStatus, payload: Record<string, unknown>) {\n type PaymentGatewayEventId = Parameters<typeof emitPaymentGatewayEvent>[0]\n const eventMap: Partial<Record<UnifiedPaymentStatus, PaymentGatewayEventId>> = {\n authorized: 'payment_gateways.payment.authorized',\n captured: 'payment_gateways.payment.captured',\n failed: 'payment_gateways.payment.failed',\n refunded: 'payment_gateways.payment.refunded',\n cancelled: 'payment_gateways.payment.cancelled',\n }\n const eventId = eventMap[status]\n if (!eventId) return\n await emitPaymentGatewayEvent(eventId, payload)\n }\n\n async function writeTransactionLog(\n providerKey: string,\n scope: { organizationId: string; tenantId: string },\n transactionId: string,\n level: 'info' | 'warn' | 'error',\n message: string,\n payload?: Record<string, unknown> | null,\n code?: string | null,\n ) {\n if (!integrationLogService) return\n await integrationLogService.write({\n integrationId: `gateway_${providerKey}`,\n scopeEntityType: 'payment_transaction',\n scopeEntityId: transactionId,\n level,\n message,\n code,\n payload: payload ?? null,\n }, scope)\n }\n\n async function resolveAdapterAndCredentials(providerKey: string, scope: { organizationId: string; tenantId: string }) {\n const integrationId = `gateway_${providerKey}`\n const selectedVersion = deps.integrationStateService\n ? await deps.integrationStateService.resolveApiVersion(integrationId, scope)\n : undefined\n const adapter = getGatewayAdapter(providerKey, selectedVersion)\n if (!adapter) {\n throw new Error(\n selectedVersion\n ? `No gateway adapter registered for provider: ${providerKey} (version: ${selectedVersion})`\n : `No gateway adapter registered for provider: ${providerKey}`,\n )\n }\n const credentials = await integrationCredentialsService.resolve(integrationId, scope) ?? {}\n\n return { adapter, credentials }\n }\n\n return {\n async createPaymentSession(input: CreatePaymentSessionInput): Promise<{ transaction: GatewayTransaction; session: CreateSessionResult }> {\n const scope = { organizationId: input.organizationId, tenantId: input.tenantId }\n const { adapter, credentials } = await resolveAdapterAndCredentials(input.providerKey, scope)\n\n const sessionInput: CreateSessionInput = {\n paymentId: input.paymentId,\n orderId: input.orderId,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n amount: input.amount,\n currencyCode: input.currencyCode,\n captureMethod: input.captureMethod,\n description: input.description,\n successUrl: input.successUrl,\n cancelUrl: input.cancelUrl,\n metadata: input.metadata,\n credentials,\n }\n\n const session = await adapter.createSession(sessionInput)\n\n const transaction = em.create(GatewayTransaction, {\n paymentId: input.paymentId,\n providerKey: input.providerKey,\n providerSessionId: session.sessionId,\n unifiedStatus: session.status,\n redirectUrl: session.redirectUrl ?? null,\n clientSecret: null,\n amount: String(input.amount),\n currencyCode: input.currencyCode,\n gatewayMetadata: session.providerData ?? null,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n })\n await em.persistAndFlush(transaction)\n await emitPaymentGatewayEvent('payment_gateways.session.created', {\n transactionId: transaction.id,\n paymentId: transaction.paymentId,\n providerKey: transaction.providerKey,\n status: transaction.unifiedStatus,\n organizationId: transaction.organizationId,\n tenantId: transaction.tenantId,\n })\n await writeTransactionLog(\n transaction.providerKey,\n scope,\n transaction.id,\n 'info',\n 'Payment session created',\n {\n paymentId: transaction.paymentId,\n providerSessionId: transaction.providerSessionId,\n status: transaction.unifiedStatus,\n amount: input.amount,\n currencyCode: input.currencyCode,\n },\n )\n\n return { transaction, session }\n },\n\n async capturePayment(transactionId: string, amount: number | undefined, scope: { organizationId: string; tenantId: string }): Promise<CaptureResult> {\n const transaction = await findTransactionOrThrow(transactionId, scope)\n const { adapter, credentials } = await resolveAdapterAndCredentials(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n )\n\n const result = await adapter.capture({\n sessionId: readProviderSessionId(transaction),\n amount,\n credentials,\n })\n\n transaction.unifiedStatus = result.status\n transaction.gatewayMetadata = { ...transaction.gatewayMetadata, captureResult: result.providerData }\n await em.flush()\n await emitStatusEvent(result.status, {\n transactionId: transaction.id,\n paymentId: transaction.paymentId,\n providerKey: transaction.providerKey,\n organizationId: transaction.organizationId,\n tenantId: transaction.tenantId,\n })\n await writeTransactionLog(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n transaction.id,\n 'info',\n 'Payment captured',\n {\n amount: amount ?? null,\n status: result.status,\n capturedAmount: result.capturedAmount,\n },\n )\n\n return result\n },\n\n async refundPayment(\n transactionId: string,\n amount: number | undefined,\n reason: string | undefined,\n scope: { organizationId: string; tenantId: string },\n ): Promise<RefundResult> {\n const transaction = await findTransactionOrThrow(transactionId, scope)\n const { adapter, credentials } = await resolveAdapterAndCredentials(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n )\n\n const result = await adapter.refund({\n sessionId: readProviderSessionId(transaction),\n amount,\n reason,\n credentials,\n })\n\n transaction.unifiedStatus = result.status\n transaction.gatewayRefundId = result.refundId\n transaction.gatewayMetadata = { ...transaction.gatewayMetadata, refundResult: result.providerData }\n await em.flush()\n await emitStatusEvent(result.status, {\n transactionId: transaction.id,\n paymentId: transaction.paymentId,\n providerKey: transaction.providerKey,\n organizationId: transaction.organizationId,\n tenantId: transaction.tenantId,\n })\n await writeTransactionLog(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n transaction.id,\n 'info',\n 'Payment refunded',\n {\n amount: amount ?? null,\n reason: reason ?? null,\n status: result.status,\n refundId: result.refundId,\n },\n )\n\n return result\n },\n\n async cancelPayment(\n transactionId: string,\n reason: string | undefined,\n scope: { organizationId: string; tenantId: string },\n ): Promise<CancelResult> {\n const transaction = await findTransactionOrThrow(transactionId, scope)\n const { adapter, credentials } = await resolveAdapterAndCredentials(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n )\n\n const result = await adapter.cancel({\n sessionId: readProviderSessionId(transaction),\n reason,\n credentials,\n })\n\n transaction.unifiedStatus = result.status\n await em.flush()\n await emitStatusEvent(result.status, {\n transactionId: transaction.id,\n paymentId: transaction.paymentId,\n providerKey: transaction.providerKey,\n organizationId: transaction.organizationId,\n tenantId: transaction.tenantId,\n })\n await writeTransactionLog(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n transaction.id,\n 'info',\n 'Payment cancelled',\n {\n reason: reason ?? null,\n status: result.status,\n },\n )\n\n return result\n },\n\n async getPaymentStatus(transactionId: string, scope: { organizationId: string; tenantId: string }): Promise<GatewayPaymentStatus> {\n const transaction = await findTransactionOrThrow(transactionId, scope)\n const { adapter, credentials } = await resolveAdapterAndCredentials(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n )\n\n const status = await adapter.getStatus({\n sessionId: readProviderSessionId(transaction),\n credentials,\n })\n\n if (status.status !== transaction.unifiedStatus && isValidTransition(transaction.unifiedStatus as UnifiedPaymentStatus, status.status)) {\n const previousStatus = transaction.unifiedStatus\n transaction.unifiedStatus = status.status\n transaction.gatewayStatus = status.status\n transaction.gatewayMetadata = { ...transaction.gatewayMetadata, statusResult: status.providerData ?? null }\n transaction.lastPolledAt = new Date()\n await em.flush()\n await emitStatusEvent(status.status, {\n transactionId: transaction.id,\n paymentId: transaction.paymentId,\n providerKey: transaction.providerKey,\n previousStatus,\n organizationId: transaction.organizationId,\n tenantId: transaction.tenantId,\n })\n await writeTransactionLog(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n transaction.id,\n 'info',\n 'Payment status updated by poller',\n {\n previousStatus,\n nextStatus: status.status,\n },\n )\n }\n\n return status\n },\n\n async syncTransactionStatus(transactionId: string, update: {\n unifiedStatus: UnifiedPaymentStatus\n providerStatus?: string\n providerData?: Record<string, unknown>\n webhookEvent?: {\n eventType: string\n idempotencyKey: string\n processed: boolean\n receivedAt?: string\n }\n }, scope: { organizationId: string; tenantId: string }): Promise<void> {\n const transaction = await findTransactionOrThrow(transactionId, scope)\n const currentStatus = transaction.unifiedStatus as UnifiedPaymentStatus\n const canTransition = isValidTransition(currentStatus, update.unifiedStatus)\n const shouldApplyStatus = canTransition && update.unifiedStatus !== currentStatus\n const previousStatus = transaction.unifiedStatus\n if (shouldApplyStatus) {\n transaction.unifiedStatus = update.unifiedStatus\n }\n if (update.providerStatus) {\n transaction.gatewayStatus = update.providerStatus\n }\n if (update.providerData) {\n transaction.gatewayMetadata = { ...transaction.gatewayMetadata, ...update.providerData }\n }\n if (update.webhookEvent) {\n const webhookLog = Array.isArray(transaction.webhookLog) ? transaction.webhookLog : []\n webhookLog.push({\n eventType: update.webhookEvent.eventType,\n receivedAt: update.webhookEvent.receivedAt ?? new Date().toISOString(),\n idempotencyKey: update.webhookEvent.idempotencyKey,\n unifiedStatus: update.unifiedStatus,\n processed: update.webhookEvent.processed,\n })\n transaction.webhookLog = webhookLog\n }\n transaction.lastWebhookAt = new Date()\n await em.flush()\n if (shouldApplyStatus) {\n await emitStatusEvent(update.unifiedStatus, {\n transactionId: transaction.id,\n paymentId: transaction.paymentId,\n providerKey: transaction.providerKey,\n previousStatus,\n organizationId: transaction.organizationId,\n tenantId: transaction.tenantId,\n })\n }\n await writeTransactionLog(\n transaction.providerKey,\n { organizationId: transaction.organizationId, tenantId: transaction.tenantId },\n transaction.id,\n shouldApplyStatus ? 'info' : 'warn',\n shouldApplyStatus ? 'Payment status synchronized from webhook' : 'Webhook received with no status transition',\n {\n previousStatus,\n nextStatus: update.unifiedStatus,\n providerStatus: update.providerStatus ?? null,\n eventType: update.webhookEvent?.eventType ?? null,\n idempotencyKey: update.webhookEvent?.idempotencyKey ?? null,\n },\n )\n },\n\n async findTransaction(id: string, scope: { organizationId: string; tenantId: string }): Promise<GatewayTransaction | null> {\n return findOneWithDecryption(\n em,\n GatewayTransaction,\n {\n id,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n },\n\n async findTransactionBySessionId(\n providerSessionId: string,\n scope: { organizationId: string; tenantId: string },\n providerKey?: string,\n ): Promise<GatewayTransaction | null> {\n return findOneWithDecryption(\n em,\n GatewayTransaction,\n {\n providerSessionId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n ...(providerKey ? { providerKey } : {}),\n },\n undefined,\n scope,\n )\n },\n\n async listTransactionsForStatusPolling(scope?: {\n organizationId?: string\n tenantId?: string\n providerKey?: string\n limit?: number\n }): Promise<GatewayTransaction[]> {\n const where: Record<string, unknown> = {\n unifiedStatus: { $in: ['pending', 'authorized', 'partially_captured'] },\n deletedAt: null,\n }\n if (scope?.organizationId) where.organizationId = scope.organizationId\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.providerKey) where.providerKey = scope.providerKey\n\n return findWithDecryption(\n em,\n GatewayTransaction,\n where,\n {\n orderBy: { updatedAt: 'asc' },\n limit: scope?.limit ?? 100,\n },\n scope,\n )\n },\n }\n}\n\nexport type PaymentGatewayService = ReturnType<typeof createPaymentGatewayService>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createQueue } from "@open-mercato/queue";
|
|
2
|
+
import { getRedisUrl } from "@open-mercato/shared/lib/redis/connection";
|
|
3
|
+
const queues = /* @__PURE__ */ new Map();
|
|
4
|
+
function getPaymentGatewayQueue(queueName) {
|
|
5
|
+
const existing = queues.get(queueName);
|
|
6
|
+
if (existing) return existing;
|
|
7
|
+
const created = process.env.QUEUE_STRATEGY === "async" ? createQueue(queueName, "async", {
|
|
8
|
+
connection: { url: getRedisUrl("QUEUE") },
|
|
9
|
+
concurrency: Math.max(1, Number.parseInt(process.env.PAYMENT_GATEWAY_QUEUE_CONCURRENCY ?? "5", 10) || 5)
|
|
10
|
+
}) : createQueue(queueName, "local");
|
|
11
|
+
queues.set(queueName, created);
|
|
12
|
+
return created;
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
getPaymentGatewayQueue
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/payment_gateways/lib/queue.ts"],
|
|
4
|
+
"sourcesContent": ["import { createQueue, type Queue } from '@open-mercato/queue'\nimport { getRedisUrl } from '@open-mercato/shared/lib/redis/connection'\n\nconst queues = new Map<string, Queue<Record<string, unknown>>>()\n\nexport function getPaymentGatewayQueue(queueName: string): Queue<Record<string, unknown>> {\n const existing = queues.get(queueName)\n if (existing) return existing\n\n const created = process.env.QUEUE_STRATEGY === 'async'\n ? createQueue<Record<string, unknown>>(queueName, 'async', {\n connection: { url: getRedisUrl('QUEUE') },\n concurrency: Math.max(1, Number.parseInt(process.env.PAYMENT_GATEWAY_QUEUE_CONCURRENCY ?? '5', 10) || 5),\n })\n : createQueue<Record<string, unknown>>(queueName, 'local')\n\n queues.set(queueName, created)\n return created\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,mBAA+B;AACxC,SAAS,mBAAmB;AAE5B,MAAM,SAAS,oBAAI,IAA4C;AAExD,SAAS,uBAAuB,WAAmD;AACxF,QAAM,WAAW,OAAO,IAAI,SAAS;AACrC,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,QAAQ,IAAI,mBAAmB,UAC3C,YAAqC,WAAW,SAAS;AAAA,IACzD,YAAY,EAAE,KAAK,YAAY,OAAO,EAAE;AAAA,IACxC,aAAa,KAAK,IAAI,GAAG,OAAO,SAAS,QAAQ,IAAI,qCAAqC,KAAK,EAAE,KAAK,CAAC;AAAA,EACzG,CAAC,IACC,YAAqC,WAAW,OAAO;AAE3D,SAAO,IAAI,WAAW,OAAO;AAC7B,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const VALID_TRANSITIONS = {
|
|
2
|
+
pending: ["authorized", "captured", "failed", "expired", "cancelled"],
|
|
3
|
+
authorized: ["captured", "partially_captured", "cancelled", "failed"],
|
|
4
|
+
captured: ["refunded", "partially_refunded"],
|
|
5
|
+
partially_captured: ["captured", "refunded", "partially_refunded", "cancelled"],
|
|
6
|
+
partially_refunded: ["refunded"]
|
|
7
|
+
// Terminal states: refunded, cancelled, failed, expired — no valid transitions out
|
|
8
|
+
};
|
|
9
|
+
const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
10
|
+
"refunded",
|
|
11
|
+
"cancelled",
|
|
12
|
+
"failed",
|
|
13
|
+
"expired"
|
|
14
|
+
]);
|
|
15
|
+
function isValidTransition(from, to) {
|
|
16
|
+
if (from === to) return false;
|
|
17
|
+
const allowed = VALID_TRANSITIONS[from];
|
|
18
|
+
if (!allowed) return false;
|
|
19
|
+
return allowed.includes(to);
|
|
20
|
+
}
|
|
21
|
+
function isTerminalStatus(status) {
|
|
22
|
+
return TERMINAL_STATUSES.has(status);
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
TERMINAL_STATUSES,
|
|
26
|
+
isTerminalStatus,
|
|
27
|
+
isValidTransition
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=status-machine.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/payment_gateways/lib/status-machine.ts"],
|
|
4
|
+
"sourcesContent": ["import type { UnifiedPaymentStatus } from '@open-mercato/shared/modules/payment_gateways/types'\n\nconst VALID_TRANSITIONS: Record<string, UnifiedPaymentStatus[]> = {\n pending: ['authorized', 'captured', 'failed', 'expired', 'cancelled'],\n authorized: ['captured', 'partially_captured', 'cancelled', 'failed'],\n captured: ['refunded', 'partially_refunded'],\n partially_captured: ['captured', 'refunded', 'partially_refunded', 'cancelled'],\n partially_refunded: ['refunded'],\n // Terminal states: refunded, cancelled, failed, expired \u2014 no valid transitions out\n}\n\nexport const TERMINAL_STATUSES: Set<UnifiedPaymentStatus> = new Set([\n 'refunded',\n 'cancelled',\n 'failed',\n 'expired',\n])\n\nexport function isValidTransition(from: UnifiedPaymentStatus, to: UnifiedPaymentStatus): boolean {\n if (from === to) return false\n const allowed = VALID_TRANSITIONS[from]\n if (!allowed) return false\n return allowed.includes(to)\n}\n\nexport function isTerminalStatus(status: UnifiedPaymentStatus): boolean {\n return TERMINAL_STATUSES.has(status)\n}\n"],
|
|
5
|
+
"mappings": "AAEA,MAAM,oBAA4D;AAAA,EAChE,SAAS,CAAC,cAAc,YAAY,UAAU,WAAW,WAAW;AAAA,EACpE,YAAY,CAAC,YAAY,sBAAsB,aAAa,QAAQ;AAAA,EACpE,UAAU,CAAC,YAAY,oBAAoB;AAAA,EAC3C,oBAAoB,CAAC,YAAY,YAAY,sBAAsB,WAAW;AAAA,EAC9E,oBAAoB,CAAC,UAAU;AAAA;AAEjC;AAEO,MAAM,oBAA+C,oBAAI,IAAI;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,kBAAkB,MAA4B,IAAmC;AAC/F,MAAI,SAAS,GAAI,QAAO;AACxB,QAAM,UAAU,kBAAkB,IAAI;AACtC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QAAQ,SAAS,EAAE;AAC5B;AAEO,SAAS,iBAAiB,QAAuC;AACtE,SAAO,kBAAkB,IAAI,MAAM;AACrC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { getGatewayAdapter } from "@open-mercato/shared/modules/payment_gateways/types";
|
|
2
|
+
import { claimWebhookProcessing, releaseWebhookClaim } from "./webhook-utils.js";
|
|
3
|
+
function readSessionIdFromEvent(event) {
|
|
4
|
+
const id = event.data.id;
|
|
5
|
+
if (typeof id === "string" && id.trim().length > 0) return id.trim();
|
|
6
|
+
const paymentIntent = event.data.payment_intent;
|
|
7
|
+
if (typeof paymentIntent === "string" && paymentIntent.trim().length > 0) return paymentIntent.trim();
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
function readScopeFromEvent(event) {
|
|
11
|
+
const metadata = event.data.metadata;
|
|
12
|
+
if (!metadata || typeof metadata !== "object") return null;
|
|
13
|
+
const metadataRecord = metadata;
|
|
14
|
+
const organizationId = typeof metadataRecord.organizationId === "string" ? metadataRecord.organizationId.trim() : "";
|
|
15
|
+
const tenantId = typeof metadataRecord.tenantId === "string" ? metadataRecord.tenantId.trim() : "";
|
|
16
|
+
if (!organizationId || !tenantId) return null;
|
|
17
|
+
return { organizationId, tenantId };
|
|
18
|
+
}
|
|
19
|
+
async function writeTransactionLog(integrationLogService, providerKey, scope, transactionId, level, message, payload) {
|
|
20
|
+
await integrationLogService.write({
|
|
21
|
+
integrationId: `gateway_${providerKey}`,
|
|
22
|
+
scopeEntityType: "payment_transaction",
|
|
23
|
+
scopeEntityId: transactionId,
|
|
24
|
+
level,
|
|
25
|
+
message,
|
|
26
|
+
payload: payload ?? null
|
|
27
|
+
}, scope);
|
|
28
|
+
}
|
|
29
|
+
async function processPaymentGatewayWebhookJob(deps, payload) {
|
|
30
|
+
const { em, paymentGatewayService, integrationLogService } = deps;
|
|
31
|
+
const { providerKey, event } = payload;
|
|
32
|
+
const scopedPayload = payload.scope ?? readScopeFromEvent(event);
|
|
33
|
+
let transaction = payload.transactionId && scopedPayload ? await paymentGatewayService.findTransaction(payload.transactionId, scopedPayload) : null;
|
|
34
|
+
if (!transaction) {
|
|
35
|
+
const sessionId = readSessionIdFromEvent(event);
|
|
36
|
+
if (sessionId && scopedPayload) {
|
|
37
|
+
transaction = await paymentGatewayService.findTransactionBySessionId(sessionId, scopedPayload, providerKey);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (!transaction) return;
|
|
41
|
+
const scope = { organizationId: transaction.organizationId, tenantId: transaction.tenantId };
|
|
42
|
+
const claimed = await claimWebhookProcessing(em, event.idempotencyKey, providerKey, scope, event.eventType);
|
|
43
|
+
if (!claimed) {
|
|
44
|
+
await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, "info", "Duplicate payment gateway webhook skipped", {
|
|
45
|
+
eventType: event.eventType,
|
|
46
|
+
idempotencyKey: event.idempotencyKey
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const adapter = getGatewayAdapter(providerKey);
|
|
52
|
+
if (!adapter) {
|
|
53
|
+
await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, "warn", "Missing payment gateway adapter for webhook event", {
|
|
54
|
+
providerKey,
|
|
55
|
+
eventType: event.eventType
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const providerStatus = typeof event.data.status === "string" ? event.data.status : "";
|
|
60
|
+
const unifiedStatus = adapter.mapStatus(providerStatus, event.eventType);
|
|
61
|
+
await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, "info", "Payment gateway webhook received", {
|
|
62
|
+
eventType: event.eventType,
|
|
63
|
+
providerStatus,
|
|
64
|
+
unifiedStatus
|
|
65
|
+
});
|
|
66
|
+
await paymentGatewayService.syncTransactionStatus(transaction.id, {
|
|
67
|
+
unifiedStatus,
|
|
68
|
+
providerStatus: event.eventType,
|
|
69
|
+
providerData: event.data,
|
|
70
|
+
webhookEvent: {
|
|
71
|
+
eventType: event.eventType,
|
|
72
|
+
idempotencyKey: event.idempotencyKey,
|
|
73
|
+
processed: true
|
|
74
|
+
}
|
|
75
|
+
}, scope);
|
|
76
|
+
await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, "info", "Payment gateway webhook processed", {
|
|
77
|
+
eventType: event.eventType,
|
|
78
|
+
unifiedStatus
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
await releaseWebhookClaim(em, event.idempotencyKey, providerKey, scope);
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
processPaymentGatewayWebhookJob
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=webhook-processor.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/payment_gateways/lib/webhook-processor.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { getGatewayAdapter, type WebhookEvent } from '@open-mercato/shared/modules/payment_gateways/types'\nimport type { IntegrationLogService } from '../../integrations/lib/log-service'\nimport type { PaymentGatewayService } from './gateway-service'\nimport { claimWebhookProcessing, releaseWebhookClaim } from './webhook-utils'\n\nexport type PaymentGatewayWebhookJobPayload = {\n providerKey: string\n event: WebhookEvent\n transactionId?: string | null\n scope?: {\n organizationId: string\n tenantId: string\n } | null\n}\n\ntype PaymentGatewayWebhookProcessorDeps = {\n em: EntityManager\n paymentGatewayService: PaymentGatewayService\n integrationLogService: IntegrationLogService\n}\n\nfunction readSessionIdFromEvent(event: WebhookEvent): string | null {\n const id = event.data.id\n if (typeof id === 'string' && id.trim().length > 0) return id.trim()\n const paymentIntent = event.data.payment_intent\n if (typeof paymentIntent === 'string' && paymentIntent.trim().length > 0) return paymentIntent.trim()\n return null\n}\n\nfunction readScopeFromEvent(event: WebhookEvent): { organizationId: string; tenantId: string } | null {\n const metadata = event.data.metadata\n if (!metadata || typeof metadata !== 'object') return null\n\n const metadataRecord = metadata as Record<string, unknown>\n const organizationId = typeof metadataRecord.organizationId === 'string'\n ? metadataRecord.organizationId.trim()\n : ''\n const tenantId = typeof metadataRecord.tenantId === 'string'\n ? metadataRecord.tenantId.trim()\n : ''\n\n if (!organizationId || !tenantId) return null\n return { organizationId, tenantId }\n}\n\nasync function writeTransactionLog(\n integrationLogService: IntegrationLogService,\n providerKey: string,\n scope: { organizationId: string; tenantId: string },\n transactionId: string,\n level: 'info' | 'warn' | 'error',\n message: string,\n payload?: Record<string, unknown>,\n) {\n await integrationLogService.write({\n integrationId: `gateway_${providerKey}`,\n scopeEntityType: 'payment_transaction',\n scopeEntityId: transactionId,\n level,\n message,\n payload: payload ?? null,\n }, scope)\n}\n\nexport async function processPaymentGatewayWebhookJob(\n deps: PaymentGatewayWebhookProcessorDeps,\n payload: PaymentGatewayWebhookJobPayload,\n): Promise<void> {\n const { em, paymentGatewayService, integrationLogService } = deps\n const { providerKey, event } = payload\n const scopedPayload = payload.scope ?? readScopeFromEvent(event)\n\n let transaction = payload.transactionId && scopedPayload\n ? await paymentGatewayService.findTransaction(payload.transactionId, scopedPayload)\n : null\n\n if (!transaction) {\n const sessionId = readSessionIdFromEvent(event)\n if (sessionId && scopedPayload) {\n transaction = await paymentGatewayService.findTransactionBySessionId(sessionId, scopedPayload, providerKey)\n }\n }\n if (!transaction) return\n\n const scope = { organizationId: transaction.organizationId, tenantId: transaction.tenantId }\n const claimed = await claimWebhookProcessing(em, event.idempotencyKey, providerKey, scope, event.eventType)\n if (!claimed) {\n await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, 'info', 'Duplicate payment gateway webhook skipped', {\n eventType: event.eventType,\n idempotencyKey: event.idempotencyKey,\n })\n return\n }\n\n try {\n const adapter = getGatewayAdapter(providerKey)\n if (!adapter) {\n await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, 'warn', 'Missing payment gateway adapter for webhook event', {\n providerKey,\n eventType: event.eventType,\n })\n return\n }\n\n const providerStatus = typeof event.data.status === 'string' ? event.data.status : ''\n const unifiedStatus = adapter.mapStatus(providerStatus, event.eventType)\n await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, 'info', 'Payment gateway webhook received', {\n eventType: event.eventType,\n providerStatus,\n unifiedStatus,\n })\n\n await paymentGatewayService.syncTransactionStatus(transaction.id, {\n unifiedStatus,\n providerStatus: event.eventType,\n providerData: event.data,\n webhookEvent: {\n eventType: event.eventType,\n idempotencyKey: event.idempotencyKey,\n processed: true,\n },\n }, scope)\n\n await writeTransactionLog(integrationLogService, providerKey, scope, transaction.id, 'info', 'Payment gateway webhook processed', {\n eventType: event.eventType,\n unifiedStatus,\n })\n } catch (error: unknown) {\n await releaseWebhookClaim(em, event.idempotencyKey, providerKey, scope)\n throw error\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { UniqueConstraintViolationException } from "@mikro-orm/core";
|
|
2
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
3
|
+
import { WebhookProcessedEvent } from "../data/entities.js";
|
|
4
|
+
async function claimWebhookProcessing(em, idempotencyKey, providerKey, scope, eventType) {
|
|
5
|
+
const record = em.create(WebhookProcessedEvent, {
|
|
6
|
+
idempotencyKey,
|
|
7
|
+
providerKey,
|
|
8
|
+
eventType,
|
|
9
|
+
organizationId: scope.organizationId,
|
|
10
|
+
tenantId: scope.tenantId
|
|
11
|
+
});
|
|
12
|
+
try {
|
|
13
|
+
await em.persistAndFlush(record);
|
|
14
|
+
return true;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (error instanceof UniqueConstraintViolationException) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function releaseWebhookClaim(em, idempotencyKey, providerKey, scope) {
|
|
23
|
+
const existing = await findOneWithDecryption(
|
|
24
|
+
em,
|
|
25
|
+
WebhookProcessedEvent,
|
|
26
|
+
{
|
|
27
|
+
idempotencyKey,
|
|
28
|
+
providerKey,
|
|
29
|
+
organizationId: scope.organizationId,
|
|
30
|
+
tenantId: scope.tenantId
|
|
31
|
+
},
|
|
32
|
+
void 0,
|
|
33
|
+
scope
|
|
34
|
+
);
|
|
35
|
+
if (!existing) return;
|
|
36
|
+
await em.removeAndFlush(existing);
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
claimWebhookProcessing,
|
|
40
|
+
releaseWebhookClaim
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=webhook-utils.js.map
|