@payware/mcp-server 1.0.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 (106) hide show
  1. package/.env.example +92 -0
  2. package/MCP-SETUP.md +190 -0
  3. package/README.md +483 -0
  4. package/check-keys.js +52 -0
  5. package/keys/README.md +112 -0
  6. package/mcp-config.json +9 -0
  7. package/package.json +66 -0
  8. package/payware-mcp-config.json +12 -0
  9. package/src/auth/rsa-keys.js +82 -0
  10. package/src/auth/sandbox-setup.js +187 -0
  11. package/src/config/env.js +229 -0
  12. package/src/config/partner-types.js +143 -0
  13. package/src/core/auth/jwt-factory.js +182 -0
  14. package/src/core/auth/jwt-token.js +735 -0
  15. package/src/core/utils/json-serializer.js +100 -0
  16. package/src/core/utils/key-utils.js +133 -0
  17. package/src/index.js +237 -0
  18. package/src/isv/data/index.js +291 -0
  19. package/src/isv/deep-links/delete-product-link.js +154 -0
  20. package/src/isv/deep-links/delete-transaction-link.js +154 -0
  21. package/src/isv/deep-links/get-product-link.js +167 -0
  22. package/src/isv/deep-links/get-transaction-link.js +167 -0
  23. package/src/isv/deep-links/index.js +23 -0
  24. package/src/isv/index.js +103 -0
  25. package/src/isv/oauth2/create-token-simple.js +46 -0
  26. package/src/isv/oauth2/get-token-info.js +157 -0
  27. package/src/isv/oauth2/obtain-token.js +189 -0
  28. package/src/isv/oauth2/token-helper.js +151 -0
  29. package/src/isv/products/audios.js +470 -0
  30. package/src/isv/products/create-product.js +314 -0
  31. package/src/isv/products/delete-product.js +119 -0
  32. package/src/isv/products/get-product-image.js +247 -0
  33. package/src/isv/products/get-product.js +168 -0
  34. package/src/isv/products/index.js +65 -0
  35. package/src/isv/products/list-products.js +136 -0
  36. package/src/isv/products/schedules.js +522 -0
  37. package/src/isv/products/update-product.js +265 -0
  38. package/src/isv/transactions/cancel-transaction.js +129 -0
  39. package/src/isv/transactions/create-transaction.js +361 -0
  40. package/src/isv/transactions/get-status.js +217 -0
  41. package/src/isv/transactions/process-transaction.js +145 -0
  42. package/src/isv/transactions/simulate-callback.js +146 -0
  43. package/src/isv/transactions/transaction-history.js +186 -0
  44. package/src/isv/utils/auth.js +159 -0
  45. package/src/mcp-proxy.js +150 -0
  46. package/src/merchant/data/export-report.js +108 -0
  47. package/src/merchant/data/generate-report.js +151 -0
  48. package/src/merchant/data/get-report-status.js +120 -0
  49. package/src/merchant/data/index.js +351 -0
  50. package/src/merchant/deep-links/delete-product-link.js +121 -0
  51. package/src/merchant/deep-links/delete-transaction-link.js +121 -0
  52. package/src/merchant/deep-links/get-product-link.js +134 -0
  53. package/src/merchant/deep-links/get-transaction-link.js +134 -0
  54. package/src/merchant/deep-links/index.js +23 -0
  55. package/src/merchant/index.js +92 -0
  56. package/src/merchant/products/audios.js +606 -0
  57. package/src/merchant/products/create-product.js +288 -0
  58. package/src/merchant/products/delete-product.js +111 -0
  59. package/src/merchant/products/get-product-image.js +252 -0
  60. package/src/merchant/products/get-product.js +144 -0
  61. package/src/merchant/products/index.js +65 -0
  62. package/src/merchant/products/list-products.js +112 -0
  63. package/src/merchant/products/schedules.js +646 -0
  64. package/src/merchant/products/update-product.js +282 -0
  65. package/src/merchant/transactions/cancel-transaction.js +241 -0
  66. package/src/merchant/transactions/create-transaction.js +482 -0
  67. package/src/merchant/transactions/get-status.js +196 -0
  68. package/src/merchant/transactions/process-transaction.js +349 -0
  69. package/src/merchant/transactions/simulate-callback.js +246 -0
  70. package/src/merchant/transactions/transaction-history.js +258 -0
  71. package/src/payment-institution/data/index.js +280 -0
  72. package/src/payment-institution/deep-links/delete-transaction-link.js +128 -0
  73. package/src/payment-institution/deep-links/get-transaction-link.js +141 -0
  74. package/src/payment-institution/deep-links/index.js +17 -0
  75. package/src/payment-institution/index.js +92 -0
  76. package/src/payment-institution/transactions/create-pi-transaction.js +484 -0
  77. package/src/payment-institution/transactions/finalize-transaction.js +340 -0
  78. package/src/payment-institution/transactions/get-transaction-history.js +269 -0
  79. package/src/payment-institution/transactions/get-transaction-status.js +234 -0
  80. package/src/payment-institution/transactions/process-pi-transaction.js +421 -0
  81. package/src/payment-institution/transactions/simulate-pi-callback.js +326 -0
  82. package/src/payment-institution/transactions/soundbite-transaction.js +269 -0
  83. package/src/proxy-server.js +205 -0
  84. package/src/shared/data/data-api.js +372 -0
  85. package/src/shared/deep-links/api.js +214 -0
  86. package/src/shared/index.js +44 -0
  87. package/src/shared/products/products-api.js +872 -0
  88. package/src/tools/advanced-code-generator.js +2247 -0
  89. package/src/utils/code-examples/common/auth-examples.js +1482 -0
  90. package/src/utils/code-examples/common/helpers.js +416 -0
  91. package/src/utils/code-examples/common/utils-examples.js +591 -0
  92. package/src/utils/code-examples/frameworks/examples.js +859 -0
  93. package/src/utils/code-examples/index.js +441 -0
  94. package/src/utils/code-examples/isv/oauth2.js +600 -0
  95. package/src/utils/code-examples/isv/products.js +666 -0
  96. package/src/utils/code-examples/isv/transactions.js +813 -0
  97. package/src/utils/code-examples/merchant/products.js +497 -0
  98. package/src/utils/code-examples/merchant/transactions.js +623 -0
  99. package/src/utils/code-examples/payment-institution/transactions.js +388 -0
  100. package/src/utils/code-examples/shared/data.js +607 -0
  101. package/src/utils/code-examples/shared/deep-links.js +662 -0
  102. package/src/utils/code-examples/shared/soundbites.js +808 -0
  103. package/src/utils/code-examples.js +646 -0
  104. package/src/utils/format-request.js +363 -0
  105. package/src/utils/json-formatter.js +249 -0
  106. package/src/utils/server-info.js +132 -0
@@ -0,0 +1,484 @@
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
+ * Create a payment institution transaction via payware API
8
+ * Payment institutions must specify role (SRC=payer, DST=payee) and account details
9
+ * @param {Object} params - Transaction parameters
10
+ * @returns {Object} Transaction response
11
+ */
12
+ export async function createPITransaction({
13
+ role,
14
+ account,
15
+ friendlyName,
16
+ type = 'PLAIN',
17
+ amount,
18
+ currency = 'EUR',
19
+ reasonL1,
20
+ reasonL2,
21
+ callbackUrl,
22
+ timeToLive = 120,
23
+ partnerId,
24
+ privateKey,
25
+ passbackParams,
26
+ // QR Options
27
+ qrFormat,
28
+ qrBorder,
29
+ qrErrorCorrection,
30
+ qrScale,
31
+ qrVersion,
32
+ // Barcode Options
33
+ barFormat,
34
+ barModuleWidth,
35
+ barBarHeight,
36
+ barFontSize,
37
+ barHumanReadableLocation,
38
+ useSandbox = true
39
+ }) {
40
+ if (!role || !['SRC', 'DST'].includes(role)) {
41
+ throw new Error('role is required and must be either "SRC" (payer) or "DST" (payee)');
42
+ }
43
+
44
+ if (!account) {
45
+ throw new Error('account is required (unique identifier of the account)');
46
+ }
47
+
48
+ if (!friendlyName) {
49
+ throw new Error('friendlyName is required (account holder recognizable name)');
50
+ }
51
+
52
+ if (amount !== undefined && (typeof amount !== 'string' && typeof amount !== 'number')) {
53
+ throw new Error('Amount must be a string or number representing currency value (e.g., "25.50" or 25.50)');
54
+ }
55
+
56
+ if (amount !== undefined && parseFloat(amount) < 0) {
57
+ throw new Error('Amount must be non-negative');
58
+ }
59
+
60
+ if (!['PLAIN', 'QR', 'BARCODE'].includes(type)) {
61
+ throw new Error('Transaction type must be PLAIN, QR, or BARCODE');
62
+ }
63
+
64
+ if (!partnerId || !privateKey) {
65
+ throw new Error('Partner ID and private key are required for proper JWT creation');
66
+ }
67
+
68
+ // Build QR options if applicable
69
+ const qrOptions = {};
70
+ if (type === 'QR') {
71
+ if (qrFormat) qrOptions.qrFormat = qrFormat;
72
+ if (qrBorder !== undefined) qrOptions.qrBorder = qrBorder;
73
+ if (qrErrorCorrection) qrOptions.qrErrorCorrection = qrErrorCorrection;
74
+ if (qrScale) qrOptions.qrScale = qrScale;
75
+ if (qrVersion) qrOptions.qrVersion = qrVersion;
76
+ }
77
+
78
+ // Build barcode options if applicable
79
+ const barOptions = {};
80
+ if (type === 'BARCODE') {
81
+ if (barFormat) barOptions.barFormat = barFormat;
82
+ if (barModuleWidth) barOptions.barModuleWidth = barModuleWidth;
83
+ if (barBarHeight) barOptions.barBarHeight = barBarHeight;
84
+ if (barFontSize) barOptions.barFontSize = barFontSize;
85
+ if (barHumanReadableLocation) barOptions.barHumanReadableLocation = barHumanReadableLocation;
86
+ }
87
+
88
+ // Build request body according to payment institution API documentation
89
+ const requestBody = {
90
+ role,
91
+ account,
92
+ friendlyName,
93
+ ...(callbackUrl && { callbackUrl }),
94
+ ...(passbackParams && {
95
+ passbackParams: typeof passbackParams === 'string' ? passbackParams : JSON.stringify(passbackParams)
96
+ }),
97
+ ...(amount !== undefined && {
98
+ trData: {
99
+ amount: amount.toString(),
100
+ currency,
101
+ ...(reasonL1 && { reasonL1 }),
102
+ ...(reasonL2 && { reasonL2 })
103
+ }
104
+ }),
105
+ trOptions: {
106
+ type,
107
+ timeToLive
108
+ },
109
+ ...(type === 'QR' && Object.keys(qrOptions).length > 0 && { qrOptions }),
110
+ ...(type === 'BARCODE' && Object.keys(barOptions).length > 0 && { barOptions })
111
+ };
112
+
113
+ // Convert to deterministic minimized JSON as required by payware API for MD5 calculation
114
+ const minimizedBodyString = createMinimizedJSON(requestBody);
115
+
116
+ // Create JWT token with contentMd5 for the request body (POST requires contentMd5)
117
+ const tokenData = createJWTToken(partnerId, privateKey, minimizedBodyString);
118
+
119
+ // Required headers as per payware API documentation
120
+ const headers = {
121
+ 'Authorization': `Bearer ${tokenData.token}`,
122
+ 'Content-Type': 'application/json',
123
+ 'Api-Version': '1' // Required: current API version
124
+ };
125
+
126
+ try {
127
+ const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
128
+ // Send the exact minimized JSON string that was used for MD5 calculation
129
+ // This ensures the server calculates the same MD5 hash
130
+ const response = await axios.post(`${baseUrl}/transactions`, minimizedBodyString, {
131
+ headers,
132
+ // Tell axios to send the string as-is, don't serialize it again
133
+ transformRequest: [(data) => data]
134
+ });
135
+
136
+ return {
137
+ success: true,
138
+ transaction: response.data,
139
+ requestId: response.headers['x-request-id'],
140
+ timestamp: new Date().toISOString()
141
+ };
142
+ } catch (error) {
143
+ return {
144
+ success: false,
145
+ error: {
146
+ message: error.response?.data?.message || error.message,
147
+ status: error.response?.status,
148
+ code: error.response?.data?.code,
149
+ details: error.response?.data
150
+ },
151
+ timestamp: new Date().toISOString()
152
+ };
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Create payment institution transaction tool implementation
158
+ */
159
+ export const createPITransactionTool = {
160
+ name: "payware_operations_create_transaction",
161
+ description: `Create a new payware transaction as a payment institution. Payment institutions must specify their role and account details.
162
+
163
+ **Payment Institution Features:**
164
+ - **Role**: DST (payee/receiver) or SRC (payer/sender)
165
+ - **Account**: Required unique account identifier
166
+ - **FriendlyName**: Required account holder name
167
+ - **P2P Support**: Cross-payment institution transactions
168
+ - **Flexible Amounts**: Support for amount-flexible transactions
169
+
170
+ **API Request Structure:**
171
+ \`\`\`json
172
+ {
173
+ "role": "DST",
174
+ "account": "GB29NWBK60161331926818",
175
+ "friendlyName": "John Doe",
176
+ "callbackUrl": "https://callback.url",
177
+ "passbackParams": "custom data",
178
+ "trData": {
179
+ "amount": "57.60",
180
+ "currency": "EUR",
181
+ "reasonL1": "Payment reason",
182
+ "reasonL2": "Additional details"
183
+ },
184
+ "trOptions": {
185
+ "type": "QR",
186
+ "timeToLive": 300
187
+ },
188
+ "qrOptions": { ... }
189
+ }
190
+ \`\`\``,
191
+ inputSchema: {
192
+ type: "object",
193
+ properties: {
194
+ role: {
195
+ type: "string",
196
+ enum: ["SRC", "DST"],
197
+ description: "Transaction role - SRC (payer/sender) or DST (payee/receiver)"
198
+ },
199
+ account: {
200
+ type: "string",
201
+ description: "Unique identifier of the account (required)",
202
+ maxLength: 36
203
+ },
204
+ friendlyName: {
205
+ type: "string",
206
+ description: "Account holder recognizable name (required)",
207
+ maxLength: 100
208
+ },
209
+ type: {
210
+ type: "string",
211
+ enum: ["PLAIN", "QR", "BARCODE"],
212
+ description: "Transaction type",
213
+ default: "PLAIN"
214
+ },
215
+ amount: {
216
+ type: "number",
217
+ description: "Amount as currency value (e.g., 25.50 for €25.50). Can be 0 for amount-flexible transactions",
218
+ minimum: 0,
219
+ maximum: 9999999999999.99
220
+ },
221
+ currency: {
222
+ type: "string",
223
+ pattern: "^[A-Z]{3}$",
224
+ description: "Transaction currency (ISO 3-character code)",
225
+ default: "EUR"
226
+ },
227
+ reasonL1: {
228
+ type: "string",
229
+ description: "Transaction grounds description",
230
+ maxLength: 100
231
+ },
232
+ reasonL2: {
233
+ type: "string",
234
+ description: "Transaction grounds description continuation",
235
+ maxLength: 100
236
+ },
237
+ timeToLive: {
238
+ type: "number",
239
+ description: "Time allowed for payment initiation in seconds (60-2592000 for PIs)",
240
+ minimum: 60,
241
+ maximum: 2592000,
242
+ default: 120
243
+ },
244
+ callbackUrl: {
245
+ type: "string",
246
+ description: "HTTPS URL to receive transaction status callbacks",
247
+ format: "uri"
248
+ },
249
+ partnerId: {
250
+ type: "string",
251
+ description: "Partner ID from payware dashboard. Uses PAYWARE_PARTNER_ID env var as default.",
252
+ default: getPartnerIdSafe()
253
+ },
254
+ privateKey: {
255
+ type: "string",
256
+ description: "RSA private key for JWT token creation. Uses environment-specific private key as default.",
257
+ default: getPrivateKeySafe(true)
258
+ },
259
+ passbackParams: {
260
+ type: "string",
261
+ description: "Additional parameters passed back in callbacks (max 200 chars)",
262
+ maxLength: 200
263
+ },
264
+ // QR Code Options
265
+ qrFormat: {
266
+ type: "string",
267
+ enum: ["PNG", "JPEG", "SVG"],
268
+ description: "Image format for QR code (only when type=QR, default: SVG)"
269
+ },
270
+ qrBorder: {
271
+ type: "number",
272
+ minimum: 1,
273
+ maximum: 10,
274
+ description: "Border size in modules around QR code (only when type=QR, default: 4)"
275
+ },
276
+ qrErrorCorrection: {
277
+ type: "string",
278
+ enum: ["LOW", "MEDIUM", "QUARTILE", "HIGH"],
279
+ description: "Error correction level (only when type=QR, default: QUARTILE)"
280
+ },
281
+ qrScale: {
282
+ type: "number",
283
+ minimum: 1,
284
+ maximum: 100,
285
+ description: "Size of each module in pixels (only when type=QR, default: 16)"
286
+ },
287
+ qrVersion: {
288
+ type: "number",
289
+ minimum: 1,
290
+ maximum: 40,
291
+ description: "QR code version (only when type=QR, default: 10)"
292
+ },
293
+ // Barcode Options
294
+ barFormat: {
295
+ type: "string",
296
+ enum: ["PNG", "SVG", "JPG"],
297
+ description: "Image format for barcode (only when type=BARCODE, default: SVG)"
298
+ },
299
+ barModuleWidth: {
300
+ type: "number",
301
+ minimum: 1,
302
+ maximum: 10,
303
+ description: "Barcode module width in pixels (applies when type=BARCODE)"
304
+ },
305
+ barBarHeight: {
306
+ type: "number",
307
+ minimum: 15,
308
+ maximum: 1000,
309
+ description: "Barcode height in pixels (applies when type=BARCODE)"
310
+ },
311
+ barFontSize: {
312
+ type: "number",
313
+ minimum: 0,
314
+ maximum: 24,
315
+ description: "Barcode text font size (applies when type=BARCODE)"
316
+ },
317
+ barHumanReadableLocation: {
318
+ type: "string",
319
+ enum: ["NONE", "BOTTOM", "TOP"],
320
+ description: "Location of human readable text (applies when type=BARCODE)"
321
+ },
322
+ useSandbox: {
323
+ type: "boolean",
324
+ description: "Use sandbox environment for testing",
325
+ default: true
326
+ }
327
+ },
328
+ required: ["role", "account", "friendlyName", "currency"]
329
+ },
330
+
331
+ async handler(args) {
332
+ const {
333
+ role,
334
+ account,
335
+ friendlyName,
336
+ type = 'PLAIN',
337
+ amount,
338
+ currency = 'EUR',
339
+ reasonL1,
340
+ reasonL2,
341
+ callbackUrl,
342
+ timeToLive = 120,
343
+ partnerId = getPartnerIdSafe(),
344
+ privateKey = getPrivateKeySafe(args.useSandbox ?? true),
345
+ passbackParams,
346
+ // QR Options
347
+ qrFormat,
348
+ qrBorder,
349
+ qrErrorCorrection,
350
+ qrScale,
351
+ qrVersion,
352
+ // Barcode Options
353
+ barFormat,
354
+ barModuleWidth,
355
+ barBarHeight,
356
+ barFontSize,
357
+ barHumanReadableLocation,
358
+ useSandbox = true
359
+ } = args;
360
+
361
+ if (!role) {
362
+ throw new Error("role is required and must be either 'SRC' (payer) or 'DST' (payee)");
363
+ }
364
+
365
+ if (!account) {
366
+ throw new Error("account is required (unique identifier of the account)");
367
+ }
368
+
369
+ if (!friendlyName) {
370
+ throw new Error("friendlyName is required (account holder recognizable name)");
371
+ }
372
+
373
+ if (!partnerId) {
374
+ throw new Error("Partner ID is required. Provide via 'partnerId' parameter or set PAYWARE_PARTNER_ID environment variable.");
375
+ }
376
+
377
+ if (!privateKey) {
378
+ throw new Error("Private key is required. Provide via 'privateKey' parameter or set PAYWARE_PRIVATE_KEY environment variable.");
379
+ }
380
+
381
+ const result = await createPITransaction({
382
+ role,
383
+ account,
384
+ friendlyName,
385
+ type,
386
+ amount,
387
+ currency,
388
+ reasonL1,
389
+ reasonL2,
390
+ callbackUrl,
391
+ timeToLive,
392
+ partnerId,
393
+ privateKey,
394
+ passbackParams,
395
+ // QR Options
396
+ qrFormat,
397
+ qrBorder,
398
+ qrErrorCorrection,
399
+ qrScale,
400
+ qrVersion,
401
+ // Barcode Options
402
+ barFormat,
403
+ barModuleWidth,
404
+ barBarHeight,
405
+ barFontSize,
406
+ barHumanReadableLocation,
407
+ useSandbox
408
+ });
409
+
410
+ if (result.success) {
411
+ const roleDescription = role === 'SRC' ? 'Payer (Source)' : 'Payee (Destination)';
412
+ const status = result.transaction.status || 'ACTIVE';
413
+ const statusEmoji = '⏳';
414
+
415
+ return {
416
+ content: [{
417
+ type: "text",
418
+ text: `🏦 **Payment Institution Transaction Created**
419
+
420
+ **Transaction Details:**
421
+ - ID: ${result.transaction.transactionId || 'N/A'}
422
+ - Role: ${roleDescription} (${role})
423
+ - Type: ${type}
424
+ - Status: ${statusEmoji} ${status}
425
+ - Account: ${account}
426
+ - Friendly Name: ${friendlyName}
427
+ ${amount ? `- Amount: ${amount} ${currency}` : '- Amount: Flexible (0.00)'}
428
+ ${reasonL1 ? `- Description: ${reasonL1}${reasonL2 ? ` (${reasonL2})` : ''}` : ''}
429
+ ${callbackUrl ? `- Callback URL: ${callbackUrl}` : ''}
430
+ - TTL: ${timeToLive} seconds
431
+
432
+ **API Response:**
433
+ \`\`\`json
434
+ ${JSON.stringify(result.transaction, null, 2)}
435
+ \`\`\`
436
+
437
+ **API Call Details:**
438
+ - Endpoint: POST ${baseUrl}/transactions
439
+ - Response Status: Success
440
+ - Request ID: ${result.requestId || 'N/A'}
441
+ - Timestamp: ${result.timestamp}
442
+
443
+ **Next Steps:**
444
+ 1. Save the transaction ID: \`${result.transaction.transactionId || 'N/A'}\`
445
+ 2. ${role === 'SRC' ? 'Share transaction ID with payee for processing' : 'Wait for payer to process this transaction'}
446
+ 3. Use \`payware_pi_get_transaction_status\` to check status
447
+ 4. Monitor callback notifications (if callback URL provided)
448
+ 5. ${role === 'SRC' ? 'Complete payment through payware interface' : 'Handle incoming payment processing'}`
449
+ }]
450
+ };
451
+ } else {
452
+ return {
453
+ content: [{
454
+ type: "text",
455
+ text: `❌ **Payment Institution Transaction Creation Failed**
456
+
457
+ **Error Details:**
458
+ - Message: ${result.error.message}
459
+ - Status: ${result.error.status || 'N/A'}
460
+ - Code: ${result.error.code || 'N/A'}
461
+
462
+ **API Call Details:**
463
+ - Endpoint: POST ${baseUrl}/transactions
464
+ - Headers: Api-Version=1, Content-Type=application/json
465
+
466
+ **Full Error Response:**
467
+ \`\`\`json
468
+ ${JSON.stringify(result.error.details || result.error, null, 2)}
469
+ \`\`\`
470
+
471
+ **Timestamp:** ${result.timestamp}
472
+
473
+ **Troubleshooting:**
474
+ 1. Verify role is either "SRC" or "DST"
475
+ 2. Ensure account and friendlyName are provided
476
+ 3. Check JWT token is valid and not expired
477
+ 4. Verify partner ID and API access for payment institutions
478
+ 5. Validate currency code (ISO 3-character)
479
+ 6. Check sandbox API status`
480
+ }]
481
+ };
482
+ }
483
+ }
484
+ };