@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,600 @@
1
+ /**
2
+ * ISV OAuth2 authentication flow examples
3
+ */
4
+
5
+ import { ExampleGenerator, CommonTemplates } from '../common/helpers.js';
6
+
7
+ /**
8
+ * OAuth2 operations for ISV
9
+ */
10
+ export const OAuth2Operations = {
11
+ obtain_token: {
12
+ description: 'Obtain OAuth2 access token for merchant access',
13
+ endpoint: '/oauth2/token',
14
+ method: 'POST',
15
+ sampleBody: {
16
+ grant_type: 'client_credentials',
17
+ client_id: 'YOUR_CLIENT_ID',
18
+ client_secret: 'YOUR_CLIENT_SECRET',
19
+ scope: 'merchant:transactions merchant:products merchant:data'
20
+ }
21
+ },
22
+
23
+ get_token_info: {
24
+ description: 'Get information about current OAuth2 token',
25
+ endpoint: '/oauth2/token/info',
26
+ method: 'GET',
27
+ sampleBody: null
28
+ },
29
+
30
+ create_token_simple: {
31
+ description: 'Create simple OAuth2 token with basic scope',
32
+ endpoint: '/oauth2/token/simple',
33
+ method: 'POST',
34
+ sampleBody: {
35
+ grant_type: 'client_credentials',
36
+ scope: 'merchant:read'
37
+ }
38
+ },
39
+
40
+ refresh_token: {
41
+ description: 'Refresh an existing OAuth2 token',
42
+ endpoint: '/oauth2/token/refresh',
43
+ method: 'POST',
44
+ sampleBody: {
45
+ grant_type: 'refresh_token',
46
+ refresh_token: 'REFRESH_TOKEN_HERE'
47
+ }
48
+ },
49
+
50
+ revoke_token: {
51
+ description: 'Revoke OAuth2 access token',
52
+ endpoint: '/oauth2/token/revoke',
53
+ method: 'POST',
54
+ sampleBody: {
55
+ token: 'TOKEN_TO_REVOKE',
56
+ token_type_hint: 'access_token'
57
+ }
58
+ },
59
+
60
+ list_active_tokens: {
61
+ description: 'List all active OAuth2 tokens for ISV',
62
+ endpoint: '/oauth2/tokens',
63
+ method: 'GET',
64
+ sampleBody: null
65
+ }
66
+ };
67
+
68
+ /**
69
+ * Python OAuth2 Generator
70
+ */
71
+ export class PythonOAuth2Generator extends ExampleGenerator {
72
+ constructor() {
73
+ super('python');
74
+ }
75
+
76
+ getOperationTemplate(operation, partnerType, params = {}) {
77
+ const opConfig = OAuth2Operations[operation];
78
+ if (!opConfig) {
79
+ throw new Error(`Unknown operation: ${operation}`);
80
+ }
81
+
82
+ const { merchantPartnerId = 'merchant_456', scope = 'merchant:full', ...otherParams } = params;
83
+ const functionName = `${operation}_example`;
84
+
85
+ return `def ${functionName}(merchant_partner_id='${merchantPartnerId}', scope='${scope}', use_sandbox=True):
86
+ """${opConfig.description}"""
87
+
88
+ try:
89
+ # Get OAuth2 configuration
90
+ client_id = os.getenv('PAYWARE_OAUTH_CLIENT_ID')
91
+ client_secret = os.getenv('PAYWARE_OAUTH_CLIENT_SECRET')
92
+
93
+ if not client_id or not client_secret:
94
+ print("Missing OAuth2 credentials in environment")
95
+ return None
96
+
97
+ # Get API configuration
98
+ base_url = get_api_base_url(use_sandbox)
99
+ endpoint = '${opConfig.endpoint}'
100
+ url = f"{base_url}{endpoint}"
101
+
102
+ ${this.getRequestBodySection(operation, opConfig, merchantPartnerId)}
103
+
104
+ # OAuth2 requests use application/x-www-form-urlencoded
105
+ headers = {
106
+ 'Content-Type': 'application/x-www-form-urlencoded',
107
+ 'Api-Version': '1'
108
+ }
109
+
110
+ ${this.getRequestSection(opConfig.method)}
111
+
112
+ if response.status_code == 200:
113
+ result = response.json()
114
+ print(f"${opConfig.description} successful:")
115
+ print(json.dumps(result, indent=2))
116
+
117
+ ${this.getResultProcessingSection(operation)}
118
+ return result
119
+ else:
120
+ error_msg = f"OAuth2 request failed with status {response.status_code}: {response.text}"
121
+ print(error_msg)
122
+ return None
123
+
124
+ except requests.exceptions.RequestException as e:
125
+ print(f"OAuth2 request error: {str(e)}")
126
+ return None
127
+ except Exception as e:
128
+ print(f"Unexpected error: {str(e)}")
129
+ return None
130
+
131
+ def get_oauth2_token_for_merchant(merchant_partner_id, scope='merchant:full', use_sandbox=True):
132
+ """Convenience function to get OAuth2 token for specific merchant"""
133
+
134
+ client_id = os.getenv('PAYWARE_OAUTH_CLIENT_ID')
135
+ client_secret = os.getenv('PAYWARE_OAUTH_CLIENT_SECRET')
136
+
137
+ if not client_id or not client_secret:
138
+ raise ValueError("Missing OAuth2 credentials")
139
+
140
+ base_url = get_api_base_url(use_sandbox)
141
+ url = f"{base_url}/oauth2/token"
142
+
143
+ data = {
144
+ 'grant_type': 'client_credentials',
145
+ 'client_id': client_id,
146
+ 'client_secret': client_secret,
147
+ 'scope': f"merchant:{merchant_partner_id} {scope}"
148
+ }
149
+
150
+ headers = {
151
+ 'Content-Type': 'application/x-www-form-urlencoded',
152
+ 'Api-Version': '1'
153
+ }
154
+
155
+ try:
156
+ response = requests.post(url, data=data, headers=headers)
157
+
158
+ if response.status_code == 200:
159
+ token_data = response.json()
160
+ return token_data['access_token']
161
+ else:
162
+ print(f"OAuth2 token request failed: {response.status_code} - {response.text}")
163
+ return None
164
+
165
+ except Exception as e:
166
+ print(f"OAuth2 token error: {str(e)}")
167
+ return None
168
+
169
+ def validate_oauth2_token(access_token, use_sandbox=True):
170
+ """Validate OAuth2 token and get token information"""
171
+
172
+ base_url = get_api_base_url(use_sandbox)
173
+ url = f"{base_url}/oauth2/token/info"
174
+
175
+ headers = {
176
+ 'Authorization': f'Bearer {access_token}',
177
+ 'Api-Version': '1'
178
+ }
179
+
180
+ try:
181
+ response = requests.get(url, headers=headers)
182
+
183
+ if response.status_code == 200:
184
+ token_info = response.json()
185
+ print("Token validation successful:")
186
+ print(f"- Valid: {token_info.get('active', False)}")
187
+ print(f"- Scope: {token_info.get('scope', 'N/A')}")
188
+ print(f"- Expires in: {token_info.get('expires_in', 'N/A')} seconds")
189
+ return token_info
190
+ else:
191
+ print(f"Token validation failed: {response.status_code}")
192
+ return None
193
+
194
+ except Exception as e:
195
+ print(f"Token validation error: {str(e)}")
196
+ return None
197
+
198
+ # Example usage
199
+ if __name__ == "__main__":
200
+ # Get target merchant from environment or use default
201
+ target_merchant = os.getenv('PAYWARE_TARGET_MERCHANT_ID', 'merchant_example')
202
+
203
+ print("=== OAuth2 Flow Example ===")
204
+
205
+ # Step 1: Obtain OAuth2 token
206
+ print("\\n1. Obtaining OAuth2 token...")
207
+ token_result = obtain_token_example(target_merchant)
208
+
209
+ if token_result and 'access_token' in token_result:
210
+ access_token = token_result['access_token']
211
+ print(f"✓ OAuth2 token obtained: {access_token[:20]}...")
212
+
213
+ # Step 2: Validate the token
214
+ print("\\n2. Validating OAuth2 token...")
215
+ validation_result = validate_oauth2_token(access_token)
216
+
217
+ if validation_result and validation_result.get('active'):
218
+ print("✓ Token is valid and active")
219
+
220
+ # Step 3: Use token for API calls
221
+ print("\\n3. Token ready for API calls")
222
+ print("You can now use this token with ISV JWT authentication")
223
+ else:
224
+ print("✗ Token validation failed")
225
+ else:
226
+ print("✗ Failed to obtain OAuth2 token")`;
227
+ }
228
+
229
+ getRequestBodySection(operation, opConfig, merchantPartnerId) {
230
+ if (!opConfig.sampleBody) {
231
+ return '# No request body needed for this operation\n request_data = {}';
232
+ }
233
+
234
+ let body = { ...opConfig.sampleBody };
235
+
236
+ // Customize body based on operation
237
+ if (operation === 'obtain_token') {
238
+ body.scope = `merchant:${merchantPartnerId} ${body.scope}`;
239
+ body.client_id = 'client_id'; // Will be replaced by actual value
240
+ body.client_secret = 'client_secret'; // Will be replaced by actual value
241
+ }
242
+
243
+ const bodyEntries = Object.entries(body)
244
+ .map(([key, value]) => {
245
+ if (key === 'client_id') {
246
+ return " 'client_id': client_id,";
247
+ } else if (key === 'client_secret') {
248
+ return " 'client_secret': client_secret,";
249
+ } else {
250
+ return ` '${key}': '${value}',`;
251
+ }
252
+ })
253
+ .join('\n');
254
+
255
+ return `# Prepare OAuth2 request data
256
+ request_data = {
257
+ ${bodyEntries}
258
+ }`;
259
+ }
260
+
261
+ getRequestSection(method) {
262
+ if (method === 'GET') {
263
+ return 'response = requests.get(url, headers=headers)';
264
+ } else {
265
+ return 'response = requests.post(url, data=request_data, headers=headers)';
266
+ }
267
+ }
268
+
269
+ getResultProcessingSection(operation) {
270
+ const processing = {
271
+ obtain_token: `# Store token information
272
+ access_token = result.get('access_token')
273
+ token_type = result.get('token_type', 'Bearer')
274
+ expires_in = result.get('expires_in')
275
+ scope = result.get('scope')
276
+
277
+ print(f"Access Token: {access_token[:20]}...")
278
+ print(f"Token Type: {token_type}")
279
+ print(f"Expires In: {expires_in} seconds")
280
+ print(f"Scope: {scope}")
281
+
282
+ # Store token for later use
283
+ os.environ['OAUTH2_ACCESS_TOKEN'] = access_token`,
284
+
285
+ get_token_info: `# Display token information
286
+ active = result.get('active', False)
287
+ scope = result.get('scope', 'N/A')
288
+ client_id = result.get('client_id', 'N/A')
289
+ expires_in = result.get('exp', 'N/A')
290
+
291
+ print(f"Token Active: {active}")
292
+ print(f"Client ID: {client_id}")
293
+ print(f"Scope: {scope}")
294
+ print(f"Expires: {expires_in}")`,
295
+
296
+ list_active_tokens: `# Display active tokens
297
+ tokens = result.get('tokens', [])
298
+ print(f"Found {len(tokens)} active tokens:")
299
+ for token in tokens:
300
+ print(f"- Token ID: {token.get('id')}")
301
+ print(f" Scope: {token.get('scope')}")
302
+ print(f" Created: {token.get('created_at')}")
303
+ print(f" Expires: {token.get('expires_at')}")`
304
+ };
305
+
306
+ return processing[operation] || '# Process OAuth2 result as needed';
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Node.js OAuth2 Generator
312
+ */
313
+ export class NodeJSOAuth2Generator extends ExampleGenerator {
314
+ constructor() {
315
+ super('nodejs');
316
+ }
317
+
318
+ getOperationTemplate(operation, partnerType, params = {}) {
319
+ const opConfig = OAuth2Operations[operation];
320
+ if (!opConfig) {
321
+ throw new Error(`Unknown operation: ${operation}`);
322
+ }
323
+
324
+ const { merchantPartnerId = 'merchant_456', scope = 'merchant:full', ...otherParams } = params;
325
+ const functionName = `${operation}Example`;
326
+
327
+ return `async function ${functionName}(merchantPartnerId = '${merchantPartnerId}', scope = '${scope}', useSandbox = true) {
328
+ /**
329
+ * ${opConfig.description}
330
+ */
331
+
332
+ try {
333
+ // Get OAuth2 configuration
334
+ const clientId = process.env.PAYWARE_OAUTH_CLIENT_ID;
335
+ const clientSecret = process.env.PAYWARE_OAUTH_CLIENT_SECRET;
336
+
337
+ if (!clientId || !clientSecret) {
338
+ console.error('Missing OAuth2 credentials in environment');
339
+ return null;
340
+ }
341
+
342
+ // Get API configuration
343
+ const baseUrl = getAPIBaseURL(useSandbox);
344
+ const endpoint = '${opConfig.endpoint}';
345
+ const url = \`\${baseUrl}\${endpoint}\`;
346
+
347
+ ${this.getRequestBodySection(operation, opConfig, merchantPartnerId)}
348
+
349
+ // OAuth2 requests use application/x-www-form-urlencoded
350
+ const headers = {
351
+ 'Content-Type': 'application/x-www-form-urlencoded',
352
+ 'Api-Version': '1'
353
+ };
354
+
355
+ ${this.getRequestSection(opConfig.method)}
356
+
357
+ if (response.status === 200) {
358
+ const result = response.data;
359
+ console.log('${opConfig.description} successful:');
360
+ console.log(JSON.stringify(result, null, 2));
361
+
362
+ ${this.getResultProcessingSection(operation)}
363
+
364
+ return result;
365
+ } else {
366
+ console.error(\`OAuth2 request failed with status \${response.status}: \${response.statusText}\`);
367
+ return null;
368
+ }
369
+
370
+ } catch (error) {
371
+ if (error.response) {
372
+ console.error(\`OAuth2 API Error: \${error.response.status} - \${error.response.data}\`);
373
+ } else {
374
+ console.error('OAuth2 Error:', error.message);
375
+ }
376
+ return null;
377
+ }
378
+ }
379
+
380
+ async function getOAuth2TokenForMerchant(merchantPartnerId, scope = 'merchant:full', useSandbox = true) {
381
+ /**
382
+ * Convenience function to get OAuth2 token for specific merchant
383
+ */
384
+
385
+ const clientId = process.env.PAYWARE_OAUTH_CLIENT_ID;
386
+ const clientSecret = process.env.PAYWARE_OAUTH_CLIENT_SECRET;
387
+
388
+ if (!clientId || !clientSecret) {
389
+ throw new Error('Missing OAuth2 credentials');
390
+ }
391
+
392
+ const baseUrl = getAPIBaseURL(useSandbox);
393
+ const url = \`\${baseUrl}/oauth2/token\`;
394
+
395
+ const data = new URLSearchParams({
396
+ grant_type: 'client_credentials',
397
+ client_id: clientId,
398
+ client_secret: clientSecret,
399
+ scope: \`merchant:\${merchantPartnerId} \${scope}\`
400
+ });
401
+
402
+ const headers = {
403
+ 'Content-Type': 'application/x-www-form-urlencoded',
404
+ 'Api-Version': '1'
405
+ };
406
+
407
+ try {
408
+ const response = await axios.post(url, data, { headers });
409
+
410
+ if (response.status === 200) {
411
+ return response.data.access_token;
412
+ } else {
413
+ console.error(\`OAuth2 token request failed: \${response.status} - \${response.statusText}\`);
414
+ return null;
415
+ }
416
+
417
+ } catch (error) {
418
+ console.error('OAuth2 token error:', error.message);
419
+ return null;
420
+ }
421
+ }
422
+
423
+ async function validateOAuth2Token(accessToken, useSandbox = true) {
424
+ /**
425
+ * Validate OAuth2 token and get token information
426
+ */
427
+
428
+ const baseUrl = getAPIBaseURL(useSandbox);
429
+ const url = \`\${baseUrl}/oauth2/token/info\`;
430
+
431
+ const headers = {
432
+ 'Authorization': \`Bearer \${accessToken}\`,
433
+ 'Api-Version': '1'
434
+ };
435
+
436
+ try {
437
+ const response = await axios.get(url, { headers });
438
+
439
+ if (response.status === 200) {
440
+ const tokenInfo = response.data;
441
+ console.log('Token validation successful:');
442
+ console.log(\`- Valid: \${tokenInfo.active || false}\`);
443
+ console.log(\`- Scope: \${tokenInfo.scope || 'N/A'}\`);
444
+ console.log(\`- Expires in: \${tokenInfo.expires_in || 'N/A'} seconds\`);
445
+ return tokenInfo;
446
+ } else {
447
+ console.error(\`Token validation failed: \${response.status}\`);
448
+ return null;
449
+ }
450
+
451
+ } catch (error) {
452
+ console.error('Token validation error:', error.message);
453
+ return null;
454
+ }
455
+ }
456
+
457
+ // Example usage
458
+ async function main() {
459
+ // Get target merchant from environment or use default
460
+ const targetMerchant = process.env.PAYWARE_TARGET_MERCHANT_ID || 'merchant_example';
461
+
462
+ console.log('=== OAuth2 Flow Example ===');
463
+
464
+ try {
465
+ // Step 1: Obtain OAuth2 token
466
+ console.log('\\n1. Obtaining OAuth2 token...');
467
+ const tokenResult = await obtainTokenExample(targetMerchant);
468
+
469
+ if (tokenResult && tokenResult.access_token) {
470
+ const accessToken = tokenResult.access_token;
471
+ console.log(\`✓ OAuth2 token obtained: \${accessToken.substring(0, 20)}...\`);
472
+
473
+ // Step 2: Validate the token
474
+ console.log('\\n2. Validating OAuth2 token...');
475
+ const validationResult = await validateOAuth2Token(accessToken);
476
+
477
+ if (validationResult && validationResult.active) {
478
+ console.log('✓ Token is valid and active');
479
+
480
+ // Step 3: Use token for API calls
481
+ console.log('\\n3. Token ready for API calls');
482
+ console.log('You can now use this token with ISV JWT authentication');
483
+ } else {
484
+ console.log('✗ Token validation failed');
485
+ }
486
+ } else {
487
+ console.log('✗ Failed to obtain OAuth2 token');
488
+ }
489
+
490
+ } catch (error) {
491
+ console.error('OAuth2 flow error:', error.message);
492
+ }
493
+ }
494
+
495
+ // Run example if this file is executed directly
496
+ if (require.main === module) {
497
+ main().catch(console.error);
498
+ }`;
499
+ }
500
+
501
+ getRequestBodySection(operation, opConfig, merchantPartnerId) {
502
+ if (!opConfig.sampleBody) {
503
+ return '// No request body needed for this operation\n const requestData = new URLSearchParams();';
504
+ }
505
+
506
+ let body = { ...opConfig.sampleBody };
507
+
508
+ // Customize body based on operation
509
+ if (operation === 'obtain_token') {
510
+ body.scope = `merchant:${merchantPartnerId} ${body.scope}`;
511
+ }
512
+
513
+ const bodyEntries = Object.entries(body)
514
+ .map(([key, value]) => {
515
+ if (key === 'client_id') {
516
+ return " requestData.append('client_id', clientId);";
517
+ } else if (key === 'client_secret') {
518
+ return " requestData.append('client_secret', clientSecret);";
519
+ } else {
520
+ return ` requestData.append('${key}', '${value}');`;
521
+ }
522
+ })
523
+ .join('\n');
524
+
525
+ return `// Prepare OAuth2 request data
526
+ const requestData = new URLSearchParams();
527
+ ${bodyEntries}`;
528
+ }
529
+
530
+ getRequestSection(method) {
531
+ if (method === 'GET') {
532
+ return 'const response = await axios.get(url, { headers });';
533
+ } else {
534
+ return 'const response = await axios.post(url, requestData, { headers });';
535
+ }
536
+ }
537
+
538
+ getResultProcessingSection(operation) {
539
+ const processing = {
540
+ obtain_token: `// Store token information
541
+ const accessToken = result.access_token;
542
+ const tokenType = result.token_type || 'Bearer';
543
+ const expiresIn = result.expires_in;
544
+ const scope = result.scope;
545
+
546
+ console.log(\`Access Token: \${accessToken.substring(0, 20)}...\`);
547
+ console.log(\`Token Type: \${tokenType}\`);
548
+ console.log(\`Expires In: \${expiresIn} seconds\`);
549
+ console.log(\`Scope: \${scope}\`);
550
+
551
+ // Store token for later use
552
+ process.env.OAUTH2_ACCESS_TOKEN = accessToken;`,
553
+
554
+ get_token_info: `// Display token information
555
+ const active = result.active || false;
556
+ const scope = result.scope || 'N/A';
557
+ const clientId = result.client_id || 'N/A';
558
+ const expiresIn = result.exp || 'N/A';
559
+
560
+ console.log(\`Token Active: \${active}\`);
561
+ console.log(\`Client ID: \${clientId}\`);
562
+ console.log(\`Scope: \${scope}\`);
563
+ console.log(\`Expires: \${expiresIn}\`);`,
564
+
565
+ list_active_tokens: `// Display active tokens
566
+ const tokens = result.tokens || [];
567
+ console.log(\`Found \${tokens.length} active tokens:\`);
568
+ tokens.forEach(token => {
569
+ console.log(\`- Token ID: \${token.id}\`);
570
+ console.log(\` Scope: \${token.scope}\`);
571
+ console.log(\` Created: \${token.created_at}\`);
572
+ console.log(\` Expires: \${token.expires_at}\`);
573
+ });`
574
+ };
575
+
576
+ return processing[operation] || '// Process OAuth2 result as needed';
577
+ }
578
+ }
579
+
580
+ /**
581
+ * Export all generators
582
+ */
583
+ export const OAuth2Generators = {
584
+ python: PythonOAuth2Generator,
585
+ nodejs: NodeJSOAuth2Generator,
586
+ javascript: NodeJSOAuth2Generator
587
+ };
588
+
589
+ /**
590
+ * Generate OAuth2 example
591
+ */
592
+ export function generateOAuth2Example(operation, language = 'python', options = {}) {
593
+ const GeneratorClass = OAuth2Generators[language];
594
+ if (!GeneratorClass) {
595
+ throw new Error(`Unsupported language: ${language}`);
596
+ }
597
+
598
+ const generator = new GeneratorClass();
599
+ return generator.generateExample(operation, 'isv', options);
600
+ }