@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,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
+
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 MD5 calculation
63
+ const minimizedBodyString = createMinimizedJSON(requestBody);
64
+
65
+ // Create JWT token with contentMd5 for the request body (PATCH requires contentMd5)
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 MD5 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
+
267
+ **Transaction Response:**
268
+ \`\`\`json
269
+ ${JSON.stringify(result.transaction, null, 2)}
270
+ \`\`\`
271
+
272
+ **API Call Details:**
273
+ - Endpoint: PATCH ${baseUrl}/transactions/${transactionId}
274
+ - Request ID: ${result.requestId || 'N/A'}
275
+ - Timestamp: ${result.timestamp}
276
+
277
+ **Callbacks Triggered:**
278
+ - **TRANSACTION_FINALIZED** callback sent to all parties
279
+ - Transaction moved to historical records
280
+ - Final status permanently recorded
281
+
282
+ **Next Steps:**
283
+ ${status === 'CONFIRMED' ?
284
+ `1. ✅ Payment completed successfully
285
+ 2. Transaction funds should be processed in your network
286
+ 3. Use \`payware_pi_get_transaction_history\` to retrieve details later` :
287
+ `1. ⚠️ Payment not completed due to: ${statusMessage || status}
288
+ 2. Transaction marked as ${status} in payware system
289
+ 3. All parties notified via callbacks`
290
+ }
291
+
292
+ **⚠️ Important:**
293
+ - Transaction finalization is **permanent** and cannot be reversed
294
+ - This transaction is now complete in the payware system`
295
+ }]
296
+ };
297
+ } else {
298
+ return {
299
+ content: [{
300
+ type: "text",
301
+ text: `❌ **Transaction Finalization Failed**
302
+
303
+ **Transaction ID:** ${transactionId}
304
+ **Attempted Status:** ${status}
305
+
306
+ **Error Details:**
307
+ - Message: ${result.error.message}
308
+ - Status: ${result.error.status || 'N/A'}
309
+ - Code: ${result.error.code || 'N/A'}
310
+
311
+ **Full Error Response:**
312
+ \`\`\`json
313
+ ${JSON.stringify(result.error.details || result.error, null, 2)}
314
+ \`\`\`
315
+
316
+ **Timestamp:** ${result.timestamp}
317
+
318
+ **Common Finalization Issues:**
319
+ 1. **ERR_MISSING_TRANSACTION**: Transaction ID not found or expired
320
+ 2. **ERR_TRANSACTION_NOT_PROCESSED**: Transaction hasn't been processed yet
321
+ 3. **ERR_ALREADY_PROCESSED**: Transaction already finalized
322
+ 4. **ERR_INVALID_STATUS**: Invalid status value provided
323
+ 5. **ERR_MISSING_STATUS_MESSAGE**: Status message required for failed/declined/cancelled
324
+ 6. **ERR_SPECIFYING_CURRENCY_NOT_ALLOWED**: Currency doesn't match transaction currency
325
+ 7. **ERR_INVALID_AMOUNT**: Amount validation failed
326
+ 8. **ERR_UNAUTHORIZED_OPERATION**: Not authorized to finalize this transaction
327
+
328
+ **Troubleshooting:**
329
+ 1. Verify transaction ID is correct: 10 characters total, starts with 'pw' (standard), 'pr' (product), or 'ps' (soundbite)
330
+ 2. Ensure transaction has been processed first
331
+ 3. Check status is one of: CONFIRMED, CANCELLED, DECLINED, FAILED
332
+ 4. Provide statusMessage for non-CONFIRMED statuses
333
+ 5. Include amount, fee, currency for CONFIRMED status
334
+ 6. Verify you are authorized to finalize this transaction
335
+ 7. Ensure currency matches the original transaction currency`
336
+ }]
337
+ };
338
+ }
339
+ }
340
+ };
@@ -0,0 +1,269 @@
1
+ import axios from 'axios';
2
+ import { createJWTToken } from '../../core/auth/jwt-token.js';
3
+ import { getSandboxUrl, getProductionUrl, getPartnerIdSafe, getPrivateKeySafe } from '../../config/env.js';
4
+
5
+ /**
6
+ * Get transaction history via payware API (completed/expired transactions)
7
+ * @param {Object} params - Transaction history parameters
8
+ * @returns {Object} Transaction history response
9
+ */
10
+ export async function getPITransactionHistory({
11
+ transactionId,
12
+ partnerId,
13
+ privateKey,
14
+ useSandbox = true
15
+ }) {
16
+ if (!transactionId) {
17
+ throw new Error('Transaction ID is required');
18
+ }
19
+
20
+ if (!partnerId || !privateKey) {
21
+ throw new Error('Partner ID and private key are required for proper JWT creation');
22
+ }
23
+
24
+ // Create JWT token for GET request (no contentMd5 needed for GET)
25
+ const tokenData = createJWTToken(partnerId, privateKey, null);
26
+
27
+ // Required headers as per payware API documentation
28
+ const headers = {
29
+ 'Authorization': `Bearer ${tokenData.token}`,
30
+ 'Content-Type': 'application/json',
31
+ 'Api-Version': '1' // Required: current API version
32
+ };
33
+
34
+ try {
35
+ const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
36
+ const response = await axios.get(`${baseUrl}/transactions-history/${transactionId}`, {
37
+ headers
38
+ });
39
+
40
+ return {
41
+ success: true,
42
+ transaction: response.data,
43
+ requestId: response.headers['x-request-id'],
44
+ timestamp: new Date().toISOString()
45
+ };
46
+ } catch (error) {
47
+ return {
48
+ success: false,
49
+ error: {
50
+ message: error.response?.data?.message || error.message,
51
+ status: error.response?.status,
52
+ code: error.response?.data?.code,
53
+ details: error.response?.data
54
+ },
55
+ timestamp: new Date().toISOString()
56
+ };
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Get payment institution transaction history tool implementation
62
+ */
63
+ export const getPITransactionHistoryTool = {
64
+ name: "payware_operations_get_transaction_history",
65
+ description: `Get the complete history of a completed or expired payware transaction as a payment institution.
66
+
67
+ **Use Cases:**
68
+ - Retrieve details of completed transactions
69
+ - Get information about expired transactions
70
+ - Access finalized transaction data including final status
71
+ - Audit and reconciliation purposes
72
+
73
+ **Response includes:**
74
+ - Complete transaction details
75
+ - Final status (CONFIRMED, DECLINED, FAILED, EXPIRED)
76
+ - Status message (for failed/declined transactions)
77
+ - Payee/payer account details and BICs
78
+ - Transaction amounts, currency, and timestamps
79
+ - Creation and processing timeline
80
+
81
+ **Note:** This endpoint is throttled and may return HTTP 429 (Too Many Requests). Implement appropriate retry logic.`,
82
+ inputSchema: {
83
+ type: "object",
84
+ properties: {
85
+ transactionId: {
86
+ type: "string",
87
+ description: "Transaction ID to retrieve history. Format: 2-char prefix + 8-char ID. Supports: 'pw' (standard), 'pr' (product), 'ps' (soundbite)",
88
+ pattern: "^(pw|pr|ps)[0-9A-Za-z]{8}$"
89
+ },
90
+ partnerId: {
91
+ type: "string",
92
+ description: "Partner ID from payware dashboard. Uses PAYWARE_PARTNER_ID env var as default.",
93
+ default: getPartnerIdSafe()
94
+ },
95
+ privateKey: {
96
+ type: "string",
97
+ description: "RSA private key for JWT token creation. Uses environment-specific private key as default.",
98
+ default: getPrivateKeySafe()
99
+ },
100
+ useSandbox: {
101
+ type: "boolean",
102
+ description: "Use sandbox environment for testing",
103
+ default: true
104
+ }
105
+ },
106
+ required: ["transactionId"]
107
+ },
108
+
109
+ async handler(args) {
110
+ const {
111
+ transactionId,
112
+ partnerId = getPartnerIdSafe(),
113
+ privateKey = getPrivateKeySafe(args.useSandbox ?? true),
114
+ useSandbox = true
115
+ } = args;
116
+
117
+ if (!transactionId) {
118
+ throw new Error("Transaction ID is required");
119
+ }
120
+
121
+ if (!partnerId) {
122
+ throw new Error("Partner ID is required. Provide via 'partnerId' parameter or set PAYWARE_PARTNER_ID environment variable.");
123
+ }
124
+
125
+ if (!privateKey) {
126
+ throw new Error("Private key is required. Provide via 'privateKey' parameter or set PAYWARE_PRIVATE_KEY environment variable.");
127
+ }
128
+
129
+ const result = await getPITransactionHistory({
130
+ transactionId,
131
+ partnerId,
132
+ privateKey,
133
+ useSandbox
134
+ });
135
+
136
+ if (result.success) {
137
+ const tx = result.transaction;
138
+ const createdDate = tx.created ? new Date(tx.created * 1000).toISOString() : 'N/A';
139
+
140
+ // Status emoji mapping
141
+ const statusEmojis = {
142
+ CONFIRMED: '✅',
143
+ DECLINED: '❌',
144
+ FAILED: '💥',
145
+ EXPIRED: '⏰',
146
+ CANCELLED: '🚫'
147
+ };
148
+
149
+ const statusEmoji = statusEmojis[tx.status] || '📄';
150
+ const typeDisplay = tx.transactionType || 'DEFAULT';
151
+ const initiatorDisplay = tx.initiatedBy || 'UNKNOWN';
152
+
153
+ return {
154
+ content: [{
155
+ type: "text",
156
+ text: `📜 **Payment Institution Transaction History**
157
+
158
+ **Transaction Information:**
159
+ - ID: ${tx.transactionId || transactionId}
160
+ - Type: ${typeDisplay}
161
+ - Initiated By: ${initiatorDisplay}
162
+ - Final Status: ${statusEmoji} ${tx.status || 'UNKNOWN'}
163
+ ${tx.statusMessage ? `- Status Message: ${tx.statusMessage}` : ''}
164
+ - Created: ${createdDate}
165
+ - TTL: ${tx.timeToLive || 'N/A'} seconds
166
+
167
+ **Transaction Details:**
168
+ - Amount: ${tx.amount || 'N/A'} ${tx.currency || 'N/A'}
169
+ - Reason L1: ${tx.reasonL1 || 'N/A'}
170
+ ${tx.reasonL2 ? `- Reason L2: ${tx.reasonL2}` : ''}
171
+
172
+ **Payee Information:**
173
+ - Account: ${tx.payeeAccount || 'N/A'}
174
+ - Friendly Name: ${tx.payeeFriendlyName || 'N/A'}
175
+ - BIC: ${tx.payeeBIC || 'N/A'}
176
+
177
+ **Payer Information:**
178
+ - Account: ${tx.payerAccount || 'N/A'}
179
+ - Friendly Name: ${tx.payerFriendlyName || 'N/A'}
180
+ - BIC: ${tx.payerBIC || 'N/A'}
181
+
182
+ **Full Transaction History:**
183
+ \`\`\`json
184
+ ${JSON.stringify(result.transaction, null, 2)}
185
+ \`\`\`
186
+
187
+ **API Call Details:**
188
+ - Endpoint: GET ${baseUrl}/transactions-history/${transactionId}
189
+ - Request ID: ${result.requestId || 'N/A'}
190
+ - Timestamp: ${result.timestamp}
191
+
192
+ **Transaction Outcome:**
193
+ ${tx.status === 'CONFIRMED'
194
+ ? `✅ **Transaction Completed Successfully**
195
+ - Payment was processed and confirmed
196
+ - Funds should have been transferred between accounts`
197
+ : tx.status === 'DECLINED'
198
+ ? `❌ **Transaction Declined**
199
+ - Payment was declined by the payment institution
200
+ - Reason: ${tx.statusMessage || 'No specific reason provided'}`
201
+ : tx.status === 'FAILED'
202
+ ? `💥 **Transaction Failed**
203
+ - Payment failed during processing
204
+ - Reason: ${tx.statusMessage || 'No specific reason provided'}`
205
+ : tx.status === 'EXPIRED'
206
+ ? `⏰ **Transaction Expired**
207
+ - Transaction was not completed within the time limit
208
+ - No payment was processed`
209
+ : tx.status === 'CANCELLED'
210
+ ? `🚫 **Transaction Cancelled**
211
+ - Transaction was cancelled by the creator
212
+ - Reason: ${tx.statusMessage || 'No specific reason provided'}`
213
+ : `📄 **Transaction Status: ${tx.status}**`
214
+ }
215
+
216
+ **⚠️ Historical Record:**
217
+ - This transaction is completed and cannot be modified
218
+ - Data is archived for audit and reconciliation purposes
219
+ - Use this information for financial reporting and analysis`
220
+ }]
221
+ };
222
+ } else {
223
+ return {
224
+ content: [{
225
+ type: "text",
226
+ text: `❌ **Transaction History Retrieval Failed**
227
+
228
+ **Transaction ID:** ${transactionId}
229
+
230
+ **Error Details:**
231
+ - Message: ${result.error.message}
232
+ - Status: ${result.error.status || 'N/A'}
233
+ - Code: ${result.error.code || 'N/A'}
234
+
235
+ **Full Error Response:**
236
+ \`\`\`json
237
+ ${JSON.stringify(result.error.details || result.error, null, 2)}
238
+ \`\`\`
239
+
240
+ **Timestamp:** ${result.timestamp}
241
+
242
+ **Common Issues:**
243
+ 1. **ERR_MISSING_TRANSACTION (404)**: Transaction not found in history
244
+ 2. **HTTP 429 (Too Many Requests)**: API is throttled, implement retry logic
245
+ 3. **Authentication Issues**: Verify JWT token and partner credentials
246
+ 4. **Transaction Still Active**: Use \`payware_pi_get_transaction_status\` for active transactions
247
+
248
+ **Troubleshooting:**
249
+ 1. Verify transaction ID is correct: 10 characters total, starts with 'pw' (standard), 'pr' (product), or 'ps' (soundbite)
250
+ 2. Check if transaction is still active (not yet completed/expired)
251
+ 3. Implement retry logic for rate limiting (HTTP 429)
252
+ 4. Verify your payment institution credentials and API access
253
+ 5. Ensure transaction was created or you have access to it
254
+
255
+ **Rate Limiting Notes:**
256
+ - This endpoint is throttled by payware
257
+ - If you receive HTTP 429, wait and retry
258
+ - Consider implementing exponential backoff for retries
259
+ - Avoid excessive polling of this endpoint
260
+
261
+ **Alternative Actions:**
262
+ - If transaction is still active: Use \`payware_pi_get_transaction_status\`
263
+ - If rate limited: Wait and retry after a delay
264
+ - If transaction not found: Verify the transaction ID exists`
265
+ }]
266
+ };
267
+ }
268
+ }
269
+ };