@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,666 @@
1
+ /**
2
+ * ISV product management examples with OAuth2 authentication
3
+ */
4
+
5
+ import { ExampleGenerator, CommonTemplates } from '../common/helpers.js';
6
+
7
+ /**
8
+ * ISV product operations (same endpoints as merchant but with OAuth2 auth)
9
+ */
10
+ export const ISVProductOperations = {
11
+ create_product: {
12
+ description: 'Create a product for merchant via ISV',
13
+ endpoint: '/products',
14
+ method: 'POST',
15
+ requiresOAuth: true,
16
+ sampleBody: {
17
+ name: 'ISV Managed Product',
18
+ shortDescription: 'Product created and managed via ISV integration',
19
+ prData: {
20
+ type: 'ITEM',
21
+ regularPrice: '39.99',
22
+ currency: 'EUR',
23
+ timeToLive: 86400
24
+ },
25
+ prOptions: {
26
+ imageUrl: 'https://isv-cdn.example.com/product-image.jpg',
27
+ category: 'digital',
28
+ tags: ['isv-managed', 'digital', 'premium'],
29
+ isvMetadata: {
30
+ sourceSystem: 'ISV_PLATFORM',
31
+ externalId: 'ext_prod_123'
32
+ }
33
+ }
34
+ }
35
+ },
36
+
37
+ get_product: {
38
+ description: 'Get merchant product details via ISV',
39
+ endpoint: '/products/{id}',
40
+ method: 'GET',
41
+ requiresOAuth: true,
42
+ sampleBody: null
43
+ },
44
+
45
+ update_product: {
46
+ description: 'Update merchant product via ISV',
47
+ endpoint: '/products/{id}',
48
+ method: 'PATCH',
49
+ requiresOAuth: true,
50
+ sampleBody: {
51
+ name: 'ISV Managed Product - Updated',
52
+ prData: {
53
+ regularPrice: '34.99'
54
+ },
55
+ prOptions: {
56
+ isvMetadata: {
57
+ lastUpdated: new Date().toISOString(),
58
+ updateSource: 'ISV_BULK_UPDATE'
59
+ }
60
+ }
61
+ }
62
+ },
63
+
64
+ delete_product: {
65
+ description: 'Delete merchant product via ISV',
66
+ endpoint: '/products/{id}',
67
+ method: 'DELETE',
68
+ requiresOAuth: true,
69
+ sampleBody: null
70
+ },
71
+
72
+ list_products: {
73
+ description: 'List merchant products via ISV',
74
+ endpoint: '/products',
75
+ method: 'GET',
76
+ requiresOAuth: true,
77
+ sampleBody: null,
78
+ queryParams: {
79
+ limit: 50,
80
+ offset: 0,
81
+ isvManaged: true,
82
+ status: 'active'
83
+ }
84
+ },
85
+
86
+ bulk_create_products: {
87
+ description: 'Bulk create products for merchant via ISV',
88
+ endpoint: '/products/bulk',
89
+ method: 'POST',
90
+ requiresOAuth: true,
91
+ sampleBody: {
92
+ products: [
93
+ {
94
+ name: 'Bulk Product 1',
95
+ shortDescription: 'First bulk product',
96
+ prData: { type: 'ITEM', regularPrice: '19.99', currency: 'EUR' },
97
+ prOptions: { category: 'bulk-import' }
98
+ },
99
+ {
100
+ name: 'Bulk Product 2',
101
+ shortDescription: 'Second bulk product',
102
+ prData: { type: 'ITEM', regularPrice: '29.99', currency: 'EUR' },
103
+ prOptions: { category: 'bulk-import' }
104
+ }
105
+ ],
106
+ bulkOptions: {
107
+ batchId: 'batch_001',
108
+ validateOnly: false,
109
+ continueOnError: true
110
+ }
111
+ }
112
+ },
113
+
114
+ sync_products: {
115
+ description: 'Synchronize products between ISV and merchant',
116
+ endpoint: '/products/sync',
117
+ method: 'POST',
118
+ requiresOAuth: true,
119
+ sampleBody: {
120
+ syncOptions: {
121
+ direction: 'ISV_TO_MERCHANT',
122
+ conflictResolution: 'ISV_WINS',
123
+ includeDeleted: false
124
+ },
125
+ filters: {
126
+ lastModified: '2024-01-01T00:00:00Z',
127
+ categories: ['digital', 'premium']
128
+ }
129
+ }
130
+ },
131
+
132
+ get_product_analytics: {
133
+ description: 'Get product analytics via ISV',
134
+ endpoint: '/products/{id}/analytics',
135
+ method: 'GET',
136
+ requiresOAuth: true,
137
+ sampleBody: null,
138
+ queryParams: {
139
+ startDate: '2024-01-01',
140
+ endDate: '2024-12-31',
141
+ metrics: 'sales,views,conversions'
142
+ }
143
+ },
144
+
145
+ // Audio/Soundbite Operations
146
+ register_audio: {
147
+ description: 'Register audio file for merchant product via ISV',
148
+ endpoint: '/products/{id}/audios/upload',
149
+ method: 'POST',
150
+ requiresOAuth: true,
151
+ contentType: 'multipart/form-data',
152
+ sampleBody: {
153
+ file: '@/path/to/audio.mp3'
154
+ }
155
+ },
156
+
157
+ get_audios: {
158
+ description: 'Get all audio files for merchant product via ISV',
159
+ endpoint: '/products/{id}/audios',
160
+ method: 'GET',
161
+ requiresOAuth: true,
162
+ sampleBody: null
163
+ },
164
+
165
+ get_audio: {
166
+ description: 'Get specific audio file details via ISV',
167
+ endpoint: '/products/{id}/audios/{audioId}',
168
+ method: 'GET',
169
+ requiresOAuth: true,
170
+ sampleBody: null
171
+ },
172
+
173
+ update_audio: {
174
+ description: 'Update audio file information via ISV',
175
+ endpoint: '/products/{id}/audios/{audioId}',
176
+ method: 'PATCH',
177
+ requiresOAuth: true,
178
+ sampleBody: {
179
+ title: 'Updated Audio Title',
180
+ productId: 'pr_new_product_789'
181
+ }
182
+ },
183
+
184
+ delete_audio: {
185
+ description: 'Delete audio file via ISV',
186
+ endpoint: '/products/{id}/audios/{audioId}',
187
+ method: 'DELETE',
188
+ requiresOAuth: true,
189
+ sampleBody: null
190
+ }
191
+ };
192
+
193
+ /**
194
+ * Python ISV Product Generator
195
+ */
196
+ export class PythonISVProductGenerator extends ExampleGenerator {
197
+ constructor() {
198
+ super('python');
199
+ }
200
+
201
+ getOperationTemplate(operation, partnerType, params = {}) {
202
+ const opConfig = ISVProductOperations[operation];
203
+ if (!opConfig) {
204
+ throw new Error(`Unknown operation: ${operation}`);
205
+ }
206
+
207
+ const {
208
+ productId = 'pr_example_123',
209
+ merchantPartnerId = 'merchant_456',
210
+ audioId = 'aud_example_789',
211
+ ...otherParams
212
+ } = params;
213
+
214
+ let endpoint = opConfig.endpoint.replace('{id}', productId);
215
+ if (endpoint.includes('{audioId}')) {
216
+ endpoint = endpoint.replace('{audioId}', audioId);
217
+ }
218
+ const functionName = `${operation}_example`;
219
+
220
+ return `def ${functionName}(product_id='${productId}', merchant_partner_id='${merchantPartnerId}'${audioId && operation.includes('audio') && !operation.includes('get_audios') && !operation.includes('register') ? `, audio_id='${audioId}'` : ''}, use_sandbox=True):
221
+ """${opConfig.description}"""
222
+
223
+ try:
224
+ # Step 1: Get OAuth2 token for merchant access
225
+ oauth2_token = get_oauth2_token(merchant_partner_id)
226
+ if not oauth2_token:
227
+ print("Failed to obtain OAuth2 token")
228
+ return None
229
+
230
+ # Step 2: Get API configuration
231
+ base_url = get_api_base_url(use_sandbox)
232
+ endpoint = '${endpoint}'
233
+ url = f"{base_url}{endpoint}"
234
+
235
+ ${this.getQueryParamsSection(operation, opConfig)}
236
+ ${this.getRequestBodySection(operation, opConfig)}
237
+
238
+ # Step 3: Create ISV JWT token with OAuth2 token
239
+ token, body_string = create_isv_jwt_token(merchant_partner_id, oauth2_token, request_body, use_sandbox)
240
+ headers = get_api_headers(token)
241
+
242
+ # Step 4: Make API request
243
+ ${this.getRequestSection(opConfig.method)}
244
+
245
+ if response.status_code == 200:
246
+ result = response.json()
247
+ print(f"${opConfig.description} successful:")
248
+ print(json.dumps(result, indent=2))
249
+
250
+ ${this.getResultProcessingSection(operation)}
251
+ return result
252
+ else:
253
+ error_msg = f"Request failed with status {response.status_code}: {response.text}"
254
+ print(error_msg)
255
+ return None
256
+
257
+ except Exception as e:
258
+ print(f"Error in ${operation}: {str(e)}")
259
+ return None
260
+
261
+ def create_isv_jwt_token(merchant_partner_id, oauth2_token, request_body=None, use_sandbox=True):
262
+ """Create ISV JWT token with OAuth2 authentication"""
263
+
264
+ # Get ISV configuration
265
+ isv_partner_id = os.getenv('PAYWARE_ISV_PARTNER_ID')
266
+ if use_sandbox:
267
+ private_key_path = os.getenv('PAYWARE_SANDBOX_ISV_PRIVATE_KEY_PATH')
268
+ else:
269
+ private_key_path = os.getenv('PAYWARE_PRODUCTION_ISV_PRIVATE_KEY_PATH')
270
+
271
+ if not isv_partner_id or not private_key_path:
272
+ raise ValueError("Missing ISV configuration")
273
+
274
+ # Load private key
275
+ with open(private_key_path, 'r') as f:
276
+ private_key = f.read()
277
+
278
+ # Create JWT header
279
+ header = {
280
+ 'alg': 'RS256',
281
+ 'typ': 'JWT'
282
+ }
283
+
284
+ # Add content MD5 for requests with body
285
+ body_string = None
286
+ if request_body:
287
+ body_string = create_minimized_json(request_body)
288
+ content_md5 = base64.b64encode(
289
+ hashlib.md5(body_string.encode('utf-8')).digest()
290
+ ).decode('utf-8')
291
+ header['contentMd5'] = content_md5
292
+
293
+ # Create JWT payload for ISV
294
+ payload = {
295
+ 'iss': isv_partner_id, # ISV Partner ID
296
+ 'aud': merchant_partner_id, # Target Merchant ID
297
+ 'sub': oauth2_token, # OAuth2 access token
298
+ 'iat': int(datetime.utcnow().timestamp())
299
+ }
300
+
301
+ # Create and return token
302
+ token = jwt.encode(payload, private_key, algorithm='RS256', headers=header)
303
+ return token, body_string
304
+
305
+ # Example usage
306
+ if __name__ == "__main__":
307
+ # Set target merchant
308
+ target_merchant = os.getenv('PAYWARE_TARGET_MERCHANT_ID', 'merchant_example')
309
+
310
+ # ${opConfig.description}
311
+ result = ${functionName}(merchant_partner_id=target_merchant)
312
+
313
+ if result:
314
+ print("ISV operation completed successfully")
315
+ ${this.getISVResultProcessingSection(operation)}
316
+ else:
317
+ print("ISV operation failed")`;
318
+ }
319
+
320
+ getQueryParamsSection(operation, opConfig) {
321
+ if (!opConfig.queryParams) {
322
+ return '';
323
+ }
324
+
325
+ const paramsStr = Object.entries(opConfig.queryParams)
326
+ .map(([key, value]) => ` '${key}': ${typeof value === 'string' ? `'${value}'` : value}`)
327
+ .join(',\n');
328
+
329
+ return `# Add query parameters
330
+ params = {
331
+ ${paramsStr}
332
+ }
333
+ if params:
334
+ url += '?' + '&'.join([f"{k}={v}" for k, v in params.items()])`;
335
+ }
336
+
337
+ getRequestBodySection(operation, opConfig) {
338
+ if (!opConfig.sampleBody) {
339
+ return '# No request body needed for this operation\n request_body = None';
340
+ }
341
+
342
+ const bodyStr = JSON.stringify(opConfig.sampleBody, null, 8).replace(/^/gm, ' ');
343
+ return `# Prepare request body
344
+ request_body = ${bodyStr}`;
345
+ }
346
+
347
+ getRequestSection(method) {
348
+ if (method === 'GET') {
349
+ return 'response = requests.get(url, headers=headers)';
350
+ } else if (method === 'DELETE') {
351
+ return 'response = requests.delete(url, headers=headers)';
352
+ } else {
353
+ return `response = requests.${method.toLowerCase()}(
354
+ url,
355
+ headers=headers,
356
+ data=body_string if request_body else None
357
+ )`;
358
+ }
359
+ }
360
+
361
+ getResultProcessingSection(operation) {
362
+ const processing = {
363
+ create_product: `# Store product ID and ISV metadata
364
+ product_id = result.get('productId')
365
+ isv_metadata = result.get('prOptions', {}).get('isvMetadata', {})
366
+ print(f"Product created with ID: {product_id}")
367
+ print(f"ISV metadata: {isv_metadata}")`,
368
+
369
+ bulk_create_products: `# Process bulk creation results
370
+ created_products = result.get('createdProducts', [])
371
+ failed_products = result.get('failedProducts', [])
372
+ print(f"Successfully created: {len(created_products)} products")
373
+ print(f"Failed to create: {len(failed_products)} products")`,
374
+
375
+ sync_products: `# Display sync results
376
+ sync_stats = result.get('syncStats', {})
377
+ print(f"Sync completed:")
378
+ print(f"- Created: {sync_stats.get('created', 0)}")
379
+ print(f"- Updated: {sync_stats.get('updated', 0)}")
380
+ print(f"- Deleted: {sync_stats.get('deleted', 0)}")`,
381
+
382
+ get_product_analytics: `# Display analytics data
383
+ analytics = result.get('analytics', {})
384
+ metrics = analytics.get('metrics', {})
385
+ print("Product Analytics:")
386
+ for metric, value in metrics.items():
387
+ print(f"- {metric}: {value}")`
388
+ };
389
+
390
+ return processing[operation] || '# Process ISV result as needed';
391
+ }
392
+
393
+ getISVResultProcessingSection(operation) {
394
+ const processing = {
395
+ create_product: `# Log ISV operation for audit
396
+ print("ISV Product Creation completed - check merchant dashboard")`,
397
+
398
+ bulk_create_products: `# Generate ISV report
399
+ print("Bulk creation completed - generating ISV summary report")`,
400
+
401
+ sync_products: `# Update ISV sync status
402
+ print("Product synchronization completed - updating ISV tracking")`
403
+ };
404
+
405
+ return processing[operation] || '# Log ISV operation completion';
406
+ }
407
+ }
408
+
409
+ /**
410
+ * Node.js ISV Product Generator
411
+ */
412
+ export class NodeJSISVProductGenerator extends ExampleGenerator {
413
+ constructor() {
414
+ super('nodejs');
415
+ }
416
+
417
+ getOperationTemplate(operation, partnerType, params = {}) {
418
+ const opConfig = ISVProductOperations[operation];
419
+ if (!opConfig) {
420
+ throw new Error(`Unknown operation: ${operation}`);
421
+ }
422
+
423
+ const {
424
+ productId = 'pr_example_123',
425
+ merchantPartnerId = 'merchant_456',
426
+ audioId = 'aud_example_789',
427
+ ...otherParams
428
+ } = params;
429
+
430
+ let endpoint = opConfig.endpoint.replace('{id}', productId);
431
+ if (endpoint.includes('{audioId}')) {
432
+ endpoint = endpoint.replace('{audioId}', audioId);
433
+ }
434
+ const functionName = `${operation}Example`;
435
+
436
+ return `async function ${functionName}(productId = '${productId}', merchantPartnerId = '${merchantPartnerId}'${audioId && operation.includes('audio') && !operation.includes('get_audios') && !operation.includes('register') ? `, audioId = '${audioId}'` : ''}, useSandbox = true) {
437
+ /**
438
+ * ${opConfig.description}
439
+ */
440
+
441
+ try {
442
+ // Step 1: Get OAuth2 token for merchant access
443
+ const oauth2Token = await getOAuth2Token(merchantPartnerId);
444
+ if (!oauth2Token) {
445
+ console.error('Failed to obtain OAuth2 token');
446
+ return null;
447
+ }
448
+
449
+ // Step 2: Get API configuration
450
+ const baseUrl = getAPIBaseURL(useSandbox);
451
+ const endpoint = '${endpoint}';
452
+ let url = \`\${baseUrl}\${endpoint}\`;
453
+
454
+ ${this.getQueryParamsSection(operation, opConfig)}
455
+ ${this.getRequestBodySection(operation, opConfig)}
456
+
457
+ // Step 3: Create ISV JWT token with OAuth2 token
458
+ const { token, bodyString } = createISVJWTToken(merchantPartnerId, oauth2Token, requestBody, useSandbox);
459
+ const headers = getAPIHeaders(token);
460
+
461
+ // Step 4: Make API request
462
+ ${this.getRequestSection(opConfig.method)}
463
+
464
+ if (response.status === 200) {
465
+ const result = response.data;
466
+ console.log('${opConfig.description} successful:');
467
+ console.log(JSON.stringify(result, null, 2));
468
+
469
+ ${this.getResultProcessingSection(operation)}
470
+
471
+ return result;
472
+ } else {
473
+ console.error(\`Request failed with status \${response.status}: \${response.statusText}\`);
474
+ return null;
475
+ }
476
+
477
+ } catch (error) {
478
+ console.error(\`Error in ${operation}:\`, error.message);
479
+ if (error.response) {
480
+ console.error('API Error:', error.response.data);
481
+ }
482
+ return null;
483
+ }
484
+ }
485
+
486
+ function createISVJWTToken(merchantPartnerId, oauth2Token, requestBody = null, useSandbox = true) {
487
+ /**
488
+ * Create ISV JWT token with OAuth2 authentication
489
+ */
490
+
491
+ // Get ISV configuration
492
+ const isvPartnerId = process.env.PAYWARE_ISV_PARTNER_ID;
493
+ const privateKeyPath = useSandbox ?
494
+ process.env.PAYWARE_SANDBOX_ISV_PRIVATE_KEY_PATH :
495
+ process.env.PAYWARE_PRODUCTION_ISV_PRIVATE_KEY_PATH;
496
+
497
+ if (!isvPartnerId || !privateKeyPath) {
498
+ throw new Error('Missing ISV configuration');
499
+ }
500
+
501
+ // Load private key
502
+ const privateKey = fs.readFileSync(privateKeyPath, 'utf8');
503
+
504
+ // Create JWT header
505
+ const header = {
506
+ alg: 'RS256',
507
+ typ: 'JWT'
508
+ };
509
+
510
+ // Add content MD5 for requests with body
511
+ let bodyString = null;
512
+ if (requestBody) {
513
+ bodyString = createMinimizedJSON(requestBody);
514
+ const contentMd5 = crypto
515
+ .createHash('md5')
516
+ .update(bodyString, 'utf8')
517
+ .digest('base64');
518
+ header.contentMd5 = contentMd5;
519
+ }
520
+
521
+ // Create JWT payload for ISV
522
+ const payload = {
523
+ iss: isvPartnerId, // ISV Partner ID
524
+ aud: merchantPartnerId, // Target Merchant ID
525
+ sub: oauth2Token, // OAuth2 access token
526
+ iat: Math.floor(Date.now() / 1000)
527
+ };
528
+
529
+ // Create and return token
530
+ const token = jwt.sign(payload, privateKey, {
531
+ algorithm: 'RS256',
532
+ header
533
+ });
534
+
535
+ return { token, bodyString };
536
+ }
537
+
538
+ // Example usage
539
+ async function main() {
540
+ console.log('ISV Product Management Example');
541
+
542
+ // Set target merchant
543
+ const targetMerchant = process.env.PAYWARE_TARGET_MERCHANT_ID || 'merchant_example';
544
+
545
+ const result = await ${functionName}(undefined, targetMerchant);
546
+
547
+ if (result) {
548
+ console.log('ISV operation completed successfully');
549
+ ${this.getISVResultProcessingSection(operation)}
550
+ } else {
551
+ console.log('ISV operation failed');
552
+ }
553
+ }
554
+
555
+ // Run example if this file is executed directly
556
+ if (require.main === module) {
557
+ main().catch(console.error);
558
+ }`;
559
+ }
560
+
561
+ getQueryParamsSection(operation, opConfig) {
562
+ if (!opConfig.queryParams) {
563
+ return '';
564
+ }
565
+
566
+ const paramsStr = JSON.stringify(opConfig.queryParams, null, 4).replace(/^/gm, ' ');
567
+ return `// Add query parameters
568
+ const queryParams = ${paramsStr};
569
+ const searchParams = new URLSearchParams(queryParams);
570
+ url += \`?\${searchParams.toString()}\`;`;
571
+ }
572
+
573
+ getRequestBodySection(operation, opConfig) {
574
+ if (!opConfig.sampleBody) {
575
+ return '// No request body needed for this operation\n const requestBody = null;';
576
+ }
577
+
578
+ const bodyStr = JSON.stringify(opConfig.sampleBody, null, 4).replace(/^/gm, ' ');
579
+ return `// Prepare request body
580
+ const requestBody = ${bodyStr};`;
581
+ }
582
+
583
+ getRequestSection(method) {
584
+ if (method === 'GET') {
585
+ return 'const response = await axios.get(url, { headers });';
586
+ } else if (method === 'DELETE') {
587
+ return 'const response = await axios.delete(url, { headers });';
588
+ } else {
589
+ return `const response = await axios.${method.toLowerCase()}(
590
+ url,
591
+ bodyString || undefined,
592
+ { headers }
593
+ );`;
594
+ }
595
+ }
596
+
597
+ getResultProcessingSection(operation) {
598
+ const processing = {
599
+ create_product: `// Store product ID and ISV metadata
600
+ const productId = result.productId;
601
+ const isvMetadata = result.prOptions?.isvMetadata || {};
602
+ console.log(\`Product created with ID: \${productId}\`);
603
+ console.log('ISV metadata:', isvMetadata);`,
604
+
605
+ bulk_create_products: `// Process bulk creation results
606
+ const createdProducts = result.createdProducts || [];
607
+ const failedProducts = result.failedProducts || [];
608
+ console.log(\`Successfully created: \${createdProducts.length} products\`);
609
+ console.log(\`Failed to create: \${failedProducts.length} products\`);`,
610
+
611
+ sync_products: `// Display sync results
612
+ const syncStats = result.syncStats || {};
613
+ console.log('Sync completed:');
614
+ console.log(\`- Created: \${syncStats.created || 0}\`);
615
+ console.log(\`- Updated: \${syncStats.updated || 0}\`);
616
+ console.log(\`- Deleted: \${syncStats.deleted || 0}\`);`,
617
+
618
+ get_product_analytics: `// Display analytics data
619
+ const analytics = result.analytics || {};
620
+ const metrics = analytics.metrics || {};
621
+ console.log('Product Analytics:');
622
+ Object.entries(metrics).forEach(([metric, value]) => {
623
+ console.log(\`- \${metric}: \${value}\`);
624
+ });`
625
+ };
626
+
627
+ return processing[operation] || '// Process ISV result as needed';
628
+ }
629
+
630
+ getISVResultProcessingSection(operation) {
631
+ const processing = {
632
+ create_product: `// Log ISV operation for audit
633
+ console.log('ISV Product Creation completed - check merchant dashboard');`,
634
+
635
+ bulk_create_products: `// Generate ISV report
636
+ console.log('Bulk creation completed - generating ISV summary report');`,
637
+
638
+ sync_products: `// Update ISV sync status
639
+ console.log('Product synchronization completed - updating ISV tracking');`
640
+ };
641
+
642
+ return processing[operation] || '// Log ISV operation completion';
643
+ }
644
+ }
645
+
646
+ /**
647
+ * Export all generators
648
+ */
649
+ export const ISVProductGenerators = {
650
+ python: PythonISVProductGenerator,
651
+ nodejs: NodeJSISVProductGenerator,
652
+ javascript: NodeJSISVProductGenerator
653
+ };
654
+
655
+ /**
656
+ * Generate ISV product example
657
+ */
658
+ export function generateISVProductExample(operation, language = 'python', options = {}) {
659
+ const GeneratorClass = ISVProductGenerators[language];
660
+ if (!GeneratorClass) {
661
+ throw new Error(`Unsupported language: ${language}`);
662
+ }
663
+
664
+ const generator = new GeneratorClass();
665
+ return generator.generateExample(operation, 'isv', options);
666
+ }