The following PayProtocol (P3) refund messages are supported by the PayServer. Also see,
Message
Specification as a starting point.
Refunds allow your merchants to transfer the full or partial amount of a previous charge
transaction back to the shopper.
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
their 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:
{
"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",
}
}
}
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 localized, human readable information about the state of the
transaction. You can use them straight in your POS UI.
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.
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. The shopper must present their 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 absolutely 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 authorized store personal must be allowed to use them.
Your POS system protects usage of the Standalone Refund feature, i.e., your POS
system make sure that only authorized 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.
Stand Alone Refunds are run via the
EXECUTE_TRANSACTION_REQUEST
message,
similar to charge transactions, 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"
}
}
}