Refunds

This page specifically describes all the messages of the P3 protocol related to refunds. Make sure to make yourself familiar with the overall Message Specification first.


 

Refunds allow your merchants to transfer the full or partial amount of a previous charge transaction back to the shopper.

Linked Refunds

Refunds are implemented as Linked Refunds, meaning you need to provide the transactionIdentifier of the previous charge transaction in order to perform the refund. For Linked Refunds it is not required for the shopper to present his card again and the refund will be paid out on the exact same card as used for the charge.

To run a full or partial Linked Refund, you need to implement the AMEND_TRANSACTION messages. Those messages are part of a long running operation but do not require a card reader device.

Then sending the AMEND_TRANSACTION_REQUEST message, you need to specify REFUND as the type and provide the transactionIdentifier of the previous charge transaction as the referencedTransactionIdentifier. For partial refunds, you also need to specify the amount and currency that should be refunded:

Request Data
{
    "tag": "abc123",
    "type": "AMEND_TRANSACTION_REQUEST",
    "resource": null,
    "amendTransactionRequest": {
        "mode" : "ONLINE | OFFLINE",
        "transactionParameters": {
            "type": "REFUND",
            "referencedTransactionIdentifier": "97a293ca3b804d639d8552962e0e3522",
            "amount": 5.00,
            "currency": <Currency>,
            "subject": "My Refund Subject",
            "customIdentifier": "my-custom-identifier",
        }
    }
}
Update Data

Since amending transactions is a long running operation, the server provides the client with update messages which inform about the current state of the process.

{
    "tag": "abc123",
    "type": "AMEND_TRANSACTION_UPDATE",
    "resource": null,
    "amendTransactionUpdate": {
        "state": <TransactionProcessDetailsState>,
        "stateDetails": <TransactionProcessDetailsStateDetails>,
        "information": ["Processing", "payment..."],
        "abortable": false,
    }
}

The field information is an array of exactly two strings which contain localised, human readable information about the state of the transaction. You can use them straight in your POS UI.

Response Data

Receiving an amend transaction response means that the long running operation is over and there will be no more related updates.

{
    "tag": "abc123",
    "type": "AMEND_TRANSACTION_RESPONSE",
    "resource": null,
    "amendTransactionResponse": {
        "state": <TransactionProcessDetailsState>,
        "stateDetails": <TransactionProcessDetailsStateDetails>,
        "transaction": {
            "amount": 10.00,
            "currency": <Currency>,
            "type": "CHARGE",
            "subject": "My Charge Subject",
            "statementDescriptor": "My Statement Descriptor",
            "status": <TransactionStatus>,
            "identifier": "97a293ca3b804d639d8552962e0e3522",
            "createdTimestamp": 1464009191,
            "customIdentifier": "my-custom-identifier",
            "refundDetails": {
                "status": <RefundDetailsStatus>,
                "process": [<RefundDetailsProcess>],
                "refundTransactions": [
                    {
                        "identifier": "c735ec8ed1794e83882fba8c99ccd7d2",
                        "createdTimestamp": 1464609191,
                        "amount": 5.00,
			            "currency": <Currency>,
            			"subject": "My Refund Subject",
			            "customIdentifier": "my-custom-identifier",
                        "type": "REFUND",
                        "code": <RefundTransactionCode>,
                        "status": <TransactionStatus>,
                        "statusDetails": {
                            "code": <TransactionStatusDetailsCodes>,
                            "description": "A description",
                            "developerDescription": "A developer description",
                        }
                    }
                ]
            }
        }
    }
}

The returned transaction object is the one from the original charge transaction, but in case of a successful refund, the refundDetails now contains the refund transactions. In case the refund failed (i.e. the refundDetails are empty), make sure to notify the merchant accordingly.

In order to create the required refund receipts you need to take the last $refundDetails.refundTransactions.identifier from the array (e.g. c735ec8ed1794e83882fba8c99ccd7d2 in the sample above) and use it to retrieve the merchantReceipt and customerReceipt data via the GET_TRANSACTION_REQUEST message.

Further details on the GET_TRANSACTION_REQUEST message can be found in the overall Message Specification.

Standalone Refunds

There might be the rare occasion when the transactionIdentifier of the previous charge is not available, e.g. should your POS system not allow the merchant to retrieve the original invoice containing the transactionIdentifier.

In this scenario Standalone Refunds allow the merchant to perform a refund without reference to the previous charge transaction and the shopper needs to present his card again.

Standalone Refunds have a high risk profile, i.e. merchant money can be paid out without limitations. Only consider offering them after you are absolutly sure that Linked Refunds are not possible in your setup.

Should your merchants require Standalone Refunds, please talk to your account manager beforehand to ensure all prerequisites are met. Specifically you need to ensure that:

  • Each merchant provides you with a written confirmation that they understand that Standalone Refunds potentially allow to pay out merchant money without limitations and that only authorised store personal must be allowed to use them.
  • Your POS system protects usage of the Standalone Refund feature, i.e. your POS system make sures that only authorised store personal (like store owner or supervisor) can use it and that usage is protected by a password or PIN. Note that before allowing you to go LIVE with Standalone Refunds, we will verify this requirements as part of our Testing.

Once enabled, Standalone Refunds are run exactly like charge transactions via the EXECUTE_TRANSACTION_REQUEST message, but using REFUND as type (instead of CHARGE).

Standalone refunds with transaction parameters:
{
	"tag": "abc123",
	"type": "EXECUTE_TRANSACTION_REQUEST",
	"resource": "devices/usbReader",
	"executeTransactionRequest": {
		"transactionParameters": {
			"amount": 5.00,
			"currency": "EUR",
			"type": "REFUND",
			"subject": "Refund of previous charge"
		}
	}
}