Skip to main content

Token Refunds

In addition to the Token Wallet functionality, Checkout allows for the unique token to be used for refund processing via API. One such use case for this functionality is in back-office systems where refunds/compensation payments which do not always relate to an initial purchase can then be processed.

Refund only

This method can only be used for Refunds. If you wish to make Merchant Initiated Transactions, you should use the Recurring Transaction API instead.

Authentication

As the payment instrument, the token, is being passed in by the integrator the authentication method required is the same as used when initiating a new payment. See Authentication for the full breakdown of the request and response. It is important to remember that this authentication method means that certain fields in the authentication request (e.g. amount, invoiceId etc.) must match in the below request, otherwise the request will be rejected.

Token Refund Request

MethodPOST
tokenPayment
Field NameStateData TypeDescription
transactionTypeOptionalStringType of transaction.
REFUNDRefund
invoiceIdMandatoryStringOrder/invoice/transaction/basket number generated by the host website, as passed in the request.
accountIdOptionalStringUnique reference for the store processing the transaction.
descriptionOptionalStringMessage from host website to consumer.
merchantCustomDataOptional

String

Max 1024 bytes
Free text field for integrated system to pass custom data that will be stored against the transaction. This data will be returned in the result and available via the Transaction Management functions.
terminalIdMandatoryStringTerminal ID used when authorising the transaction.
amountMandatoryDecimalTotal amount of the original order/authorisation including decimal places where applicable.
ipAddressOptionalStringIP address of the computer on which the transaction is being performed.
currencyMandatoryStringCurrency of the transaction.
GBPPound Sterling
phoneOptionalStringConsumer’s contact phone number.
emailOptional

String

Max 256 Char.
Email address provided by consumer as main contact address.

Token Refund Request > Card

tokenPayment.card
Field NameStateData TypeDescription
accountNumberOptionalStringMasked PAN showing the last four digits of the card – for example “************9909”.
cardTokenIdMandatoryStringThe Token for the card, returned in the previous integrated transaction.
cscOptionalEncrypted String

If required by the merchant, the token transaction can also verify the card security code (CSC).

If this validation is required, the CSC should be encrypted with RSA-OAEP (sha256 is used as a hash function) algorithm using DNA Public Key (key length 4096 bits) with an OAuth token used as the label parameter and base64 encoded.

For more details on how to complete this encryption please see Encrypting the Card Security Code (CSC).

cardTypeOptionalStringThe Optomany card scheme ID for the card whose token is presented.
expirationMonthOptionalStringThe month, in digits, in which the card expires. For example, a card expiring in December would be “12”.
expirationYearOptionalStringThe year, in digits, in which the card expires. For example, a card expiring in 2022 would be “22”.
danger

The CSC must never be stored beyond the time taken to capture, encrypt and send the request. For more detail, please see Encrypting the Card Security Code (CSC)

Token Refund Response

Transaction Settlement
Field NameData TypeDescription
idStringUnique transaction ID. This ID should be stored as it is required for later transaction actions.
descriptionStringDescriptive text for the transaction.
phoneStringPhone number passed in the request.
amountDecimalTotal amount of the order including decimal places where applicable. ‘Whole’ amounts (e.g. “1”) on a GBP account represents £1.00.
currencyStringCurrency of the transaction.
GBPPound Sterling
invoiceIdStringOrder/invoice/transaction/basket number generated by the host website, as passed in the request.
accountIdStringUnique reference for the store processing the transaction, as passed in the request.
authDateTimeUTCStringDate and time of when the transaction was authorised with the acquirer.
responseCodeStringReturned by the acquirer detailing the result of the transaction. A full list of Response Codes can be found here.
successBooleanConfirms whether the transaction has been successful.
trueTransaction approved.
falseTransaction not approved.
settledBooleanConfirms whether the transaction has been submitted for overnight settlement.
trueTransaction settled.
falseTransaction not settled.
messageStringMessage confirming the processing result of the transaction request. 
authCodeStringAuthorisation code issued for the transaction.
cscResultStringConfirms the result of the Card Security Code (CSC) validation check.
Not SetCSC check was not requested
Not CheckedCSC could not be checked
MatchedCSC matched
Not MatchedCSC did not match
payerAuthenticationResultStringResult of the Payer Authentication process provided in the following format “enrolment result/authentication result”. As the Token Payment is not processed using Payer Authentication the result will always be the below.
EnrollmentAuthentication
-Not Attempted-Not Attempted
optomanyTerminalIdStringOptomany Terminal ID used when authorising the transaction.
cardExpiryDateStringExpiry date for the card used in the transaction. Provided in the “MM/YY” format.
cardPanStarredStringStarred PAN for the card used in the transaction - for example ************9909.
cardTokenIdStringOptomany Token ID for the card presented.
cardSchemeIdIntegerOptomany Card Scheme ID for the card used in the transaction.
cardSchemeNameStringName of the Card scheme for the card used in the transaction.
cardIssuingCountryStringCountry where the card was issued. This information will only be returned when this can be determined. This information is subject to change and as such we recommend only using this data as a guide.

Encrypting the Card Security Code

The Card Security Code (CSC) should be encrypted with RSA-OAEP (sha256 is used as a hash function) algorithm using DNA Public Key (key length 4096 bits) with the OAuth token from the authentication process used as the label parameter and base64 encoded.

tip

OAEP is parameterised by a hash function that is used as a random oracle. Encryption and decryption of a given message must use the same hash function (sha256.New() is used as a hash function).

The random parameter is used as a source of entropy to ensure that encrypting the same message twice does not result in the same ciphertext.

The label parameter may contain arbitrary data that will not be encrypted, but which gives important context to the message. For example, if a given public key is used to decrypt two types of messages then distinct label values could be used to ensure that a ciphertext for one purpose cannot be used for another by an attacker.

For the processing of test transactions the below RSA key should be used.

Test RSA Key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1NxKkkEAfAGw9Lo1/26oE9d2REF5fz2TC1WobV7WgDnuAhBsmyMy/TnQRVmyC8u1vy8Sxvspn9jY2YGe6/n249FK1RAzafV7mXOrMF1yqfXBMZhBwd+CHIXhETb/Pl7pjVPs8Fsk+uq/ZPB8WUVK6sNSzbAYG6TC4/DEFADxFHAxXOq9QaTO/QTX9JqzfP13XqOQqW5DmpWG52Qn69pV9fgI5eSLc25DgOjjw8fQvDnbM2MQNYr/YhjrDUZN1jrWWMrjqAN9V9dg9dE+YAmyq9boexJ/WC027MgkkVIMDO252U3qg2mpvbtdcs9Lfg0tL8z2nRUBc/cS3HRXcu4nP7E9pzqsLeWpC0BJw/kAwL79yZTOlTqdhDGo1WWRL3km9EFfEqugf3yguSR+mOODPyruD7r8OI40GLRqlorgiwF2srUZWhx+UObirtTIb4fLqrRl5wfi+mHgHt7Q0qOTX/qAXiWr3fueiNPs8AsmCoIq6OGIGCyFgjSNL2SK5RrtV5fB561Lu4FxurIH3KQq5EryGSjPlL2vl6fJFsFyEw8Cx3isuMVVmGx7DSVznXQDIhcU+akvQkjNHgtj+Ac0V5+h/uWhbF8DmnHyjhejs7vBVZvFl1hcCHVDQCmi/H2BPJ39Z+2rz4ljyYjkM74IPWF6CwJumST7ITF03zDh3akCAwEAAQ==
-----END PUBLIC KEY-----
note

For live integrations, the live RSA Key will be issued by the Implementations team following the completion of Integration Approval.

Examples

Tokenisation Request and Response Examples

Request
{
"transactionType":"SALE",
"invoiceId": "TESTSDTOKEN2",
"accountId": "1724",
"description": "Order description",
"merchantCustomData": "Custom data",
"terminalId": "a398d836-aeae-44e8-90b3-6726ecbdb604",
"amount": 5,
"ipAddress": "202.31.57.4",
"currency": "GBP",
"phone": "45373945",
"email": "test@email.com",
"card": {
"accountNumber":"************9909",
"cardTokenId": "XZXIx6WNM+vyvTFBOlGObOZazHurxVN6Sgjxq+CYhVcfMQ==",
"csc": "XqO8gM2GZDvEMjYcLnl/b3uMsz2TV6lIr00Ve0KIWkzqfptho4mWSe+s272+GD2FS5eZ5k6dNBr17FDwYm/UFG+iHml4bCN9KDld7SfSAnBHYXEymOItU6Md0UR8NpNHOHrEaDSQrua+jIjQ2RmwrQwGEzPrILD8Qb+EbTERDuS86CzlXI43EMiKn+iFW6Zt1YYtuQF3zh4qFXUFWAccudKAohhjaVl56nK/kW9dZO54xR6JatUpoCaHD1OWqw3aVGReFw7HdCgLsRfYflIvJGy6mQ2/Glt0JnNjW4BMCkJ1fwgT8Ge0UxN7dfmvnEDLqd3a0r2vcxSgxc1mnIzXbTAY7DTiiR2WraI9Xwyk5rOf2rg4SgqCmExrwrakHw4B1GNY9QFqDayRELVEgdU1nno5q27R2PnfDXG2uzIti24KtdfDJmG3gGzdWt0VHEgzHFPui4LojMeVKtAAfi6Ouy1UxrJo6YbKiJXM3mfRCDM4jD5T2rApMmD+9RkdRdEwpkwego2LpbrqBkW5Sz0N6e/g2qYmslgrJdN5qSJ/XHzKsCx51KbGoo7fMtskgDMuy3j+OoY/GBjL1Bi4SyUZhqe9jGL0I76g6NBqp4DwHhhrbZs4AsId9n25bAOgH3+U+uzelMeK5ppEINa+v3407WnlE6UUzPgq0EoApDsPPPo=",
"cardType": "8",
"expirationMonth": "12",
"expirationYear": "22"
}
}

CSC Encryption Example

note

You can view and execute this code here

Request Example in GO
package main

import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"log"
)

func main() {

//<<<<<<The first parameter in the "encrypt" function below is the CSC to encrypt,>>>>>
//<<<<<<and the third parameter is the authentication token.>>>>>>>

ciperText, err := encrypt("321", getIdRsaPub(), "3QA-wH4Zf5YfkF_g44Pyf$1ufZ$BAOG1!EQ0PYTD-nEo!OZJjqtV7dRnjZpxDmAk")
if err != nil {
log.Printf("ERROR: fail encrypt - %s", err.Error())
}
log.Printf("INFO: ciper text - %s", ciperText)
}

func encrypt(payload string, key *rsa.PublicKey, token string) (string, error) {
// params
msg := []byte(payload)
rnd := rand.Reader
hash := sha256.New()

// encrypt with OAEP
ciperText, err := rsa.EncryptOAEP(hash, rnd, key, msg, []byte(token))
if err != nil {
log.Printf("ERROR: fail to encrypt, %s", err.Error())
return "", err
}

return base64.StdEncoding.EncodeToString(ciperText), nil
}

func getIdRsaPub() *rsa.PublicKey {
keyData := `-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1NxKkkEAfAGw9Lo1/26oE9d2REF5fz2TC1WobV7WgDnuAhBsmyMy/TnQRVmyC8u1vy8Sxvspn9jY2YGe6/n249FK1RAzafV7mXOrMF1yqfXBMZhBwd+CHIXhETb/Pl7pjVPs8Fsk+uq/ZPB8WUVK6sNSzbAYG6TC4/DEFADxFHAxXOq9QaTO/QTX9JqzfP13XqOQqW5DmpWG52Qn69pV9fgI5eSLc25DgOjjw8fQvDnbM2MQNYr/YhjrDUZN1jrWWMrjqAN9V9dg9dE+YAmyq9boexJ/WC027MgkkVIMDO252U3qg2mpvbtdcs9Lfg0tL8z2nRUBc/cS3HRXcu4nP7E9pzqsLeWpC0BJw/kAwL79yZTOlTqdhDGo1WWRL3km9EFfEqugf3yguSR+mOODPyruD7r8OI40GLRqlorgiwF2srUZWhx+UObirtTIb4fLqrRl5wfi+mHgHt7Q0qOTX/qAXiWr3fueiNPs8AsmCoIq6OGIGCyFgjSNL2SK5RrtV5fB561Lu4FxurIH3KQq5EryGSjPlL2vl6fJFsFyEw8Cx3isuMVVmGx7DSVznXQDIhcU+akvQkjNHgtj+Ac0V5+h/uWhbF8DmnHyjhejs7vBVZvFl1hcCHVDQCmi/H2BPJ39Z+2rz4ljyYjkM74IPWF6CwJumST7ITF03zDh3akCAwEAAQ==
-----END PUBLIC KEY-----`

keyBlock, _ := pem.Decode([]byte(keyData))
if keyBlock == nil {
log.Printf("ERROR: fail get idrsapub, invalid key")
return nil
}

publicKey, err := x509.ParsePKIXPublicKey(keyBlock.Bytes)
if err != nil {
log.Printf("ERROR: fail get idrsapub, %s", err.Error())
return nil
}
switch publicKey := publicKey.(type) {
case *rsa.PublicKey:
return publicKey
default:
return nil
}
}
note

This code is provided as an example only, please ensure you understand any code you include in your project as you will be responsible for it.