@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,234 @@
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 status via payware API (active transactions)
7
+ * @param {Object} params - Transaction status parameters
8
+ * @returns {Object} Transaction status response
9
+ */
10
+ export async function getPITransactionStatus({
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/${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 status tool implementation
62
+ */
63
+ export const getPITransactionStatusTool = {
64
+ name: "payware_operations_get_transaction_status",
65
+ description: `Get the current status of an active payware transaction as a payment institution.
66
+
67
+ **Use Cases:**
68
+ - Check transaction status and details
69
+ - Monitor transaction progress
70
+ - Get participant information (payee/payer accounts, BICs)
71
+ - Check remaining time to live
72
+
73
+ **Response includes:**
74
+ - Transaction ID and type
75
+ - Payee/payer account details and BICs
76
+ - Transaction amount and currency
77
+ - Reason lines and creation timestamp
78
+ - Remaining time to live
79
+ - Current transaction state
80
+
81
+ **Note:** This endpoint only returns active transactions. Use \`payware_pi_get_transaction_history\` for completed/expired transactions.`,
82
+ inputSchema: {
83
+ type: "object",
84
+ properties: {
85
+ transactionId: {
86
+ type: "string",
87
+ description: "Transaction ID to check status. 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 getPITransactionStatus({
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
+ // Transaction type display
141
+ const typeDisplay = tx.transactionType || 'DEFAULT';
142
+ const initiatorDisplay = tx.initiatedBy || 'UNKNOWN';
143
+
144
+ return {
145
+ content: [{
146
+ type: "text",
147
+ text: `📊 **Payment Institution Transaction Status**
148
+
149
+ **Transaction Information:**
150
+ - ID: ${tx.transactionId || transactionId}
151
+ - Type: ${typeDisplay}
152
+ - Initiated By: ${initiatorDisplay}
153
+ - Status: ⏳ ACTIVE
154
+ - Created: ${createdDate}
155
+ - Remaining TTL: ${tx.timeToLive || 'N/A'} seconds
156
+
157
+ **Transaction Details:**
158
+ - Amount: ${tx.amount || 'N/A'} ${tx.currency || 'N/A'}
159
+ - Reason L1: ${tx.reasonL1 || 'N/A'}
160
+ ${tx.reasonL2 ? `- Reason L2: ${tx.reasonL2}` : ''}
161
+
162
+ **Payee Information:**
163
+ - Account: ${tx.payeeAccount || 'N/A'}
164
+ - Friendly Name: ${tx.payeeFriendlyName || 'N/A'}
165
+ - BIC: ${tx.payeeBIC || 'N/A'}
166
+
167
+ **Payer Information:**
168
+ - Account: ${tx.payerAccount || 'N/A'}
169
+ - Friendly Name: ${tx.payerFriendlyName || 'N/A'}
170
+ - BIC: ${tx.payerBIC || 'N/A'}
171
+
172
+ **Full API Response:**
173
+ \`\`\`json
174
+ ${JSON.stringify(result.transaction, null, 2)}
175
+ \`\`\`
176
+
177
+ **API Call Details:**
178
+ - Endpoint: GET ${baseUrl}/transactions/${transactionId}
179
+ - Request ID: ${result.requestId || 'N/A'}
180
+ - Timestamp: ${result.timestamp}
181
+
182
+ **Next Steps:**
183
+ 1. ${!tx.payerAccount ? 'Transaction waiting for payer to process' : 'Transaction processed, waiting for finalization'}
184
+ 2. ${tx.timeToLive && parseInt(tx.timeToLive) < 60 ? '⚠️ Transaction expires soon!' : 'Monitor remaining TTL'}
185
+ 3. Use \`payware_pi_process_transaction\` if you need to process this transaction
186
+ 4. Use \`payware_pi_finalize_transaction\` to confirm/decline after processing
187
+
188
+ **⚠️ Transaction State:**
189
+ - This is an **active** transaction
190
+ - Participants can still interact with it
191
+ - Will expire in ${tx.timeToLive || 'unknown'} seconds if not completed`
192
+ }]
193
+ };
194
+ } else {
195
+ return {
196
+ content: [{
197
+ type: "text",
198
+ text: `❌ **Transaction Status Check Failed**
199
+
200
+ **Transaction ID:** ${transactionId}
201
+
202
+ **Error Details:**
203
+ - Message: ${result.error.message}
204
+ - Status: ${result.error.status || 'N/A'}
205
+ - Code: ${result.error.code || 'N/A'}
206
+
207
+ **Full Error Response:**
208
+ \`\`\`json
209
+ ${JSON.stringify(result.error.details || result.error, null, 2)}
210
+ \`\`\`
211
+
212
+ **Timestamp:** ${result.timestamp}
213
+
214
+ **Common Issues:**
215
+ 1. **ERR_MISSING_TRANSACTION (404)**: Transaction not found, expired, or already completed
216
+ 2. **Invalid Transaction ID**: Check transaction ID format (10 chars: 'pw'/'pr'/'ps' + 8 chars)
217
+ 3. **Authentication Issues**: Verify JWT token and partner credentials
218
+
219
+ **Troubleshooting:**
220
+ 1. Verify transaction ID is correct: 10 characters total, starts with 'pw' (standard), 'pr' (product), or 'ps' (soundbite)
221
+ 2. Check if transaction has expired or been completed
222
+ 3. Use \`payware_pi_get_transaction_history\` for completed/expired transactions
223
+ 4. Verify your partner credentials and API access
224
+ 5. Ensure transaction was created or you have access to it
225
+
226
+ **Alternative Actions:**
227
+ - If transaction is completed: Use \`payware_pi_get_transaction_history\`
228
+ - If transaction ID is wrong: Verify the correct transaction ID
229
+ - If access issues: Check your payment institution credentials`
230
+ }]
231
+ };
232
+ }
233
+ }
234
+ };
@@ -0,0 +1,421 @@
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
+ * Process a transaction as a payment institution via payware API
8
+ * Payment institutions can process transactions they didn't create
9
+ * @param {Object} params - Transaction processing parameters
10
+ * @returns {Object} Transaction processing response
11
+ */
12
+ export async function processPITransaction({
13
+ transactionId,
14
+ account,
15
+ friendlyName,
16
+ amount,
17
+ currency,
18
+ reasonL1,
19
+ reasonL2,
20
+ callbackUrl,
21
+ passbackParams,
22
+ timeToLive,
23
+ partnerId,
24
+ privateKey,
25
+ // Delivery address for SHIPPABLE transactions
26
+ deliveryAddress,
27
+ useSandbox = true
28
+ }) {
29
+ if (!transactionId) {
30
+ throw new Error('Transaction ID is required');
31
+ }
32
+
33
+ if (!account) {
34
+ throw new Error('account is required for payment institutions');
35
+ }
36
+
37
+ if (!friendlyName) {
38
+ throw new Error('friendlyName is required for payment institutions');
39
+ }
40
+
41
+ if (!currency) {
42
+ throw new Error('currency is required for payment institutions');
43
+ }
44
+
45
+ if (!reasonL1) {
46
+ throw new Error('reasonL1 is required for payment institutions');
47
+ }
48
+
49
+ if (!partnerId || !privateKey) {
50
+ throw new Error('Partner ID and private key are required for proper JWT creation');
51
+ }
52
+
53
+ // Build request body according to payment institution API documentation
54
+ const requestBody = {
55
+ account,
56
+ friendlyName,
57
+ ...(callbackUrl && { callbackUrl }),
58
+ ...(passbackParams && { passbackParams }),
59
+ trData: {
60
+ ...(amount !== undefined && { amount: amount.toString() }),
61
+ currency,
62
+ reasonL1,
63
+ ...(reasonL2 && { reasonL2 })
64
+ },
65
+ ...(timeToLive && {
66
+ trOptions: {
67
+ timeToLive
68
+ }
69
+ }),
70
+ ...(deliveryAddress && { deliveryAddress })
71
+ };
72
+
73
+ // Convert to deterministic minimized JSON for MD5 calculation
74
+ const minimizedBodyString = createMinimizedJSON(requestBody);
75
+
76
+ // Create JWT token with contentMd5 for the request body (POST requires contentMd5)
77
+ const tokenData = createJWTToken(partnerId, privateKey, minimizedBodyString);
78
+
79
+ // Required headers as per payware API documentation
80
+ const headers = {
81
+ 'Authorization': `Bearer ${tokenData.token}`,
82
+ 'Content-Type': 'application/json',
83
+ 'Api-Version': '1' // Required: current API version
84
+ };
85
+
86
+ try {
87
+ const baseUrl = useSandbox ? getSandboxUrl() : getProductionUrl();
88
+ // Send the exact minimized JSON string that was used for MD5 calculation
89
+ const response = await axios.post(`${baseUrl}/transactions/${transactionId}`, minimizedBodyString, {
90
+ headers,
91
+ // Tell axios to send the string as-is, don't serialize it again
92
+ transformRequest: [(data) => data]
93
+ });
94
+
95
+ return {
96
+ success: true,
97
+ transaction: response.data,
98
+ requestId: response.headers['x-request-id'],
99
+ timestamp: new Date().toISOString()
100
+ };
101
+ } catch (error) {
102
+ return {
103
+ success: false,
104
+ error: {
105
+ message: error.response?.data?.message || error.message,
106
+ status: error.response?.status,
107
+ code: error.response?.data?.code,
108
+ details: error.response?.data
109
+ },
110
+ timestamp: new Date().toISOString()
111
+ };
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Process payment institution transaction tool implementation
117
+ */
118
+ export const processPITransactionTool = {
119
+ name: "payware_operations_process_transaction",
120
+ description: `Process a transaction as a payment institution. Payment institutions can process transactions created by others and must provide account/friendlyName details.
121
+
122
+ **Use Cases:**
123
+ - **As Payer (SRC)**: Process a transaction initiated by payee (pay a request)
124
+ - **As Payee (DST)**: Process a transaction initiated by payer (accept payment)
125
+ - **Cross-PI**: Process transactions from other payment institutions
126
+
127
+ **Required for Payment Institutions:**
128
+ - account: Your account identifier
129
+ - friendlyName: Your account holder name
130
+ - currency: Transaction currency (required)
131
+ - reasonL1: Transaction grounds description (required)
132
+
133
+ **API Request Structure:**
134
+ \`\`\`json
135
+ {
136
+ "account": "GB29NWBK60161331926818",
137
+ "friendlyName": "Jane Doe Bank",
138
+ "callbackUrl": "https://callback.url",
139
+ "passbackParams": "internal-ref-123",
140
+ "trData": {
141
+ "amount": "57.60",
142
+ "currency": "EUR",
143
+ "reasonL1": "Bill payment",
144
+ "reasonL2": "Invoice #12345"
145
+ },
146
+ "trOptions": {
147
+ "timeToLive": 300
148
+ }
149
+ }
150
+ \`\`\``,
151
+ inputSchema: {
152
+ type: "object",
153
+ properties: {
154
+ transactionId: {
155
+ type: "string",
156
+ description: "Transaction ID to process. Format: 2-char prefix + 8-char ID. Supports: 'pw' (standard), 'pr' (product), 'ps' (soundbite)",
157
+ pattern: "^(pw|pr|ps)[0-9A-Za-z]{8}$"
158
+ },
159
+ account: {
160
+ type: "string",
161
+ description: "Your account identifier (required for payment institutions)",
162
+ maxLength: 36
163
+ },
164
+ friendlyName: {
165
+ type: "string",
166
+ description: "Your account holder recognizable name (required for payment institutions)",
167
+ maxLength: 100
168
+ },
169
+ amount: {
170
+ type: ["number", "string"],
171
+ description: "Amount as currency value to process. For payee: must be <= original amount. For payer: can be >= original amount (tipping)",
172
+ minimum: 0.01,
173
+ maximum: 9999999999999.99
174
+ },
175
+ currency: {
176
+ type: "string",
177
+ pattern: "^[A-Z]{3}$",
178
+ description: "Transaction currency (ISO 3-character code, required for payment institutions)"
179
+ },
180
+ reasonL1: {
181
+ type: "string",
182
+ description: "Transaction grounds description (required for payment institutions - omit for SHIPPABLE to get merchant name)",
183
+ maxLength: 100
184
+ },
185
+ reasonL2: {
186
+ type: "string",
187
+ description: "Transaction grounds description continuation (optional - omit for SHIPPABLE to get product name)",
188
+ maxLength: 100
189
+ },
190
+ callbackUrl: {
191
+ type: "string",
192
+ description: "HTTPS URL to receive transaction status callbacks (mandatory when processing as payee)",
193
+ format: "uri"
194
+ },
195
+ passbackParams: {
196
+ type: "string",
197
+ description: "Parameters passed back through callback",
198
+ maxLength: 200
199
+ },
200
+ timeToLive: {
201
+ type: "number",
202
+ description: "Time allowed for transaction finalization in seconds (PI can extend: 60-2592000, Merchant: original+120 max)",
203
+ minimum: 60,
204
+ maximum: 2592000
205
+ },
206
+ partnerId: {
207
+ type: "string",
208
+ description: "Partner ID from payware dashboard. Uses PAYWARE_PARTNER_ID env var as default.",
209
+ default: getPartnerIdSafe()
210
+ },
211
+ privateKey: {
212
+ type: "string",
213
+ description: "RSA private key for JWT token creation. Uses environment-specific private key as default.",
214
+ default: getPrivateKeySafe()
215
+ },
216
+ // Delivery address for SHIPPABLE transactions
217
+ deliveryAddress: {
218
+ type: "object",
219
+ description: "Delivery address (required when processing SHIPPABLE transactions)",
220
+ properties: {
221
+ fullName: {
222
+ type: "string",
223
+ description: "Recipient full name (required)",
224
+ maxLength: 300
225
+ },
226
+ streetAddressLine1: {
227
+ type: "string",
228
+ description: "Street address line 1 (required)",
229
+ maxLength: 300
230
+ },
231
+ streetAddressLine2: {
232
+ type: "string",
233
+ description: "Street address line 2 (optional)",
234
+ maxLength: 300
235
+ },
236
+ zipCode: {
237
+ type: "string",
238
+ description: "ZIP code (required)",
239
+ maxLength: 20
240
+ },
241
+ city: {
242
+ type: "string",
243
+ description: "City name (required)",
244
+ maxLength: 100
245
+ },
246
+ region: {
247
+ type: "string",
248
+ description: "Region (required)",
249
+ maxLength: 200
250
+ },
251
+ country: {
252
+ type: "string",
253
+ description: "Country (required)",
254
+ maxLength: 32
255
+ },
256
+ phoneNumber: {
257
+ type: "string",
258
+ description: "Recipient phone number (required if email not provided)",
259
+ maxLength: 255
260
+ },
261
+ email: {
262
+ type: "string",
263
+ description: "Recipient email address (required if phoneNumber not provided)",
264
+ format: "email",
265
+ maxLength: 255
266
+ }
267
+ },
268
+ required: ["fullName", "streetAddressLine1", "zipCode", "city", "region", "country"]
269
+ },
270
+ useSandbox: {
271
+ type: "boolean",
272
+ description: "Use sandbox environment for testing",
273
+ default: true
274
+ }
275
+ },
276
+ required: ["transactionId", "account", "friendlyName", "currency", "reasonL1"]
277
+ },
278
+
279
+ async handler(args) {
280
+ const {
281
+ transactionId,
282
+ account,
283
+ friendlyName,
284
+ amount,
285
+ currency,
286
+ reasonL1,
287
+ reasonL2,
288
+ callbackUrl,
289
+ passbackParams,
290
+ timeToLive,
291
+ partnerId = getPartnerIdSafe(),
292
+ privateKey = getPrivateKeySafe(args.useSandbox ?? true),
293
+ deliveryAddress,
294
+ useSandbox = true
295
+ } = args;
296
+
297
+ if (!transactionId) {
298
+ throw new Error("Transaction ID is required");
299
+ }
300
+
301
+ if (!account) {
302
+ throw new Error("account is required for payment institutions");
303
+ }
304
+
305
+ if (!friendlyName) {
306
+ throw new Error("friendlyName is required for payment institutions");
307
+ }
308
+
309
+ if (!currency) {
310
+ throw new Error("currency is required for payment institutions");
311
+ }
312
+
313
+ if (!reasonL1) {
314
+ throw new Error("reasonL1 is required for payment institutions");
315
+ }
316
+
317
+ if (!partnerId) {
318
+ throw new Error("Partner ID is required. Provide via 'partnerId' parameter or set PAYWARE_PARTNER_ID environment variable.");
319
+ }
320
+
321
+ if (!privateKey) {
322
+ throw new Error("Private key is required. Provide via 'privateKey' parameter or set PAYWARE_PRIVATE_KEY environment variable.");
323
+ }
324
+
325
+ const result = await processPITransaction({
326
+ transactionId,
327
+ account,
328
+ friendlyName,
329
+ amount,
330
+ currency,
331
+ reasonL1,
332
+ reasonL2,
333
+ callbackUrl,
334
+ passbackParams,
335
+ timeToLive,
336
+ partnerId,
337
+ privateKey,
338
+ deliveryAddress,
339
+ useSandbox
340
+ });
341
+
342
+ if (result.success) {
343
+ return {
344
+ content: [{
345
+ type: "text",
346
+ text: `🔄 **Payment Institution Transaction Processing Initiated**
347
+
348
+ **Transaction ID:** ${transactionId}
349
+ **Processing Status:** ✅ Successful
350
+
351
+ **Your Details:**
352
+ - Account: ${account}
353
+ - Friendly Name: ${friendlyName}
354
+ ${amount ? `- Amount: ${amount} ${currency}` : ''}
355
+ ${reasonL1 ? `- Reason: ${reasonL1}${reasonL2 ? ` (${reasonL2})` : ''}` : ''}
356
+ ${timeToLive ? `- Time to Live: ${timeToLive} seconds` : ''}
357
+ ${callbackUrl ? `- Callback URL: ${callbackUrl}` : ''}
358
+ ${passbackParams ? `- Passback Params: ${passbackParams}` : ''}
359
+
360
+ **Transaction Details:**
361
+ \`\`\`json
362
+ ${JSON.stringify(result.transaction, null, 2)}
363
+ \`\`\`
364
+
365
+ **Request ID:** ${result.requestId || 'N/A'}
366
+ **Timestamp:** ${result.timestamp}
367
+
368
+ **Next Steps:**
369
+ 1. **TRANSACTION_PROCESSED** callback will be sent to counterparty
370
+ 2. Wait for callback notification to your URL (if provided)
371
+ 3. Monitor transaction status for completion
372
+ 4. Use \`payware_pi_finalize_transaction\` to confirm/decline the transaction
373
+ 5. Handle final TRANSACTION_FINALIZED callbacks
374
+
375
+ **⚠️ Important:**
376
+ - As a payment institution, you must finalize this transaction
377
+ - Transaction will expire if not finalized within TTL
378
+ - Callback URL is mandatory when processing as payee`
379
+ }]
380
+ };
381
+ } else {
382
+ return {
383
+ content: [{
384
+ type: "text",
385
+ text: `❌ **Payment Institution Transaction Processing Failed**
386
+
387
+ **Transaction ID:** ${transactionId}
388
+
389
+ **Error Details:**
390
+ - Message: ${result.error.message}
391
+ - Status: ${result.error.status || 'N/A'}
392
+ - Code: ${result.error.code || 'N/A'}
393
+
394
+ **Full Error Response:**
395
+ \`\`\`json
396
+ ${JSON.stringify(result.error.details || result.error, null, 2)}
397
+ \`\`\`
398
+
399
+ **Timestamp:** ${result.timestamp}
400
+
401
+ **Common Payment Institution Issues:**
402
+ 1. **ERR_MISSING_TRANSACTION**: Transaction ID not found or expired
403
+ 2. **ERR_ALREADY_PROCESSED**: Transaction already processed
404
+ 3. **ERR_MISSING_PARTNER_ACCOUNT**: Account parameter missing or empty
405
+ 4. **ERR_MISSING_FRIENDLY_NAME**: Friendly name parameter missing
406
+ 5. **ERR_MISSING_CALLBACK_URL**: Callback URL required when processing as payee
407
+ 6. **ERR_INVALID_AMOUNT**: Amount validation failed
408
+ 7. **ERR_SPECIFYING_CURRENCY_NOT_ALLOWED**: Cannot change currency on merchant transactions
409
+
410
+ **Troubleshooting:**
411
+ 1. Verify transaction ID is correct: 10 characters total, starts with 'pw' (standard), 'pr' (product), or 'ps' (soundbite)
412
+ 2. Ensure account and friendlyName are provided
413
+ 3. Check currency matches original transaction currency
414
+ 4. Verify callback URL is provided (especially for payee role)
415
+ 5. Validate amount constraints based on your role in the transaction
416
+ 6. Check if transaction requires delivery address (SHIPPABLE type)`
417
+ }]
418
+ };
419
+ }
420
+ }
421
+ };