I'm getting the "Token validation failed" error when I submit a request to the Visa Payments (CyberSource) API and can't tell what's off in my code:
Boolean testMode = true; String endPoint = testMode?'https://sandbox.api.visa.com/cybersource/payments/v1/sales?apikey='+apiKey:'https://api.visa.com/cybersource/payments/v1/sales?apikey='+apiKey; Http objhttp = new Http(); HttpRequest req = new HttpRequest(); HttpResponse res = new HttpResponse(); req.setMethod('GET'); req.setEndpoint(endpoint); String queryString = 'apikey='+apiKey; String URI = 'payments/v1/sales'; DateTime dateTimeNow = dateTime.now(); String unixTime = ''+dateTimeNow.getTime()/1000; String timeStampUTC = unixTime; String payload = '{\"encryptionType\":\"WebCryptoAPI\"}'; System.debug('=====> timestamp, uri, query string, payload = '+timeStampUTC+URI+queryString+payload); Blob hmacData = Crypto.generateMac('HmacSHA256', Blob.valueOf(timeStampUTC+URI+queryString+payload), Blob.valueOf(sharedSecret)); String encodedDigest = EncodingUtil.base64Encode(hmacData); xPayToken = 'xv2:'+ timeStampUTC + ':'+ encodedDigest; System.debug('=====> xPayToken = '+xPayToken); req.setHeader('x-pay-token', xPayToken); req.setHeader('Content-Type','application/json'); req.setTimeout(120000); System.debug('=====> request body: '+reqBody); req.setBody(reqBody); try { res = objhttp.send(req); System.debug('=====> http response: '+res.getBody()); } catch(System.CalloutException e) { System.debug('Callout error: '+ e); }
I've checked the timestamp value to make sure it's the current time (UTC), the apiKey and shared secret match those in the sandbox, and the Hmac digest seems to be in order (at least code samples on the Salesforce developer forums for this type of header value).
The debug output includes:
=====> timestamp, uri, query string, payload = 1500065746payments/v1/salesapikey=...hidden...{"encryptionType":"WebCryptoAPI"}
=====> xPayToken = xv2:1500065746:69fTj20b36apeCz3KAOWKOr889w/m+tCgazRDiTeM3M=
=====> http response: {"responseStatus":{"code":"9159","severity":"ERROR","message":"Token validation failed","info":"","status":401}}
Could someone kindly point out what I'm doing wrong?
Few things to note while generating token:
Note:
For Flex Keys resource we have to send xpaytoken
https://sandbox.api.visa.com/cybersource/payments/flex/v1/keys?apikey={apikey}
for flex Tokens there will be no xpaytoken
https://sandbox.api.visa.com/cybersource/payments/flex/v1/tokens
Try this out and keep me updated!
Thanks
Sanobar
Hi Sanobar -
Thanks for your response. It turns out I was calculating the HMAC value wrong.
Cheers,
Ron
I have a similar problem where the most likely thing to go wrong is the resource path area where I've tried many times to generate tokens in code that won't work but the token generated on SoapUI will work
@Jitesh_Shah or @shrtando - are you able to help out here?