@sakeetech/medusa-payment-viva 0.2.2
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/README.md +816 -0
- package/dist/api/index.d.ts +15 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +22 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/middlewares.d.ts +27 -0
- package/dist/api/middlewares.d.ts.map +1 -0
- package/dist/api/middlewares.js +62 -0
- package/dist/api/middlewares.js.map +1 -0
- package/dist/api/viva/admin/_admin-auth.d.ts +26 -0
- package/dist/api/viva/admin/_admin-auth.d.ts.map +1 -0
- package/dist/api/viva/admin/_admin-auth.js +49 -0
- package/dist/api/viva/admin/_admin-auth.js.map +1 -0
- package/dist/api/viva/admin/_mode-gate.d.ts +28 -0
- package/dist/api/viva/admin/_mode-gate.d.ts.map +1 -0
- package/dist/api/viva/admin/_mode-gate.js +45 -0
- package/dist/api/viva/admin/_mode-gate.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.d.ts +21 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.js +93 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.d.ts +18 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.js +59 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.d.ts +34 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.js +234 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/route.d.ts +19 -0
- package/dist/api/viva/admin/connected-accounts/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/route.js +78 -0
- package/dist/api/viva/admin/connected-accounts/route.js.map +1 -0
- package/dist/api/viva/internal/auth-status/route.d.ts +19 -0
- package/dist/api/viva/internal/auth-status/route.d.ts.map +1 -0
- package/dist/api/viva/internal/auth-status/route.js +91 -0
- package/dist/api/viva/internal/auth-status/route.js.map +1 -0
- package/dist/api/viva/internal/metrics/route.d.ts +13 -0
- package/dist/api/viva/internal/metrics/route.d.ts.map +1 -0
- package/dist/api/viva/internal/metrics/route.js +48 -0
- package/dist/api/viva/internal/metrics/route.js.map +1 -0
- package/dist/api/viva/webhook/health/route.d.ts +16 -0
- package/dist/api/viva/webhook/health/route.d.ts.map +1 -0
- package/dist/api/viva/webhook/health/route.js +27 -0
- package/dist/api/viva/webhook/health/route.js.map +1 -0
- package/dist/api/viva/webhook/route.d.ts +57 -0
- package/dist/api/viva/webhook/route.d.ts.map +1 -0
- package/dist/api/viva/webhook/route.js +269 -0
- package/dist/api/viva/webhook/route.js.map +1 -0
- package/dist/cli/bin.d.ts +12 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +78 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/plan.d.ts +51 -0
- package/dist/cli/plan.d.ts.map +1 -0
- package/dist/cli/plan.js +128 -0
- package/dist/cli/plan.js.map +1 -0
- package/dist/cli/register-webhooks.d.ts +54 -0
- package/dist/cli/register-webhooks.d.ts.map +1 -0
- package/dist/cli/register-webhooks.js +366 -0
- package/dist/cli/register-webhooks.js.map +1 -0
- package/dist/cli/types.d.ts +62 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +12 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/config.d.ts +158 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +236 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/loaders/viva-oauth2-strategy.d.ts +26 -0
- package/dist/loaders/viva-oauth2-strategy.d.ts.map +1 -0
- package/dist/loaders/viva-oauth2-strategy.js +58 -0
- package/dist/loaders/viva-oauth2-strategy.js.map +1 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.d.ts +19 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.js +136 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.js.map +1 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.d.ts +31 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.js +71 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.js.map +1 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.d.ts +18 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.js +42 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.js.map +1 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.d.ts +29 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.js +74 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.js.map +1 -0
- package/dist/models/index.d.ts +7 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +10 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/viva-tenant-merchant.d.ts +11 -0
- package/dist/models/viva-tenant-merchant.d.ts.map +1 -0
- package/dist/models/viva-tenant-merchant.js +54 -0
- package/dist/models/viva-tenant-merchant.js.map +1 -0
- package/dist/models/viva-transaction.d.ts +34 -0
- package/dist/models/viva-transaction.d.ts.map +1 -0
- package/dist/models/viva-transaction.js +104 -0
- package/dist/models/viva-transaction.js.map +1 -0
- package/dist/models/viva-webhook-event.d.ts +32 -0
- package/dist/models/viva-webhook-event.d.ts.map +1 -0
- package/dist/models/viva-webhook-event.js +88 -0
- package/dist/models/viva-webhook-event.js.map +1 -0
- package/dist/observability/config.d.ts +34 -0
- package/dist/observability/config.d.ts.map +1 -0
- package/dist/observability/config.js +57 -0
- package/dist/observability/config.js.map +1 -0
- package/dist/observability/index.d.ts +8 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +15 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/prom-metrics.d.ts +41 -0
- package/dist/observability/prom-metrics.d.ts.map +1 -0
- package/dist/observability/prom-metrics.js +219 -0
- package/dist/observability/prom-metrics.js.map +1 -0
- package/dist/providers/payment-provider.d.ts +19 -0
- package/dist/providers/payment-provider.d.ts.map +1 -0
- package/dist/providers/payment-provider.js +24 -0
- package/dist/providers/payment-provider.js.map +1 -0
- package/dist/resolvers/auth-strategy-factory.d.ts +42 -0
- package/dist/resolvers/auth-strategy-factory.d.ts.map +1 -0
- package/dist/resolvers/auth-strategy-factory.js +60 -0
- package/dist/resolvers/auth-strategy-factory.js.map +1 -0
- package/dist/resolvers/tenant-resolver.d.ts +104 -0
- package/dist/resolvers/tenant-resolver.d.ts.map +1 -0
- package/dist/resolvers/tenant-resolver.js +118 -0
- package/dist/resolvers/tenant-resolver.js.map +1 -0
- package/dist/service.d.ts +200 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +1003 -0
- package/dist/service.js.map +1 -0
- package/dist/subscribers/index.d.ts +5 -0
- package/dist/subscribers/index.d.ts.map +1 -0
- package/dist/subscribers/index.js +10 -0
- package/dist/subscribers/index.js.map +1 -0
- package/dist/subscribers/viva-webhook-event.d.ts +38 -0
- package/dist/subscribers/viva-webhook-event.d.ts.map +1 -0
- package/dist/subscribers/viva-webhook-event.js +133 -0
- package/dist/subscribers/viva-webhook-event.js.map +1 -0
- package/dist/workflows/cleanup-old-webhook-events.d.ts +39 -0
- package/dist/workflows/cleanup-old-webhook-events.d.ts.map +1 -0
- package/dist/workflows/cleanup-old-webhook-events.js +68 -0
- package/dist/workflows/cleanup-old-webhook-events.js.map +1 -0
- package/dist/workflows/index.d.ts +14 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +19 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/per-tenant-semaphore.d.ts +47 -0
- package/dist/workflows/per-tenant-semaphore.d.ts.map +1 -0
- package/dist/workflows/per-tenant-semaphore.js +89 -0
- package/dist/workflows/per-tenant-semaphore.js.map +1 -0
- package/dist/workflows/process-webhook-event.d.ts +80 -0
- package/dist/workflows/process-webhook-event.d.ts.map +1 -0
- package/dist/workflows/process-webhook-event.js +280 -0
- package/dist/workflows/process-webhook-event.js.map +1 -0
- package/dist/workflows/reprocess-unresolved-tenants.d.ts +58 -0
- package/dist/workflows/reprocess-unresolved-tenants.d.ts.map +1 -0
- package/dist/workflows/reprocess-unresolved-tenants.js +121 -0
- package/dist/workflows/reprocess-unresolved-tenants.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api/index.ts — barrel re-export for Medusa v2 API route registration.
|
|
3
|
+
*
|
|
4
|
+
* Medusa v2 file-based routing convention: the framework scans `src/api/`
|
|
5
|
+
* for `route.ts` files and mounts them at the path matching the directory
|
|
6
|
+
* structure. `middlewares.ts` at the root of `src/api/` is auto-loaded as the
|
|
7
|
+
* middleware configuration for all routes in this API tree.
|
|
8
|
+
*
|
|
9
|
+
* - `src/api/middlewares.ts` → middleware config (raw body capture)
|
|
10
|
+
* - `src/api/viva/webhook/route.ts` → GET + POST handlers at /viva/webhook
|
|
11
|
+
*
|
|
12
|
+
* @see @medusajs/framework dist/http/router.d.ts (ApiLoader file-based convention)
|
|
13
|
+
*/
|
|
14
|
+
export { default as middlewares } from './middlewares.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* api/index.ts — barrel re-export for Medusa v2 API route registration.
|
|
4
|
+
*
|
|
5
|
+
* Medusa v2 file-based routing convention: the framework scans `src/api/`
|
|
6
|
+
* for `route.ts` files and mounts them at the path matching the directory
|
|
7
|
+
* structure. `middlewares.ts` at the root of `src/api/` is auto-loaded as the
|
|
8
|
+
* middleware configuration for all routes in this API tree.
|
|
9
|
+
*
|
|
10
|
+
* - `src/api/middlewares.ts` → middleware config (raw body capture)
|
|
11
|
+
* - `src/api/viva/webhook/route.ts` → GET + POST handlers at /viva/webhook
|
|
12
|
+
*
|
|
13
|
+
* @see @medusajs/framework dist/http/router.d.ts (ApiLoader file-based convention)
|
|
14
|
+
*/
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.middlewares = void 0;
|
|
20
|
+
var middlewares_js_1 = require("./middlewares.js");
|
|
21
|
+
Object.defineProperty(exports, "middlewares", { enumerable: true, get: function () { return __importDefault(middlewares_js_1).default; } });
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;;;;AAEH,mDAA0D;AAAjD,8HAAA,OAAO,OAAe"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* middlewares.ts — Medusa v2 middleware registration for the Viva webhook route.
|
|
3
|
+
*
|
|
4
|
+
* Captures raw request body as Buffer before JSON body-parser runs.
|
|
5
|
+
* Required for HMAC-SHA256 signature verification of event 7936.
|
|
6
|
+
*
|
|
7
|
+
* Convention used: `defineMiddlewares()` from `@medusajs/framework/http`, which
|
|
8
|
+
* is the standard Medusa v2 plugin middleware pattern.
|
|
9
|
+
*
|
|
10
|
+
* @see references/viva-docs/md/webhooks-for-payments.txt:254 (webhook security model P7)
|
|
11
|
+
* @see references/viva-docs/md/wh-sale-transactions.txt:149 (HMAC raw body requirement)
|
|
12
|
+
*/
|
|
13
|
+
import type { MedusaNextFunction, MedusaRequest, MedusaResponse } from '@medusajs/framework/http';
|
|
14
|
+
/**
|
|
15
|
+
* Express middleware that captures the raw request body as a Buffer.
|
|
16
|
+
* Must run BEFORE any JSON body-parser so the unmodified bytes are available
|
|
17
|
+
* for HMAC-SHA256 signature verification (event 7936).
|
|
18
|
+
*
|
|
19
|
+
* Attaches the Buffer to `req.rawBody`. Medusa's MedusaRequest type already
|
|
20
|
+
* declares `rawBody?: any`, so no augmentation is needed.
|
|
21
|
+
*
|
|
22
|
+
* @see references/viva-docs/md/wh-sale-transactions.txt:149 (HMAC raw bytes)
|
|
23
|
+
*/
|
|
24
|
+
export declare function vivaWebhookRawBodyMiddleware(): (req: MedusaRequest, _res: MedusaResponse, next: MedusaNextFunction) => void;
|
|
25
|
+
declare const _default: import("@medusajs/framework/http").MiddlewaresConfig;
|
|
26
|
+
export default _default;
|
|
27
|
+
//# sourceMappingURL=middlewares.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/api/middlewares.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAOlG;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,KAExC,KAAK,aAAa,EAClB,MAAM,cAAc,EACpB,MAAM,kBAAkB,KACvB,IAAI,CAgBR;;AAYD,wBAOG"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* middlewares.ts — Medusa v2 middleware registration for the Viva webhook route.
|
|
4
|
+
*
|
|
5
|
+
* Captures raw request body as Buffer before JSON body-parser runs.
|
|
6
|
+
* Required for HMAC-SHA256 signature verification of event 7936.
|
|
7
|
+
*
|
|
8
|
+
* Convention used: `defineMiddlewares()` from `@medusajs/framework/http`, which
|
|
9
|
+
* is the standard Medusa v2 plugin middleware pattern.
|
|
10
|
+
*
|
|
11
|
+
* @see references/viva-docs/md/webhooks-for-payments.txt:254 (webhook security model P7)
|
|
12
|
+
* @see references/viva-docs/md/wh-sale-transactions.txt:149 (HMAC raw body requirement)
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.vivaWebhookRawBodyMiddleware = vivaWebhookRawBodyMiddleware;
|
|
16
|
+
const http_1 = require("@medusajs/framework/http");
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Raw body capture middleware
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
/**
|
|
21
|
+
* Express middleware that captures the raw request body as a Buffer.
|
|
22
|
+
* Must run BEFORE any JSON body-parser so the unmodified bytes are available
|
|
23
|
+
* for HMAC-SHA256 signature verification (event 7936).
|
|
24
|
+
*
|
|
25
|
+
* Attaches the Buffer to `req.rawBody`. Medusa's MedusaRequest type already
|
|
26
|
+
* declares `rawBody?: any`, so no augmentation is needed.
|
|
27
|
+
*
|
|
28
|
+
* @see references/viva-docs/md/wh-sale-transactions.txt:149 (HMAC raw bytes)
|
|
29
|
+
*/
|
|
30
|
+
function vivaWebhookRawBodyMiddleware() {
|
|
31
|
+
return function captureRawBody(req, _res, next) {
|
|
32
|
+
const chunks = [];
|
|
33
|
+
req.on('data', (chunk) => {
|
|
34
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
35
|
+
});
|
|
36
|
+
req.on('end', () => {
|
|
37
|
+
req.rawBody = Buffer.concat(chunks);
|
|
38
|
+
next();
|
|
39
|
+
});
|
|
40
|
+
req.on('error', (err) => {
|
|
41
|
+
next(err);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Middleware registration (Medusa v2 convention)
|
|
47
|
+
//
|
|
48
|
+
// Medusa v2 loads `src/api/middlewares.ts` and calls the default export to
|
|
49
|
+
// obtain a MiddlewaresConfig. `defineMiddlewares` validates and types the config.
|
|
50
|
+
//
|
|
51
|
+
// `bodyParser: false` disables Medusa's built-in JSON parser for the POST route
|
|
52
|
+
// so we control body consumption ourselves in the raw-body middleware.
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
exports.default = (0, http_1.defineMiddlewares)([
|
|
55
|
+
{
|
|
56
|
+
matcher: '/viva/webhook',
|
|
57
|
+
methods: ['POST'],
|
|
58
|
+
bodyParser: false,
|
|
59
|
+
middlewares: [vivaWebhookRawBodyMiddleware()],
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
62
|
+
//# sourceMappingURL=middlewares.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/api/middlewares.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AAmBH,oEAqBC;AArCD,mDAA6D;AAE7D,8EAA8E;AAC9E,8BAA8B;AAC9B,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,SAAgB,4BAA4B;IAC1C,OAAO,SAAS,cAAc,CAC5B,GAAkB,EAClB,IAAoB,EACpB,IAAwB;QAExB,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;YACxC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;YAC7B,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,iDAAiD;AACjD,EAAE;AACF,2EAA2E;AAC3E,kFAAkF;AAClF,EAAE;AACF,gFAAgF;AAChF,uEAAuE;AACvE,8EAA8E;AAE9E,kBAAe,IAAA,wBAAiB,EAAC;IAC/B;QACE,OAAO,EAAE,eAAe;QACxB,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,CAAC,4BAA4B,EAAE,CAAC;KAC9C;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _admin-auth.ts — shared admin-token gate for `/viva/admin/*` routes.
|
|
3
|
+
*
|
|
4
|
+
* Extracted in slice F so all admin routes share one timing-safe token check.
|
|
5
|
+
* Behaviour is identical to the inline copies that previously lived in each
|
|
6
|
+
* route file: reads `VIVA_ADMIN_TOKEN` from the process env, compares it
|
|
7
|
+
* against the `x-viva-admin-token` request header using `timingSafeEqual`,
|
|
8
|
+
* and writes a `401 { error: 'unauthorized' }` envelope on mismatch.
|
|
9
|
+
*
|
|
10
|
+
* When `VIVA_ADMIN_TOKEN` is unset the gate fails closed with
|
|
11
|
+
* `{ error: 'unauthorized', reason: 'admin-token-not-configured' }` — same
|
|
12
|
+
* envelope shape used by `/viva/internal/*` so the operator gets a clear
|
|
13
|
+
* configuration hint without leaking whether a token was provided.
|
|
14
|
+
*
|
|
15
|
+
* @see docs/plans/multi-mode-v0.md §6 (admin REST table)
|
|
16
|
+
*/
|
|
17
|
+
import type { MedusaRequest, MedusaResponse } from '@medusajs/framework/http';
|
|
18
|
+
/**
|
|
19
|
+
* Returns `true` and writes a 401 response when the admin token is missing
|
|
20
|
+
* or invalid. Returns `false` when the request is authorized.
|
|
21
|
+
*
|
|
22
|
+
* Reads `VIVA_ADMIN_TOKEN` lazily from `process.env` so tests can swap it
|
|
23
|
+
* between requests.
|
|
24
|
+
*/
|
|
25
|
+
export declare function reject401IfUnauthorized(req: MedusaRequest, res: MedusaResponse): boolean;
|
|
26
|
+
//# sourceMappingURL=_admin-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_admin-auth.d.ts","sourceRoot":"","sources":["../../../../src/api/viva/admin/_admin-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAW9E;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,aAAa,EAClB,GAAG,EAAE,cAAc,GAClB,OAAO,CAeT"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* _admin-auth.ts — shared admin-token gate for `/viva/admin/*` routes.
|
|
4
|
+
*
|
|
5
|
+
* Extracted in slice F so all admin routes share one timing-safe token check.
|
|
6
|
+
* Behaviour is identical to the inline copies that previously lived in each
|
|
7
|
+
* route file: reads `VIVA_ADMIN_TOKEN` from the process env, compares it
|
|
8
|
+
* against the `x-viva-admin-token` request header using `timingSafeEqual`,
|
|
9
|
+
* and writes a `401 { error: 'unauthorized' }` envelope on mismatch.
|
|
10
|
+
*
|
|
11
|
+
* When `VIVA_ADMIN_TOKEN` is unset the gate fails closed with
|
|
12
|
+
* `{ error: 'unauthorized', reason: 'admin-token-not-configured' }` — same
|
|
13
|
+
* envelope shape used by `/viva/internal/*` so the operator gets a clear
|
|
14
|
+
* configuration hint without leaking whether a token was provided.
|
|
15
|
+
*
|
|
16
|
+
* @see docs/plans/multi-mode-v0.md §6 (admin REST table)
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.reject401IfUnauthorized = reject401IfUnauthorized;
|
|
20
|
+
const node_crypto_1 = require("node:crypto");
|
|
21
|
+
function isTokenValid(provided, expected) {
|
|
22
|
+
if (provided.length !== expected.length)
|
|
23
|
+
return false;
|
|
24
|
+
return (0, node_crypto_1.timingSafeEqual)(Buffer.from(provided, 'utf-8'), Buffer.from(expected, 'utf-8'));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns `true` and writes a 401 response when the admin token is missing
|
|
28
|
+
* or invalid. Returns `false` when the request is authorized.
|
|
29
|
+
*
|
|
30
|
+
* Reads `VIVA_ADMIN_TOKEN` lazily from `process.env` so tests can swap it
|
|
31
|
+
* between requests.
|
|
32
|
+
*/
|
|
33
|
+
function reject401IfUnauthorized(req, res) {
|
|
34
|
+
const adminToken = process.env['VIVA_ADMIN_TOKEN'];
|
|
35
|
+
if (!adminToken) {
|
|
36
|
+
res
|
|
37
|
+
.status(401)
|
|
38
|
+
.json({ error: 'unauthorized', reason: 'admin-token-not-configured' });
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
const provided = req.headers['x-viva-admin-token'];
|
|
42
|
+
const providedStr = Array.isArray(provided) ? provided[0] : provided;
|
|
43
|
+
if (!providedStr || !isTokenValid(providedStr, adminToken)) {
|
|
44
|
+
res.status(401).json({ error: 'unauthorized' });
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=_admin-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_admin-auth.js","sourceRoot":"","sources":["../../../../src/api/viva/admin/_admin-auth.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;AAoBH,0DAkBC;AAnCD,6CAA8C;AAE9C,SAAS,YAAY,CAAC,QAAgB,EAAE,QAAgB;IACtD,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACtD,OAAO,IAAA,6BAAe,EACpB,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,EAC9B,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAC/B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,GAAkB,EAClB,GAAmB;IAEnB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,GAAG;aACA,MAAM,CAAC,GAAG,CAAC;aACX,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrE,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _mode-gate.ts — shared 404 short-circuit for ISV-only admin routes.
|
|
3
|
+
*
|
|
4
|
+
* Medusa v2 uses filesystem-based route registration: every `route.ts` is
|
|
5
|
+
* mounted unconditionally at boot. There is no clean hook to skip a file
|
|
6
|
+
* based on plugin config. So ISV-only admin routes use a per-handler
|
|
7
|
+
* short-circuit instead — when `VivaPluginConfig.mode === 'merchant'`, the
|
|
8
|
+
* handler returns 404 immediately, mimicking an unmounted route.
|
|
9
|
+
*
|
|
10
|
+
* Config is read lazily via `loadConfigFromEnv()` so test code that swaps
|
|
11
|
+
* env vars between requests sees the change.
|
|
12
|
+
*
|
|
13
|
+
* Slice F will add the `/sources` route which uses this same gate.
|
|
14
|
+
*
|
|
15
|
+
* @see docs/plans/multi-mode-v0.md §6 (mode-surface gating)
|
|
16
|
+
*/
|
|
17
|
+
import type { MedusaRequest, MedusaResponse } from '@medusajs/framework/http';
|
|
18
|
+
/**
|
|
19
|
+
* Returns `true` and writes a 404 response when the plugin is in merchant
|
|
20
|
+
* mode (or when config fails to load — fail closed). Returns `false` when
|
|
21
|
+
* the route should proceed.
|
|
22
|
+
*
|
|
23
|
+
* Note: this also implicitly covers misconfigured deployments. If config
|
|
24
|
+
* cannot be loaded, ISV-only surfaces stay closed rather than crash with a
|
|
25
|
+
* 500.
|
|
26
|
+
*/
|
|
27
|
+
export declare function reject404IfNotIsv(_req: MedusaRequest, res: MedusaResponse): boolean;
|
|
28
|
+
//# sourceMappingURL=_mode-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_mode-gate.d.ts","sourceRoot":"","sources":["../../../../src/api/viva/admin/_mode-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG9E;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,cAAc,GAClB,OAAO,CAcT"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* _mode-gate.ts — shared 404 short-circuit for ISV-only admin routes.
|
|
4
|
+
*
|
|
5
|
+
* Medusa v2 uses filesystem-based route registration: every `route.ts` is
|
|
6
|
+
* mounted unconditionally at boot. There is no clean hook to skip a file
|
|
7
|
+
* based on plugin config. So ISV-only admin routes use a per-handler
|
|
8
|
+
* short-circuit instead — when `VivaPluginConfig.mode === 'merchant'`, the
|
|
9
|
+
* handler returns 404 immediately, mimicking an unmounted route.
|
|
10
|
+
*
|
|
11
|
+
* Config is read lazily via `loadConfigFromEnv()` so test code that swaps
|
|
12
|
+
* env vars between requests sees the change.
|
|
13
|
+
*
|
|
14
|
+
* Slice F will add the `/sources` route which uses this same gate.
|
|
15
|
+
*
|
|
16
|
+
* @see docs/plans/multi-mode-v0.md §6 (mode-surface gating)
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.reject404IfNotIsv = reject404IfNotIsv;
|
|
20
|
+
const config_js_1 = require("../../../config.js");
|
|
21
|
+
/**
|
|
22
|
+
* Returns `true` and writes a 404 response when the plugin is in merchant
|
|
23
|
+
* mode (or when config fails to load — fail closed). Returns `false` when
|
|
24
|
+
* the route should proceed.
|
|
25
|
+
*
|
|
26
|
+
* Note: this also implicitly covers misconfigured deployments. If config
|
|
27
|
+
* cannot be loaded, ISV-only surfaces stay closed rather than crash with a
|
|
28
|
+
* 500.
|
|
29
|
+
*/
|
|
30
|
+
function reject404IfNotIsv(_req, res) {
|
|
31
|
+
let isIsv = false;
|
|
32
|
+
try {
|
|
33
|
+
const config = (0, config_js_1.loadConfigFromEnv)(process.env);
|
|
34
|
+
isIsv = config.mode === 'isv';
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
isIsv = false;
|
|
38
|
+
}
|
|
39
|
+
if (!isIsv) {
|
|
40
|
+
res.status(404).json({ error: 'Not Found' });
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=_mode-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_mode-gate.js","sourceRoot":"","sources":["../../../../src/api/viva/admin/_mode-gate.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;AAcH,8CAiBC;AA5BD,kDAAuD;AAEvD;;;;;;;;GAQG;AACH,SAAgB,iBAAiB,CAC/B,IAAmB,EACnB,GAAmB;IAEnB,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,6BAAiB,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* route.ts — POST /viva/admin/connected-accounts/:id/reconcile
|
|
3
|
+
*
|
|
4
|
+
* ISV-only admin endpoint. Forces a re-fetch of the connected-account state
|
|
5
|
+
* from Viva and applies the latest verification/acquiring flags onto the
|
|
6
|
+
* local `viva_tenant_merchant` row (when one exists). Used to recover from
|
|
7
|
+
* missed 8194 webhook deliveries.
|
|
8
|
+
*
|
|
9
|
+
* 1. Validates plugin is in ISV mode (404 in merchant mode).
|
|
10
|
+
* 2. Validates admin token (401 if missing/wrong).
|
|
11
|
+
* 3. Fetches current state via `IsvAccounts.retrieveConnectedAccount`.
|
|
12
|
+
* 4. UPDATEs `viva_tenant_merchant.verification_status` when a row matches.
|
|
13
|
+
* 5. Returns `{ accountId, verified, acquiringEnabled, reconciled }`.
|
|
14
|
+
*
|
|
15
|
+
* @see docs/plans/multi-mode-v0.md §6 (mode-surface gating)
|
|
16
|
+
*/
|
|
17
|
+
import type { MedusaRequest, MedusaResponse } from '@medusajs/framework/http';
|
|
18
|
+
export declare const POST: (req: MedusaRequest<unknown, {
|
|
19
|
+
id: string;
|
|
20
|
+
}>, res: MedusaResponse) => Promise<void>;
|
|
21
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/viva/admin/connected-accounts/[id]/reconcile/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAU9E,eAAO,MAAM,IAAI,GACf,KAAK,aAAa,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAC3C,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CAoEd,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* route.ts — POST /viva/admin/connected-accounts/:id/reconcile
|
|
4
|
+
*
|
|
5
|
+
* ISV-only admin endpoint. Forces a re-fetch of the connected-account state
|
|
6
|
+
* from Viva and applies the latest verification/acquiring flags onto the
|
|
7
|
+
* local `viva_tenant_merchant` row (when one exists). Used to recover from
|
|
8
|
+
* missed 8194 webhook deliveries.
|
|
9
|
+
*
|
|
10
|
+
* 1. Validates plugin is in ISV mode (404 in merchant mode).
|
|
11
|
+
* 2. Validates admin token (401 if missing/wrong).
|
|
12
|
+
* 3. Fetches current state via `IsvAccounts.retrieveConnectedAccount`.
|
|
13
|
+
* 4. UPDATEs `viva_tenant_merchant.verification_status` when a row matches.
|
|
14
|
+
* 5. Returns `{ accountId, verified, acquiringEnabled, reconciled }`.
|
|
15
|
+
*
|
|
16
|
+
* @see docs/plans/multi-mode-v0.md §6 (mode-surface gating)
|
|
17
|
+
*/
|
|
18
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.POST = void 0;
|
|
23
|
+
const pg_1 = __importDefault(require("pg"));
|
|
24
|
+
const isv_1 = require("@sakeetech/viva-payments-core/isv");
|
|
25
|
+
const errors_1 = require("@sakeetech/viva-payments-core/errors");
|
|
26
|
+
const config_js_1 = require("../../../../../../config.js");
|
|
27
|
+
const auth_strategy_factory_js_1 = require("../../../../../../resolvers/auth-strategy-factory.js");
|
|
28
|
+
const _mode_gate_js_1 = require("../../../_mode-gate.js");
|
|
29
|
+
const _admin_auth_js_1 = require("../../../_admin-auth.js");
|
|
30
|
+
const POST = async (req, res) => {
|
|
31
|
+
if ((0, _mode_gate_js_1.reject404IfNotIsv)(req, res))
|
|
32
|
+
return;
|
|
33
|
+
if ((0, _admin_auth_js_1.reject401IfUnauthorized)(req, res))
|
|
34
|
+
return;
|
|
35
|
+
const id = req.params?.id;
|
|
36
|
+
if (!id) {
|
|
37
|
+
res.status(400).json({ error: 'id is required' });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let pool = null;
|
|
41
|
+
try {
|
|
42
|
+
const config = (0, config_js_1.loadConfigFromEnv)(process.env);
|
|
43
|
+
const authStrategies = (0, auth_strategy_factory_js_1.buildAuthStrategies)(config);
|
|
44
|
+
const httpClient = new isv_1.IsvHttpClient({
|
|
45
|
+
environment: config.environment,
|
|
46
|
+
authStrategy: authStrategies.primary,
|
|
47
|
+
});
|
|
48
|
+
const accounts = new isv_1.IsvAccounts(httpClient);
|
|
49
|
+
const account = await accounts.retrieveConnectedAccount(id);
|
|
50
|
+
// Best-effort sync to viva_tenant_merchant. If no row matches (account
|
|
51
|
+
// hasn't been registered locally yet), report reconciled=false.
|
|
52
|
+
const connString = process.env['DATABASE_URL'] ??
|
|
53
|
+
`postgresql://${process.env['USER'] ?? 'postgres'}@localhost:5432/postgres`;
|
|
54
|
+
pool = new pg_1.default.Pool({ connectionString: connString, max: 1 });
|
|
55
|
+
const verificationStatus = account.verified ? 'verified' : 'unverified';
|
|
56
|
+
const client = await pool.connect();
|
|
57
|
+
let rowCount = 0;
|
|
58
|
+
try {
|
|
59
|
+
const result = await client.query(`UPDATE viva_tenant_merchant
|
|
60
|
+
SET verification_status = $1, updated_at = now()
|
|
61
|
+
WHERE connected_account_id = $2`, [verificationStatus, id]);
|
|
62
|
+
rowCount = result.rowCount ?? 0;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
client.release();
|
|
66
|
+
}
|
|
67
|
+
res.status(200).json({
|
|
68
|
+
accountId: account.accountId,
|
|
69
|
+
verified: account.verified,
|
|
70
|
+
acquiringEnabled: account.acquiringEnabled,
|
|
71
|
+
reconciled: rowCount > 0,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
if (err instanceof errors_1.VivaApiError) {
|
|
76
|
+
res.status(err.httpStatus ?? 502).json({
|
|
77
|
+
error: 'viva_api_error',
|
|
78
|
+
code: err.code,
|
|
79
|
+
message: err.message,
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const logger = req.scope?.resolve?.('logger');
|
|
84
|
+
logger?.error?.(`[viva] POST /viva/admin/connected-accounts/:id/reconcile failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
85
|
+
res.status(500).json({ error: 'internal_error' });
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
if (pool)
|
|
89
|
+
await pool.end().catch(() => undefined);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
exports.POST = POST;
|
|
93
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/viva/admin/connected-accounts/[id]/reconcile/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* route.ts — GET /viva/admin/connected-accounts/:id
|
|
3
|
+
*
|
|
4
|
+
* ISV-only admin endpoint. Returns the current onboarding/verification status
|
|
5
|
+
* of a connected account by id.
|
|
6
|
+
*
|
|
7
|
+
* 1. Validates plugin is in ISV mode (404 in merchant mode).
|
|
8
|
+
* 2. Validates admin token (401 if missing/wrong).
|
|
9
|
+
* 3. Calls `IsvAccounts.retrieveConnectedAccount` against Viva.
|
|
10
|
+
* 4. Returns the response body.
|
|
11
|
+
*
|
|
12
|
+
* @see docs/plans/multi-mode-v0.md §6 (mode-surface gating)
|
|
13
|
+
*/
|
|
14
|
+
import type { MedusaRequest, MedusaResponse } from '@medusajs/framework/http';
|
|
15
|
+
export declare const GET: (req: MedusaRequest<unknown, {
|
|
16
|
+
id: string;
|
|
17
|
+
}>, res: MedusaResponse) => Promise<void>;
|
|
18
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/api/viva/admin/connected-accounts/[id]/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAS9E,eAAO,MAAM,GAAG,GACd,KAAK,aAAa,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAC3C,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CAqCd,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* route.ts — GET /viva/admin/connected-accounts/:id
|
|
4
|
+
*
|
|
5
|
+
* ISV-only admin endpoint. Returns the current onboarding/verification status
|
|
6
|
+
* of a connected account by id.
|
|
7
|
+
*
|
|
8
|
+
* 1. Validates plugin is in ISV mode (404 in merchant mode).
|
|
9
|
+
* 2. Validates admin token (401 if missing/wrong).
|
|
10
|
+
* 3. Calls `IsvAccounts.retrieveConnectedAccount` against Viva.
|
|
11
|
+
* 4. Returns the response body.
|
|
12
|
+
*
|
|
13
|
+
* @see docs/plans/multi-mode-v0.md §6 (mode-surface gating)
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.GET = void 0;
|
|
17
|
+
const isv_1 = require("@sakeetech/viva-payments-core/isv");
|
|
18
|
+
const errors_1 = require("@sakeetech/viva-payments-core/errors");
|
|
19
|
+
const config_js_1 = require("../../../../../config.js");
|
|
20
|
+
const auth_strategy_factory_js_1 = require("../../../../../resolvers/auth-strategy-factory.js");
|
|
21
|
+
const _mode_gate_js_1 = require("../../_mode-gate.js");
|
|
22
|
+
const _admin_auth_js_1 = require("../../_admin-auth.js");
|
|
23
|
+
const GET = async (req, res) => {
|
|
24
|
+
if ((0, _mode_gate_js_1.reject404IfNotIsv)(req, res))
|
|
25
|
+
return;
|
|
26
|
+
if ((0, _admin_auth_js_1.reject401IfUnauthorized)(req, res))
|
|
27
|
+
return;
|
|
28
|
+
const id = req.params?.id;
|
|
29
|
+
if (!id) {
|
|
30
|
+
res.status(400).json({ error: 'id is required' });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const config = (0, config_js_1.loadConfigFromEnv)(process.env);
|
|
35
|
+
const authStrategies = (0, auth_strategy_factory_js_1.buildAuthStrategies)(config);
|
|
36
|
+
const httpClient = new isv_1.IsvHttpClient({
|
|
37
|
+
environment: config.environment,
|
|
38
|
+
authStrategy: authStrategies.primary,
|
|
39
|
+
});
|
|
40
|
+
const accounts = new isv_1.IsvAccounts(httpClient);
|
|
41
|
+
const account = await accounts.retrieveConnectedAccount(id);
|
|
42
|
+
res.status(200).json(account);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
if (err instanceof errors_1.VivaApiError) {
|
|
46
|
+
res.status(err.httpStatus ?? 502).json({
|
|
47
|
+
error: 'viva_api_error',
|
|
48
|
+
code: err.code,
|
|
49
|
+
message: err.message,
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const logger = req.scope?.resolve?.('logger');
|
|
54
|
+
logger?.error?.(`[viva] GET /viva/admin/connected-accounts/:id failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
55
|
+
res.status(500).json({ error: 'internal_error' });
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
exports.GET = GET;
|
|
59
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../src/api/viva/admin/connected-accounts/[id]/route.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAGH,2DAA+E;AAC/E,iEAAoE;AAEpE,wDAA6D;AAC7D,gGAAwF;AACxF,uDAAwD;AACxD,yDAA+D;AAExD,MAAM,GAAG,GAAG,KAAK,EACtB,GAA2C,EAC3C,GAAmB,EACJ,EAAE;IACjB,IAAI,IAAA,iCAAiB,EAAC,GAAG,EAAE,GAAG,CAAC;QAAE,OAAO;IACxC,IAAI,IAAA,wCAAuB,EAAC,GAAG,EAAE,GAAG,CAAC;QAAE,OAAO;IAE9C,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,6BAAiB,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,cAAc,GAAG,IAAA,8CAAmB,EAAC,MAAM,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,IAAI,mBAAa,CAAC;YACnC,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,YAAY,EAAE,cAAc,CAAC,OAAO;SACrC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,iBAAW,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,wBAAwB,CAAC,EAAwB,CAAC,CAAC;QAClF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,qBAAY,EAAE,CAAC;YAChC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;gBACrC,KAAK,EAAE,gBAAgB;gBACvB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,OAAO,EAAE,GAAG,CAAC,OAAO;aACrB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,QAAQ,CAE/B,CAAC;QACd,MAAM,EAAE,KAAK,EAAE,CACb,yDAAyD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC5G,CAAC;QACF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC,CAAC;AAxCW,QAAA,GAAG,OAwCd"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* route.ts — POST /viva/admin/connected-accounts/:id/sources
|
|
3
|
+
*
|
|
4
|
+
* ISV-only admin endpoint. Creates a payment source (ecommerce or physical)
|
|
5
|
+
* on a connected merchant's Viva account via `POST /api/sources` on the
|
|
6
|
+
* legacy host, authenticated with **Reseller Basic** auth.
|
|
7
|
+
*
|
|
8
|
+
* 1. Validates plugin is in ISV mode (404 in merchant mode).
|
|
9
|
+
* 2. Validates admin token (401 if missing/wrong).
|
|
10
|
+
* 3. Requires `config.reseller` (412 with `VIVA_RESELLER_CREDENTIALS_MISSING`).
|
|
11
|
+
* 4. Resolves the connected merchant's `merchantId` UUID via
|
|
12
|
+
* `IsvAccounts.retrieveConnectedAccount(:id)` — 409 with
|
|
13
|
+
* `VIVA_ACCOUNT_NOT_VERIFIED` when `verified !== true` or `merchantId`
|
|
14
|
+
* is null.
|
|
15
|
+
* 5. Builds a per-request `BasicAuthClient` with `authVariant: 'reseller'`
|
|
16
|
+
* whose username slot carries `resellerId:account.merchantId` (NOT the
|
|
17
|
+
* platform's merchant id — see AUTH.md §1.2 line 98 + ENDPOINTS.md §5.1).
|
|
18
|
+
* 6. Calls `IsvSources.createEcommerceSource` or `createPhysicalSource`
|
|
19
|
+
* based on the body's `kind` discriminator.
|
|
20
|
+
* 7. Returns 201 + `{ sourceCode, name, kind }`.
|
|
21
|
+
*
|
|
22
|
+
* Viva 4xx on `/api/sources` is mapped to 422 with `VIVA_SOURCE_CREATION_FAILED`.
|
|
23
|
+
* Viva 5xx / non-API errors fall through to the existing 5xx envelope.
|
|
24
|
+
*
|
|
25
|
+
* @see docs/plans/multi-mode-v0.md §6 (admin REST table)
|
|
26
|
+
* @see docs/ENDPOINTS.md §5.1
|
|
27
|
+
* @see docs/AUTH.md §1.2 (Reseller Basic)
|
|
28
|
+
* @see docs/ERRORS.md (VIVA_SOURCE_CREATION_FAILED, VIVA_RESELLER_CREDENTIALS_MISSING)
|
|
29
|
+
*/
|
|
30
|
+
import type { MedusaRequest, MedusaResponse } from '@medusajs/framework/http';
|
|
31
|
+
export declare const POST: (req: MedusaRequest<unknown, {
|
|
32
|
+
id: string;
|
|
33
|
+
}>, res: MedusaResponse) => Promise<void>;
|
|
34
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/viva/admin/connected-accounts/[id]/sources/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAyH9E,eAAO,MAAM,IAAI,GACf,KAAK,aAAa,CAAC,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAC3C,KAAK,cAAc,KAClB,OAAO,CAAC,IAAI,CAoId,CAAC"}
|