Visa Click to Pay

Merchants and Payment Service Providers

Unencrypted Payload Contents - Visa SRC SDK

Payload

Payload provides metadata that includes the information based on if the consumer uses the PAN, or token.

Field

Description

card

Card data associated with the PAN used for the purchase. Supplied if the indicated payload type is FULL or PAYMENT and the SRC system determines that a PAN-based payload is returned.

Note: Either a Card or a Payment Token credential is returned, never both

Format: Card structure

token

Payment Token data associated with the PAN used for the purchase. Supplied if the indicated payload type is FULL or PAYMENT and the SRC system determines that a Payment Token- based payload is returned.

Note: Either a Card or a Payment Token credential is returned, never both

Format: PaymentToken structure

paymentAccountReference

The Payment Account Reference (PAR) associated with the cardholder account that uniquely identifies the account to which the payment card is associated.

Format: String

dynamicData

Dynamic data (cryptograms) applicable for transactions. If Click to Pay facilitates Issuer Authentication (3DS), then CAVV will be provided in the dynamic data.

Format: List of DynamicData structures

billingAddress

Billing address of the selected card.

Format: Address structure

shippingAddress

Shipping address of the consumer; supplied when available, for example:

  • Identified Shipping Address is available in the SRC Profile
  • Shipping address is requested (based on dpaShippingPre­ ference)
  • PayloadTypeIndicator is “FULL” or “NON_PAYMENT”

Format: Address structure

consumer

Consumer's information.

Format: Consumer structure

panExpirationYear

The year when the account number is set to expire.

Format: Numeric; 4 digits

threeDsOutputData

(Deprecated) Result of 3DS payment authentication.

Decrypted PAN Payload Example

{
    "card": {
        "primaryAccountNumber": "430...08",
        "panExpirationMonth": "12",
        "panExpirationYear": "2023",
        "cardholderFullName": ".	",
        "cardholderFirstName": ".	",
        "cardholderLastName": ".	"
    },
    "billingAddress": {
        "addressId": "e43.	02",
        "countryCode": "US"
    },
    "shippingAddress": {
        "addressId": "5c4.	01",
        "line1": ".	",
        "city": ".	",
        "state": ".	",
        "zip": ".	",
        "countryCode": "US"
    },
    "consumer": {
        "firstName": ".	",
        "lastName": ".	",
        "fullName": ".	",
        "emailAddress": "[email protected]",
        "mobileNumber": {},
        "countryCode": "US",
        "languageCode": "en-US"
    },
    "threeDsOutputData": []
}
		

Decrypted Token Payload Example

{
    "token": {
        "paymentToken": "489...69",
        "tokenExpirationMonth": "12",
        "tokenExpirationYear": "2024"
    },
    "paymentAccountReference": "V00...23",
    "dynamicData": [
        {
            "dynamicData": "AgA...A=",
            "dynamicDataType": "CARD_APPLICATION_CRYPTOGRAM_LONG_FORM",
            "dynamicDataExpiration": "Thu Jun 25 03:23:13 GMT 2020"
        },
        {
            "dynamicDataValue": "Y2F...g=",
            "dynamicDataType": "CARDHOLDER_AUTHENTICATION_CRYPTOGRAM"
        }
    ],
    "billingAddress": {
        "addressId": "b3f...02",
        "countryCode": "GB"
    },
    "shippingAddress": {
        "addressId": "89e...01",
        "line1": "...",
        "city": "...",
        "state": "ON",
        "zip": "K1G 4B5",
        "countryCode": "CA"
    },
    "consumer": {
        "firstName": "...",
        "lastName": "...",
        "fullName": ".	",
        "emailAddress": ".	@gmail.com",
        "mobileNumber": {},
        "countryCode": "US",
        "languageCode": "en-US"
    },
    "threeDsOutputData": []
}
		

Decrypted 3DS Assurance Data

3DS provides additional fields in the response.

"assuranceData": {
    "verificationData": [
        {
            "methodResults": {
                "transStatus": "Y",
                "dsTransId": "06c...16",
                "acsTransId": "6f5...09"
            }
        }
    ],
    "eci": "05"
}
		

Appendix

Appendix A - Decrypting the SRC Payload

Java Example for SRC Payload Symmetric Decryption

The following Java code, using the JOSE4j API jose4j-0.6.5.jar, provides an example of decrypting the payload.

package ...;
import java.security.MessageDigest;
import javax.crypto.spec.SecretKeySpec; import org.jose4j.jwe.JsonWebEncryption;
public class DecryptJWE {
public static String decryptJWE(String secret, String jwe) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digest = md.digest(secret.getBytes("UTF-8"));
        JsonWebEncryption jweDecryptor = new JsonWebEncryption(); jweDecryptor.setCompactSerialization(jwe); jweDecryptor.setKey(new SecretKeySpec(digest, "AES"));
        return jweDecryptor.getPlaintextString();
    }
}
		

Node.js Example for SRC Payload Symmetric Decryption

var jose = require('node-jose'); var crypto = require('crypto');
module.exports = {
    decryptJWE: function (secret, payload) {
        return new Promise(function (resolve, reject) {
            var SS_Hashed =
                crypto.createHash('sha256').update(secret).digest('hex'); jose.JWK.asKey({
                    kty: 'oct', k: Buffer.from(SS_Hashed,
                        'hex')
                })
                    .then(function (key) {
                        jose.JWE.createDecrypt(key)
                            .decrypt(payload)
                            .then(function (result) {
                                resolve(result);
                            })
                            .catch(function (error) {
                                reject(error);
                            });
                    })
                    .catch(function (error) {
                        reject(error);
                    });
        });
    }
};
		

Appendix B - Generating a JWE for PAN Encryption

Encrypting the PAN

This code snippet is used for creating PAN JWE on the browser side. This example uses the node-jose library in browserify format.

// getNodeJoseLib(); Get node-jose library in browserify format
// Code to generate JWE using node-jose library
/**
*	@param kid kid for public certificate. Contact Visa representative for this value
*	@param keys Public key to be used for encryption.
Contact Visa representative for *
@param payload Card information to be encrypted,
{"card":{ "primaryAccountNumber":"424..2", "panExpirationMonth":"10",
.."panExpirationYear":"2022", "cardSecurityCode":"123",
.."cardholderFullName":"cardholder name"}
}
* @param cb Returning encrypted PAN as JWE string to this callback function */

function generateJWE(kid, keys, payload, cb) {
    const keyInput = {
        "kty": "RSA",
        "e": keys.e, // Public key exponent "kid": kid,
        "use": "enc",
        "n": keys.n, // Public key modulus "alg": "RSA-OAEP-256",
        "ext_content": "payload"
    };
    jose.JWK.asKey(keyInput)
        .then((key) => {
            console.log("JWK ", JSON.stringify(key)); const contentAlg = 'A25..CM';
            let options = {
                format: 'compact',
                contentAlg: contentAlg, fields: {
                    kid: key.kid, typ: 'JOSE',
                    iat: Date.now(), alg: key.alg, enc: contentAlg
                }
            };
            jose.JWE.createEncrypt(options, key).update(payload).
                final().then((serializedJWE) => {
                    console.log("Encrypted data: ", JSON.stringify(serializedJWE));
                    cb(serializedJWE);
                }, (error) => {
                    console.log("Error occurred: ", error.message); cb(null);
                });
        }, (error) => {
            console.log("Error occurred: ", error.message); cb(null);
        })
}
		

Appendix C - JWE Composition Details

JSON Web Encryption (JWE) Using Shared Secret

The encryption key provided during onboarding is used to encrypt and decrypt payloads. JSON Web Encryption (JWE) content should be signed or encrypted using the shared secret that was provided to client at the time of onboarding.

Introduction

Visa uses JSON Web Encryption (JWE) to encode sensitive field level information. Encrypted input parameters should be constructed before sending them in API requests.

Visa Installment Solutions APIs use the following naming convention for fields that require encryption in this document.

"enc<FIELD>" : "JWE ( ... ) "

See the complete specification for JWE: https://tools.ietf.org/html/draft-ietf-jose-json-web- encryption-40.

JWE Composition and Conventions

BASE64URL (UTF8 (JWE Header)) || ‘.’ ||
BASE64URL (JWE Encrypted Key) || ‘.’ || BASE64URL (JWE IV) || ‘.’ ||
BASE64URL (JWE Ciphertext) || ‘.’ || BASE64URL (JWE Authentication Tag)
		

The conventions are as follows:

  • BASE64URL encoding with NO padding.
  • Compact serialization style (elements separated by “.”)
  • Use a CEK (Content Encryption Key) of 256bits size.
  • Authentication Tag will be generated as an additional output of the AES-GCM-256 encryption. Size of this field is 128 bits.
  • All String to byte and vice-versa conversions are done with UTF-8 charset.

Note: The JWE Protected Header is input as the AAD (Additional Authenticated Data) parameter of the authenticated encryption (AES-GCM) of the “text to encrypt”.

Sample JWE Header for Asymmetric Encryption

"header": {
    "alg": "RSA-OAEP-256""typ": "JOSE",
    "kid": "50charAPIKey", // API key "enc": "A256GCM"
}
		

Sample JWE Header for Symmetric Encryption

"header": {
    "alg": "AGCM256KW""typ": "JOSE",
    "tag": "<128bitvalue>", // HMAC generated from applying AES-256-GCM-KW to the CEK
    "kid": "50charAPIKey", // API key "enc": "AGCM256"
}
		
"header": {
    "alg": "AGCM256KW""typ": "JOSE",
    "tag": "<128bitvalue>", // HMAC generated from applying AES-256-GCM-KW to the CEK
    "kid": "50charAPIKey", // API key "enc": "AGCM256"
}
		

Sample JWE Body

  • encrypted_key: base64 encoded form. CEK encrypted using AGCM256KW (alg) algorithm and the CEK IV
  • iv: base64 encoded form. IV for the text encryption. Size of IV is to be 96 bit Base64 encoded form
  • ciphertext: encrypted blob generated using the AES-GCM encryption (enc) of the text to encrypt
  • tag: base64 encoded form. HMAC generated using the AES-GCM encryption of the text to encrypt. The size of the tag should be 128 bits
“encrypted_key”: “UghIOgu ... MR4gp_A=”, “iv”: “AxY8DctDa….GlsbGljb3RoZQ=”,
“ciphertext”: “KDlTthhZTGufMY…….xPSUrfmqCHXaI9wOGY=”, “tag”: “Mz-VPPyU4…RlcuYv1IwIvzw=”