@sakeetech/vendure-payment-viva 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +952 -0
- package/dist/api/admin-internal.controller.d.ts +59 -0
- package/dist/api/admin-internal.controller.d.ts.map +1 -0
- package/dist/api/admin-internal.controller.js +229 -0
- package/dist/api/admin-internal.controller.js.map +1 -0
- package/dist/api/admin-onboarding.controller.d.ts +72 -0
- package/dist/api/admin-onboarding.controller.d.ts.map +1 -0
- package/dist/api/admin-onboarding.controller.js +496 -0
- package/dist/api/admin-onboarding.controller.js.map +1 -0
- package/dist/api/admin-sources.controller.d.ts +50 -0
- package/dist/api/admin-sources.controller.d.ts.map +1 -0
- package/dist/api/admin-sources.controller.js +283 -0
- package/dist/api/admin-sources.controller.js.map +1 -0
- package/dist/api/shop-api.extension.d.ts +15 -0
- package/dist/api/shop-api.extension.d.ts.map +1 -0
- package/dist/api/shop-api.extension.js +35 -0
- package/dist/api/shop-api.extension.js.map +1 -0
- package/dist/api/shop-api.resolver.d.ts +42 -0
- package/dist/api/shop-api.resolver.d.ts.map +1 -0
- package/dist/api/shop-api.resolver.js +256 -0
- package/dist/api/shop-api.resolver.js.map +1 -0
- package/dist/api/webhook.controller.d.ts +58 -0
- package/dist/api/webhook.controller.d.ts.map +1 -0
- package/dist/api/webhook.controller.js +204 -0
- package/dist/api/webhook.controller.js.map +1 -0
- package/dist/cli/bin.d.ts +28 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +104 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/plan.d.ts +41 -0
- package/dist/cli/plan.d.ts.map +1 -0
- package/dist/cli/plan.js +115 -0
- package/dist/cli/plan.js.map +1 -0
- package/dist/cli/register-webhooks.d.ts +45 -0
- package/dist/cli/register-webhooks.d.ts.map +1 -0
- package/dist/cli/register-webhooks.js +400 -0
- package/dist/cli/register-webhooks.js.map +1 -0
- package/dist/cli/types.d.ts +75 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +10 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/constants.d.ts +35 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +40 -0
- package/dist/constants.js.map +1 -0
- package/dist/entities/index.d.ts +4 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +3 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/viva-transaction.entity.d.ts +70 -0
- package/dist/entities/viva-transaction.entity.d.ts.map +1 -0
- package/dist/entities/viva-transaction.entity.js +133 -0
- package/dist/entities/viva-transaction.entity.js.map +1 -0
- package/dist/entities/viva-webhook-event.entity.d.ts +71 -0
- package/dist/entities/viva-webhook-event.entity.d.ts.map +1 -0
- package/dist/entities/viva-webhook-event.entity.js +138 -0
- package/dist/entities/viva-webhook-event.entity.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/process-viva-webhook.handler.d.ts +95 -0
- package/dist/jobs/process-viva-webhook.handler.d.ts.map +1 -0
- package/dist/jobs/process-viva-webhook.handler.js +530 -0
- package/dist/jobs/process-viva-webhook.handler.js.map +1 -0
- package/dist/jobs/queue-names.d.ts +18 -0
- package/dist/jobs/queue-names.d.ts.map +1 -0
- package/dist/jobs/queue-names.js +19 -0
- package/dist/jobs/queue-names.js.map +1 -0
- package/dist/jobs/retention-cleanup.handler.d.ts +31 -0
- package/dist/jobs/retention-cleanup.handler.d.ts.map +1 -0
- package/dist/jobs/retention-cleanup.handler.js +94 -0
- package/dist/jobs/retention-cleanup.handler.js.map +1 -0
- package/dist/loaders/bootstrap.d.ts +28 -0
- package/dist/loaders/bootstrap.d.ts.map +1 -0
- package/dist/loaders/bootstrap.js +90 -0
- package/dist/loaders/bootstrap.js.map +1 -0
- package/dist/migrations/1714000000000-create-viva-tables.d.ts +22 -0
- package/dist/migrations/1714000000000-create-viva-tables.d.ts.map +1 -0
- package/dist/migrations/1714000000000-create-viva-tables.js +105 -0
- package/dist/migrations/1714000000000-create-viva-tables.js.map +1 -0
- package/dist/observability/metrics-state.service.d.ts +43 -0
- package/dist/observability/metrics-state.service.d.ts.map +1 -0
- package/dist/observability/metrics-state.service.js +207 -0
- package/dist/observability/metrics-state.service.js.map +1 -0
- package/dist/payment-method-handler.d.ts +26 -0
- package/dist/payment-method-handler.d.ts.map +1 -0
- package/dist/payment-method-handler.js +693 -0
- package/dist/payment-method-handler.js.map +1 -0
- package/dist/plugin.d.ts +95 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +241 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/viva-oauth2-strategy.provider.d.ts +41 -0
- package/dist/providers/viva-oauth2-strategy.provider.d.ts.map +1 -0
- package/dist/providers/viva-oauth2-strategy.provider.js +60 -0
- package/dist/providers/viva-oauth2-strategy.provider.js.map +1 -0
- package/dist/services/connected-accounts.service.d.ts +53 -0
- package/dist/services/connected-accounts.service.d.ts.map +1 -0
- package/dist/services/connected-accounts.service.js +108 -0
- package/dist/services/connected-accounts.service.js.map +1 -0
- package/dist/services/per-merchant-semaphore.service.d.ts +49 -0
- package/dist/services/per-merchant-semaphore.service.d.ts.map +1 -0
- package/dist/services/per-merchant-semaphore.service.js +156 -0
- package/dist/services/per-merchant-semaphore.service.js.map +1 -0
- package/dist/services/state-machine.service.d.ts +100 -0
- package/dist/services/state-machine.service.d.ts.map +1 -0
- package/dist/services/state-machine.service.js +233 -0
- package/dist/services/state-machine.service.js.map +1 -0
- package/dist/types.d.ts +286 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/dist/util/currency.d.ts +32 -0
- package/dist/util/currency.d.ts.map +1 -0
- package/dist/util/currency.js +90 -0
- package/dist/util/currency.js.map +1 -0
- package/dist/util/error-envelope.d.ts +51 -0
- package/dist/util/error-envelope.d.ts.map +1 -0
- package/dist/util/error-envelope.js +157 -0
- package/dist/util/error-envelope.js.map +1 -0
- package/dist/util/ip-allowlist.d.ts +44 -0
- package/dist/util/ip-allowlist.d.ts.map +1 -0
- package/dist/util/ip-allowlist.js +139 -0
- package/dist/util/ip-allowlist.js.map +1 -0
- package/dist/util/normalize-options.d.ts +24 -0
- package/dist/util/normalize-options.d.ts.map +1 -0
- package/dist/util/normalize-options.js +189 -0
- package/dist/util/normalize-options.js.map +1 -0
- package/dist/util/url-template.d.ts +18 -0
- package/dist/util/url-template.d.ts.map +1 -0
- package/dist/util/url-template.js +22 -0
- package/dist/util/url-template.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* services/state-machine.service.ts — Low-level VivaTransaction row helpers
|
|
3
|
+
* AND Vendure order/payment transition wrappers (V7 extension).
|
|
4
|
+
*
|
|
5
|
+
* Row helpers: INSERT-OR-NOTHING idempotent writes + lookups for VivaTransaction.
|
|
6
|
+
* Transition helpers: wraps OrderService + PaymentService state-machine calls;
|
|
7
|
+
* used exclusively by the webhook worker (V7). Implements the stale-recovery
|
|
8
|
+
* re-walk (AddingItems → ArrangingPayment → PaymentAuthorized → PaymentSettled)
|
|
9
|
+
* with fail-loud semantics per Q4 decision.
|
|
10
|
+
*
|
|
11
|
+
* Repository injection via Vendure's TransactionalConnection.
|
|
12
|
+
*
|
|
13
|
+
* @see docs/plans/vendure-plugin-v0.md §"Build Plan — V5 + V7"
|
|
14
|
+
* @see docs/plans/vendure-plugin-v0.md §D6 (state transitions via OrderService)
|
|
15
|
+
* @see docs/plans/vendure-plugin-v0.md §D11 (idempotency)
|
|
16
|
+
*/
|
|
17
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
18
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
20
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
21
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
22
|
+
};
|
|
23
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
24
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
25
|
+
};
|
|
26
|
+
import { Injectable, Logger as NestLogger } from '@nestjs/common';
|
|
27
|
+
import { TransactionalConnection, Logger, OrderService, PaymentService } from '@vendure/core';
|
|
28
|
+
import { QueryFailedError } from 'typeorm';
|
|
29
|
+
import { VivaTransaction } from '../entities/viva-transaction.entity.js';
|
|
30
|
+
import { VIVA_LOG_CONTEXT } from '../constants.js';
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Service
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
let StateMachineService = class StateMachineService {
|
|
35
|
+
connection;
|
|
36
|
+
orderService;
|
|
37
|
+
paymentService;
|
|
38
|
+
constructor(connection, orderService, paymentService) {
|
|
39
|
+
this.connection = connection;
|
|
40
|
+
this.orderService = orderService;
|
|
41
|
+
this.paymentService = paymentService;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Load a VivaTransaction row by (channelId, paymentId).
|
|
45
|
+
* Returns null if not found.
|
|
46
|
+
*/
|
|
47
|
+
async getVivaTransaction(ctx, channelId, paymentId) {
|
|
48
|
+
const repo = this.connection.getRepository(ctx, VivaTransaction);
|
|
49
|
+
return repo.findOne({
|
|
50
|
+
where: { channelId: channelId, paymentId: paymentId },
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* INSERT-OR-NOTHING write of a pending VivaTransaction row.
|
|
55
|
+
*
|
|
56
|
+
* Idempotency key D11: keyed on (channelId, paymentId).
|
|
57
|
+
* If a row already exists with the same key and a non-null vivaOrderCode,
|
|
58
|
+
* returns that existing row so the handler can skip the Viva API call.
|
|
59
|
+
*
|
|
60
|
+
* Returns: { row, wasInserted }
|
|
61
|
+
* wasInserted=true → freshly inserted; handler must call Viva.
|
|
62
|
+
* wasInserted=false → already existed; check row.vivaOrderCode.
|
|
63
|
+
*/
|
|
64
|
+
async upsertPendingTransaction(ctx, input) {
|
|
65
|
+
const repo = this.connection.getRepository(ctx, VivaTransaction);
|
|
66
|
+
// Check if already exists
|
|
67
|
+
const existing = await repo.findOne({
|
|
68
|
+
where: {
|
|
69
|
+
channelId: input.channelId,
|
|
70
|
+
paymentId: input.paymentId,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
if (existing) {
|
|
74
|
+
return { row: existing, wasInserted: false };
|
|
75
|
+
}
|
|
76
|
+
// Try to INSERT; handle race condition via duplicate-key error.
|
|
77
|
+
const row = repo.create({
|
|
78
|
+
channelId: input.channelId,
|
|
79
|
+
paymentId: input.paymentId,
|
|
80
|
+
status: 'pending',
|
|
81
|
+
vivaOrderCode: null,
|
|
82
|
+
vivaTransactionId: null,
|
|
83
|
+
amountMinor: input.amountMinor.toString(),
|
|
84
|
+
currencyCode: input.currencyCode,
|
|
85
|
+
isvAmountMinor: input.isvAmountMinor.toString(),
|
|
86
|
+
metadata: { idempotencyKey: input.idempotencyKey },
|
|
87
|
+
});
|
|
88
|
+
try {
|
|
89
|
+
const saved = await repo.save(row);
|
|
90
|
+
return { row: saved, wasInserted: true };
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
// Duplicate key: another request beat us to the insert (race).
|
|
94
|
+
if (err instanceof QueryFailedError && this._isDuplicateKeyError(err)) {
|
|
95
|
+
const existing2 = await repo.findOne({
|
|
96
|
+
where: {
|
|
97
|
+
channelId: input.channelId,
|
|
98
|
+
paymentId: input.paymentId,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
if (existing2) {
|
|
102
|
+
return { row: existing2, wasInserted: false };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Update the vivaOrderCode on a pending row after createOrder succeeds.
|
|
110
|
+
*/
|
|
111
|
+
async setOrderCode(ctx, rowId, vivaOrderCode, metadata) {
|
|
112
|
+
const repo = this.connection.getRepository(ctx, VivaTransaction);
|
|
113
|
+
// Use query builder to avoid exactOptionalPropertyTypes issues with TypeORM _QueryDeepPartialEntity.
|
|
114
|
+
await repo
|
|
115
|
+
.createQueryBuilder()
|
|
116
|
+
.update(VivaTransaction)
|
|
117
|
+
.set({ vivaOrderCode, metadata: () => ':meta' })
|
|
118
|
+
.where('id = :id', { id: rowId })
|
|
119
|
+
.setParameter('meta', JSON.stringify(metadata))
|
|
120
|
+
.execute();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Update row status (e.g. pending → captured, pending → cancelled).
|
|
124
|
+
*/
|
|
125
|
+
async setStatus(ctx, rowId, status, metadata) {
|
|
126
|
+
const repo = this.connection.getRepository(ctx, VivaTransaction);
|
|
127
|
+
if (metadata !== undefined) {
|
|
128
|
+
await repo
|
|
129
|
+
.createQueryBuilder()
|
|
130
|
+
.update(VivaTransaction)
|
|
131
|
+
.set({ status, metadata: () => ':meta' })
|
|
132
|
+
.where('id = :id', { id: rowId })
|
|
133
|
+
.setParameter('meta', JSON.stringify(metadata))
|
|
134
|
+
.execute();
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
await repo
|
|
138
|
+
.createQueryBuilder()
|
|
139
|
+
.update(VivaTransaction)
|
|
140
|
+
.set({ status })
|
|
141
|
+
.where('id = :id', { id: rowId })
|
|
142
|
+
.execute();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// Order / Payment transition helpers (V7)
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
/**
|
|
149
|
+
* Transition a Payment to `Settled` via `PaymentService.transitionToState`.
|
|
150
|
+
*
|
|
151
|
+
* Vendure's canonical path for webhook-driven settlement.
|
|
152
|
+
* @see docs/plans/vendure-plugin-v0.md §D6, §D5 (1796 settle path)
|
|
153
|
+
*/
|
|
154
|
+
async transitionPaymentToSettled(ctx, orderId, paymentId) {
|
|
155
|
+
// Vendure state machine: Created → Authorized → Settled
|
|
156
|
+
// OrderService.settlePayment handles the two-step transition internally.
|
|
157
|
+
const result = await this.orderService.settlePayment(ctx, paymentId);
|
|
158
|
+
if ('errorCode' in result) {
|
|
159
|
+
throw new Error(`[StateMachineService] Failed to settle payment ${String(paymentId)} for order ${String(orderId)}: ${result.message ?? JSON.stringify(result)}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Transition a Payment to `Declined` via `PaymentService.transitionToState`.
|
|
164
|
+
*
|
|
165
|
+
* Called on webhook 1798 (Transaction Failed). Order stays in ArrangingPayment.
|
|
166
|
+
* @see docs/plans/vendure-plugin-v0.md §D5 (1798 path)
|
|
167
|
+
*/
|
|
168
|
+
async transitionPaymentToDeclined(ctx, paymentId) {
|
|
169
|
+
await this.paymentService.transitionToState(ctx, paymentId, 'Declined');
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Transition a Payment to `Cancelled` via `PaymentService.transitionToState`.
|
|
173
|
+
*
|
|
174
|
+
* Called on webhook 4865 user-cancel detection.
|
|
175
|
+
* @see docs/plans/vendure-plugin-v0.md §D5 (4865 path)
|
|
176
|
+
*/
|
|
177
|
+
async transitionPaymentToCancelled(ctx, paymentId) {
|
|
178
|
+
await this.paymentService.transitionToState(ctx, paymentId, 'Cancelled');
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Stale-order re-walk: AddingItems → ArrangingPayment → PaymentSettled.
|
|
182
|
+
*
|
|
183
|
+
* Implements the Q4 decision: fail-loud on any transition failure — log an
|
|
184
|
+
* ERROR-level message, throw, let the webhook row stay unprocessed. The
|
|
185
|
+
* storefront will surface "basket changed" via the live order state.
|
|
186
|
+
*
|
|
187
|
+
* Sequence:
|
|
188
|
+
* 1. AddingItems → ArrangingPayment (transitionOrderToState)
|
|
189
|
+
* 2. ArrangingPayment → settlePayment (OrderService.settlePayment)
|
|
190
|
+
*
|
|
191
|
+
* @see docs/plans/vendure-plugin-v0.md §"Process flow" step 4e
|
|
192
|
+
* @see docs/plans/vendure-plugin-v0.md §"Architecture Decisions Q4"
|
|
193
|
+
*/
|
|
194
|
+
async recoverStaleOrderAndSettle(ctx, orderId, paymentId) {
|
|
195
|
+
Logger.info(`[StateMachineService] Starting stale-order re-walk for order ${String(orderId)}, payment ${String(paymentId)}.`, VIVA_LOG_CONTEXT);
|
|
196
|
+
// Step 1: AddingItems → ArrangingPayment
|
|
197
|
+
const transitionResult = await this.orderService.transitionToState(ctx, orderId, 'ArrangingPayment');
|
|
198
|
+
if ('errorCode' in transitionResult) {
|
|
199
|
+
const msg = `[StateMachineService] Stale re-walk FAILED on AddingItems→ArrangingPayment for order ${String(orderId)}: ${transitionResult.message ?? JSON.stringify(transitionResult)}`;
|
|
200
|
+
Logger.error(msg, VIVA_LOG_CONTEXT);
|
|
201
|
+
throw new Error(msg);
|
|
202
|
+
}
|
|
203
|
+
// Step 2: ArrangingPayment → settle (Created → Authorized → Settled)
|
|
204
|
+
const settleResult = await this.orderService.settlePayment(ctx, paymentId);
|
|
205
|
+
if ('errorCode' in settleResult) {
|
|
206
|
+
const msg = `[StateMachineService] Stale re-walk FAILED on settlePayment for order ${String(orderId)}, payment ${String(paymentId)}: ${settleResult.message ?? JSON.stringify(settleResult)}`;
|
|
207
|
+
Logger.error(msg, VIVA_LOG_CONTEXT);
|
|
208
|
+
throw new Error(msg);
|
|
209
|
+
}
|
|
210
|
+
Logger.info(`[StateMachineService] Stale re-walk complete: order ${String(orderId)} now PaymentSettled.`, VIVA_LOG_CONTEXT);
|
|
211
|
+
}
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
// Private helpers
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
_isDuplicateKeyError(err) {
|
|
216
|
+
const msg = err.code ?? '';
|
|
217
|
+
// Postgres unique violation
|
|
218
|
+
if (msg === '23505')
|
|
219
|
+
return true;
|
|
220
|
+
// SQLite UNIQUE constraint
|
|
221
|
+
if (err.message.toLowerCase().includes('unique'))
|
|
222
|
+
return true;
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
StateMachineService = __decorate([
|
|
227
|
+
Injectable(),
|
|
228
|
+
__metadata("design:paramtypes", [TransactionalConnection,
|
|
229
|
+
OrderService,
|
|
230
|
+
PaymentService])
|
|
231
|
+
], StateMachineService);
|
|
232
|
+
export { StateMachineService };
|
|
233
|
+
//# sourceMappingURL=state-machine.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-machine.service.js","sourceRoot":"","sources":["../../src/services/state-machine.service.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* types.ts — Public configuration types for VivaPaymentPlugin.
|
|
3
|
+
*
|
|
4
|
+
* v0.2.0: `VivaPaymentPluginOptions` is now a **discriminated union** on `mode`.
|
|
5
|
+
*
|
|
6
|
+
* - `mode: 'isv'` (default until 0.3.0) — multi-merchant ISV partner setup.
|
|
7
|
+
* - `mode: 'merchant'` — single direct Viva merchant, no reseller hierarchy.
|
|
8
|
+
*
|
|
9
|
+
* Field rename (one-minor back-compat):
|
|
10
|
+
* - `isvClientId` → `clientId` (old name accepted with deprecation warning)
|
|
11
|
+
* - `isvClientSecret` → `clientSecret`
|
|
12
|
+
*
|
|
13
|
+
* Plan ref: docs/plans/multi-mode-v0.md §5 (config shape), §10 (Vendure adapter).
|
|
14
|
+
*
|
|
15
|
+
* Vendure types (RequestContext, Order) are imported as peer-dep types only —
|
|
16
|
+
* no runtime Vendure import here so the types module is safe to import in
|
|
17
|
+
* non-Vendure test environments.
|
|
18
|
+
*
|
|
19
|
+
* viva-payments-core types are imported from sub-paths to avoid pulling in
|
|
20
|
+
* implementation code.
|
|
21
|
+
*/
|
|
22
|
+
import type { MetricsHook, OTelTracerHook, Logger } from '@sakeetech/viva-payments-core/observability';
|
|
23
|
+
import type { VivaEnvironment } from '@sakeetech/viva-payments-core/types';
|
|
24
|
+
/**
|
|
25
|
+
* Minimal shape of Vendure's RequestContext used in plugin callbacks.
|
|
26
|
+
* Avoids importing @vendure/core in this file so unit tests don't require
|
|
27
|
+
* the full Vendure dependency graph.
|
|
28
|
+
*/
|
|
29
|
+
export interface VendureRequestContext {
|
|
30
|
+
readonly channelId: string | number;
|
|
31
|
+
readonly channel: {
|
|
32
|
+
readonly id: string | number;
|
|
33
|
+
readonly code: string;
|
|
34
|
+
readonly customFields: Record<string, any>;
|
|
35
|
+
};
|
|
36
|
+
readonly apiType: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Minimal shape of Vendure's Order used in plugin callbacks.
|
|
40
|
+
*/
|
|
41
|
+
export interface VendureOrder {
|
|
42
|
+
readonly id: string | number;
|
|
43
|
+
readonly code: string;
|
|
44
|
+
readonly totalWithTax: number;
|
|
45
|
+
readonly currencyCode: string;
|
|
46
|
+
readonly state: string;
|
|
47
|
+
}
|
|
48
|
+
export interface RedlockClient {
|
|
49
|
+
acquire(resources: string[], duration: number): Promise<{
|
|
50
|
+
release(): Promise<void>;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
export type VivaMode = 'merchant' | 'isv';
|
|
54
|
+
/**
|
|
55
|
+
* Fields shared by both merchant and ISV mode configurations.
|
|
56
|
+
*
|
|
57
|
+
* Field-name rationale:
|
|
58
|
+
* - `clientId` / `clientSecret` — mode-agnostic OAuth2 client_credentials.
|
|
59
|
+
* Renamed from `isvClientId` / `isvClientSecret` in 0.2.0. Old names still
|
|
60
|
+
* accepted via `init()` with a deprecation warning (removal in 0.3.0).
|
|
61
|
+
* - `legacyMerchantId` / `legacyApiKey` — Basic-auth pair against the legacy
|
|
62
|
+
* host. Required in both modes for Standard refund + IsvSources merchant
|
|
63
|
+
* variant. Probe-verified 2026-04-25 (F1): POST /checkout/v2/transactions/{id}
|
|
64
|
+
* returns 405, only the legacy host works for refunds.
|
|
65
|
+
*/
|
|
66
|
+
export interface VivaCommonOptions {
|
|
67
|
+
/** Target environment. Switches Viva API base URL. */
|
|
68
|
+
environment: VivaEnvironment;
|
|
69
|
+
/**
|
|
70
|
+
* OAuth2 client_credentials — mode-agnostic.
|
|
71
|
+
* (The credential pair differs by Self Care location, but the field shape
|
|
72
|
+
* is the same in both modes.)
|
|
73
|
+
*
|
|
74
|
+
* @see references/viva-docs/md/oauth2-authentication.txt:119
|
|
75
|
+
*/
|
|
76
|
+
clientId: string;
|
|
77
|
+
/** OAuth2 client_credentials — paired with `clientId`. */
|
|
78
|
+
clientSecret: string;
|
|
79
|
+
/**
|
|
80
|
+
* Viva Merchant ID (UUID) for the legacy Basic-auth API.
|
|
81
|
+
* Required for `createRefund` to work.
|
|
82
|
+
*
|
|
83
|
+
* @see references/viva-docs/md/merchant-id-and-api-key.txt:1
|
|
84
|
+
* @see references/viva-docs/md/tut-create-recurring-payment.txt:288
|
|
85
|
+
*/
|
|
86
|
+
legacyMerchantId: string;
|
|
87
|
+
/**
|
|
88
|
+
* Viva API Key for the legacy Basic-auth API.
|
|
89
|
+
* Required for `createRefund` to work. Paired with `legacyMerchantId`.
|
|
90
|
+
*
|
|
91
|
+
* @see references/viva-docs/md/merchant-id-and-api-key.txt:1
|
|
92
|
+
*/
|
|
93
|
+
legacyApiKey: string;
|
|
94
|
+
/**
|
|
95
|
+
* URL-verification key returned on Viva's GET probe at registration.
|
|
96
|
+
* NOT a per-request HMAC. Generated by `vendure-viva-register-webhooks` CLI.
|
|
97
|
+
*/
|
|
98
|
+
webhookVerificationKey: string;
|
|
99
|
+
/**
|
|
100
|
+
* Storefront success URL after Smart Checkout completes.
|
|
101
|
+
* `{orderCode}` placeholder is substituted server-side after Viva returns the
|
|
102
|
+
* order code. `{channel.origin}` substitution is the SaaS's responsibility.
|
|
103
|
+
*/
|
|
104
|
+
successUrl: string | ((ctx: VendureRequestContext) => string);
|
|
105
|
+
/**
|
|
106
|
+
* Storefront failure URL after Smart Checkout is cancelled or fails.
|
|
107
|
+
* Same substitution rules as `successUrl`.
|
|
108
|
+
*/
|
|
109
|
+
failureUrl: string | ((ctx: VendureRequestContext) => string);
|
|
110
|
+
/**
|
|
111
|
+
* Refund strategy. Defaults to `'auto'`.
|
|
112
|
+
*
|
|
113
|
+
* 'auto' — pick fast or standard based on transaction state.
|
|
114
|
+
* 'fast' — POST /api/transactions/refund (fast/OAuth2 path).
|
|
115
|
+
* 'standard' — POST /api/transactions/{id} (legacy Basic auth).
|
|
116
|
+
*/
|
|
117
|
+
refundStrategy?: 'auto' | 'fast' | 'standard';
|
|
118
|
+
/**
|
|
119
|
+
* Redlock client for multi-worker distributed semaphore.
|
|
120
|
+
* Default: in-process semaphore only (5 permits per merchantId).
|
|
121
|
+
*/
|
|
122
|
+
redlock?: RedlockClient;
|
|
123
|
+
/**
|
|
124
|
+
* Structured logger. Default: Vendure's built-in logger (Logger from
|
|
125
|
+
* @sakeetech/viva-payments-core/observability).
|
|
126
|
+
*/
|
|
127
|
+
logger?: Logger;
|
|
128
|
+
/**
|
|
129
|
+
* Metrics hook for Prometheus-style counters + histograms.
|
|
130
|
+
* Default: NoopMetricsHook.
|
|
131
|
+
*/
|
|
132
|
+
metricsHook?: MetricsHook;
|
|
133
|
+
/**
|
|
134
|
+
* OpenTelemetry tracer hook.
|
|
135
|
+
* Default: NoopTracerHook (no-op).
|
|
136
|
+
*/
|
|
137
|
+
tracer?: OTelTracerHook;
|
|
138
|
+
/**
|
|
139
|
+
* IP allowlist for webhook receiver.
|
|
140
|
+
* Default: Viva's published demo + production CIDRs.
|
|
141
|
+
*/
|
|
142
|
+
webhookIpAllowlist?: string[];
|
|
143
|
+
/**
|
|
144
|
+
* How many trailing `X-Forwarded-For` hops are set by infrastructure you
|
|
145
|
+
* actually control. The webhook source-IP check walks the X-F-F chain from
|
|
146
|
+
* the **rightmost** end and picks the entry `trustedProxyDepth` from the
|
|
147
|
+
* end. Defaults to `0` — ignore X-F-F entirely and use the socket address,
|
|
148
|
+
* which is safe for direct exposure but rejects every webhook when a real
|
|
149
|
+
* proxy sits in front.
|
|
150
|
+
*
|
|
151
|
+
* Typical values:
|
|
152
|
+
* 0 — no proxy / direct exposure (default)
|
|
153
|
+
* 1 — one reverse proxy (nginx, Caddy, ALB)
|
|
154
|
+
* 2 — CDN in front of LB (e.g. Cloudflare → ALB)
|
|
155
|
+
*
|
|
156
|
+
* CSO Finding #2 (HIGH): leaving this at the implicit "trust leftmost X-F-F"
|
|
157
|
+
* default lets any client claim to be a whitelisted Viva IP.
|
|
158
|
+
*
|
|
159
|
+
* @see docs/TODO-CSO.md "Finding 2"
|
|
160
|
+
*/
|
|
161
|
+
trustedProxyDepth?: number;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Merchant-mode config. Used when the plugin acts on behalf of a single
|
|
165
|
+
* direct Viva merchant account (no reseller hierarchy).
|
|
166
|
+
*
|
|
167
|
+
* NOTE (slice A, v0.2.0): runtime entry points (createPayment, settlePayment,
|
|
168
|
+
* cancelPayment, createRefund) currently throw `VIVA_MODE_MISMATCH` —
|
|
169
|
+
* merchant-mode handlers ship in Phase 3 slice B.
|
|
170
|
+
*/
|
|
171
|
+
export interface VivaMerchantOptions extends VivaCommonOptions {
|
|
172
|
+
mode: 'merchant';
|
|
173
|
+
/**
|
|
174
|
+
* Optional Smart Checkout sourceCode. Defaults to `'Default'` when unset.
|
|
175
|
+
*
|
|
176
|
+
* @see references/viva-docs/md/payment-source-for-isv.txt:101
|
|
177
|
+
*/
|
|
178
|
+
sourceCode?: string;
|
|
179
|
+
/**
|
|
180
|
+
* Optional hex color (no leading `#`) for Smart Checkout theming.
|
|
181
|
+
* Appended as `&color=<value>` to the Smart Checkout redirect URL.
|
|
182
|
+
*/
|
|
183
|
+
checkoutColor?: string;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* ISV-mode config. Used when the plugin acts on behalf of merchants under
|
|
187
|
+
* an ISV partner agreement. All per-tenant resolvers + onboarding fields
|
|
188
|
+
* live here.
|
|
189
|
+
*/
|
|
190
|
+
export interface VivaIsvOptions extends VivaCommonOptions {
|
|
191
|
+
mode: 'isv';
|
|
192
|
+
/**
|
|
193
|
+
* Resolve the Viva merchantId UUID for the current channel.
|
|
194
|
+
* Default: reads `ctx.channel.customFields.vivaMerchantId`.
|
|
195
|
+
*/
|
|
196
|
+
resolveMerchantId?: (ctx: VendureRequestContext) => string;
|
|
197
|
+
/**
|
|
198
|
+
* Resolve the Viva source code for the current channel.
|
|
199
|
+
* Default: reads `ctx.channel.customFields.vivaSourceCode ?? 'Default'`.
|
|
200
|
+
*/
|
|
201
|
+
resolveSourceCode?: (ctx: VendureRequestContext) => string;
|
|
202
|
+
/**
|
|
203
|
+
* Resolve the ISV platform fee (in minor units) for an order.
|
|
204
|
+
* MUST return a value strictly less than the order total; plugin validates
|
|
205
|
+
* this and throws `VIVA_ISV_AMOUNT_TOO_HIGH` if violated.
|
|
206
|
+
* Default: `() => 0`.
|
|
207
|
+
*/
|
|
208
|
+
resolveIsvAmount?: (order: VendureOrder, ctx: VendureRequestContext) => number;
|
|
209
|
+
/**
|
|
210
|
+
* Resolve an optional checkout theme color (hex string, no leading `#`).
|
|
211
|
+
* Appended as `&color=<value>` to the Smart Checkout redirect URL.
|
|
212
|
+
* Default: `() => undefined` (no color param).
|
|
213
|
+
*/
|
|
214
|
+
resolveCheckoutColor?: (ctx: VendureRequestContext) => string | undefined;
|
|
215
|
+
/**
|
|
216
|
+
* Required by `POST /isv/v1/accounts` — the URL the merchant is sent back to
|
|
217
|
+
* after completing the Viva-hosted onboarding flow. Probe-verified 2026-05-11:
|
|
218
|
+
* the ISV API rejects the create call when this field is absent.
|
|
219
|
+
*
|
|
220
|
+
* The admin-onboarding controller falls back to the per-request `overrides.returnUrl`
|
|
221
|
+
* if a caller supplies one; otherwise this value is used.
|
|
222
|
+
*/
|
|
223
|
+
onboardingReturnUrl: string | ((ctx: VendureRequestContext) => string);
|
|
224
|
+
/**
|
|
225
|
+
* Optional ISV branding shown on Viva's onboarding pages.
|
|
226
|
+
* When supplied, all three of `partnerName`, `logoUrl` (and optionally
|
|
227
|
+
* `primaryColor`) are passed verbatim to `POST /isv/v1/accounts`.
|
|
228
|
+
*/
|
|
229
|
+
onboardingBranding?: {
|
|
230
|
+
partnerName: string;
|
|
231
|
+
logoUrl: string;
|
|
232
|
+
/** Hex code, e.g. `#1F2439`. */
|
|
233
|
+
primaryColor?: string;
|
|
234
|
+
};
|
|
235
|
+
/**
|
|
236
|
+
* Reseller Basic-auth — required only when the plugin will call
|
|
237
|
+
* POST /api/sources (IsvSources). All three fields are all-or-nothing.
|
|
238
|
+
*
|
|
239
|
+
* @see references/viva-docs/md/payment-isv-api.txt:1
|
|
240
|
+
*/
|
|
241
|
+
reseller?: {
|
|
242
|
+
resellerId: string;
|
|
243
|
+
merchantId: string;
|
|
244
|
+
resellerApiKey: string;
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Configuration passed to `VivaPaymentPlugin.init(options)`.
|
|
249
|
+
*
|
|
250
|
+
* Discriminated union on `mode`. See `VivaMerchantOptions` and `VivaIsvOptions`.
|
|
251
|
+
*
|
|
252
|
+
* @see docs/plans/multi-mode-v0.md §5, §10
|
|
253
|
+
*/
|
|
254
|
+
export type VivaPaymentPluginOptions = VivaMerchantOptions | VivaIsvOptions;
|
|
255
|
+
/**
|
|
256
|
+
* Loose shape `VivaPaymentPlugin.init()` accepts before normalization.
|
|
257
|
+
*
|
|
258
|
+
* - `mode` is optional — defaults to `'merchant'` with a startup warning (or
|
|
259
|
+
* auto-detected as `'isv'` when ISV-only fields are present).
|
|
260
|
+
* - `clientId` / `clientSecret` may be replaced by their deprecated aliases
|
|
261
|
+
* `isvClientId` / `isvClientSecret` (one-minor back-compat, removal in 0.3.0).
|
|
262
|
+
*
|
|
263
|
+
* Callers may pass any mix of merchant + ISV fields here; `init()` validates +
|
|
264
|
+
* narrows to the strict `VivaPaymentPluginOptions` union.
|
|
265
|
+
*/
|
|
266
|
+
export interface VivaPaymentPluginInitInput extends Partial<Omit<VivaCommonOptions, 'clientId' | 'clientSecret'>> {
|
|
267
|
+
mode?: VivaMode;
|
|
268
|
+
/** Preferred name (0.2.0+). */
|
|
269
|
+
clientId?: string;
|
|
270
|
+
/** Preferred name (0.2.0+). */
|
|
271
|
+
clientSecret?: string;
|
|
272
|
+
/** @deprecated Use `clientId`. Accepted for one minor (removal in 0.3.0). */
|
|
273
|
+
isvClientId?: string;
|
|
274
|
+
/** @deprecated Use `clientSecret`. Accepted for one minor (removal in 0.3.0). */
|
|
275
|
+
isvClientSecret?: string;
|
|
276
|
+
sourceCode?: string;
|
|
277
|
+
checkoutColor?: string;
|
|
278
|
+
resolveMerchantId?: (ctx: VendureRequestContext) => string;
|
|
279
|
+
resolveSourceCode?: (ctx: VendureRequestContext) => string;
|
|
280
|
+
resolveIsvAmount?: (order: VendureOrder, ctx: VendureRequestContext) => number;
|
|
281
|
+
resolveCheckoutColor?: (ctx: VendureRequestContext) => string | undefined;
|
|
282
|
+
onboardingReturnUrl?: string | ((ctx: VendureRequestContext) => string);
|
|
283
|
+
onboardingBranding?: VivaIsvOptions['onboardingBranding'];
|
|
284
|
+
reseller?: VivaIsvOptions['reseller'];
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,6CAA6C,CAAC;AACvG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAM3E;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAEtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC5C,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAMD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAC;CACvF;AAMD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,KAAK,CAAC;AAM1C;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,WAAW,EAAE,eAAe,CAAC;IAE7B;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAC;IAerB;;;;;;OAMG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IAMrB;;;OAGG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAM/B;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC,CAAC;IAE9D;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC,CAAC;IAM9D;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAM9C;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;;;;;;;;;;;;;;;;OAiBG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC5D,IAAI,EAAE,UAAU,CAAC;IAEjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;GAIG;AACH,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACvD,IAAI,EAAE,KAAK,CAAC;IAOZ;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAE3D;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAE3D;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAE/E;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,GAAG,SAAS,CAAC;IAE1E;;;;;;;OAOG;IACH,mBAAmB,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC,CAAC;IAEvE;;;;OAIG;IACH,kBAAkB,CAAC,EAAE;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,gCAAgC;QAChC,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF;;;;;OAKG;IACH,QAAQ,CAAC,EAAE;QACT,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAMD;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,mBAAmB,GAAG,cAAc,CAAC;AAM5E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,0BACf,SAAQ,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,cAAc,CAAC,CAAC;IACrE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAC3D,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAC3D,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAC/E,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1E,mBAAmB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC,CAAC;IACxE,kBAAkB,CAAC,EAAE,cAAc,CAAC,oBAAoB,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;CACvC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* types.ts — Public configuration types for VivaPaymentPlugin.
|
|
3
|
+
*
|
|
4
|
+
* v0.2.0: `VivaPaymentPluginOptions` is now a **discriminated union** on `mode`.
|
|
5
|
+
*
|
|
6
|
+
* - `mode: 'isv'` (default until 0.3.0) — multi-merchant ISV partner setup.
|
|
7
|
+
* - `mode: 'merchant'` — single direct Viva merchant, no reseller hierarchy.
|
|
8
|
+
*
|
|
9
|
+
* Field rename (one-minor back-compat):
|
|
10
|
+
* - `isvClientId` → `clientId` (old name accepted with deprecation warning)
|
|
11
|
+
* - `isvClientSecret` → `clientSecret`
|
|
12
|
+
*
|
|
13
|
+
* Plan ref: docs/plans/multi-mode-v0.md §5 (config shape), §10 (Vendure adapter).
|
|
14
|
+
*
|
|
15
|
+
* Vendure types (RequestContext, Order) are imported as peer-dep types only —
|
|
16
|
+
* no runtime Vendure import here so the types module is safe to import in
|
|
17
|
+
* non-Vendure test environments.
|
|
18
|
+
*
|
|
19
|
+
* viva-payments-core types are imported from sub-paths to avoid pulling in
|
|
20
|
+
* implementation code.
|
|
21
|
+
*/
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* currency.ts — ISO 4217 alpha ↔ numeric conversion helpers.
|
|
3
|
+
*
|
|
4
|
+
* Viva's API requires numeric currency codes (e.g. 826 for GBP).
|
|
5
|
+
* Vendure stores alpha codes (e.g. 'GBP').
|
|
6
|
+
*
|
|
7
|
+
* @see references/viva-docs/md/wh-transaction-payment-created.txt:487
|
|
8
|
+
* @see docs/plans/vendure-plugin-v0.md §"Constraints" (Currency: Numeric ISO 4217)
|
|
9
|
+
*/
|
|
10
|
+
import type { CurrencyCode } from '@sakeetech/viva-payments-core/types';
|
|
11
|
+
/**
|
|
12
|
+
* Convert ISO 4217 alpha code to branded numeric CurrencyCode.
|
|
13
|
+
* Throws if the alpha code is unknown.
|
|
14
|
+
*
|
|
15
|
+
* @example alphaToNumeric('GBP') // → '826' (branded CurrencyCode)
|
|
16
|
+
*/
|
|
17
|
+
export declare function alphaToNumeric(alpha: string): CurrencyCode;
|
|
18
|
+
/**
|
|
19
|
+
* Convert ISO 4217 numeric string to alpha code.
|
|
20
|
+
* Coerces numeric input (string or number) defensively.
|
|
21
|
+
* Throws if the numeric code is unknown.
|
|
22
|
+
*
|
|
23
|
+
* @example numericToAlpha('826') // → 'GBP'
|
|
24
|
+
* @example numericToAlpha(826) // → 'GBP'
|
|
25
|
+
*/
|
|
26
|
+
export declare function numericToAlpha(numeric: string | number): string;
|
|
27
|
+
/**
|
|
28
|
+
* Coerce a webhook payload currency value (may be string or number) to the
|
|
29
|
+
* branded CurrencyCode type. Throws on unknown code.
|
|
30
|
+
*/
|
|
31
|
+
export declare function coerceCurrencyCode(raw: string | number): CurrencyCode;
|
|
32
|
+
//# sourceMappingURL=currency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../../src/util/currency.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AA8CxE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAO1D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAO/D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,CAMrE"}
|