@payware/mcp-server 1.2.0 → 1.3.0

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.
Files changed (58) hide show
  1. package/README.md +5 -0
  2. package/package.json +69 -66
  3. package/src/auth/sandbox-setup.js +186 -186
  4. package/src/isv/index.js +29 -1
  5. package/src/isv/invitations/index.js +471 -0
  6. package/src/isv/oauth2/obtain-token.js +19 -8
  7. package/src/isv/oauth2/token-helper.js +5 -2
  8. package/src/isv/poi/cancel-price.js +2 -10
  9. package/src/isv/poi/create.js +19 -0
  10. package/src/isv/poi/get-poi.js +2 -10
  11. package/src/isv/poi/get-qrcode.js +2 -10
  12. package/src/isv/poi/get-status.js +2 -10
  13. package/src/isv/poi/index.js +5 -0
  14. package/src/isv/poi/list-pois.js +2 -10
  15. package/src/isv/poi/set-price.js +217 -225
  16. package/src/isv/products/create-product.js +313 -313
  17. package/src/isv/products/update-product.js +264 -264
  18. package/src/isv/reference/index.js +249 -0
  19. package/src/isv/shops/index.js +22 -0
  20. package/src/isv/transactions/cancel-transaction.js +41 -10
  21. package/src/isv/transactions/create-transaction.js +20 -4
  22. package/src/isv/transactions/get-status.js +18 -11
  23. package/src/isv/transactions/process-transaction.js +160 -42
  24. package/src/isv/transactions/simulate-callback.js +128 -109
  25. package/src/isv/transactions/transaction-history.js +86 -90
  26. package/src/merchant/data/generate-report.js +19 -1
  27. package/src/merchant/index.js +21 -1
  28. package/src/merchant/logs/index.js +366 -0
  29. package/src/merchant/products/create-product.js +287 -287
  30. package/src/merchant/products/update-product.js +281 -281
  31. package/src/merchant/shops/index.js +18 -0
  32. package/src/merchant/transactions/cancel-transaction.js +10 -13
  33. package/src/merchant/transactions/create-transaction.js +88 -8
  34. package/src/merchant/transactions/get-status.js +40 -11
  35. package/src/merchant/transactions/process-transaction.js +2 -10
  36. package/src/merchant/transactions/simulate-callback.js +68 -9
  37. package/src/merchant/transactions/transaction-history.js +275 -257
  38. package/src/payment-institution/transactions/create-pi-transaction.js +2 -10
  39. package/src/payment-institution/transactions/finalize-transaction.js +333 -340
  40. package/src/payment-institution/transactions/get-transaction-history.js +2 -10
  41. package/src/payment-institution/transactions/get-transaction-status.js +38 -11
  42. package/src/payment-institution/transactions/process-pi-transaction.js +2 -10
  43. package/src/payment-institution/transactions/simulate-pi-callback.js +49 -9
  44. package/src/payment-institution/transactions/soundbite-transaction.js +2 -10
  45. package/src/shared/api-errors.js +188 -0
  46. package/src/shared/auth-headers.js +62 -0
  47. package/src/shared/data/data-api.js +11 -10
  48. package/src/shared/deep-links/api.js +5 -4
  49. package/src/shared/logs/logs-api.js +242 -0
  50. package/src/shared/poi/poi-create-api.js +419 -0
  51. package/src/shared/products/products-api.js +17 -16
  52. package/src/shared/shops/shops-api.js +155 -0
  53. package/src/tools/advanced-code-generator.js +2255 -2246
  54. package/src/utils/code-examples/common/auth-examples.js +1484 -1481
  55. package/src/utils/code-examples/common/helpers.js +7 -4
  56. package/src/utils/code-examples/isv/oauth2.js +458 -600
  57. package/src/utils/code-examples/isv/transactions.js +815 -812
  58. package/MCP-SETUP.md +0 -190
@@ -1,341 +1,334 @@
1
- import axios from 'axios';
2
- import { createJWTToken } from '../../core/auth/jwt-token.js';
3
- import { createMinimizedJSON } from '../../core/utils/json-serializer.js';
4
- import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
5
-
6
- /**
7
- * Finalize a transaction as a payment institution via payware API
8
- * Payment institutions can update transaction status after execution in their network
9
- * @param {Object} params - Transaction finalization parameters
10
- * @returns {Object} Transaction finalization response
11
- */
12
- export async function finalizeTransaction({
13
- transactionId,
14
- status,
15
- statusMessage,
16
- amount,
17
- fee,
18
- currency,
19
- partnerId,
20
- privateKey,
21
- useSandbox = true
22
- }) {
23
- if (!transactionId) {
24
- throw new Error('Transaction ID is required');
25
- }
26
-
27
- if (!status || !['CONFIRMED', 'CANCELLED', 'DECLINED', 'FAILED'].includes(status)) {
28
- throw new Error('status is required and must be one of: CONFIRMED, CANCELLED, DECLINED, FAILED');
29
- }
30
-
31
- if (['CANCELLED', 'DECLINED', 'FAILED'].includes(status) && !statusMessage) {
32
- throw new Error(`statusMessage is required for status: ${status}`);
33
- }
34
-
35
- if (status === 'CONFIRMED') {
36
- if (!amount) {
37
- throw new Error('amount is required for CONFIRMED transactions');
38
- }
39
- if (!currency) {
40
- throw new Error('currency is required for CONFIRMED transactions');
41
- }
42
- if (fee === undefined) {
43
- throw new Error('fee is required for CONFIRMED transactions (use 0 for no fee)');
44
- }
45
- }
46
-
47
- if (!partnerId || !privateKey) {
48
- throw new Error('Partner ID and private key are required for proper JWT creation');
49
- }
50
-
51
- // Build request body according to payment institution API documentation
52
- const requestBody = {
53
- status,
54
- ...(statusMessage && { statusMessage }),
55
- ...(status === 'CONFIRMED' && {
56
- amount: amount.toString(),
57
- fee: fee.toString(),
58
- currency
59
- })
60
- };
61
-
62
- // Convert to deterministic minimized JSON for SHA-256 calculation
63
- const minimizedBodyString = createMinimizedJSON(requestBody);
64
-
65
- // Create JWT token with contentSha256 for the request body (PATCH requires contentSha256)
66
- const tokenData = createJWTToken(partnerId, privateKey, minimizedBodyString);
67
-
68
- // Required headers as per payware API documentation
69
- const headers = {
70
- 'Authorization': `Bearer ${tokenData.token}`,
71
- 'Content-Type': 'application/json',
72
- 'Api-Version': '1' // Required: current API version
73
- };
74
-
75
- try {
76
- const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
77
- // Send the exact minimized JSON string that was used for SHA-256 calculation
78
- const response = await axios.patch(`${baseUrl}/transactions/${transactionId}`, minimizedBodyString, {
79
- headers,
80
- // Tell axios to send the string as-is, don't serialize it again
81
- transformRequest: [(data) => data]
82
- });
83
-
84
- return {
85
- success: true,
86
- transaction: response.data,
87
- requestId: response.headers['x-request-id'],
88
- timestamp: new Date().toISOString()
89
- };
90
- } catch (error) {
91
- return {
92
- success: false,
93
- error: {
94
- message: error.response?.data?.message || error.message,
95
- status: error.response?.status,
96
- code: error.response?.data?.code,
97
- details: error.response?.data
98
- },
99
- timestamp: new Date().toISOString()
100
- };
101
- }
102
- }
103
-
104
- /**
105
- * Finalize transaction tool implementation
106
- */
107
- export const finalizeTransactionTool = {
108
- name: "payware_operations_finalize_transaction",
109
- description: `Finalize a transaction as a payment institution. This updates the transaction status after execution in your payment network.
110
-
111
- **Payment Institution Finalization:**
112
- - **CONFIRMED**: Transaction executed successfully (requires amount, fee, currency)
113
- - **CANCELLED**: Transaction cancelled by creator
114
- - **DECLINED**: Transaction declined by payment institution (requires statusMessage)
115
- - **FAILED**: Transaction failed during execution (requires statusMessage)
116
-
117
- **Requirements:**
118
- - Only payment institutions can finalize transactions
119
- - Currency must match the processing currency of the transaction
120
- - Amount/fee required for CONFIRMED status
121
- - StatusMessage required for CANCELLED/DECLINED/FAILED status
122
-
123
- **API Request Structure:**
124
- \`\`\`json
125
- {
126
- "status": "CONFIRMED",
127
- "amount": "57.60",
128
- "fee": "0.29",
129
- "currency": "EUR"
130
- }
131
- \`\`\``,
132
- inputSchema: {
133
- type: "object",
134
- properties: {
135
- transactionId: {
136
- type: "string",
137
- description: "Transaction ID to finalize. Format: 2-char prefix + 8-char ID. Supports: 'pw' (standard), 'pr' (product), 'ps' (soundbite)",
138
- pattern: "^(pw|pr|ps)[0-9A-Za-z]{8}$"
139
- },
140
- status: {
141
- type: "string",
142
- enum: ["CONFIRMED", "CANCELLED", "DECLINED", "FAILED"],
143
- description: "Final transaction status"
144
- },
145
- statusMessage: {
146
- type: "string",
147
- description: "Transaction failure/cancellation reason (required for CANCELLED, DECLINED, FAILED)",
148
- maxLength: 100
149
- },
150
- amount: {
151
- type: ["number", "string"],
152
- description: "Final transaction amount (required for CONFIRMED status)",
153
- minimum: 0.01,
154
- maximum: 9999999999999.99
155
- },
156
- fee: {
157
- type: ["number", "string"],
158
- description: "Fee amount collected by payment institution (required for CONFIRMED status, use 0 for no fee)",
159
- minimum: 0,
160
- maximum: 9999999999999.99
161
- },
162
- currency: {
163
- type: "string",
164
- pattern: "^[A-Z]{3}$",
165
- description: "Transaction currency (required for CONFIRMED status, must match processing currency)"
166
- },
167
- partnerId: {
168
- type: "string",
169
- description: "Partner ID from payware dashboard. Uses PAYWARE_PARTNER_ID env var as default.",
170
- default: getPartnerIdSafe()
171
- },
172
- privateKey: {
173
- type: "string",
174
- description: "RSA private key for JWT token creation. Uses environment-specific private key as default.",
175
- default: getPrivateKeySafe()
176
- },
177
- useSandbox: {
178
- type: "boolean",
179
- description: "Use sandbox environment for testing",
180
- default: true
181
- }
182
- },
183
- required: ["transactionId", "status"]
184
- },
185
-
186
- async handler(args) {
187
- const {
188
- transactionId,
189
- status,
190
- statusMessage,
191
- amount,
192
- fee,
193
- currency,
194
- partnerId = getPartnerIdSafe(),
195
- privateKey = getPrivateKeySafe(args.useSandbox ?? true),
196
- useSandbox = true
197
- } = args;
198
-
199
- if (!transactionId) {
200
- throw new Error("Transaction ID is required");
201
- }
202
-
203
- if (!status) {
204
- throw new Error("status is required and must be one of: CONFIRMED, CANCELLED, DECLINED, FAILED");
205
- }
206
-
207
- // Validate status-specific requirements
208
- if (['CANCELLED', 'DECLINED', 'FAILED'].includes(status) && !statusMessage) {
209
- throw new Error(`statusMessage is required for status: ${status}`);
210
- }
211
-
212
- if (status === 'CONFIRMED') {
213
- if (!amount) {
214
- throw new Error("amount is required for CONFIRMED transactions");
215
- }
216
- if (!currency) {
217
- throw new Error("currency is required for CONFIRMED transactions");
218
- }
219
- if (fee === undefined) {
220
- throw new Error("fee is required for CONFIRMED transactions (use 0 for no fee)");
221
- }
222
- }
223
-
224
- if (!partnerId) {
225
- throw new Error("Partner ID is required. Provide via 'partnerId' parameter or set PAYWARE_PARTNER_ID environment variable.");
226
- }
227
-
228
- if (!privateKey) {
229
- throw new Error("Private key is required. Provide via 'privateKey' parameter or set PAYWARE_PRIVATE_KEY environment variable.");
230
- }
231
-
232
- const result = await finalizeTransaction({
233
- transactionId,
234
- status,
235
- statusMessage,
236
- amount,
237
- fee,
238
- currency,
239
- partnerId,
240
- privateKey,
241
- useSandbox
242
- });
243
-
244
- if (result.success) {
245
- const statusEmojis = {
246
- CONFIRMED: '✅',
247
- CANCELLED: '🚫',
248
- DECLINED: '❌',
249
- FAILED: '💥'
250
- };
251
-
252
- const statusEmoji = statusEmojis[status] || '📄';
253
-
254
- return {
255
- content: [{
256
- type: "text",
257
- text: `${statusEmoji} **Transaction Finalized Successfully**
258
-
259
- **Transaction ID:** ${transactionId}
260
- **Final Status:** ${status}
261
-
262
- **Finalization Details:**
263
- ${statusMessage ? `- Status Message: ${statusMessage}` : ''}
264
- ${amount ? `- Final Amount: ${amount} ${currency}` : ''}
265
- ${fee !== undefined ? `- Fee Collected: ${fee} ${currency}` : ''}
266
- ${result.transaction.paymentMethod ? `- Payment Method: ${result.transaction.paymentMethod}` : ''}
267
-
268
- **Transaction Response:**
269
- \`\`\`json
270
- ${JSON.stringify(result.transaction, null, 2)}
271
- \`\`\`
272
-
273
- **API Call Details:**
274
- - Endpoint: PATCH ${baseUrl}/transactions/${transactionId}
275
- - Request ID: ${result.requestId || 'N/A'}
276
- - Timestamp: ${result.timestamp}
277
-
278
- **Callbacks Triggered:**
279
- - **TRANSACTION_FINALIZED** callback sent to all parties
280
- - Transaction moved to historical records
281
- - Final status permanently recorded
282
-
283
- **Next Steps:**
284
- ${status === 'CONFIRMED' ?
285
- `1. ✅ Payment completed successfully
286
- 2. Transaction funds should be processed in your network
287
- 3. Use \`payware_pi_get_transaction_history\` to retrieve details later` :
288
- `1. ⚠️ Payment not completed due to: ${statusMessage || status}
289
- 2. Transaction marked as ${status} in payware system
290
- 3. All parties notified via callbacks`
291
- }
292
-
293
- **⚠️ Important:**
294
- - Transaction finalization is **permanent** and cannot be reversed
295
- - This transaction is now complete in the payware system`
296
- }]
297
- };
298
- } else {
299
- return {
300
- content: [{
301
- type: "text",
302
- text: `❌ **Transaction Finalization Failed**
303
-
304
- **Transaction ID:** ${transactionId}
305
- **Attempted Status:** ${status}
306
-
307
- **Error Details:**
308
- - Message: ${result.error.message}
309
- - Status: ${result.error.status || 'N/A'}
310
- - Code: ${result.error.code || 'N/A'}
311
-
312
- **Full Error Response:**
313
- \`\`\`json
314
- ${JSON.stringify(result.error.details || result.error, null, 2)}
315
- \`\`\`
316
-
317
- **Timestamp:** ${result.timestamp}
318
-
319
- **Common Finalization Issues:**
320
- 1. **ERR_MISSING_TRANSACTION**: Transaction ID not found or expired
321
- 2. **ERR_TRANSACTION_NOT_PROCESSED**: Transaction hasn't been processed yet
322
- 3. **ERR_ALREADY_PROCESSED**: Transaction already finalized
323
- 4. **ERR_INVALID_STATUS**: Invalid status value provided
324
- 5. **ERR_MISSING_STATUS_MESSAGE**: Status message required for failed/declined/cancelled
325
- 6. **ERR_SPECIFYING_CURRENCY_NOT_ALLOWED**: Currency doesn't match transaction currency
326
- 7. **ERR_INVALID_AMOUNT**: Amount validation failed
327
- 8. **ERR_UNAUTHORIZED_OPERATION**: Not authorized to finalize this transaction
328
-
329
- **Troubleshooting:**
330
- 1. Verify transaction ID is correct: 10 characters total, starts with 'pw' (standard), 'pr' (product), or 'ps' (soundbite)
331
- 2. Ensure transaction has been processed first
332
- 3. Check status is one of: CONFIRMED, CANCELLED, DECLINED, FAILED
333
- 4. Provide statusMessage for non-CONFIRMED statuses
334
- 5. Include amount, fee, currency for CONFIRMED status
335
- 6. Verify you are authorized to finalize this transaction
336
- 7. Ensure currency matches the original transaction currency`
337
- }]
338
- };
339
- }
340
- }
1
+ import axios from 'axios';
2
+ import { createJWTToken } from '../../core/auth/jwt-token.js';
3
+ import { createMinimizedJSON } from '../../core/utils/json-serializer.js';
4
+ import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
5
+ import { apiErrorResult } from '../../shared/api-errors.js';
6
+
7
+ /**
8
+ * Finalize a transaction as a payment institution via payware API
9
+ * Payment institutions can update transaction status after execution in their network
10
+ * @param {Object} params - Transaction finalization parameters
11
+ * @returns {Object} Transaction finalization response
12
+ */
13
+ export async function finalizeTransaction({
14
+ transactionId,
15
+ status,
16
+ statusMessage,
17
+ amount,
18
+ fee,
19
+ currency,
20
+ partnerId,
21
+ privateKey,
22
+ useSandbox = true
23
+ }) {
24
+ if (!transactionId) {
25
+ throw new Error('Transaction ID is required');
26
+ }
27
+
28
+ if (!status || !['CONFIRMED', 'CANCELLED', 'DECLINED', 'FAILED'].includes(status)) {
29
+ throw new Error('status is required and must be one of: CONFIRMED, CANCELLED, DECLINED, FAILED');
30
+ }
31
+
32
+ if (['CANCELLED', 'DECLINED', 'FAILED'].includes(status) && !statusMessage) {
33
+ throw new Error(`statusMessage is required for status: ${status}`);
34
+ }
35
+
36
+ if (status === 'CONFIRMED') {
37
+ if (!amount) {
38
+ throw new Error('amount is required for CONFIRMED transactions');
39
+ }
40
+ if (!currency) {
41
+ throw new Error('currency is required for CONFIRMED transactions');
42
+ }
43
+ if (fee === undefined) {
44
+ throw new Error('fee is required for CONFIRMED transactions (use 0 for no fee)');
45
+ }
46
+ }
47
+
48
+ if (!partnerId || !privateKey) {
49
+ throw new Error('Partner ID and private key are required for proper JWT creation');
50
+ }
51
+
52
+ // Build request body according to payment institution API documentation
53
+ const requestBody = {
54
+ status,
55
+ ...(statusMessage && { statusMessage }),
56
+ ...(status === 'CONFIRMED' && {
57
+ amount: amount.toString(),
58
+ fee: fee.toString(),
59
+ currency
60
+ })
61
+ };
62
+
63
+ // Convert to deterministic minimized JSON for SHA-256 calculation
64
+ const minimizedBodyString = createMinimizedJSON(requestBody);
65
+
66
+ // Create JWT token with contentSha256 for the request body (PATCH requires contentSha256)
67
+ const tokenData = createJWTToken(partnerId, privateKey, minimizedBodyString);
68
+
69
+ // Required headers as per payware API documentation
70
+ const headers = {
71
+ 'Authorization': `Bearer ${tokenData.token}`,
72
+ 'Content-Type': 'application/json',
73
+ 'Api-Version': '1' // Required: current API version
74
+ };
75
+
76
+ try {
77
+ const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
78
+ // Send the exact minimized JSON string that was used for SHA-256 calculation
79
+ const response = await axios.patch(`${baseUrl}/transactions/${transactionId}`, minimizedBodyString, {
80
+ headers,
81
+ // Tell axios to send the string as-is, don't serialize it again
82
+ transformRequest: [(data) => data]
83
+ });
84
+
85
+ return {
86
+ success: true,
87
+ transaction: response.data,
88
+ requestId: response.headers['x-request-id'],
89
+ timestamp: new Date().toISOString()
90
+ };
91
+ } catch (error) {
92
+ return apiErrorResult(error);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Finalize transaction tool implementation
98
+ */
99
+ export const finalizeTransactionTool = {
100
+ name: "payware_operations_finalize_transaction",
101
+ description: `Finalize a transaction as a payment institution. This updates the transaction status after execution in your payment network.
102
+
103
+ **Payment Institution Finalization:**
104
+ - **CONFIRMED**: Transaction executed successfully (requires amount, fee, currency)
105
+ - **CANCELLED**: Transaction cancelled by creator
106
+ - **DECLINED**: Transaction declined by payment institution (requires statusMessage)
107
+ - **FAILED**: Transaction failed during execution (requires statusMessage)
108
+
109
+ **Requirements:**
110
+ - Only payment institutions can finalize transactions
111
+ - Currency must match the processing currency of the transaction
112
+ - Amount/fee required for CONFIRMED status
113
+ - StatusMessage required for CANCELLED/DECLINED/FAILED status
114
+ - **fee**: payware calculates it, the institution executes it. Echo the \`fee\` from the process response verbatim - do not recompute it from \`feeFixed\`/\`feeRate\` and do not re-round it, or the call is rejected with ERR_FEE_MISMATCH.
115
+
116
+ **API Request Structure:**
117
+ \`\`\`json
118
+ {
119
+ "status": "CONFIRMED",
120
+ "amount": "57.60",
121
+ "fee": "0.29",
122
+ "currency": "EUR"
123
+ }
124
+ \`\`\``,
125
+ inputSchema: {
126
+ type: "object",
127
+ properties: {
128
+ transactionId: {
129
+ type: "string",
130
+ description: "Transaction ID to finalize. Format: 2-char prefix + 8-char ID. Supports: 'pw' (standard), 'pr' (product), 'ps' (soundbite)",
131
+ pattern: "^(pw|pr|ps)[0-9A-Za-z]{8}$"
132
+ },
133
+ status: {
134
+ type: "string",
135
+ enum: ["CONFIRMED", "CANCELLED", "DECLINED", "FAILED"],
136
+ description: "Final transaction status"
137
+ },
138
+ statusMessage: {
139
+ type: "string",
140
+ description: "Transaction failure/cancellation reason (required for CANCELLED, DECLINED, FAILED)",
141
+ maxLength: 100
142
+ },
143
+ amount: {
144
+ type: ["number", "string"],
145
+ description: "Final transaction amount (required for CONFIRMED status)",
146
+ minimum: 0.01,
147
+ maximum: 9999999999999.99
148
+ },
149
+ fee: {
150
+ type: ["number", "string"],
151
+ description: "The payware transaction fee. Echo back the `fee` value from the process/get response EXACTLY - payware calculates the fee and the institution executes it. Do not recompute it from feeFixed/feeRate and do not re-round it; it already carries the currency's smallest payable unit (2 decimals for EUR/USD, 0 for JPY, 3 for KWD). A recomputed value is rejected with ERR_FEE_MISMATCH. Required for CONFIRMED status; use 0 when no fee applies.",
152
+ minimum: 0,
153
+ maximum: 9999999999999.99
154
+ },
155
+ currency: {
156
+ type: "string",
157
+ pattern: "^[A-Z]{3}$",
158
+ description: "Transaction currency (required for CONFIRMED status, must match processing currency)"
159
+ },
160
+ partnerId: {
161
+ type: "string",
162
+ description: "Partner ID from payware dashboard. Uses PAYWARE_PARTNER_ID env var as default.",
163
+ default: getPartnerIdSafe()
164
+ },
165
+ privateKey: {
166
+ type: "string",
167
+ description: "RSA private key for JWT token creation. Uses environment-specific private key as default.",
168
+ default: getPrivateKeySafe()
169
+ },
170
+ useSandbox: {
171
+ type: "boolean",
172
+ description: "Use sandbox environment for testing",
173
+ default: true
174
+ }
175
+ },
176
+ required: ["transactionId", "status"]
177
+ },
178
+
179
+ async handler(args) {
180
+ const {
181
+ transactionId,
182
+ status,
183
+ statusMessage,
184
+ amount,
185
+ fee,
186
+ currency,
187
+ partnerId = getPartnerIdSafe(),
188
+ privateKey = getPrivateKeySafe(args.useSandbox ?? true),
189
+ useSandbox = true
190
+ } = args;
191
+
192
+ if (!transactionId) {
193
+ throw new Error("Transaction ID is required");
194
+ }
195
+
196
+ if (!status) {
197
+ throw new Error("status is required and must be one of: CONFIRMED, CANCELLED, DECLINED, FAILED");
198
+ }
199
+
200
+ // Validate status-specific requirements
201
+ if (['CANCELLED', 'DECLINED', 'FAILED'].includes(status) && !statusMessage) {
202
+ throw new Error(`statusMessage is required for status: ${status}`);
203
+ }
204
+
205
+ if (status === 'CONFIRMED') {
206
+ if (!amount) {
207
+ throw new Error("amount is required for CONFIRMED transactions");
208
+ }
209
+ if (!currency) {
210
+ throw new Error("currency is required for CONFIRMED transactions");
211
+ }
212
+ if (fee === undefined) {
213
+ throw new Error("fee is required for CONFIRMED transactions (use 0 for no fee)");
214
+ }
215
+ }
216
+
217
+ if (!partnerId) {
218
+ throw new Error("Partner ID is required. Provide via 'partnerId' parameter or set PAYWARE_PARTNER_ID environment variable.");
219
+ }
220
+
221
+ if (!privateKey) {
222
+ throw new Error("Private key is required. Provide via 'privateKey' parameter or set PAYWARE_PRIVATE_KEY environment variable.");
223
+ }
224
+
225
+ const result = await finalizeTransaction({
226
+ transactionId,
227
+ status,
228
+ statusMessage,
229
+ amount,
230
+ fee,
231
+ currency,
232
+ partnerId,
233
+ privateKey,
234
+ useSandbox
235
+ });
236
+
237
+ if (result.success) {
238
+ const statusEmojis = {
239
+ CONFIRMED: '✅',
240
+ CANCELLED: '🚫',
241
+ DECLINED: '❌',
242
+ FAILED: '💥'
243
+ };
244
+
245
+ const statusEmoji = statusEmojis[status] || '📄';
246
+
247
+ return {
248
+ content: [{
249
+ type: "text",
250
+ text: `${statusEmoji} **Transaction Finalized Successfully**
251
+
252
+ **Transaction ID:** ${transactionId}
253
+ **Final Status:** ${status}
254
+
255
+ **Finalization Details:**
256
+ ${statusMessage ? `- Status Message: ${statusMessage}` : ''}
257
+ ${amount ? `- Final Amount: ${amount} ${currency}` : ''}
258
+ ${fee !== undefined ? `- Fee Collected: ${fee} ${currency}` : ''}
259
+ ${result.transaction.paymentMethod ? `- Payment Method: ${result.transaction.paymentMethod}` : ''}
260
+
261
+ **Transaction Response:**
262
+ \`\`\`json
263
+ ${JSON.stringify(result.transaction, null, 2)}
264
+ \`\`\`
265
+
266
+ **API Call Details:**
267
+ - Endpoint: PATCH ${baseUrl}/transactions/${transactionId}
268
+ - Request ID: ${result.requestId || 'N/A'}
269
+ - Timestamp: ${result.timestamp}
270
+
271
+ **Callbacks Triggered:**
272
+ - **TRANSACTION_FINALIZED** callback sent to all parties
273
+ - Transaction moved to historical records
274
+ - Final status permanently recorded
275
+
276
+ **Next Steps:**
277
+ ${status === 'CONFIRMED' ?
278
+ `1. ✅ Payment completed successfully
279
+ 2. Transaction funds should be processed in your network
280
+ 3. Use \`payware_pi_get_transaction_history\` to retrieve details later` :
281
+ `1. ⚠️ Payment not completed due to: ${statusMessage || status}
282
+ 2. Transaction marked as ${status} in payware system
283
+ 3. All parties notified via callbacks`
284
+ }
285
+
286
+ **⚠️ Important:**
287
+ - Transaction finalization is **permanent** and cannot be reversed
288
+ - This transaction is now complete in the payware system`
289
+ }]
290
+ };
291
+ } else {
292
+ return {
293
+ content: [{
294
+ type: "text",
295
+ text: `❌ **Transaction Finalization Failed**
296
+
297
+ **Transaction ID:** ${transactionId}
298
+ **Attempted Status:** ${status}
299
+
300
+ **Error Details:**
301
+ - Message: ${result.error.message}
302
+ - Status: ${result.error.status || 'N/A'}
303
+ - Code: ${result.error.code || 'N/A'}
304
+
305
+ **Full Error Response:**
306
+ \`\`\`json
307
+ ${JSON.stringify(result.error.details || result.error, null, 2)}
308
+ \`\`\`
309
+
310
+ **Timestamp:** ${result.timestamp}
311
+
312
+ **Common Finalization Issues:**
313
+ 1. **ERR_MISSING_TRANSACTION**: Transaction ID not found or expired
314
+ 2. **ERR_TRANSACTION_NOT_PROCESSED**: Transaction hasn't been processed yet
315
+ 3. **ERR_ALREADY_PROCESSED**: Transaction already finalized
316
+ 4. **ERR_INVALID_STATUS**: Invalid status value provided
317
+ 5. **ERR_MISSING_STATUS_MESSAGE**: Status message required for failed/declined/cancelled
318
+ 6. **ERR_SPECIFYING_CURRENCY_NOT_ALLOWED**: Currency doesn't match transaction currency
319
+ 7. **ERR_INVALID_AMOUNT**: Amount validation failed
320
+ 8. **ERR_UNAUTHORIZED_OPERATION**: Not authorized to finalize this transaction
321
+
322
+ **Troubleshooting:**
323
+ 1. Verify transaction ID is correct: 10 characters total, starts with 'pw' (standard), 'pr' (product), or 'ps' (soundbite)
324
+ 2. Ensure transaction has been processed first
325
+ 3. Check status is one of: CONFIRMED, CANCELLED, DECLINED, FAILED
326
+ 4. Provide statusMessage for non-CONFIRMED statuses
327
+ 5. Include amount, fee, currency for CONFIRMED status
328
+ 6. Verify you are authorized to finalize this transaction
329
+ 7. Ensure currency matches the original transaction currency`
330
+ }]
331
+ };
332
+ }
333
+ }
341
334
  };