Appearance
Troubleshooting Signature Verification
Common Issue: SIGNATURE_VERIFICATION_FAILED
If you're getting SIGNATURE_VERIFICATION_FAILED error when calling handleRedirectReturn, here are the most common causes and solutions:
1. Check API Secret
Problem: Using the wrong API secret or API key instead of secret.
Solution:
- Ensure you're using the API Secret (starts with
sk_), not the API Key (starts withpk_) - API secrets should be retrieved from your backend server, never stored in frontend code
- Verify the secret matches your environment (sandbox vs live)
javascript
// ❌ WRONG - Using API key
const result = await kore.handleRedirectReturn(urlParams, 'pk_test_xxx');
// ✅ CORRECT - Using API secret
const apiSecret = await fetch('/api/get-secret').then(r => r.text());
const result = await kore.handleRedirectReturn(urlParams, apiSecret);2. Enable Debug Mode (development only)
Use debug mode only when troubleshooting locally. Do not enable in production. Enable debug to see what payload is being generated:
javascript
const kore = new Kore({
apiKey: 'pk_test_xxx',
debug: true // Enable debug logging
});
// Now when you call handleRedirectReturn, you'll see detailed logs
const result = await kore.handleRedirectReturn(urlParams, apiSecret);This will log:
- The parameters being used for signature
- The payload being generated
- The computed signatures (hex and base64)
- The provided signature
3. Verify URL Parameters
Check that all required parameters are present in the URL:
javascript
const urlParams = new URLSearchParams(window.location.search);
// Log all parameters
console.log('URL Parameters:', Object.fromEntries(urlParams));
// Required parameters:
// - order_id
// - status
// - signature
// Optional but may be present:
// - payment_id
// - gateway
// - error_code
// - error_message4. Signature Format
According to the specification, the signature format is:
- HMAC-SHA256 algorithm
- Hexadecimal string (lowercase)
- Case-sensitive comparison
The SDK now implements the exact algorithm from the specification:
- Sort parameter keys alphabetically
- Create canonical string:
key=value&key2=value2(NO URL encoding) - Compute HMAC-SHA256, output as hex lowercase
- Compare signatures (case-sensitive, constant-time)
5. Payload Construction
According to the specification, the payload format is:
- Filter out undefined, null, and empty string values
- Sort parameter keys alphabetically
- Canonicalize:
key=value&key2=value2(NO URL encoding - raw values) - Example:
gateway=checkout&order_id=123&status=captured
Important: The specification explicitly states NO URL encoding should be used in the canonical string. Values are used as-is from the URL parameters.
6. Server-Side Verification (Recommended)
Best Practice: Verify signatures on your backend server instead of client-side.
Backend Endpoint Example
javascript
// Frontend: Send redirect params to backend
const urlParams = new URLSearchParams(window.location.search);
const result = await fetch('/api/verify-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
payment_id: urlParams.get('payment_id'),
order_id: urlParams.get('order_id'),
status: urlParams.get('status'),
gateway: urlParams.get('gateway'),
signature: urlParams.get('signature')
})
}).then(r => r.json());
if (result.success) {
// Payment verified
} else {
// Handle error
}Backend Verification (Node.js Example)
javascript
const crypto = require('crypto');
function verifySignature(params, apiSecret) {
const { signature, ...dataToSign } = params;
// Filter empty values
const filtered = {};
for (const [key, value] of Object.entries(dataToSign)) {
if (value !== undefined && value !== null && value !== '') {
filtered[key] = value;
}
}
// Create payload (adjust format to match backend)
const payload = Object.keys(filtered)
.sort()
.map(key => `${key}=${encodeURIComponent(filtered[key])}`)
.join('&');
// Generate HMAC-SHA256
const computed = crypto
.createHmac('sha256', apiSecret)
.update(payload)
.digest('hex');
// Compare (constant-time)
return crypto.timingSafeEqual(
Buffer.from(computed, 'hex'),
Buffer.from(signature, 'hex')
);
}7. Check Backend Documentation
Verify the exact signature format with your backend team:
- What parameters are included in the signature?
- What order are parameters in?
- Are values URL-encoded or raw?
- Is the signature hex or base64?
- Is it case-sensitive?
8. Common Mistakes
Mistake 1: Including signature in payload
javascript
// ❌ WRONG - Don't include signature in the payload
const payload = `order_id=123&status=captured&signature=${signature}`;
// ✅ CORRECT - Signature is separate
const payload = `order_id=123&status=captured`;Mistake 2: Wrong parameter order
javascript
// Backend might require specific order
// Check backend docs for exact orderMistake 3: Extra whitespace
javascript
// ❌ WRONG - Extra spaces
const payload = `order_id = 123 & status = captured`;
// ✅ CORRECT - No spaces
const payload = `order_id=123&status=captured`;Debug Checklist
- [ ] API secret is correct (starts with
sk_) - [ ] API secret matches environment (sandbox/live)
- [ ] All required parameters are present
- [ ] Signature parameter is included
- [ ] Debug mode enabled to see logs
- [ ] Check browser console for detailed error messages
- [ ] Verify with backend team about signature format
Still Having Issues?
If you've tried all the above and still getting errors:
- Enable debug mode and share the logs with support
- Contact backend team to verify signature format
- Use server-side verification as a workaround
- Contact Kore support with:
- Error message
- Debug logs
- Sample redirect URL (with sensitive data redacted)
- Backend signature format documentation
Note: For production, always verify signatures server-side for security.