Handling the Token ID/Transfer ID Callback

Briefly introduced in the previous topic, you'll need to be prepared to handle the TPP callback URL for both types of payment flows. Auth PLUS Transfer delivers a tokenId, which you can then redeem for payment. Auth AND Transfer redeems the token automatically and returns a transferId and status. Knowing which one to invoke depends on the value of requires_one_step_payment in the bank object of the token request payload containing the request-id. If requires_one_step_payment is true, the bank supports Auth AND Transfer and the callback will contain a transferId. If requires_one-step_payment is false, the bank supports Auth PLUS Transfer and an unredeemed tokenId is included in the callback.

Let's drill down into both scenarios, beginning with handling the tokenId.

Parsing a Token ID Callback

The callback is essentially the TPP's base callback URL (specified with setredirectUrl in the token request), combined with the request-id, signature, a token ID, a transferId, and a transferStatus returned by the bank (all added to the base redirect URL when you generated the token request URL). It looks something like this:

https://merchant-site.com/callback?request_id=rq:3UQL47opJxxYFxZgtGD4H6kUGRep:5zKtXEAq&signature={"memberId":"m:3rKtsoKaE1QUti3KCWPrcSQYvJj9:5zKtXEAq","keyId":"lgf2Mn0G4kkcXd5m","signature":"Bzh
SptPcYBlIuEzK1K7_mPDt_ws7U0rmugiHMkQh__Be7QwlZMxbv9Hto-L52nHuonGKgUnyToQJf1QGHXyMAQ"}&tokenId=tt: 4KhFVRQqcZWCjHwrm5san6fsmTeQwj8wWuEQH682hkXL:4hGGDVR3NcU7X8CUa9f&transferId=t:Gz2N7t5vChmsGDoBMKm
VDo7dewPT9ryejvuRqiJ7fC9y:4hGGDVR3NcU7X8CUa9f&transferStatus=FAILURE_GENERIC

For it to have any meaning, however, it needs to be parsed into its constituent components to validate the cryptographic signature binding together csrfToken, status, and tokenId to produce a decrypted request-id, tokenId, signature, and status.

Used to validate that each token request is initiated and completed by the same user session to protect against any potential attack, the csrfToken is a unique string bound to the session of the user. It can be a hash of the session cookie or a string associated with the server-side user session. Token.io strongly recommends binding the csrfToken to the user's authenticated state in accordance with ITEF guidelines.

Hence, the session cookie can be safely used as the csrfToken because the Token.io SDK hashes the token before using it. However, if your application doesn't authenticate the user, you can use the SDK's Util.generateNonce() method to generate a secure random string that can serve as the csrfToken.

The state value parsed from the callback is the callBackState specified in the transfer token request (see Fields in a Transfer Token Request). Although it can contain additional application-specific information, it should not be used to authenticate the user. Authentication must be performed before initiating the token request flow, and the callback should therefore use the same authenticated session.

Thus, when your server-side listener receives a HTTP GET request at the callback URL, it needs to call the SDK's parseTokenRequestCallbackUrlBlocking() method to extract the tokenId and verify both the signature and the csrfToken. Here's how:

// retrieve CSRF token from browser cookie

String csrfToken = req.cookie(CSRF_TOKEN_KEY);

 

// check CSRF token and retrieve state and token ID from callback

TokenRequestCallback callback = tokenClient.parseTokenRequestCallbackUrlBlocking(

    callbackUrl,

    csrfToken);

 

//get the token and check its validity

Token token = merchantMember.getTokenBlocking(callback.getTokenId());

From a pop-up, your server-side listener may receive an HTTP POST request in format. In which case, use parseTokenRequestCallbackParamsBlocking() to extract the tokenId and verify the signature and user session.

// retrieve CSRF token from browser cookie

String csrfToken = req.cookie(CSRF_TOKEN_KEY);

 

// check CSRF token and retrieve state and token ID from callback

TokenRequestCallback callback = tokenClient.parseTokenRequestCallbackParamsBlocking(

    data, // these are the callback params in JSON format

    csrfToken);

 

//get the token and check its validity

Token token = merchantMember.getTokenBlocking(callback.getTokenId());

Parsing a Transfer ID Callback

From banks supporting immediate token redemption (Auth AND Transfer), the callback will contain the transferId, in addition to the request-id,csrfToken, transferStatus, and tokenId, thereby obviating any need for the TPP to redeem the token.

request-id=rq:3UQL47opJxxYFxZgtGD4H6kUGRep:5zKtXEAq&signature={"memberId":"m:3rKtsoKaE1QUti3KCWPrcSQYvJj9:5zKtXEAq","keyId":"lgf2Mn0G4kkcXd5m",
"signature":"BzhSptPcYBlIuEzK1K7_mPDt_ws7U0rmugiHMkQh__Be7QwlZMxbv9Hto-L52nHuonGK
gUnyToQJf1QGHXyMAQ"}&tokenId=tt:4KhFVRQqcZWCjHwrm5san6fsmTeQwj8wWuEQH682hkXL:4hG
GDVR3NcU7X8CUa9f&transferId=t:Gz2N7t5vChmsGDoBMKmVDo7dewPT9ryejvuRqiJ7fC9y:4hGGD
VR3NcU7X8CUa9f&transferStatus=FAILURE_GENERIC

However, the Auth AND Transfer payment flow requires that you include the transfer destination(s) in the stored token request, rather than waiting for a request-id in the response payload and/or including the transferDestination in a token redemption call (discussed in the next topic). Bearing that in mind, you parse a Transfer ID callback URL just like the Token.io ID callback Url, by including it in a parseTokenRequestCallbackUrlBlocking() call after a straight redirect, and in a parseTokenRequestCallbackParamsBlocking() call after a redirect pop-up. Both methods parse and return the respective constituent components, including transferId and transferStatus.

Once you process a successful transfer ID callback, you can display the transfer status to the customer in accordance with your UX protocols (e.g., "transaction succeeded" or "Thank you for your payment," etc.).