@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,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api/admin-sources.controller.ts — ISV-only admin REST for /api/sources wrapping.
|
|
3
|
+
*
|
|
4
|
+
* Single route:
|
|
5
|
+
*
|
|
6
|
+
* POST /viva/admin/connected-accounts/:id/sources
|
|
7
|
+
* Creates a payment source (ecommerce or physical) on a connected
|
|
8
|
+
* merchant's Viva account via POST /api/sources on the legacy host,
|
|
9
|
+
* authenticated with Reseller Basic auth (per AUTH.md §1.2).
|
|
10
|
+
*
|
|
11
|
+
* Flow:
|
|
12
|
+
* 1. Mode gate: 404 in merchant mode (mirrors Medusa _mode-gate.ts).
|
|
13
|
+
* 2. Reseller gate: 412 VIVA_RESELLER_CREDENTIALS_MISSING when
|
|
14
|
+
* options.reseller is absent.
|
|
15
|
+
* 3. Body parse: 400 on missing/invalid fields or unknown kind.
|
|
16
|
+
* 4. Account lookup: IsvAccounts.retrieveConnectedAccount(:id).
|
|
17
|
+
* → 409 VIVA_ACCOUNT_NOT_VERIFIED when verified !== true or
|
|
18
|
+
* merchantId is null.
|
|
19
|
+
* 5. BasicAuthClient {authVariant:'reseller'} built with the connected
|
|
20
|
+
* merchant's UUID (account.merchantId — NOT config.reseller.merchantId).
|
|
21
|
+
* 6. IsvSources.createEcommerceSource / createPhysicalSource.
|
|
22
|
+
* 7. 201 with {sourceCode, name, kind}.
|
|
23
|
+
*
|
|
24
|
+
* Viva 4xx on /api/sources → 422 VIVA_SOURCE_CREATION_FAILED.
|
|
25
|
+
* Viva 5xx / auth errors → 503 VIVA_AUTH_DOWN (existing envelope rule).
|
|
26
|
+
*
|
|
27
|
+
* @see docs/plans/multi-mode-v0.md §6 (admin REST table)
|
|
28
|
+
* @see docs/AUTH.md §1.2 (Reseller Basic)
|
|
29
|
+
* @see docs/ENDPOINTS.md §5.1
|
|
30
|
+
* @see packages/medusa-payment-viva/src/api/viva/admin/connected-accounts/[id]/sources/route.ts
|
|
31
|
+
*/
|
|
32
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
33
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
34
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
35
|
+
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;
|
|
36
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
37
|
+
};
|
|
38
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
39
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
40
|
+
};
|
|
41
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
42
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
43
|
+
};
|
|
44
|
+
import { Controller, Post, Param, Body, Res, Inject, UseGuards, } from '@nestjs/common';
|
|
45
|
+
import { Allow, Permission, Logger, AuthGuard } from '@vendure/core';
|
|
46
|
+
import { IsvAccounts, IsvHttpClient, IsvSources, } from '@sakeetech/viva-payments-core/isv';
|
|
47
|
+
import { BasicAuthClient } from '@sakeetech/viva-payments-core/legacy';
|
|
48
|
+
import { VivaApiError, VivaAuthError, VivaValidationError, } from '@sakeetech/viva-payments-core/errors';
|
|
49
|
+
import { VivaPluginError } from '../util/error-envelope.js';
|
|
50
|
+
import { VIVA_PLUGIN_OPTIONS, VIVA_OAUTH2_STRATEGY_TOKEN, VIVA_LOG_CONTEXT, } from '../constants.js';
|
|
51
|
+
function parseBody(raw) {
|
|
52
|
+
const body = (raw ?? {});
|
|
53
|
+
const kind = body.kind;
|
|
54
|
+
if (kind !== 'ecommerce' && kind !== 'physical') {
|
|
55
|
+
return {
|
|
56
|
+
ok: false,
|
|
57
|
+
status: 400,
|
|
58
|
+
message: "body.kind must be 'ecommerce' or 'physical'",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const sourceCode = body.sourceCode;
|
|
62
|
+
if (sourceCode !== undefined && typeof sourceCode !== 'number') {
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
status: 400,
|
|
66
|
+
message: 'sourceCode must be a number',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (kind === 'physical') {
|
|
70
|
+
if (typeof body.name !== 'string' || body.name.trim() === '') {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
status: 400,
|
|
74
|
+
message: 'name is required for physical sources',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const input = {
|
|
78
|
+
name: body.name,
|
|
79
|
+
...(sourceCode !== undefined ? { sourceCode: sourceCode } : {}),
|
|
80
|
+
};
|
|
81
|
+
return { ok: true, kind, input };
|
|
82
|
+
}
|
|
83
|
+
if (typeof body.domain !== 'string' || body.domain.trim() === '') {
|
|
84
|
+
return { ok: false, status: 400, message: 'domain is required for ecommerce sources' };
|
|
85
|
+
}
|
|
86
|
+
if (typeof body.pathSuccess !== 'string' || body.pathSuccess.trim() === '') {
|
|
87
|
+
return { ok: false, status: 400, message: 'pathSuccess is required for ecommerce sources' };
|
|
88
|
+
}
|
|
89
|
+
if (typeof body.pathFail !== 'string' || body.pathFail.trim() === '') {
|
|
90
|
+
return { ok: false, status: 400, message: 'pathFail is required for ecommerce sources' };
|
|
91
|
+
}
|
|
92
|
+
const ecomInput = {
|
|
93
|
+
domain: body.domain,
|
|
94
|
+
pathSuccess: body.pathSuccess,
|
|
95
|
+
pathFail: body.pathFail,
|
|
96
|
+
...(typeof body.name === 'string' ? { name: body.name } : {}),
|
|
97
|
+
...(typeof body.isSecure === 'boolean' ? { isSecure: body.isSecure } : {}),
|
|
98
|
+
...(sourceCode !== undefined ? { sourceCode: sourceCode } : {}),
|
|
99
|
+
};
|
|
100
|
+
return { ok: true, kind, input: ecomInput };
|
|
101
|
+
}
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
// Helpers
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
function writeError(res, status, err) {
|
|
106
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
107
|
+
res.end(JSON.stringify(err.toJSON()));
|
|
108
|
+
}
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// Controller
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
let AdminSourcesController = class AdminSourcesController {
|
|
113
|
+
options;
|
|
114
|
+
oauth2;
|
|
115
|
+
constructor(options, oauth2) {
|
|
116
|
+
this.options = options;
|
|
117
|
+
this.oauth2 = oauth2;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Narrow options to ISV mode + reseller block.
|
|
121
|
+
* Returns:
|
|
122
|
+
* - { ok: true, isv } on success.
|
|
123
|
+
* - { ok: false, status, err } on mode mismatch (404) or missing reseller (412).
|
|
124
|
+
*/
|
|
125
|
+
requireIsvWithReseller() {
|
|
126
|
+
if (this.options.mode !== 'isv') {
|
|
127
|
+
return {
|
|
128
|
+
ok: false,
|
|
129
|
+
status: 404,
|
|
130
|
+
err: VivaPluginError.channelMisconfigured('POST /viva/admin/connected-accounts/:id/sources is ISV-only — not available in merchant mode.'),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (!this.options.reseller) {
|
|
134
|
+
return {
|
|
135
|
+
ok: false,
|
|
136
|
+
status: 412,
|
|
137
|
+
err: VivaPluginError.resellerCredentialsMissing(),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
ok: true,
|
|
142
|
+
isv: this.options,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Build the OAuth2-backed IsvAccounts client (platform creds). */
|
|
146
|
+
buildIsvAccounts() {
|
|
147
|
+
const client = new IsvHttpClient({
|
|
148
|
+
environment: this.options.environment,
|
|
149
|
+
authStrategy: this.oauth2,
|
|
150
|
+
});
|
|
151
|
+
return new IsvAccounts(client);
|
|
152
|
+
}
|
|
153
|
+
// -------------------------------------------------------------------------
|
|
154
|
+
// POST /viva/admin/connected-accounts/:id/sources
|
|
155
|
+
// -------------------------------------------------------------------------
|
|
156
|
+
async createSource(id, body, res) {
|
|
157
|
+
if (!id) {
|
|
158
|
+
writeError(res, 400, VivaPluginError.channelMisconfigured('id is required'));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// 1. Mode + reseller gate
|
|
162
|
+
const gate = this.requireIsvWithReseller();
|
|
163
|
+
if (!gate.ok) {
|
|
164
|
+
writeError(res, gate.status, gate.err);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const { isv } = gate;
|
|
168
|
+
// 2. Parse body
|
|
169
|
+
const parsed = parseBody(body);
|
|
170
|
+
if (!parsed.ok) {
|
|
171
|
+
writeError(res, parsed.status, VivaPluginError.channelMisconfigured(parsed.message));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// 3. Resolve connected account
|
|
175
|
+
let account;
|
|
176
|
+
try {
|
|
177
|
+
const accounts = this.buildIsvAccounts();
|
|
178
|
+
account = await accounts.retrieveConnectedAccount(id);
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
if (err instanceof VivaAuthError || (err instanceof VivaApiError && (err.httpStatus ?? 0) >= 500)) {
|
|
182
|
+
writeError(res, 503, VivaPluginError.authDown(err instanceof Error ? err.message : 'Viva service unavailable', err));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (err instanceof VivaApiError) {
|
|
186
|
+
const status = err.httpStatus ?? 502;
|
|
187
|
+
writeError(res, status >= 400 && status < 600 ? status : 502, VivaPluginError.apiError({
|
|
188
|
+
message: err.message,
|
|
189
|
+
vivaErrorMessage: err.message,
|
|
190
|
+
cause: err,
|
|
191
|
+
}));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
Logger.error(`[AdminSources] retrieveConnectedAccount failed for id=${id}: ${String(err)}`, VIVA_LOG_CONTEXT);
|
|
195
|
+
writeError(res, 500, VivaPluginError.internalError('Unexpected error', err));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (account.verified !== true || account.merchantId == null) {
|
|
199
|
+
const err = VivaPluginError.accountNotVerified(`Connected account ${id} is not verified yet (verified=${String(account.verified)}, ` +
|
|
200
|
+
`merchantId=${account.merchantId == null ? 'null' : 'set'}). ` +
|
|
201
|
+
`Wait for webhook 8194 or POST /viva/admin/connected-accounts/${id}/reconcile.`);
|
|
202
|
+
writeError(res, 409, err);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// 4. Build Reseller Basic client scoped to THIS connected merchant.
|
|
206
|
+
// Per AUTH.md §1.2: the MerchantId slot of Reseller Basic is the
|
|
207
|
+
// connected merchant's UUID (account.merchantId), NOT the platform's
|
|
208
|
+
// merchant id (isv.reseller.merchantId — unused here despite the name).
|
|
209
|
+
const basic = new BasicAuthClient({
|
|
210
|
+
authVariant: 'reseller',
|
|
211
|
+
environment: isv.environment,
|
|
212
|
+
resellerId: isv.reseller.resellerId,
|
|
213
|
+
merchantId: account.merchantId,
|
|
214
|
+
resellerApiKey: isv.reseller.resellerApiKey,
|
|
215
|
+
});
|
|
216
|
+
const sources = new IsvSources(basic);
|
|
217
|
+
// 5. Dispatch on kind.
|
|
218
|
+
try {
|
|
219
|
+
const response = parsed.kind === 'ecommerce'
|
|
220
|
+
? await sources.createEcommerceSource(parsed.input)
|
|
221
|
+
: await sources.createPhysicalSource(parsed.input);
|
|
222
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
223
|
+
res.end(JSON.stringify({
|
|
224
|
+
sourceCode: response.sourceCode,
|
|
225
|
+
name: response.name ?? parsed.input.name,
|
|
226
|
+
kind: parsed.kind,
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
if (err instanceof VivaValidationError) {
|
|
231
|
+
writeError(res, 400, VivaPluginError.channelMisconfigured(err.message));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (err instanceof VivaApiError) {
|
|
235
|
+
const status = err.httpStatus;
|
|
236
|
+
if (typeof status === 'number' && status >= 400 && status < 500) {
|
|
237
|
+
const rawCode = err.vivaCode !== undefined ? Number(err.vivaCode) : undefined;
|
|
238
|
+
const opts = {
|
|
239
|
+
message: err.message,
|
|
240
|
+
vivaStatus: status,
|
|
241
|
+
cause: err,
|
|
242
|
+
};
|
|
243
|
+
if (rawCode !== undefined && !Number.isNaN(rawCode)) {
|
|
244
|
+
opts.vivaErrorCode = rawCode;
|
|
245
|
+
}
|
|
246
|
+
writeError(res, 422, VivaPluginError.sourceCreationFailed(opts));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (typeof status === 'number' && status >= 500) {
|
|
250
|
+
writeError(res, 503, VivaPluginError.authDown(err.message, err));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
writeError(res, 502, VivaPluginError.apiError({
|
|
254
|
+
message: err.message,
|
|
255
|
+
vivaErrorMessage: err.message,
|
|
256
|
+
cause: err,
|
|
257
|
+
}));
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
Logger.error(`[AdminSources] createSource failed for id=${id}: ${String(err)}`, VIVA_LOG_CONTEXT);
|
|
261
|
+
writeError(res, 500, VivaPluginError.internalError('Unexpected error', err));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
__decorate([
|
|
266
|
+
Post(':id/sources'),
|
|
267
|
+
Allow(Permission.SuperAdmin),
|
|
268
|
+
__param(0, Param('id')),
|
|
269
|
+
__param(1, Body()),
|
|
270
|
+
__param(2, Res()),
|
|
271
|
+
__metadata("design:type", Function),
|
|
272
|
+
__metadata("design:paramtypes", [String, Object, Function]),
|
|
273
|
+
__metadata("design:returntype", Promise)
|
|
274
|
+
], AdminSourcesController.prototype, "createSource", null);
|
|
275
|
+
AdminSourcesController = __decorate([
|
|
276
|
+
Controller('viva/admin/connected-accounts'),
|
|
277
|
+
UseGuards(AuthGuard),
|
|
278
|
+
__param(0, Inject(VIVA_PLUGIN_OPTIONS)),
|
|
279
|
+
__param(1, Inject(VIVA_OAUTH2_STRATEGY_TOKEN)),
|
|
280
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
281
|
+
], AdminSourcesController);
|
|
282
|
+
export { AdminSourcesController };
|
|
283
|
+
//# sourceMappingURL=admin-sources.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-sources.controller.js","sourceRoot":"","sources":["../../src/api/admin-sources.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api/shop-api.extension.ts — GraphQL Shop API schema extension.
|
|
3
|
+
*
|
|
4
|
+
* Adds the `cancelPayment(paymentId)` mutation to the Shop API.
|
|
5
|
+
* `Order` is Vendure's existing built-in entity; `ErrorResult` interface
|
|
6
|
+
* is already in scope from @vendure/core so `CancelPaymentError implements
|
|
7
|
+
* ErrorResult` is valid without re-declaring the interface.
|
|
8
|
+
*
|
|
9
|
+
* Wired into plugin via `shopApiExtensions.schema` (see plugin.ts).
|
|
10
|
+
*
|
|
11
|
+
* @see docs/plans/vendure-plugin-v0.md §"API Surface — Shop API extension"
|
|
12
|
+
* @see docs/plans/vendure-plugin-v0.md §"Build Plan — V8"
|
|
13
|
+
*/
|
|
14
|
+
export declare const shopApiExtensions: import("graphql").DocumentNode;
|
|
15
|
+
//# sourceMappingURL=shop-api.extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shop-api.extension.d.ts","sourceRoot":"","sources":["../../src/api/shop-api.extension.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,eAAO,MAAM,iBAAiB,gCAmB5B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api/shop-api.extension.ts — GraphQL Shop API schema extension.
|
|
3
|
+
*
|
|
4
|
+
* Adds the `cancelPayment(paymentId)` mutation to the Shop API.
|
|
5
|
+
* `Order` is Vendure's existing built-in entity; `ErrorResult` interface
|
|
6
|
+
* is already in scope from @vendure/core so `CancelPaymentError implements
|
|
7
|
+
* ErrorResult` is valid without re-declaring the interface.
|
|
8
|
+
*
|
|
9
|
+
* Wired into plugin via `shopApiExtensions.schema` (see plugin.ts).
|
|
10
|
+
*
|
|
11
|
+
* @see docs/plans/vendure-plugin-v0.md §"API Surface — Shop API extension"
|
|
12
|
+
* @see docs/plans/vendure-plugin-v0.md §"Build Plan — V8"
|
|
13
|
+
*/
|
|
14
|
+
import { parse } from 'graphql';
|
|
15
|
+
export const shopApiExtensions = parse(`
|
|
16
|
+
extend type Mutation {
|
|
17
|
+
"""
|
|
18
|
+
Cancel a Vendure payment by ID. Voids the Viva-side authorization
|
|
19
|
+
(DELETE /checkout/v2/orders/{orderCode}) AND transitions the order back
|
|
20
|
+
to AddingItems. Storefront calls this on ?paymentCancelled=1.
|
|
21
|
+
Permission: order owner (active customer or active anonymous order).
|
|
22
|
+
"""
|
|
23
|
+
cancelPayment(paymentId: ID!): CancelPaymentResult!
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
union CancelPaymentResult = Order | CancelPaymentError
|
|
27
|
+
|
|
28
|
+
type CancelPaymentError implements ErrorResult {
|
|
29
|
+
errorCode: String!
|
|
30
|
+
message: String!
|
|
31
|
+
vivaErrorCode: Int
|
|
32
|
+
vivaErrorMessage: String
|
|
33
|
+
}
|
|
34
|
+
`);
|
|
35
|
+
//# sourceMappingURL=shop-api.extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shop-api.extension.js","sourceRoot":"","sources":["../../src/api/shop-api.extension.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;;;;;;;;;;;;;;;;;;;CAmBtC,CAAC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api/shop-api.resolver.ts — VivaShopApiResolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves the `cancelPayment(paymentId)` Shop API mutation.
|
|
5
|
+
*
|
|
6
|
+
* Authorization pattern (D5 + D8, §3 cancel ownership):
|
|
7
|
+
* - Authenticated customer: ctx.activeUserId must match order.customer.user.id.
|
|
8
|
+
* - Anonymous order: the session's active order (looked up via
|
|
9
|
+
* OrderService.getActiveOrderForUser or by active-order token) must have the
|
|
10
|
+
* same id as the payment's order. We load the active order for the current
|
|
11
|
+
* session (ctx) and compare order ids — if they match, the caller owns it.
|
|
12
|
+
* Returns CancelPaymentError { errorCode: 'AUTHORIZATION_FAILED' } when neither
|
|
13
|
+
* condition is satisfied. Does NOT throw — returns the union error member per
|
|
14
|
+
* Vendure GraphQL conventions.
|
|
15
|
+
*
|
|
16
|
+
* Idempotency on re-cancel:
|
|
17
|
+
* The row-status guard (step 6) fires before the Viva DELETE call.
|
|
18
|
+
* If viva_transaction.status is already 'cancelled', we return
|
|
19
|
+
* CancelPaymentError('VIVA_PAYMENT_NOT_CANCELLABLE') immediately — no Viva
|
|
20
|
+
* network call is made. If the row is NOT yet 'cancelled' but Viva 4xx with
|
|
21
|
+
* "already cancelled", the handler's error map converts it to
|
|
22
|
+
* CancelPaymentError('VIVA_API_ERROR'). Both paths are tested.
|
|
23
|
+
*
|
|
24
|
+
* @see docs/plans/vendure-plugin-v0.md §"API Surface — Shop API extension"
|
|
25
|
+
* @see docs/plans/vendure-plugin-v0.md §"Build Plan — V8"
|
|
26
|
+
* @see docs/plans/vendure-plugin-v0.md §D5, §D8
|
|
27
|
+
* @see docs/VENDURE-CONTRACT.MD §3
|
|
28
|
+
*/
|
|
29
|
+
import { RequestContext, OrderService, PaymentService, TransactionalConnection } from '@vendure/core';
|
|
30
|
+
import { StateMachineService } from '../services/state-machine.service.js';
|
|
31
|
+
import type { VivaPaymentPluginOptions } from '../types.js';
|
|
32
|
+
export declare class VivaShopApiResolver {
|
|
33
|
+
private readonly orderService;
|
|
34
|
+
private readonly paymentService;
|
|
35
|
+
private readonly connection;
|
|
36
|
+
private readonly stateMachine;
|
|
37
|
+
private readonly options;
|
|
38
|
+
constructor(orderService: OrderService, paymentService: PaymentService, connection: TransactionalConnection, stateMachine: StateMachineService, options: VivaPaymentPluginOptions);
|
|
39
|
+
cancelPayment(paymentId: string, ctx: RequestContext): Promise<object>;
|
|
40
|
+
private _isOrderOwner;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=shop-api.resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shop-api.resolver.d.ts","sourceRoot":"","sources":["../../src/api/shop-api.resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAEL,cAAc,EACd,YAAY,EACZ,cAAc,EACd,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAG3E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAgC5D,qBACa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY;IACA,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAJpC,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,uBAAuB,EACnC,YAAY,EAAE,mBAAmB,EACJ,OAAO,EAAE,wBAAwB;IAI3E,aAAa,CACE,SAAS,EAAE,MAAM,EAC7B,GAAG,EAAE,cAAc,GACzB,OAAO,CAAC,MAAM,CAAC;YAqJJ,aAAa;CA4B5B"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api/shop-api.resolver.ts — VivaShopApiResolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves the `cancelPayment(paymentId)` Shop API mutation.
|
|
5
|
+
*
|
|
6
|
+
* Authorization pattern (D5 + D8, §3 cancel ownership):
|
|
7
|
+
* - Authenticated customer: ctx.activeUserId must match order.customer.user.id.
|
|
8
|
+
* - Anonymous order: the session's active order (looked up via
|
|
9
|
+
* OrderService.getActiveOrderForUser or by active-order token) must have the
|
|
10
|
+
* same id as the payment's order. We load the active order for the current
|
|
11
|
+
* session (ctx) and compare order ids — if they match, the caller owns it.
|
|
12
|
+
* Returns CancelPaymentError { errorCode: 'AUTHORIZATION_FAILED' } when neither
|
|
13
|
+
* condition is satisfied. Does NOT throw — returns the union error member per
|
|
14
|
+
* Vendure GraphQL conventions.
|
|
15
|
+
*
|
|
16
|
+
* Idempotency on re-cancel:
|
|
17
|
+
* The row-status guard (step 6) fires before the Viva DELETE call.
|
|
18
|
+
* If viva_transaction.status is already 'cancelled', we return
|
|
19
|
+
* CancelPaymentError('VIVA_PAYMENT_NOT_CANCELLABLE') immediately — no Viva
|
|
20
|
+
* network call is made. If the row is NOT yet 'cancelled' but Viva 4xx with
|
|
21
|
+
* "already cancelled", the handler's error map converts it to
|
|
22
|
+
* CancelPaymentError('VIVA_API_ERROR'). Both paths are tested.
|
|
23
|
+
*
|
|
24
|
+
* @see docs/plans/vendure-plugin-v0.md §"API Surface — Shop API extension"
|
|
25
|
+
* @see docs/plans/vendure-plugin-v0.md §"Build Plan — V8"
|
|
26
|
+
* @see docs/plans/vendure-plugin-v0.md §D5, §D8
|
|
27
|
+
* @see docs/VENDURE-CONTRACT.MD §3
|
|
28
|
+
*/
|
|
29
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
30
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
31
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
32
|
+
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;
|
|
33
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
34
|
+
};
|
|
35
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
36
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
37
|
+
};
|
|
38
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
39
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
40
|
+
};
|
|
41
|
+
import { Resolver, Mutation, Args } from '@nestjs/graphql';
|
|
42
|
+
import { Inject } from '@nestjs/common';
|
|
43
|
+
import { Ctx, RequestContext, OrderService, PaymentService, TransactionalConnection, Logger, } from '@vendure/core';
|
|
44
|
+
import { StateMachineService } from '../services/state-machine.service.js';
|
|
45
|
+
import { VivaPluginError } from '../util/error-envelope.js';
|
|
46
|
+
import { VIVA_PLUGIN_OPTIONS, VIVA_LOG_CONTEXT } from '../constants.js';
|
|
47
|
+
import { vivaPaymentMethodHandler } from '../payment-method-handler.js';
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Terminal statuses that cannot be cancelled
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
const TERMINAL_STATUSES = new Set(['captured', 'refunded', 'partially_refunded', 'failed', 'cancelled']);
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// GraphQL union return types (plain objects with __typename for Vendure)
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
function cancelPaymentError(opts) {
|
|
56
|
+
return {
|
|
57
|
+
__typename: 'CancelPaymentError',
|
|
58
|
+
errorCode: opts.errorCode,
|
|
59
|
+
message: opts.message,
|
|
60
|
+
...(opts.vivaErrorCode !== undefined ? { vivaErrorCode: opts.vivaErrorCode } : {}),
|
|
61
|
+
...(opts.vivaErrorMessage !== undefined ? { vivaErrorMessage: opts.vivaErrorMessage } : {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Resolver
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
let VivaShopApiResolver = class VivaShopApiResolver {
|
|
68
|
+
orderService;
|
|
69
|
+
paymentService;
|
|
70
|
+
connection;
|
|
71
|
+
stateMachine;
|
|
72
|
+
options;
|
|
73
|
+
constructor(orderService, paymentService, connection, stateMachine, options) {
|
|
74
|
+
this.orderService = orderService;
|
|
75
|
+
this.paymentService = paymentService;
|
|
76
|
+
this.connection = connection;
|
|
77
|
+
this.stateMachine = stateMachine;
|
|
78
|
+
this.options = options;
|
|
79
|
+
}
|
|
80
|
+
async cancelPayment(paymentId, ctx) {
|
|
81
|
+
// -------------------------------------------------------------------------
|
|
82
|
+
// Step 1: load the Vendure Payment (with relations)
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
let payment;
|
|
85
|
+
try {
|
|
86
|
+
payment = await this.paymentService.findOneOrThrow(ctx, paymentId, ['order']);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Payment not found
|
|
90
|
+
}
|
|
91
|
+
if (!payment) {
|
|
92
|
+
return cancelPaymentError({
|
|
93
|
+
errorCode: 'VIVA_PAYMENT_NOT_CANCELLABLE',
|
|
94
|
+
message: 'Payment not found.',
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// -------------------------------------------------------------------------
|
|
98
|
+
// Step 2: load the Order (full record with customer.user relation)
|
|
99
|
+
// -------------------------------------------------------------------------
|
|
100
|
+
const orderStub = payment.order;
|
|
101
|
+
if (!orderStub) {
|
|
102
|
+
return cancelPaymentError({
|
|
103
|
+
errorCode: 'VIVA_PAYMENT_NOT_CANCELLABLE',
|
|
104
|
+
message: 'Payment is not associated with an order.',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
const order = await this.orderService.findOne(ctx, orderStub.id, ['customer', 'customer.user']);
|
|
108
|
+
if (!order) {
|
|
109
|
+
return cancelPaymentError({
|
|
110
|
+
errorCode: 'VIVA_PAYMENT_NOT_CANCELLABLE',
|
|
111
|
+
message: 'Order not found.',
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// -------------------------------------------------------------------------
|
|
115
|
+
// Step 3: Authorization — order owner check
|
|
116
|
+
//
|
|
117
|
+
// Case A — Authenticated customer: ctx.activeUserId matches order.customer.user.id
|
|
118
|
+
// Case B — Anonymous order: order matches the session's active order
|
|
119
|
+
// (Vendure stores activeOrderId / activeOrder.code on session)
|
|
120
|
+
// -------------------------------------------------------------------------
|
|
121
|
+
const isAuthorized = await this._isOrderOwner(ctx, order);
|
|
122
|
+
if (!isAuthorized) {
|
|
123
|
+
return cancelPaymentError({
|
|
124
|
+
errorCode: 'AUTHORIZATION_FAILED',
|
|
125
|
+
message: 'You may only cancel your own payments.',
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// -------------------------------------------------------------------------
|
|
129
|
+
// Step 4: load viva_transaction row
|
|
130
|
+
// -------------------------------------------------------------------------
|
|
131
|
+
const vivaRow = await this.stateMachine.getVivaTransaction(ctx, ctx.channelId, paymentId);
|
|
132
|
+
// -------------------------------------------------------------------------
|
|
133
|
+
// Step 5: row missing or no vivaOrderCode
|
|
134
|
+
// -------------------------------------------------------------------------
|
|
135
|
+
if (!vivaRow || !vivaRow.vivaOrderCode) {
|
|
136
|
+
return cancelPaymentError({
|
|
137
|
+
errorCode: 'VIVA_PAYMENT_NOT_CANCELLABLE',
|
|
138
|
+
message: 'No Viva order code found — payment may not have been initiated.',
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// -------------------------------------------------------------------------
|
|
142
|
+
// Step 6: already-terminal status guard (row-level, no Viva call needed)
|
|
143
|
+
// -------------------------------------------------------------------------
|
|
144
|
+
if (TERMINAL_STATUSES.has(vivaRow.status)) {
|
|
145
|
+
return cancelPaymentError({
|
|
146
|
+
errorCode: 'VIVA_PAYMENT_NOT_CANCELLABLE',
|
|
147
|
+
message: `Payment is already in terminal state: ${vivaRow.status}.`,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// -------------------------------------------------------------------------
|
|
151
|
+
// Step 7: invoke the payment handler's cancelPayment (voids Viva auth +
|
|
152
|
+
// updates viva_transaction.status = 'cancelled')
|
|
153
|
+
// -------------------------------------------------------------------------
|
|
154
|
+
try {
|
|
155
|
+
// cancelPayment on the handler throws VivaPluginError on failure
|
|
156
|
+
await vivaPaymentMethodHandler.cancelPaymentFn(ctx, order, payment, {});
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
if (err instanceof VivaPluginError) {
|
|
160
|
+
return cancelPaymentError({
|
|
161
|
+
errorCode: err.code,
|
|
162
|
+
message: err.message,
|
|
163
|
+
...(err.vivaErrorCode !== undefined ? { vivaErrorCode: err.vivaErrorCode } : {}),
|
|
164
|
+
...(err.vivaErrorMessage !== undefined ? { vivaErrorMessage: err.vivaErrorMessage } : {}),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
// Unexpected error — surface as internal
|
|
168
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
169
|
+
Logger.error(`[cancelPayment] Unexpected error for paymentId=${paymentId}: ${msg}`, VIVA_LOG_CONTEXT);
|
|
170
|
+
return cancelPaymentError({
|
|
171
|
+
errorCode: 'VIVA_INTERNAL_ERROR',
|
|
172
|
+
message: 'An unexpected error occurred while cancelling the payment.',
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
// -------------------------------------------------------------------------
|
|
176
|
+
// Step 8: transition Order back to AddingItems
|
|
177
|
+
// -------------------------------------------------------------------------
|
|
178
|
+
const refreshedOrder = await this.orderService.findOne(ctx, order.id);
|
|
179
|
+
if (refreshedOrder && refreshedOrder.state !== 'AddingItems') {
|
|
180
|
+
try {
|
|
181
|
+
await this.orderService.transitionToState(ctx, order.id, 'AddingItems');
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
// Race with webhook sweep — if already AddingItems treat as idempotent success
|
|
185
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
186
|
+
Logger.warn(`[cancelPayment] transitionToState('AddingItems') failed for order ${String(order.id)}: ${msg}. ` +
|
|
187
|
+
`Treating as idempotent (order may already be AddingItems).`, VIVA_LOG_CONTEXT);
|
|
188
|
+
// Re-check current state
|
|
189
|
+
const recheckOrder = await this.orderService.findOne(ctx, order.id);
|
|
190
|
+
if (recheckOrder && recheckOrder.state !== 'AddingItems') {
|
|
191
|
+
return cancelPaymentError({
|
|
192
|
+
errorCode: 'VIVA_INTERNAL_ERROR',
|
|
193
|
+
message: `Failed to transition order to AddingItems: ${msg}`,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// -------------------------------------------------------------------------
|
|
199
|
+
// Step 9: return the updated Order
|
|
200
|
+
// -------------------------------------------------------------------------
|
|
201
|
+
const finalOrder = await this.orderService.findOne(ctx, order.id);
|
|
202
|
+
return { ...(finalOrder ?? order), __typename: 'Order' };
|
|
203
|
+
}
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// Private: authorization helper
|
|
206
|
+
//
|
|
207
|
+
// Vendure anonymous-order pattern:
|
|
208
|
+
// OrderService.getActiveOrderForUser(ctx) returns the session's current
|
|
209
|
+
// active order (keyed by session token, not customer). We compare by id.
|
|
210
|
+
// For authenticated users, ctx.activeUserId is available.
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
async _isOrderOwner(ctx, order) {
|
|
213
|
+
// Case A: authenticated customer
|
|
214
|
+
if (ctx.activeUserId) {
|
|
215
|
+
const orderCustomerUserId = order.customer?.user?.id;
|
|
216
|
+
if (orderCustomerUserId !== undefined && orderCustomerUserId !== null) {
|
|
217
|
+
return String(ctx.activeUserId) === String(orderCustomerUserId);
|
|
218
|
+
}
|
|
219
|
+
// Customer exists but user relation missing — fall through to active-order check
|
|
220
|
+
}
|
|
221
|
+
// Case B: anonymous order — compare with session's active order
|
|
222
|
+
try {
|
|
223
|
+
const activeOrder = await this.orderService.getActiveOrderForUser(ctx, ctx.session?.user?.id);
|
|
224
|
+
if (activeOrder && String(activeOrder.id) === String(order.id)) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
// getActiveOrderForUser may throw if no session — treat as unauthorized
|
|
230
|
+
}
|
|
231
|
+
// Case B fallback: check activeOrderId on session (Vendure stores this on CachedSession)
|
|
232
|
+
const sessionActiveOrderId = ctx.session?.activeOrderId;
|
|
233
|
+
if (sessionActiveOrderId !== undefined && sessionActiveOrderId !== null) {
|
|
234
|
+
return String(sessionActiveOrderId) === String(order.id);
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
__decorate([
|
|
240
|
+
Mutation(),
|
|
241
|
+
__param(0, Args('paymentId')),
|
|
242
|
+
__param(1, Ctx()),
|
|
243
|
+
__metadata("design:type", Function),
|
|
244
|
+
__metadata("design:paramtypes", [String, RequestContext]),
|
|
245
|
+
__metadata("design:returntype", Promise)
|
|
246
|
+
], VivaShopApiResolver.prototype, "cancelPayment", null);
|
|
247
|
+
VivaShopApiResolver = __decorate([
|
|
248
|
+
Resolver(),
|
|
249
|
+
__param(4, Inject(VIVA_PLUGIN_OPTIONS)),
|
|
250
|
+
__metadata("design:paramtypes", [OrderService,
|
|
251
|
+
PaymentService,
|
|
252
|
+
TransactionalConnection,
|
|
253
|
+
StateMachineService, Object])
|
|
254
|
+
], VivaShopApiResolver);
|
|
255
|
+
export { VivaShopApiResolver };
|
|
256
|
+
//# sourceMappingURL=shop-api.resolver.js.map
|