@payware/mcp-server 1.1.0 → 1.2.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 +0 -0
- package/MCP-SETUP.md +0 -0
- package/README.md +56 -17
- package/check-keys.js +0 -0
- package/keys/README.md +0 -0
- package/mcp-config.json +0 -0
- package/package.json +1 -1
- package/payware-mcp-config.json +0 -0
- package/src/auth/rsa-keys.js +0 -0
- package/src/auth/sandbox-setup.js +2 -2
- package/src/config/env.js +0 -0
- package/src/config/partner-types.js +0 -0
- package/src/core/auth/jwt-factory.js +4 -4
- package/src/core/auth/jwt-token.js +107 -66
- package/src/core/utils/json-serializer.js +5 -5
- package/src/core/utils/key-utils.js +0 -0
- package/src/index.js +0 -0
- package/src/isv/data/index.js +0 -0
- package/src/isv/deep-links/delete-product-link.js +0 -0
- package/src/isv/deep-links/delete-transaction-link.js +0 -0
- package/src/isv/deep-links/get-product-link.js +0 -0
- package/src/isv/deep-links/get-transaction-link.js +0 -0
- package/src/isv/deep-links/index.js +0 -0
- package/src/isv/index.js +0 -0
- package/src/isv/oauth2/create-token-simple.js +0 -0
- package/src/isv/oauth2/get-token-info.js +0 -0
- package/src/isv/oauth2/obtain-token.js +0 -0
- package/src/isv/oauth2/token-helper.js +0 -0
- package/src/isv/poi/cancel-price.js +0 -0
- package/src/isv/poi/get-poi.js +0 -0
- package/src/isv/poi/get-qrcode.js +0 -0
- package/src/isv/poi/get-status.js +0 -0
- package/src/isv/poi/index.js +0 -0
- package/src/isv/poi/list-pois.js +0 -0
- package/src/isv/poi/set-price.js +0 -0
- package/src/isv/products/audios.js +0 -0
- package/src/isv/products/create-product.js +0 -0
- package/src/isv/products/delete-product.js +0 -0
- package/src/isv/products/get-product-image.js +0 -0
- package/src/isv/products/get-product.js +0 -0
- package/src/isv/products/index.js +0 -0
- package/src/isv/products/list-products.js +0 -0
- package/src/isv/products/schedules.js +0 -0
- package/src/isv/products/update-product.js +0 -0
- package/src/isv/transactions/cancel-transaction.js +2 -2
- package/src/isv/transactions/create-transaction.js +2 -2
- package/src/isv/transactions/get-status.js +0 -0
- package/src/isv/transactions/process-transaction.js +2 -2
- package/src/isv/transactions/simulate-callback.js +2 -2
- package/src/isv/transactions/transaction-history.js +0 -0
- package/src/isv/utils/auth.js +2 -2
- package/src/mcp-proxy.js +0 -0
- package/src/merchant/data/export-report.js +0 -0
- package/src/merchant/data/generate-report.js +0 -0
- package/src/merchant/data/get-export-list.js +0 -0
- package/src/merchant/data/get-report-requests.js +0 -0
- package/src/merchant/data/get-report-status.js +0 -0
- package/src/merchant/data/index.js +0 -0
- package/src/merchant/data/list-reports.js +0 -0
- package/src/merchant/deep-links/delete-product-link.js +0 -0
- package/src/merchant/deep-links/delete-transaction-link.js +0 -0
- package/src/merchant/deep-links/get-product-link.js +0 -0
- package/src/merchant/deep-links/get-transaction-link.js +0 -0
- package/src/merchant/deep-links/index.js +0 -0
- package/src/merchant/index.js +0 -0
- package/src/merchant/products/audios.js +0 -0
- package/src/merchant/products/create-product.js +0 -0
- package/src/merchant/products/delete-product.js +0 -0
- package/src/merchant/products/get-product-image.js +0 -0
- package/src/merchant/products/get-product.js +0 -0
- package/src/merchant/products/index.js +0 -0
- package/src/merchant/products/list-products.js +0 -0
- package/src/merchant/products/schedules.js +0 -0
- package/src/merchant/products/update-product.js +0 -0
- package/src/merchant/transactions/cancel-transaction.js +6 -6
- package/src/merchant/transactions/create-transaction.js +13 -13
- package/src/merchant/transactions/get-status.js +1 -1
- package/src/merchant/transactions/process-transaction.js +6 -6
- package/src/merchant/transactions/simulate-callback.js +0 -0
- package/src/merchant/transactions/transaction-history.js +1 -1
- package/src/payment-institution/data/index.js +0 -0
- package/src/payment-institution/deep-links/delete-transaction-link.js +0 -0
- package/src/payment-institution/deep-links/get-transaction-link.js +0 -0
- package/src/payment-institution/deep-links/index.js +0 -0
- package/src/payment-institution/index.js +0 -0
- package/src/payment-institution/transactions/create-pi-transaction.js +4 -4
- package/src/payment-institution/transactions/finalize-transaction.js +3 -3
- package/src/payment-institution/transactions/get-transaction-history.js +1 -1
- package/src/payment-institution/transactions/get-transaction-status.js +1 -1
- package/src/payment-institution/transactions/process-pi-transaction.js +3 -3
- package/src/payment-institution/transactions/simulate-pi-callback.js +0 -0
- package/src/payment-institution/transactions/soundbite-transaction.js +3 -3
- package/src/proxy-server.js +0 -0
- package/src/shared/data/data-api.js +0 -0
- package/src/shared/deep-links/api.js +0 -0
- package/src/shared/index.js +0 -0
- package/src/shared/products/products-api.js +0 -0
- package/src/tools/advanced-code-generator.js +53 -53
- package/src/utils/code-examples/common/auth-examples.js +38 -38
- package/src/utils/code-examples/common/helpers.js +0 -0
- package/src/utils/code-examples/common/utils-examples.js +0 -0
- package/src/utils/code-examples/frameworks/examples.js +4 -4
- package/src/utils/code-examples/index.js +0 -0
- package/src/utils/code-examples/isv/oauth2.js +0 -0
- package/src/utils/code-examples/isv/products.js +8 -8
- package/src/utils/code-examples/isv/transactions.js +9 -9
- package/src/utils/code-examples/merchant/products.js +0 -0
- package/src/utils/code-examples/merchant/transactions.js +9 -9
- package/src/utils/code-examples/payment-institution/transactions.js +0 -0
- package/src/utils/code-examples/shared/data.js +0 -0
- package/src/utils/code-examples/shared/deep-links.js +0 -0
- package/src/utils/code-examples/shared/soundbites.js +0 -0
- package/src/utils/code-examples.js +24 -24
- package/src/utils/format-request.js +3 -3
- package/src/utils/json-formatter.js +20 -20
- package/src/utils/server-info.js +0 -0
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Features:
|
|
10
10
|
* - Framework-specific code generation with proper patterns
|
|
11
|
-
* - JWT authentication with
|
|
11
|
+
* - JWT authentication with contentSha256 (SHA-256) for all languages
|
|
12
12
|
* - Production-ready error handling and validation
|
|
13
13
|
* - Comprehensive documentation generation
|
|
14
14
|
* - Multi-partner type support with operation-specific logic
|
|
@@ -362,8 +362,8 @@ def ${operation.replace('-', '_')}_example(${needsId ? "resource_id='example_123
|
|
|
362
362
|
${opDef.sampleBody ? `${includeComments ? '# Request payload' : ''}
|
|
363
363
|
payload = ${JSON.stringify(opDef.sampleBody, null, 4)}
|
|
364
364
|
|
|
365
|
-
${includeComments ? '# CRITICAL: Use deterministic JSON serialization for both
|
|
366
|
-
${includeComments ? '# This prevents
|
|
365
|
+
${includeComments ? '# CRITICAL: Use deterministic JSON serialization for both SHA-256 hash and HTTP body' : ''}
|
|
366
|
+
${includeComments ? '# This prevents ERR_INVALID_CONTENT_HASH authentication errors' : ''}
|
|
367
367
|
${includeComments ? '# Import: from core.utils.json_serializer import create_deterministic_json' : ''}
|
|
368
368
|
json_body = json.dumps(payload, sort_keys=True, separators=(',', ':'))` : `${includeComments ? '# No request body required' : ''}`}
|
|
369
369
|
|
|
@@ -379,7 +379,7 @@ def ${operation.replace('-', '_')}_example(${needsId ? "resource_id='example_123
|
|
|
379
379
|
|
|
380
380
|
${includeErrorHandling ? 'try:' : ''}
|
|
381
381
|
${includeComments ? '# Execute API request' : ''}
|
|
382
|
-
${includeComments && opDef.sampleBody ? '# CRITICAL: Send the EXACT same json_body used for JWT
|
|
382
|
+
${includeComments && opDef.sampleBody ? '# CRITICAL: Send the EXACT same json_body used for JWT contentSha256' : ''}
|
|
383
383
|
response = requests.${opDef.method.toLowerCase()}(
|
|
384
384
|
url,
|
|
385
385
|
headers=headers${opDef.sampleBody ? ',\n data=json_body' : ''}
|
|
@@ -410,7 +410,7 @@ def create_jwt_token(json_body_string=None):
|
|
|
410
410
|
${includeComments ? ' ' : ''}
|
|
411
411
|
${includeComments ? ' CRITICAL: json_body_string must be the exact same string' : ''}
|
|
412
412
|
${includeComments ? ' that will be sent in the HTTP request body to ensure' : ''}
|
|
413
|
-
${includeComments ? '
|
|
413
|
+
${includeComments ? ' SHA-256 hash consistency and prevent ERR_INVALID_CONTENT_HASH errors.' : ''}
|
|
414
414
|
${includeComments ? ' """' : ''}
|
|
415
415
|
${includeComments ? ' import json' : ''}
|
|
416
416
|
${includeComments ? ' import jwt # PyJWT library' : ''}
|
|
@@ -425,11 +425,11 @@ def create_jwt_token(json_body_string=None):
|
|
|
425
425
|
${includeComments ? ' # JWT header' : ''}
|
|
426
426
|
${includeComments ? ' headers = {"alg": "RS256", "typ": "JWT"}' : ''}
|
|
427
427
|
${includeComments ? ' ' : ''}
|
|
428
|
-
${includeComments ? ' # Add
|
|
428
|
+
${includeComments ? ' # Add contentSha256 to header if request body exists' : ''}
|
|
429
429
|
${includeComments ? ' if json_body_string:' : ''}
|
|
430
|
-
${includeComments ? ' # CRITICAL: Calculate
|
|
431
|
-
${includeComments ? '
|
|
432
|
-
${includeComments ? ' headers["
|
|
430
|
+
${includeComments ? ' # CRITICAL: Calculate SHA-256 from exact same string sent in HTTP request' : ''}
|
|
431
|
+
${includeComments ? ' sha256_hash = hashlib.sha256(json_body_string.encode("utf-8")).digest()' : ''}
|
|
432
|
+
${includeComments ? ' headers["contentSha256"] = base64.b64encode(sha256_hash).decode("ascii")' : ''}
|
|
433
433
|
${includeComments ? ' ' : ''}
|
|
434
434
|
${includeComments ? ' # JWT payload' : ''}
|
|
435
435
|
${includeComments ? ' payload = {' : ''}
|
|
@@ -481,8 +481,8 @@ async function ${operation.replace('-', '_')}Example(${needsId ? "resourceId = '
|
|
|
481
481
|
${opDef.sampleBody ? `${includeComments ? '// Request payload' : ''}
|
|
482
482
|
const payload = ${JSON.stringify(opDef.sampleBody, null, 4)};
|
|
483
483
|
|
|
484
|
-
${includeComments ? '// CRITICAL: Use deterministic JSON serialization for both
|
|
485
|
-
${includeComments ? '// This prevents
|
|
484
|
+
${includeComments ? '// CRITICAL: Use deterministic JSON serialization for both SHA-256 and HTTP body' : ''}
|
|
485
|
+
${includeComments ? '// This prevents ERR_INVALID_CONTENT_HASH authentication errors' : ''}
|
|
486
486
|
${includeComments ? '// Import: const { createDeterministicJSON } = require(\'./core/utils/json-serializer\');' : ''}
|
|
487
487
|
const jsonBody = JSON.stringify(payload, Object.keys(payload).sort());` : `${includeComments ? '// No request body required' : ''}`}
|
|
488
488
|
|
|
@@ -498,7 +498,7 @@ async function ${operation.replace('-', '_')}Example(${needsId ? "resourceId = '
|
|
|
498
498
|
|
|
499
499
|
${includeErrorHandling ? 'try {' : ''}
|
|
500
500
|
${includeComments ? '// Execute API request' : ''}
|
|
501
|
-
${includeComments && opDef.sampleBody ? '// CRITICAL: Send same jsonBody used for JWT
|
|
501
|
+
${includeComments && opDef.sampleBody ? '// CRITICAL: Send same jsonBody used for JWT contentSha256' : ''}
|
|
502
502
|
const response = await axios.${opDef.method.toLowerCase()}(
|
|
503
503
|
url,
|
|
504
504
|
${opDef.sampleBody ? 'jsonBody,' : 'undefined,'}
|
|
@@ -528,7 +528,7 @@ function createJWTToken(jsonBodyString = null) {
|
|
|
528
528
|
${includeComments ? ' * ' : ''}
|
|
529
529
|
${includeComments ? ' * CRITICAL: jsonBodyString must be the exact same string' : ''}
|
|
530
530
|
${includeComments ? ' * that will be sent in the HTTP request body to ensure' : ''}
|
|
531
|
-
${includeComments ? ' *
|
|
531
|
+
${includeComments ? ' * SHA-256 hash consistency and prevent ERR_INVALID_CONTENT_HASH errors.' : ''}
|
|
532
532
|
${includeComments ? ' */' : ''}
|
|
533
533
|
${includeComments ? ' const jwt = require("jsonwebtoken");' : ''}
|
|
534
534
|
${includeComments ? ' const crypto = require("crypto");' : ''}
|
|
@@ -540,11 +540,11 @@ function createJWTToken(jsonBodyString = null) {
|
|
|
540
540
|
${includeComments ? ' // JWT header' : ''}
|
|
541
541
|
${includeComments ? ' const header = { alg: "RS256", typ: "JWT" };' : ''}
|
|
542
542
|
${includeComments ? ' ' : ''}
|
|
543
|
-
${includeComments ? ' // Add
|
|
543
|
+
${includeComments ? ' // Add contentSha256 to header if request body exists' : ''}
|
|
544
544
|
${includeComments ? ' if (jsonBodyString) {' : ''}
|
|
545
|
-
${includeComments ? ' // CRITICAL: Calculate
|
|
546
|
-
${includeComments ? ' const
|
|
547
|
-
${includeComments ? ' header.
|
|
545
|
+
${includeComments ? ' // CRITICAL: Calculate SHA-256 from exact same string sent in HTTP request' : ''}
|
|
546
|
+
${includeComments ? ' const sha256Hash = crypto.createHash("sha256").update(jsonBodyString, "utf8").digest("base64");' : ''}
|
|
547
|
+
${includeComments ? ' header.contentSha256 = sha256Hash;' : ''}
|
|
548
548
|
${includeComments ? ' }' : ''}
|
|
549
549
|
${includeComments ? ' ' : ''}
|
|
550
550
|
${includeComments ? ' // JWT payload' : ''}
|
|
@@ -792,8 +792,8 @@ class PaywareClient
|
|
|
792
792
|
${opDef.sampleBody ? `${includeComments ? '// Request payload' : ''}
|
|
793
793
|
$payload = ${this.generatePHPArray(opDef.sampleBody, ' ')};
|
|
794
794
|
|
|
795
|
-
${includeComments ? '// CRITICAL: Use deterministic JSON serialization for both
|
|
796
|
-
${includeComments ? '// This prevents
|
|
795
|
+
${includeComments ? '// CRITICAL: Use deterministic JSON serialization for both SHA-256 and HTTP body' : ''}
|
|
796
|
+
${includeComments ? '// This prevents ERR_INVALID_CONTENT_HASH authentication errors' : ''}
|
|
797
797
|
${includeComments ? '// Note: Implement createDeterministicJSON() function with ksort()' : ''}
|
|
798
798
|
ksort($payload);
|
|
799
799
|
$requestBody = json_encode($payload, JSON_UNESCAPED_SLASHES);` : `${includeComments ? '// No request body required' : ''}`}
|
|
@@ -823,7 +823,7 @@ class PaywareClient
|
|
|
823
823
|
CURLOPT_SSL_VERIFYHOST => 2
|
|
824
824
|
]);
|
|
825
825
|
|
|
826
|
-
${opDef.sampleBody ? `${includeComments ? '// CRITICAL: Send same requestBody used for JWT
|
|
826
|
+
${opDef.sampleBody ? `${includeComments ? '// CRITICAL: Send same requestBody used for JWT contentSha256' : ''}
|
|
827
827
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);` : ''}
|
|
828
828
|
|
|
829
829
|
${includeComments ? '// Execute request' : ''}
|
|
@@ -864,7 +864,7 @@ class PaywareClient
|
|
|
864
864
|
|
|
865
865
|
/**
|
|
866
866
|
* Create JWT token for payware API authentication
|
|
867
|
-
* @param string|null $requestBody Request body for content
|
|
867
|
+
* @param string|null $requestBody Request body for content SHA-256
|
|
868
868
|
* @return string JWT token
|
|
869
869
|
*/
|
|
870
870
|
private function createJWTToken($requestBody = null)
|
|
@@ -872,16 +872,16 @@ class PaywareClient
|
|
|
872
872
|
${includeComments ? '/**' : '/*'}
|
|
873
873
|
${includeComments ? ' * CRITICAL: requestBody must be the exact same string' : ''}
|
|
874
874
|
${includeComments ? ' * that will be sent in the HTTP request body to ensure' : ''}
|
|
875
|
-
${includeComments ? ' *
|
|
875
|
+
${includeComments ? ' * SHA-256 hash consistency and prevent ERR_INVALID_CONTENT_HASH errors.' : ''}
|
|
876
876
|
${includeComments ? ' */' : '*/'}
|
|
877
877
|
|
|
878
878
|
${includeComments ? '// JWT header' : ''}
|
|
879
879
|
$header = ['alg' => 'RS256', 'typ' => 'JWT'];
|
|
880
880
|
|
|
881
|
-
${includeComments ? '// Add
|
|
881
|
+
${includeComments ? '// Add contentSha256 to header if request body exists' : ''}
|
|
882
882
|
if ($requestBody !== null) {
|
|
883
|
-
${includeComments ? '// CRITICAL: Calculate
|
|
884
|
-
$header['
|
|
883
|
+
${includeComments ? '// CRITICAL: Calculate SHA-256 from exact same string sent in HTTP request' : ''}
|
|
884
|
+
$header['contentSha256'] = base64_encode(hash('sha256', $requestBody, true));
|
|
885
885
|
}
|
|
886
886
|
|
|
887
887
|
${includeComments ? '// JWT payload' : ''}
|
|
@@ -1411,8 +1411,8 @@ EOF` : '# No request body required'}
|
|
|
1411
1411
|
# Authentication (placeholder - implement JWT token creation)
|
|
1412
1412
|
JWT_TOKEN="your-jwt-token"
|
|
1413
1413
|
|
|
1414
|
-
# Content-
|
|
1415
|
-
${opDef.sampleBody ? `
|
|
1414
|
+
# Content-SHA256 for payware API (if request body exists)
|
|
1415
|
+
${opDef.sampleBody ? `CONTENT_SHA256=$(echo -n "$REQUEST_BODY" | openssl dgst -sha256 -binary | base64)` : ''}
|
|
1416
1416
|
|
|
1417
1417
|
echo "🚀 Executing ${opDef.description}..."
|
|
1418
1418
|
echo "URL: $URL"
|
|
@@ -1423,7 +1423,7 @@ curl -X ${opDef.method} "$URL" \\
|
|
|
1423
1423
|
-H "Authorization: Bearer $JWT_TOKEN" \\
|
|
1424
1424
|
-H "Content-Type: application/json" \\
|
|
1425
1425
|
-H "Api-Version: 1" \\
|
|
1426
|
-
${opDef.sampleBody ? '-H "Content-
|
|
1426
|
+
${opDef.sampleBody ? '-H "Content-SHA256: $CONTENT_SHA256" \\' : ''}
|
|
1427
1427
|
${includeErrorHandling ? '-f -s -S \\' : '-v \\'}
|
|
1428
1428
|
${opDef.sampleBody ? '-d "$REQUEST_BODY"' : ''}` : `
|
|
1429
1429
|
curl -X ${opDef.method} "$URL" \\
|
|
@@ -1465,10 +1465,10 @@ def create_jwt_token(request_body=None):
|
|
|
1465
1465
|
YOUR_PRIVATE_KEY_HERE
|
|
1466
1466
|
-----END RSA PRIVATE KEY-----"""
|
|
1467
1467
|
|
|
1468
|
-
# Create content
|
|
1469
|
-
|
|
1468
|
+
# Create content SHA-256 for request body
|
|
1469
|
+
content_sha256 = ""
|
|
1470
1470
|
if request_body:
|
|
1471
|
-
|
|
1471
|
+
content_sha256 = base64.b64encode(hashlib.sha256(request_body.encode()).digest()).decode()
|
|
1472
1472
|
|
|
1473
1473
|
# JWT payload
|
|
1474
1474
|
payload = {
|
|
@@ -1476,7 +1476,7 @@ YOUR_PRIVATE_KEY_HERE
|
|
|
1476
1476
|
"aud": "payware.eu",
|
|
1477
1477
|
"iat": int(datetime.now(timezone.utc).timestamp()),
|
|
1478
1478
|
"exp": int(datetime.now(timezone.utc).timestamp()) + 300,
|
|
1479
|
-
"
|
|
1479
|
+
"contentSha256": content_sha256
|
|
1480
1480
|
}
|
|
1481
1481
|
|
|
1482
1482
|
# Create JWT token
|
|
@@ -1500,10 +1500,10 @@ function createJWTToken(requestBody = null) {
|
|
|
1500
1500
|
YOUR_PRIVATE_KEY_HERE
|
|
1501
1501
|
-----END RSA PRIVATE KEY-----\`;
|
|
1502
1502
|
|
|
1503
|
-
${includeComments ? '// Create content
|
|
1504
|
-
let
|
|
1503
|
+
${includeComments ? '// Create content SHA-256' : ''} for request body
|
|
1504
|
+
let contentSha256 = "";
|
|
1505
1505
|
if (requestBody) {
|
|
1506
|
-
|
|
1506
|
+
contentSha256 = crypto.createHash('sha256').update(requestBody).digest('base64');
|
|
1507
1507
|
}
|
|
1508
1508
|
|
|
1509
1509
|
// JWT payload
|
|
@@ -1512,7 +1512,7 @@ YOUR_PRIVATE_KEY_HERE
|
|
|
1512
1512
|
aud: "payware.eu",
|
|
1513
1513
|
iat: Math.floor(Date.now() / 1000),
|
|
1514
1514
|
exp: Math.floor(Date.now() / 1000) + 300,
|
|
1515
|
-
|
|
1515
|
+
contentSha256: contentSha256
|
|
1516
1516
|
};
|
|
1517
1517
|
|
|
1518
1518
|
// Create JWT token
|
|
@@ -1543,12 +1543,12 @@ public class PaywareAuth {
|
|
|
1543
1543
|
String partnerId = "YOUR_PARTNER_ID";
|
|
1544
1544
|
String privateKeyPEM = "-----BEGIN RSA PRIVATE KEY-----\\nYOUR_PRIVATE_KEY_HERE\\n-----END RSA PRIVATE KEY-----";
|
|
1545
1545
|
|
|
1546
|
-
${includeComments ? '// Create content
|
|
1547
|
-
String
|
|
1546
|
+
${includeComments ? '// Create content SHA-256' : ''}
|
|
1547
|
+
String contentSha256 = "";
|
|
1548
1548
|
if (requestBody != null) {
|
|
1549
|
-
MessageDigest md = MessageDigest.getInstance("
|
|
1549
|
+
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
1550
1550
|
byte[] digest = md.digest(requestBody.getBytes());
|
|
1551
|
-
|
|
1551
|
+
contentSha256 = Base64.getEncoder().encodeToString(digest);
|
|
1552
1552
|
}
|
|
1553
1553
|
|
|
1554
1554
|
// JWT payload
|
|
@@ -1557,7 +1557,7 @@ public class PaywareAuth {
|
|
|
1557
1557
|
claims.put("aud", "payware.eu");
|
|
1558
1558
|
claims.put("iat", new Date().getTime() / 1000);
|
|
1559
1559
|
claims.put("exp", (new Date().getTime() / 1000) + 300);
|
|
1560
|
-
claims.put("
|
|
1560
|
+
claims.put("contentSha256", contentSha256);
|
|
1561
1561
|
|
|
1562
1562
|
// Note: You'll need to implement private key loading
|
|
1563
1563
|
// PrivateKey privateKey = loadPrivateKey(privateKeyPEM);
|
|
@@ -1592,14 +1592,14 @@ public class PaywareAuth
|
|
|
1592
1592
|
YOUR_PRIVATE_KEY_HERE
|
|
1593
1593
|
-----END RSA PRIVATE KEY-----";
|
|
1594
1594
|
|
|
1595
|
-
${includeComments ? '// Create content
|
|
1596
|
-
var
|
|
1595
|
+
${includeComments ? '// Create content SHA-256' : ''}
|
|
1596
|
+
var contentSha256 = "";
|
|
1597
1597
|
if (!string.IsNullOrEmpty(requestBody))
|
|
1598
1598
|
{
|
|
1599
|
-
using (var
|
|
1599
|
+
using (var sha256 = SHA256.Create())
|
|
1600
1600
|
{
|
|
1601
|
-
var hash =
|
|
1602
|
-
|
|
1601
|
+
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(requestBody));
|
|
1602
|
+
contentSha256 = Convert.ToBase64String(hash);
|
|
1603
1603
|
}
|
|
1604
1604
|
}
|
|
1605
1605
|
|
|
@@ -1610,7 +1610,7 @@ YOUR_PRIVATE_KEY_HERE
|
|
|
1610
1610
|
new Claim("aud", "payware.eu"),
|
|
1611
1611
|
new Claim("iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer),
|
|
1612
1612
|
new Claim("exp", DateTimeOffset.UtcNow.AddMinutes(5).ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer),
|
|
1613
|
-
new Claim("
|
|
1613
|
+
new Claim("contentSha256", contentSha256)
|
|
1614
1614
|
};
|
|
1615
1615
|
|
|
1616
1616
|
// Note: You'll need to implement RSA key loading
|
|
@@ -1639,10 +1639,10 @@ function createJWTToken($requestBody = null) {
|
|
|
1639
1639
|
YOUR_PRIVATE_KEY_HERE
|
|
1640
1640
|
-----END RSA PRIVATE KEY-----";
|
|
1641
1641
|
|
|
1642
|
-
${includeComments ? '// Create content
|
|
1643
|
-
$
|
|
1642
|
+
${includeComments ? '// Create content SHA-256' : ''}
|
|
1643
|
+
$contentSha256 = "";
|
|
1644
1644
|
if ($requestBody !== null) {
|
|
1645
|
-
$
|
|
1645
|
+
$contentSha256 = base64_encode(hash('sha256', $requestBody, true));
|
|
1646
1646
|
}
|
|
1647
1647
|
|
|
1648
1648
|
// JWT payload
|
|
@@ -1651,7 +1651,7 @@ YOUR_PRIVATE_KEY_HERE
|
|
|
1651
1651
|
'aud' => 'payware.eu',
|
|
1652
1652
|
'iat' => time(),
|
|
1653
1653
|
'exp' => time() + 300,
|
|
1654
|
-
'
|
|
1654
|
+
'contentSha256' => $contentSha256
|
|
1655
1655
|
];
|
|
1656
1656
|
|
|
1657
1657
|
// Create JWT token
|
|
@@ -1673,10 +1673,10 @@ PRIVATE_KEY_FILE="path/to/private-key.pem"
|
|
|
1673
1673
|
# Function to create JWT token (simplified)
|
|
1674
1674
|
create_jwt_token() {
|
|
1675
1675
|
local request_body="\$1"
|
|
1676
|
-
local
|
|
1676
|
+
local content_sha256=""
|
|
1677
1677
|
|
|
1678
1678
|
if [ -n "\$request_body" ]; then
|
|
1679
|
-
|
|
1679
|
+
content_sha256=\$(echo -n "\$request_body" | openssl dgst -sha256 -binary | base64)
|
|
1680
1680
|
fi
|
|
1681
1681
|
|
|
1682
1682
|
echo "your-jwt-token" # Placeholder - implement JWT creation with openssl
|
|
@@ -57,13 +57,13 @@ from cryptography.hazmat.primitives import serialization`;
|
|
|
57
57
|
'typ': 'JWT'
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
${options.includeComments ? '# Add content
|
|
60
|
+
${options.includeComments ? '# Add content SHA-256 for requests with body\n ' : ''}body_string = None
|
|
61
61
|
if request_body:
|
|
62
62
|
body_string = create_minimized_json(request_body)
|
|
63
|
-
|
|
64
|
-
hashlib.
|
|
63
|
+
content_sha256 = base64.b64encode(
|
|
64
|
+
hashlib.sha256(body_string.encode('utf-8')).digest()
|
|
65
65
|
).decode('utf-8')
|
|
66
|
-
header['
|
|
66
|
+
header['contentSha256'] = content_sha256
|
|
67
67
|
|
|
68
68
|
${options.includeComments ? '# Create JWT payload\n ' : ''}payload = {
|
|
69
69
|
'iss': partner_id,
|
|
@@ -75,7 +75,7 @@ from cryptography.hazmat.primitives import serialization`;
|
|
|
75
75
|
return token, body_string
|
|
76
76
|
|
|
77
77
|
def create_minimized_json(data):
|
|
78
|
-
${options.includeComments ? '"""Create deterministic minimized JSON for
|
|
78
|
+
${options.includeComments ? '"""Create deterministic minimized JSON for SHA-256 calculation"""\n ' : ''}def sort_dict(obj):
|
|
79
79
|
if isinstance(obj, dict):
|
|
80
80
|
return {k: sort_dict(v) for k, v in sorted(obj.items())}
|
|
81
81
|
elif isinstance(obj, list):
|
|
@@ -172,14 +172,14 @@ require('dotenv').config();`;
|
|
|
172
172
|
typ: 'JWT'
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
${options.includeComments ? '// Add content
|
|
175
|
+
${options.includeComments ? '// Add content SHA-256 for requests with body\n ' : ''}let bodyString = null;
|
|
176
176
|
if (requestBody) {
|
|
177
177
|
bodyString = createMinimizedJSON(requestBody);
|
|
178
|
-
const
|
|
179
|
-
.createHash('
|
|
178
|
+
const contentSha256 = crypto
|
|
179
|
+
.createHash('sha256')
|
|
180
180
|
.update(bodyString, 'utf8')
|
|
181
181
|
.digest('base64');
|
|
182
|
-
header.
|
|
182
|
+
header.contentSha256 = contentSha256;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
${options.includeComments ? '// Create JWT payload\n ' : ''}const payload = {
|
|
@@ -314,11 +314,11 @@ class PaywareAuth {
|
|
|
314
314
|
'typ' => 'JWT'
|
|
315
315
|
];
|
|
316
316
|
|
|
317
|
-
${options.includeComments ? '// Add content
|
|
317
|
+
${options.includeComments ? '// Add content SHA-256 for requests with body\n ' : ''}$bodyString = null;
|
|
318
318
|
if ($requestBody) {
|
|
319
319
|
$bodyString = self::createMinimizedJSON($requestBody);
|
|
320
|
-
$
|
|
321
|
-
$header['
|
|
320
|
+
$contentSha256 = base64_encode(hash('sha256', $bodyString, true));
|
|
321
|
+
$header['contentSha256'] = $contentSha256;
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
${options.includeComments ? '// Create JWT payload\n ' : ''}$payload = [
|
|
@@ -438,11 +438,11 @@ import java.security.MessageDigest;`;
|
|
|
438
438
|
header.put("alg", "RS256");
|
|
439
439
|
header.put("typ", "JWT");
|
|
440
440
|
|
|
441
|
-
${options.includeComments ? '// Handle request body and
|
|
441
|
+
${options.includeComments ? '// Handle request body and SHA-256\n ' : ''}String bodyString = null;
|
|
442
442
|
if (requestBody != null) {
|
|
443
443
|
bodyString = createMinimizedJSON(requestBody);
|
|
444
|
-
String
|
|
445
|
-
header.put("
|
|
444
|
+
String contentSha256 = calculateSHA256(bodyString);
|
|
445
|
+
header.put("contentSha256", contentSha256);
|
|
446
446
|
}
|
|
447
447
|
|
|
448
448
|
${options.includeComments ? '// Create JWT payload\n ' : ''}Map<String, Object> payload = new HashMap<>();
|
|
@@ -498,8 +498,8 @@ import java.security.MessageDigest;`;
|
|
|
498
498
|
return node;
|
|
499
499
|
}
|
|
500
500
|
|
|
501
|
-
private String
|
|
502
|
-
MessageDigest md = MessageDigest.getInstance("
|
|
501
|
+
private String calculateSHA256(String input) throws Exception {
|
|
502
|
+
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
503
503
|
byte[] digest = md.digest(input.getBytes("UTF-8"));
|
|
504
504
|
return Base64.getEncoder().encodeToString(digest);
|
|
505
505
|
}
|
|
@@ -655,13 +655,13 @@ using Microsoft.Extensions.Configuration;`;
|
|
|
655
655
|
["typ"] = "JWT"
|
|
656
656
|
};
|
|
657
657
|
|
|
658
|
-
// Handle request body and
|
|
658
|
+
// Handle request body and SHA-256
|
|
659
659
|
string bodyString = null;
|
|
660
660
|
if (requestBody != null)
|
|
661
661
|
{
|
|
662
662
|
bodyString = CreateMinimizedJSON(requestBody);
|
|
663
|
-
var
|
|
664
|
-
header["
|
|
663
|
+
var contentSha256 = CalculateSHA256(bodyString);
|
|
664
|
+
header["contentSha256"] = contentSha256;
|
|
665
665
|
}
|
|
666
666
|
|
|
667
667
|
// Create JWT payload
|
|
@@ -737,11 +737,11 @@ using Microsoft.Extensions.Configuration;`;
|
|
|
737
737
|
return token;
|
|
738
738
|
}
|
|
739
739
|
|
|
740
|
-
private string
|
|
740
|
+
private string CalculateSHA256(string input)
|
|
741
741
|
{
|
|
742
|
-
using var
|
|
742
|
+
using var sha256 = SHA256.Create();
|
|
743
743
|
var inputBytes = Encoding.UTF8.GetBytes(input);
|
|
744
|
-
var hashBytes =
|
|
744
|
+
var hashBytes = sha256.ComputeHash(inputBytes);
|
|
745
745
|
return Convert.ToBase64String(hashBytes);
|
|
746
746
|
}
|
|
747
747
|
|
|
@@ -857,7 +857,7 @@ func init() {
|
|
|
857
857
|
package main
|
|
858
858
|
|
|
859
859
|
import (
|
|
860
|
-
"crypto/
|
|
860
|
+
"crypto/sha256"
|
|
861
861
|
"crypto/rsa"
|
|
862
862
|
"crypto/x509"
|
|
863
863
|
"encoding/base64"
|
|
@@ -927,7 +927,7 @@ func (p *PaywareAuthenticator) CreateJWTToken(requestBody interface{}, useSandbo
|
|
|
927
927
|
"typ": "JWT",
|
|
928
928
|
}
|
|
929
929
|
|
|
930
|
-
// Handle request body and
|
|
930
|
+
// Handle request body and SHA-256
|
|
931
931
|
var bodyString string
|
|
932
932
|
if requestBody != nil {
|
|
933
933
|
bodyString, err = p.createMinimizedJSON(requestBody)
|
|
@@ -935,11 +935,11 @@ func (p *PaywareAuthenticator) CreateJWTToken(requestBody interface{}, useSandbo
|
|
|
935
935
|
return nil, fmt.Errorf("failed to create minimized JSON: %w", err)
|
|
936
936
|
}
|
|
937
937
|
|
|
938
|
-
|
|
938
|
+
contentSha256, err := p.calculateSHA256(bodyString)
|
|
939
939
|
if err != nil {
|
|
940
|
-
return nil, fmt.Errorf("failed to calculate
|
|
940
|
+
return nil, fmt.Errorf("failed to calculate SHA-256: %w", err)
|
|
941
941
|
}
|
|
942
|
-
header["
|
|
942
|
+
header["contentSha256"] = contentSha256
|
|
943
943
|
}
|
|
944
944
|
|
|
945
945
|
// Create JWT claims
|
|
@@ -1027,8 +1027,8 @@ func (p *PaywareAuthenticator) sortObjectKeys(data interface{}) interface{} {
|
|
|
1027
1027
|
}
|
|
1028
1028
|
}
|
|
1029
1029
|
|
|
1030
|
-
func (p *PaywareAuthenticator)
|
|
1031
|
-
hash :=
|
|
1030
|
+
func (p *PaywareAuthenticator) calculateSHA256(input string) (string, error) {
|
|
1031
|
+
hash := sha256.Sum256([]byte(input))
|
|
1032
1032
|
return base64.StdEncoding.EncodeToString(hash[:]), nil
|
|
1033
1033
|
}
|
|
1034
1034
|
|
|
@@ -1165,12 +1165,12 @@ require 'dotenv/load'`;
|
|
|
1165
1165
|
typ: 'JWT'
|
|
1166
1166
|
}
|
|
1167
1167
|
|
|
1168
|
-
# Handle request body and
|
|
1168
|
+
# Handle request body and SHA-256
|
|
1169
1169
|
body_string = nil
|
|
1170
1170
|
if request_body
|
|
1171
1171
|
body_string = create_minimized_json(request_body)
|
|
1172
|
-
|
|
1173
|
-
header[:
|
|
1172
|
+
content_sha256 = calculate_sha256(body_string)
|
|
1173
|
+
header[:contentSha256] = content_sha256
|
|
1174
1174
|
end
|
|
1175
1175
|
|
|
1176
1176
|
# Create JWT payload
|
|
@@ -1219,8 +1219,8 @@ require 'dotenv/load'`;
|
|
|
1219
1219
|
end
|
|
1220
1220
|
end
|
|
1221
1221
|
|
|
1222
|
-
def
|
|
1223
|
-
digest = Digest::
|
|
1222
|
+
def calculate_sha256(input)
|
|
1223
|
+
digest = Digest::SHA256.digest(input)
|
|
1224
1224
|
Base64.encode64(digest).strip
|
|
1225
1225
|
end
|
|
1226
1226
|
|
|
@@ -1330,12 +1330,12 @@ create_jwt_token() {
|
|
|
1330
1330
|
# Create JWT header
|
|
1331
1331
|
local header='{"alg":"RS256","typ":"JWT"}'
|
|
1332
1332
|
|
|
1333
|
-
# Handle request body and
|
|
1333
|
+
# Handle request body and SHA-256
|
|
1334
1334
|
local body_string=""
|
|
1335
1335
|
if [ -n "$request_body" ]; then
|
|
1336
1336
|
body_string=$(echo "$request_body" | jq -S -c .)
|
|
1337
|
-
local
|
|
1338
|
-
header=$(echo "$header" | jq --arg
|
|
1337
|
+
local content_sha256=$(echo -n "$body_string" | openssl dgst -sha256 -binary | base64)
|
|
1338
|
+
header=$(echo "$header" | jq --arg sha256 "$content_sha256" '. + {contentSha256: $sha256}')
|
|
1339
1339
|
fi
|
|
1340
1340
|
|
|
1341
1341
|
# Create JWT payload
|
|
File without changes
|
|
File without changes
|
|
@@ -722,12 +722,12 @@ class PaywareService
|
|
|
722
722
|
'typ' => 'JWT'
|
|
723
723
|
];
|
|
724
724
|
|
|
725
|
-
// Add content
|
|
725
|
+
// Add content SHA-256 for requests with body
|
|
726
726
|
$bodyString = null;
|
|
727
727
|
if ($requestBody) {
|
|
728
728
|
$bodyString = $this->createMinimizedJSON($requestBody);
|
|
729
|
-
$
|
|
730
|
-
$header['
|
|
729
|
+
$contentSha256 = base64_encode(hash('sha256', $bodyString, true));
|
|
730
|
+
$header['contentSha256'] = $contentSha256;
|
|
731
731
|
}
|
|
732
732
|
|
|
733
733
|
// Create JWT payload
|
|
@@ -747,7 +747,7 @@ class PaywareService
|
|
|
747
747
|
}
|
|
748
748
|
|
|
749
749
|
/**
|
|
750
|
-
* Create minimized JSON for deterministic
|
|
750
|
+
* Create minimized JSON for deterministic SHA-256
|
|
751
751
|
*/
|
|
752
752
|
protected function createMinimizedJSON($data)
|
|
753
753
|
{
|
|
File without changes
|
|
File without changes
|
|
@@ -281,14 +281,14 @@ def create_isv_jwt_token(merchant_partner_id, oauth2_token, request_body=None, u
|
|
|
281
281
|
'typ': 'JWT'
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
# Add content
|
|
284
|
+
# Add content SHA-256 for requests with body
|
|
285
285
|
body_string = None
|
|
286
286
|
if request_body:
|
|
287
287
|
body_string = create_minimized_json(request_body)
|
|
288
|
-
|
|
289
|
-
hashlib.
|
|
288
|
+
content_sha256 = base64.b64encode(
|
|
289
|
+
hashlib.sha256(body_string.encode('utf-8')).digest()
|
|
290
290
|
).decode('utf-8')
|
|
291
|
-
header['
|
|
291
|
+
header['contentSha256'] = content_sha256
|
|
292
292
|
|
|
293
293
|
# Create JWT payload for ISV
|
|
294
294
|
payload = {
|
|
@@ -507,15 +507,15 @@ function createISVJWTToken(merchantPartnerId, oauth2Token, requestBody = null, u
|
|
|
507
507
|
typ: 'JWT'
|
|
508
508
|
};
|
|
509
509
|
|
|
510
|
-
// Add content
|
|
510
|
+
// Add content SHA-256 for requests with body
|
|
511
511
|
let bodyString = null;
|
|
512
512
|
if (requestBody) {
|
|
513
513
|
bodyString = createMinimizedJSON(requestBody);
|
|
514
|
-
const
|
|
515
|
-
.createHash('
|
|
514
|
+
const contentSha256 = crypto
|
|
515
|
+
.createHash('sha256')
|
|
516
516
|
.update(bodyString, 'utf8')
|
|
517
517
|
.digest('base64');
|
|
518
|
-
header.
|
|
518
|
+
header.contentSha256 = contentSha256;
|
|
519
519
|
}
|
|
520
520
|
|
|
521
521
|
// Create JWT payload for ISV
|
|
@@ -201,14 +201,14 @@ def create_isv_jwt_token(merchant_partner_id, oauth2_token, request_body=None, u
|
|
|
201
201
|
'typ': 'JWT'
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
# Add content
|
|
204
|
+
# Add content SHA-256 for requests with body
|
|
205
205
|
body_string = None
|
|
206
206
|
if request_body:
|
|
207
207
|
body_string = create_minimized_json(request_body)
|
|
208
|
-
|
|
209
|
-
hashlib.
|
|
208
|
+
content_sha256 = base64.b64encode(
|
|
209
|
+
hashlib.sha256(body_string.encode('utf-8')).digest()
|
|
210
210
|
).decode('utf-8')
|
|
211
|
-
header['
|
|
211
|
+
header['contentSha256'] = content_sha256
|
|
212
212
|
|
|
213
213
|
# Create ISV JWT payload with OAuth2 token
|
|
214
214
|
payload = {
|
|
@@ -223,7 +223,7 @@ def create_isv_jwt_token(merchant_partner_id, oauth2_token, request_body=None, u
|
|
|
223
223
|
return token, body_string
|
|
224
224
|
|
|
225
225
|
def create_minimized_json(data):
|
|
226
|
-
"""Create deterministic minimized JSON for
|
|
226
|
+
"""Create deterministic minimized JSON for SHA-256 calculation"""
|
|
227
227
|
def sort_dict(obj):
|
|
228
228
|
if isinstance(obj, dict):
|
|
229
229
|
return {k: sort_dict(v) for k, v in sorted(obj.items())}
|
|
@@ -553,15 +553,15 @@ function createISVJWTToken(merchantPartnerId, oauth2Token, requestBody = null, u
|
|
|
553
553
|
typ: 'JWT'
|
|
554
554
|
};
|
|
555
555
|
|
|
556
|
-
// Add content
|
|
556
|
+
// Add content SHA-256 for requests with body
|
|
557
557
|
let bodyString = null;
|
|
558
558
|
if (requestBody) {
|
|
559
559
|
bodyString = createMinimizedJSON(requestBody);
|
|
560
|
-
const
|
|
561
|
-
.createHash('
|
|
560
|
+
const contentSha256 = crypto
|
|
561
|
+
.createHash('sha256')
|
|
562
562
|
.update(bodyString, 'utf8')
|
|
563
563
|
.digest('base64');
|
|
564
|
-
header.
|
|
564
|
+
header.contentSha256 = contentSha256;
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
// Create ISV JWT payload with OAuth2 token
|
|
File without changes
|