@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.
- package/.env.example +92 -0
- package/MCP-SETUP.md +190 -0
- package/README.md +483 -0
- package/check-keys.js +52 -0
- package/keys/README.md +112 -0
- package/mcp-config.json +9 -0
- package/package.json +66 -0
- package/payware-mcp-config.json +12 -0
- package/src/auth/rsa-keys.js +82 -0
- package/src/auth/sandbox-setup.js +187 -0
- package/src/config/env.js +229 -0
- package/src/config/partner-types.js +143 -0
- package/src/core/auth/jwt-factory.js +182 -0
- package/src/core/auth/jwt-token.js +735 -0
- package/src/core/utils/json-serializer.js +100 -0
- package/src/core/utils/key-utils.js +133 -0
- package/src/index.js +237 -0
- package/src/isv/data/index.js +291 -0
- package/src/isv/deep-links/delete-product-link.js +154 -0
- package/src/isv/deep-links/delete-transaction-link.js +154 -0
- package/src/isv/deep-links/get-product-link.js +167 -0
- package/src/isv/deep-links/get-transaction-link.js +167 -0
- package/src/isv/deep-links/index.js +23 -0
- package/src/isv/index.js +103 -0
- package/src/isv/oauth2/create-token-simple.js +46 -0
- package/src/isv/oauth2/get-token-info.js +157 -0
- package/src/isv/oauth2/obtain-token.js +189 -0
- package/src/isv/oauth2/token-helper.js +151 -0
- package/src/isv/products/audios.js +470 -0
- package/src/isv/products/create-product.js +314 -0
- package/src/isv/products/delete-product.js +119 -0
- package/src/isv/products/get-product-image.js +247 -0
- package/src/isv/products/get-product.js +168 -0
- package/src/isv/products/index.js +65 -0
- package/src/isv/products/list-products.js +136 -0
- package/src/isv/products/schedules.js +522 -0
- package/src/isv/products/update-product.js +265 -0
- package/src/isv/transactions/cancel-transaction.js +129 -0
- package/src/isv/transactions/create-transaction.js +361 -0
- package/src/isv/transactions/get-status.js +217 -0
- package/src/isv/transactions/process-transaction.js +145 -0
- package/src/isv/transactions/simulate-callback.js +146 -0
- package/src/isv/transactions/transaction-history.js +186 -0
- package/src/isv/utils/auth.js +159 -0
- package/src/mcp-proxy.js +150 -0
- package/src/merchant/data/export-report.js +108 -0
- package/src/merchant/data/generate-report.js +151 -0
- package/src/merchant/data/get-report-status.js +120 -0
- package/src/merchant/data/index.js +351 -0
- package/src/merchant/deep-links/delete-product-link.js +121 -0
- package/src/merchant/deep-links/delete-transaction-link.js +121 -0
- package/src/merchant/deep-links/get-product-link.js +134 -0
- package/src/merchant/deep-links/get-transaction-link.js +134 -0
- package/src/merchant/deep-links/index.js +23 -0
- package/src/merchant/index.js +92 -0
- package/src/merchant/products/audios.js +606 -0
- package/src/merchant/products/create-product.js +288 -0
- package/src/merchant/products/delete-product.js +111 -0
- package/src/merchant/products/get-product-image.js +252 -0
- package/src/merchant/products/get-product.js +144 -0
- package/src/merchant/products/index.js +65 -0
- package/src/merchant/products/list-products.js +112 -0
- package/src/merchant/products/schedules.js +646 -0
- package/src/merchant/products/update-product.js +282 -0
- package/src/merchant/transactions/cancel-transaction.js +241 -0
- package/src/merchant/transactions/create-transaction.js +482 -0
- package/src/merchant/transactions/get-status.js +196 -0
- package/src/merchant/transactions/process-transaction.js +349 -0
- package/src/merchant/transactions/simulate-callback.js +246 -0
- package/src/merchant/transactions/transaction-history.js +258 -0
- package/src/payment-institution/data/index.js +280 -0
- package/src/payment-institution/deep-links/delete-transaction-link.js +128 -0
- package/src/payment-institution/deep-links/get-transaction-link.js +141 -0
- package/src/payment-institution/deep-links/index.js +17 -0
- package/src/payment-institution/index.js +92 -0
- package/src/payment-institution/transactions/create-pi-transaction.js +484 -0
- package/src/payment-institution/transactions/finalize-transaction.js +340 -0
- package/src/payment-institution/transactions/get-transaction-history.js +269 -0
- package/src/payment-institution/transactions/get-transaction-status.js +234 -0
- package/src/payment-institution/transactions/process-pi-transaction.js +421 -0
- package/src/payment-institution/transactions/simulate-pi-callback.js +326 -0
- package/src/payment-institution/transactions/soundbite-transaction.js +269 -0
- package/src/proxy-server.js +205 -0
- package/src/shared/data/data-api.js +372 -0
- package/src/shared/deep-links/api.js +214 -0
- package/src/shared/index.js +44 -0
- package/src/shared/products/products-api.js +872 -0
- package/src/tools/advanced-code-generator.js +2247 -0
- package/src/utils/code-examples/common/auth-examples.js +1482 -0
- package/src/utils/code-examples/common/helpers.js +416 -0
- package/src/utils/code-examples/common/utils-examples.js +591 -0
- package/src/utils/code-examples/frameworks/examples.js +859 -0
- package/src/utils/code-examples/index.js +441 -0
- package/src/utils/code-examples/isv/oauth2.js +600 -0
- package/src/utils/code-examples/isv/products.js +666 -0
- package/src/utils/code-examples/isv/transactions.js +813 -0
- package/src/utils/code-examples/merchant/products.js +497 -0
- package/src/utils/code-examples/merchant/transactions.js +623 -0
- package/src/utils/code-examples/payment-institution/transactions.js +388 -0
- package/src/utils/code-examples/shared/data.js +607 -0
- package/src/utils/code-examples/shared/deep-links.js +662 -0
- package/src/utils/code-examples/shared/soundbites.js +808 -0
- package/src/utils/code-examples.js +646 -0
- package/src/utils/format-request.js +363 -0
- package/src/utils/json-formatter.js +249 -0
- package/src/utils/server-info.js +132 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility examples and language-specific generators
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { ExampleGenerator, CommonTemplates, CodeUtils } from './helpers.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Python code generator
|
|
9
|
+
*/
|
|
10
|
+
export class PythonGenerator extends ExampleGenerator {
|
|
11
|
+
constructor(framework = 'none') {
|
|
12
|
+
super('python', framework);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getEnvironmentTemplate(partnerType) {
|
|
16
|
+
const envVars = CommonTemplates.getEnvironmentVariables(partnerType);
|
|
17
|
+
const envString = Object.entries(envVars)
|
|
18
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
19
|
+
.join('\n');
|
|
20
|
+
|
|
21
|
+
return `# .env file configuration
|
|
22
|
+
${envString}
|
|
23
|
+
|
|
24
|
+
# Load environment variables
|
|
25
|
+
import os
|
|
26
|
+
from dotenv import load_dotenv
|
|
27
|
+
load_dotenv()`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getDependenciesTemplate(operation) {
|
|
31
|
+
const baseDeps = 'requests pyjwt cryptography python-dotenv';
|
|
32
|
+
|
|
33
|
+
if (this.framework === 'django') {
|
|
34
|
+
return `# Install dependencies:
|
|
35
|
+
# pip install ${baseDeps} django
|
|
36
|
+
|
|
37
|
+
import requests
|
|
38
|
+
import jwt
|
|
39
|
+
import json
|
|
40
|
+
import hashlib
|
|
41
|
+
import base64
|
|
42
|
+
import os
|
|
43
|
+
from datetime import datetime
|
|
44
|
+
from django.conf import settings
|
|
45
|
+
from django.http import JsonResponse
|
|
46
|
+
from django.views.decorators.csrf import csrf_exempt`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this.framework === 'fastapi') {
|
|
50
|
+
return `# Install dependencies:
|
|
51
|
+
# pip install ${baseDeps} fastapi uvicorn
|
|
52
|
+
|
|
53
|
+
import requests
|
|
54
|
+
import jwt
|
|
55
|
+
import json
|
|
56
|
+
import hashlib
|
|
57
|
+
import base64
|
|
58
|
+
import os
|
|
59
|
+
from datetime import datetime
|
|
60
|
+
from fastapi import FastAPI, HTTPException
|
|
61
|
+
from pydantic import BaseModel`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return `# Install dependencies:
|
|
65
|
+
# pip install ${baseDeps}
|
|
66
|
+
|
|
67
|
+
import requests
|
|
68
|
+
import jwt
|
|
69
|
+
import json
|
|
70
|
+
import hashlib
|
|
71
|
+
import base64
|
|
72
|
+
import os
|
|
73
|
+
from datetime import datetime`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getOperationTemplate(operation, partnerType, params) {
|
|
77
|
+
const endpoint = CommonTemplates.getApiEndpoint(operation, partnerType);
|
|
78
|
+
const method = CommonTemplates.getHttpMethod(operation);
|
|
79
|
+
const sampleBody = CommonTemplates.getSampleRequestBody(operation, partnerType, params);
|
|
80
|
+
const functionName = CodeUtils.formatFunctionName(operation, 'python');
|
|
81
|
+
|
|
82
|
+
const hasBody = method !== 'GET' && Object.keys(sampleBody).length > 0;
|
|
83
|
+
|
|
84
|
+
if (this.framework === 'django') {
|
|
85
|
+
return this.getDjangoTemplate(operation, endpoint, method, sampleBody, functionName);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (this.framework === 'fastapi') {
|
|
89
|
+
return this.getFastAPITemplate(operation, endpoint, method, sampleBody, functionName);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return `def ${functionName}(${this.getParameterList(operation, params)}):
|
|
93
|
+
"""${this.getOperationDescription(operation)}"""
|
|
94
|
+
|
|
95
|
+
# Get API configuration
|
|
96
|
+
base_url = get_api_base_url(use_sandbox)
|
|
97
|
+
|
|
98
|
+
${hasBody ? `# Prepare request body
|
|
99
|
+
request_body = ${JSON.stringify(sampleBody, null, 4).replace(/"/g, "'")}
|
|
100
|
+
|
|
101
|
+
# Create JWT token with body hash
|
|
102
|
+
token, body_string = create_jwt_token(request_body, use_sandbox)
|
|
103
|
+
headers = get_api_headers(token)
|
|
104
|
+
|
|
105
|
+
# Make API request
|
|
106
|
+
response = requests.${method.toLowerCase()}(
|
|
107
|
+
f"{base_url}${endpoint}",
|
|
108
|
+
data=body_string,
|
|
109
|
+
headers=headers
|
|
110
|
+
)` : `# Create JWT token for GET request
|
|
111
|
+
token, _ = create_jwt_token(None, use_sandbox)
|
|
112
|
+
headers = get_api_headers(token)
|
|
113
|
+
|
|
114
|
+
# Make API request
|
|
115
|
+
response = requests.${method.toLowerCase()}(
|
|
116
|
+
f"{base_url}${endpoint}",
|
|
117
|
+
headers=headers
|
|
118
|
+
)`}
|
|
119
|
+
|
|
120
|
+
# Handle response
|
|
121
|
+
if response.status_code == 200:
|
|
122
|
+
return response.json()
|
|
123
|
+
else:
|
|
124
|
+
raise Exception(f"API request failed: {response.status_code} - {response.text}")
|
|
125
|
+
|
|
126
|
+
# Example usage
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
try:
|
|
129
|
+
result = ${functionName}(${this.getExampleParameters(operation, params)})
|
|
130
|
+
print("Success:", json.dumps(result, indent=2))
|
|
131
|
+
except Exception as e:
|
|
132
|
+
print(f"Error: {e}")`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
getDjangoTemplate(operation, endpoint, method, sampleBody, functionName) {
|
|
136
|
+
return `# Django view implementation
|
|
137
|
+
@csrf_exempt
|
|
138
|
+
def ${functionName}_view(request):
|
|
139
|
+
"""Django view for ${operation}"""
|
|
140
|
+
if request.method == '${method}':
|
|
141
|
+
try:
|
|
142
|
+
${method !== 'GET' ? `# Parse request data
|
|
143
|
+
data = json.loads(request.body)
|
|
144
|
+
|
|
145
|
+
# Call payware API
|
|
146
|
+
result = ${functionName}(**data)` : `# Call payware API
|
|
147
|
+
result = ${functionName}()`}
|
|
148
|
+
|
|
149
|
+
return JsonResponse({
|
|
150
|
+
'success': True,
|
|
151
|
+
'data': result
|
|
152
|
+
})
|
|
153
|
+
except Exception as e:
|
|
154
|
+
return JsonResponse({
|
|
155
|
+
'success': False,
|
|
156
|
+
'error': str(e)
|
|
157
|
+
}, status=400)
|
|
158
|
+
|
|
159
|
+
return JsonResponse({'error': 'Method not allowed'}, status=405)`;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
getFastAPITemplate(operation, endpoint, method, sampleBody, functionName) {
|
|
163
|
+
const hasBody = method !== 'GET' && Object.keys(sampleBody).length > 0;
|
|
164
|
+
|
|
165
|
+
return `# FastAPI implementation
|
|
166
|
+
app = FastAPI()
|
|
167
|
+
|
|
168
|
+
${hasBody ? `class ${operation.charAt(0).toUpperCase() + operation.slice(1)}Request(BaseModel):
|
|
169
|
+
${Object.keys(sampleBody).map(key => `${key}: str`).join('\n ')}
|
|
170
|
+
|
|
171
|
+
@app.${method.toLowerCase()}("/${operation}")
|
|
172
|
+
async def ${functionName}(request: ${operation.charAt(0).toUpperCase() + operation.slice(1)}Request):` : `@app.${method.toLowerCase()}("/${operation}")
|
|
173
|
+
async def ${functionName}():`}
|
|
174
|
+
"""FastAPI endpoint for ${operation}"""
|
|
175
|
+
try:
|
|
176
|
+
${hasBody ? `# Convert request to dict
|
|
177
|
+
data = request.dict()
|
|
178
|
+
|
|
179
|
+
# Call payware API
|
|
180
|
+
result = ${functionName}(**data)` : `# Call payware API
|
|
181
|
+
result = ${functionName}()`}
|
|
182
|
+
|
|
183
|
+
return {"success": True, "data": result}
|
|
184
|
+
except Exception as e:
|
|
185
|
+
raise HTTPException(status_code=400, detail=str(e))`;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
getParameterList(operation, params) {
|
|
189
|
+
const baseParams = ['use_sandbox=True'];
|
|
190
|
+
|
|
191
|
+
if (operation.includes('_transaction') && !operation.includes('list')) {
|
|
192
|
+
baseParams.unshift('transaction_id');
|
|
193
|
+
}
|
|
194
|
+
if (operation.includes('product') && !operation.includes('create')) {
|
|
195
|
+
baseParams.unshift('product_id');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return baseParams.join(', ');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
getExampleParameters(operation, params) {
|
|
202
|
+
if (operation.includes('_transaction') && !operation.includes('list')) {
|
|
203
|
+
return '"pw12345678"';
|
|
204
|
+
}
|
|
205
|
+
if (operation.includes('product') && !operation.includes('create')) {
|
|
206
|
+
return '"pr12345678"';
|
|
207
|
+
}
|
|
208
|
+
return '';
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
getOperationDescription(operation) {
|
|
212
|
+
const descriptions = {
|
|
213
|
+
create_transaction: 'Create a new payment transaction',
|
|
214
|
+
get_transaction_status: 'Get the status of a transaction',
|
|
215
|
+
cancel_transaction: 'Cancel an active transaction',
|
|
216
|
+
process_transaction: 'Process a transaction',
|
|
217
|
+
create_product: 'Create a new product',
|
|
218
|
+
get_product: 'Get product details',
|
|
219
|
+
update_product: 'Update product information',
|
|
220
|
+
delete_product: 'Delete a product'
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
return descriptions[operation] || `Execute ${operation} operation`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
getErrorHandlingTemplate() {
|
|
227
|
+
return `def handle_payware_error(response):
|
|
228
|
+
"""Handle payware API errors consistently"""
|
|
229
|
+
if response.status_code == 401:
|
|
230
|
+
return "Authentication failed - check your credentials"
|
|
231
|
+
elif response.status_code == 400:
|
|
232
|
+
return f"Bad request - {response.json().get('message', 'Invalid data')}"
|
|
233
|
+
elif response.status_code == 404:
|
|
234
|
+
return "Resource not found"
|
|
235
|
+
elif response.status_code == 429:
|
|
236
|
+
return "Rate limit exceeded - please retry later"
|
|
237
|
+
else:
|
|
238
|
+
return f"API error: {response.status_code} - {response.text}"`;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
getTestTemplate(operation, partnerType) {
|
|
242
|
+
return `import unittest
|
|
243
|
+
from unittest.mock import patch, Mock
|
|
244
|
+
|
|
245
|
+
class Test${operation.charAt(0).toUpperCase() + operation.slice(1)}(unittest.TestCase):
|
|
246
|
+
|
|
247
|
+
def setUp(self):
|
|
248
|
+
"""Set up test environment"""
|
|
249
|
+
os.environ['PAYWARE_PARTNER_ID'] = 'test_partner'
|
|
250
|
+
os.environ['PAYWARE_SANDBOX_PRIVATE_KEY_PATH'] = 'test_key.pem'
|
|
251
|
+
|
|
252
|
+
@patch('requests.${CommonTemplates.getHttpMethod(operation).toLowerCase()}')
|
|
253
|
+
def test_${operation}_success(self, mock_request):
|
|
254
|
+
"""Test successful ${operation}"""
|
|
255
|
+
# Mock successful response
|
|
256
|
+
mock_response = Mock()
|
|
257
|
+
mock_response.status_code = 200
|
|
258
|
+
mock_response.json.return_value = {'transactionId': 'pw12345678'}
|
|
259
|
+
mock_request.return_value = mock_response
|
|
260
|
+
|
|
261
|
+
# Test the function
|
|
262
|
+
result = ${CodeUtils.formatFunctionName(operation, 'python')}()
|
|
263
|
+
|
|
264
|
+
# Assertions
|
|
265
|
+
self.assertEqual(result['transactionId'], 'pw12345678')
|
|
266
|
+
mock_request.assert_called_once()
|
|
267
|
+
|
|
268
|
+
@patch('requests.${CommonTemplates.getHttpMethod(operation).toLowerCase()}')
|
|
269
|
+
def test_${operation}_error(self, mock_request):
|
|
270
|
+
"""Test error handling for ${operation}"""
|
|
271
|
+
# Mock error response
|
|
272
|
+
mock_response = Mock()
|
|
273
|
+
mock_response.status_code = 400
|
|
274
|
+
mock_response.text = 'Bad Request'
|
|
275
|
+
mock_request.return_value = mock_response
|
|
276
|
+
|
|
277
|
+
# Test error handling
|
|
278
|
+
with self.assertRaises(Exception):
|
|
279
|
+
${CodeUtils.formatFunctionName(operation, 'python')}()
|
|
280
|
+
|
|
281
|
+
if __name__ == '__main__':
|
|
282
|
+
unittest.main()`;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Node.js/JavaScript code generator
|
|
288
|
+
*/
|
|
289
|
+
export class NodeJSGenerator extends ExampleGenerator {
|
|
290
|
+
constructor(framework = 'none') {
|
|
291
|
+
super('nodejs', framework);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
getEnvironmentTemplate(partnerType) {
|
|
295
|
+
const envVars = CommonTemplates.getEnvironmentVariables(partnerType);
|
|
296
|
+
const envString = Object.entries(envVars)
|
|
297
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
298
|
+
.join('\n');
|
|
299
|
+
|
|
300
|
+
return `// .env file configuration
|
|
301
|
+
${envString}
|
|
302
|
+
|
|
303
|
+
// Load environment variables
|
|
304
|
+
require('dotenv').config();`;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
getDependenciesTemplate(operation) {
|
|
308
|
+
if (this.framework === 'express') {
|
|
309
|
+
return `// Install dependencies:
|
|
310
|
+
// npm install axios jsonwebtoken crypto fs dotenv express
|
|
311
|
+
|
|
312
|
+
const express = require('express');
|
|
313
|
+
const axios = require('axios');
|
|
314
|
+
const jwt = require('jsonwebtoken');
|
|
315
|
+
const crypto = require('crypto');
|
|
316
|
+
const fs = require('fs');
|
|
317
|
+
require('dotenv').config();
|
|
318
|
+
|
|
319
|
+
const app = express();
|
|
320
|
+
app.use(express.json());`;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return `// Install dependencies:
|
|
324
|
+
// npm install axios jsonwebtoken crypto fs dotenv
|
|
325
|
+
|
|
326
|
+
const axios = require('axios');
|
|
327
|
+
const jwt = require('jsonwebtoken');
|
|
328
|
+
const crypto = require('crypto');
|
|
329
|
+
const fs = require('fs');
|
|
330
|
+
require('dotenv').config();`;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
getOperationTemplate(operation, partnerType, params) {
|
|
334
|
+
const endpoint = CommonTemplates.getApiEndpoint(operation, partnerType);
|
|
335
|
+
const method = CommonTemplates.getHttpMethod(operation);
|
|
336
|
+
const sampleBody = CommonTemplates.getSampleRequestBody(operation, partnerType, params);
|
|
337
|
+
const functionName = CodeUtils.formatFunctionName(operation, 'nodejs');
|
|
338
|
+
|
|
339
|
+
const hasBody = method !== 'GET' && Object.keys(sampleBody).length > 0;
|
|
340
|
+
|
|
341
|
+
if (this.framework === 'express') {
|
|
342
|
+
return this.getExpressTemplate(operation, endpoint, method, sampleBody, functionName);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return `async function ${functionName}(${this.getParameterList(operation, params)}) {
|
|
346
|
+
/**
|
|
347
|
+
* ${this.getOperationDescription(operation)}
|
|
348
|
+
*/
|
|
349
|
+
|
|
350
|
+
try {
|
|
351
|
+
// Get API configuration
|
|
352
|
+
const baseURL = getAPIBaseURL(useSandbox);
|
|
353
|
+
|
|
354
|
+
${hasBody ? `// Prepare request body
|
|
355
|
+
const requestBody = ${JSON.stringify(sampleBody, null, 2)};
|
|
356
|
+
|
|
357
|
+
// Create JWT token with body hash
|
|
358
|
+
const { token, bodyString } = createJWTToken(requestBody, useSandbox);
|
|
359
|
+
const headers = getAPIHeaders(token);
|
|
360
|
+
|
|
361
|
+
// Make API request
|
|
362
|
+
const response = await axios.${method.toLowerCase()}(
|
|
363
|
+
\`\${baseURL}${endpoint}\`,
|
|
364
|
+
bodyString,
|
|
365
|
+
{
|
|
366
|
+
headers,
|
|
367
|
+
transformRequest: [(data) => data]
|
|
368
|
+
}
|
|
369
|
+
);` : `// Create JWT token for GET request
|
|
370
|
+
const { token } = createJWTToken(null, useSandbox);
|
|
371
|
+
const headers = getAPIHeaders(token);
|
|
372
|
+
|
|
373
|
+
// Make API request
|
|
374
|
+
const response = await axios.${method.toLowerCase()}(
|
|
375
|
+
\`\${baseURL}${endpoint}\`,
|
|
376
|
+
{ headers }
|
|
377
|
+
);`}
|
|
378
|
+
|
|
379
|
+
return {
|
|
380
|
+
success: true,
|
|
381
|
+
data: response.data,
|
|
382
|
+
requestId: response.headers['x-request-id']
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
} catch (error) {
|
|
386
|
+
return {
|
|
387
|
+
success: false,
|
|
388
|
+
error: {
|
|
389
|
+
message: error.response?.data?.message || error.message,
|
|
390
|
+
status: error.response?.status,
|
|
391
|
+
details: error.response?.data
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Example usage
|
|
398
|
+
async function main() {
|
|
399
|
+
try {
|
|
400
|
+
const result = await ${functionName}(${this.getExampleParameters(operation, params)});
|
|
401
|
+
if (result.success) {
|
|
402
|
+
console.log('Success:', JSON.stringify(result.data, null, 2));
|
|
403
|
+
} else {
|
|
404
|
+
console.error('Error:', result.error);
|
|
405
|
+
}
|
|
406
|
+
} catch (error) {
|
|
407
|
+
console.error('Unexpected error:', error.message);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
main();`;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
getExpressTemplate(operation, endpoint, method, sampleBody, functionName) {
|
|
415
|
+
const hasBody = method !== 'GET' && Object.keys(sampleBody).length > 0;
|
|
416
|
+
|
|
417
|
+
return `// Express.js route implementation
|
|
418
|
+
app.${method.toLowerCase()}('/${operation}', async (req, res) => {
|
|
419
|
+
try {
|
|
420
|
+
${hasBody ? `// Get data from request body
|
|
421
|
+
const requestData = req.body;
|
|
422
|
+
|
|
423
|
+
// Call payware API
|
|
424
|
+
const result = await ${functionName}(requestData);` : `// Call payware API
|
|
425
|
+
const result = await ${functionName}();`}
|
|
426
|
+
|
|
427
|
+
if (result.success) {
|
|
428
|
+
res.json({
|
|
429
|
+
success: true,
|
|
430
|
+
data: result.data,
|
|
431
|
+
requestId: result.requestId
|
|
432
|
+
});
|
|
433
|
+
} else {
|
|
434
|
+
res.status(400).json({
|
|
435
|
+
success: false,
|
|
436
|
+
error: result.error
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
} catch (error) {
|
|
440
|
+
res.status(500).json({
|
|
441
|
+
success: false,
|
|
442
|
+
error: {
|
|
443
|
+
message: error.message
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// Start server
|
|
450
|
+
const PORT = process.env.PORT || 3000;
|
|
451
|
+
app.listen(PORT, () => {
|
|
452
|
+
console.log(\`Server running on port \${PORT}\`);
|
|
453
|
+
});`;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
getParameterList(operation, params) {
|
|
457
|
+
const baseParams = ['useSandbox = true'];
|
|
458
|
+
|
|
459
|
+
if (operation.includes('_transaction') && !operation.includes('list')) {
|
|
460
|
+
baseParams.unshift('transactionId');
|
|
461
|
+
}
|
|
462
|
+
if (operation.includes('product') && !operation.includes('create')) {
|
|
463
|
+
baseParams.unshift('productId');
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return baseParams.join(', ');
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
getExampleParameters(operation, params) {
|
|
470
|
+
if (operation.includes('_transaction') && !operation.includes('list')) {
|
|
471
|
+
return "'pw12345678'";
|
|
472
|
+
}
|
|
473
|
+
if (operation.includes('product') && !operation.includes('create')) {
|
|
474
|
+
return "'pr12345678'";
|
|
475
|
+
}
|
|
476
|
+
return '';
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
getOperationDescription(operation) {
|
|
480
|
+
const descriptions = {
|
|
481
|
+
create_transaction: 'Create a new payment transaction',
|
|
482
|
+
get_transaction_status: 'Get the status of a transaction',
|
|
483
|
+
cancel_transaction: 'Cancel an active transaction',
|
|
484
|
+
process_transaction: 'Process a transaction',
|
|
485
|
+
create_product: 'Create a new product',
|
|
486
|
+
get_product: 'Get product details',
|
|
487
|
+
update_product: 'Update product information',
|
|
488
|
+
delete_product: 'Delete a product'
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
return descriptions[operation] || `Execute ${operation} operation`;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
getErrorHandlingTemplate() {
|
|
495
|
+
return `function handlePaywareError(error) {
|
|
496
|
+
if (error.response) {
|
|
497
|
+
// Server responded with error status
|
|
498
|
+
const status = error.response.status;
|
|
499
|
+
const data = error.response.data;
|
|
500
|
+
|
|
501
|
+
switch (status) {
|
|
502
|
+
case 401:
|
|
503
|
+
return 'Authentication failed - check your credentials';
|
|
504
|
+
case 400:
|
|
505
|
+
return \`Bad request - \${data.message || 'Invalid data'}\`;
|
|
506
|
+
case 404:
|
|
507
|
+
return 'Resource not found';
|
|
508
|
+
case 429:
|
|
509
|
+
return 'Rate limit exceeded - please retry later';
|
|
510
|
+
default:
|
|
511
|
+
return \`API error: \${status} - \${data.message || error.message}\`;
|
|
512
|
+
}
|
|
513
|
+
} else if (error.request) {
|
|
514
|
+
// Network error
|
|
515
|
+
return 'Network error - please check your connection';
|
|
516
|
+
} else {
|
|
517
|
+
// Other error
|
|
518
|
+
return \`Error: \${error.message}\`;
|
|
519
|
+
}
|
|
520
|
+
}`;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
getTestTemplate(operation, partnerType) {
|
|
524
|
+
return `// Jest test example
|
|
525
|
+
const { ${CodeUtils.formatFunctionName(operation, 'nodejs')} } = require('./payware-client');
|
|
526
|
+
const axios = require('axios');
|
|
527
|
+
|
|
528
|
+
// Mock axios
|
|
529
|
+
jest.mock('axios');
|
|
530
|
+
const mockedAxios = axios;
|
|
531
|
+
|
|
532
|
+
describe('${operation}', () => {
|
|
533
|
+
beforeEach(() => {
|
|
534
|
+
// Set up environment variables
|
|
535
|
+
process.env.PAYWARE_PARTNER_ID = 'test_partner';
|
|
536
|
+
process.env.PAYWARE_SANDBOX_PRIVATE_KEY_PATH = 'test_key.pem';
|
|
537
|
+
|
|
538
|
+
// Clear all mocks
|
|
539
|
+
jest.clearAllMocks();
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
test('should handle successful response', async () => {
|
|
543
|
+
// Mock successful response
|
|
544
|
+
const mockResponse = {
|
|
545
|
+
data: { transactionId: 'pw12345678' },
|
|
546
|
+
headers: { 'x-request-id': 'req-123' },
|
|
547
|
+
status: 200
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
mockedAxios.${CommonTemplates.getHttpMethod(operation).toLowerCase()}.mockResolvedValue(mockResponse);
|
|
551
|
+
|
|
552
|
+
// Test the function
|
|
553
|
+
const result = await ${CodeUtils.formatFunctionName(operation, 'nodejs')}();
|
|
554
|
+
|
|
555
|
+
// Assertions
|
|
556
|
+
expect(result.success).toBe(true);
|
|
557
|
+
expect(result.data.transactionId).toBe('pw12345678');
|
|
558
|
+
expect(mockedAxios.${CommonTemplates.getHttpMethod(operation).toLowerCase()}).toHaveBeenCalledTimes(1);
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
test('should handle API errors', async () => {
|
|
562
|
+
// Mock error response
|
|
563
|
+
const mockError = {
|
|
564
|
+
response: {
|
|
565
|
+
status: 400,
|
|
566
|
+
data: { message: 'Bad Request' }
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
mockedAxios.${CommonTemplates.getHttpMethod(operation).toLowerCase()}.mockRejectedValue(mockError);
|
|
571
|
+
|
|
572
|
+
// Test error handling
|
|
573
|
+
const result = await ${CodeUtils.formatFunctionName(operation, 'nodejs')}();
|
|
574
|
+
|
|
575
|
+
// Assertions
|
|
576
|
+
expect(result.success).toBe(false);
|
|
577
|
+
expect(result.error.status).toBe(400);
|
|
578
|
+
expect(result.error.message).toBe('Bad Request');
|
|
579
|
+
});
|
|
580
|
+
});`;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Export all utility generators
|
|
586
|
+
*/
|
|
587
|
+
export const UtilityGenerators = {
|
|
588
|
+
python: PythonGenerator,
|
|
589
|
+
nodejs: NodeJSGenerator,
|
|
590
|
+
javascript: NodeJSGenerator
|
|
591
|
+
};
|