Last updated

Refund a Prior RTP Payment

The Electrum RTP solution includes a refund function. This enables you to refund a customer who has paid you as result of a prior, accepted request-to-pay.

For example, your customer may have made a manual payment on their own and also accidentally accepted an RTP request from you for the same payment (i.e., paid twice for the same invoice) or returned items from their cart, in which case a refund is required.

The refund will be processed as an outbound PayShap payment, which will allow the recipient to receive the refund in near real-time. A refund transaction has its own UETR but must link to a prior successfully paid RTP payment by referencing the original RTP UETR in the refund request. This ensures that the refund:

  • Reaches the correct recipient - the original payer to whom the RTP was sent.
  • Is of the correct value - does not exceed the amount that the original payer paid.
Note

Electrum’s RTP Refunds service supports pay-by-account refunds only.

This means that even though the original PayShap payment may have been proxy-based (whereby the payer sent payment using the requester's proxy), the refund (the payment returned from requester to payer) must be sent using the payer's account number.

This payer account number can always be found in the original payment message from payer to requester.

Each outbound request will be subject to the usual default validations including:

  • A check that the debtor account is whitelisted.
  • Creditor account check digit verification (CDV).
  • Scheme amount validations.

If any of these fail, then clearing will not proceed and Electrum will send a negative PaymentStatusReport to you to inform you of the failure.

Debtor Account

The debtorAccount object in the request message is an optional field.

If you do not populate this field then the money to be refunded will automatically be taken from the account that received the original payment (i.e., the creditor account in the original request message).

  • Do not populate ANY debtorAccount fields in this case.

You must populate this field when you wish to refund the money from a different account to the one that received the original payment.

  • You must populate ALL debtorAccount fields in this case.
Partial Refunds

You may do a refund of either the full amount of the original payment, or a partial amount of the original payment.

Only one successful refund is allowed for each successfully paid RTP. This means that if you successfully process a partial refund of a payment, you may not do any subsequent refunds for the remaining amount.

However, if your initial refund attempt is unsuccessful, then you may attempt another refund, provided that the new attempt has its own UETR and references the original RTP UETR.

RTP Refund Success

refund success

  1. You initiate an RTP refund by sending an asynchronous message using the outboundRefundInitiation operation (RefundInitiationRequest schema) to Electrum. Electrum acknowledges this and responds with an HTTP 2xx.
RefundInitiationRequest Schema
messageIdentifiersobject(MessageIdentifiers)required

Holds a point-to-point unique message identification string as well as a message's creation date time.

messageIdentifiers.​creationDateTimestring(date-time)required

The date and time at which the message was created, in senders local timezone or UTC. The date must be formatted as defined by date-time in RFC3339

messageIdentifiers.​messageIdentificationstring<= 35 charactersrequired

A reference used to unambiguously identify the message between the sending and receiving party. Take note that this uniquely identifies a single message in a potentially multi-message exchange to complete a payment.

supplementaryDataobject(SupplementaryData)

A list of key-value pairs to support adding any supplementary/additional data to an Electrum Regulated Payments API message.

transactionIdentifiersobject(TransactionIdentifiers)required

Holds a series of identifiers to identify the transaction or an individual message that is part of a transaction.

transactionIdentifiers.​endToEndIdentificationstring<= 35 charactersrequired

Unique identification, as assigned by the initiating party, to unambiguously identify the transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain. Note: this is distinct from the UETR.

transactionIdentifiers.​instructionIdentificationstring<= 35 characters

Unique identification, as assigned by an instructing party for an instructed party, to unambiguously identify the instruction. The instruction identification is a point to point reference that can be used between the instructing party and the instructed party to refer to the individual instruction. It can be included in several messages related to the instruction.

transactionIdentifiers.​transactionIdentificationstring<= 35 characters

Unique identification, as assigned by the first instructing agent, to unambiguously identify the transaction that is passed on, unchanged, throughout the entire interbank chain. Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to the transaction on the interbank level. Usage: The instructing agent has to make sure that the transaction identification is unique for a pre-agreed period.

transactionIdentifiers.​uetrstring(UUID)required

Universally unique identifier to provide an end-to-end reference of a payment transaction. This identifier remains the same for all messages related to the same transaction.

amountsobject(TransactionAmounts)
debtorAccountobject(PaymentAccount)

Representation of an account for payment purposes. Note that at least one of identification or proxy is expected to be present.

originalTransactionIdentifiersobject(TransactionIdentifiers)required

Holds a series of identifiers to identify the transaction or an individual message that is part of a transaction.

originalTransactionIdentifiers.​endToEndIdentificationstring<= 35 charactersrequired

Unique identification, as assigned by the initiating party, to unambiguously identify the transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain. Note: this is distinct from the UETR.

originalTransactionIdentifiers.​instructionIdentificationstring<= 35 characters

Unique identification, as assigned by an instructing party for an instructed party, to unambiguously identify the instruction. The instruction identification is a point to point reference that can be used between the instructing party and the instructed party to refer to the individual instruction. It can be included in several messages related to the instruction.

originalTransactionIdentifiers.​transactionIdentificationstring<= 35 characters

Unique identification, as assigned by the first instructing agent, to unambiguously identify the transaction that is passed on, unchanged, throughout the entire interbank chain. Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to the transaction on the interbank level. Usage: The instructing agent has to make sure that the transaction identification is unique for a pre-agreed period.

originalTransactionIdentifiers.​uetrstring(UUID)required

Universally unique identifier to provide an end-to-end reference of a payment transaction. This identifier remains the same for all messages related to the same transaction.

paymentSchemeobject(RefundInitiationPaymentScheme)required

Designates which scheme a refund initiation is associated with and describes scheme-specific information for the refund to be processed. Currently only ZA_RPP supported.

paymentScheme.​schemastring(PaymentSchemeName)required

Identifies the scheme used for the payment

  • ZA_RTC: South African Realtime Clearing scheme.
  • ZA_RPP: South African Realtime Payments Platform scheme.
  • ZA_EFT: South African Electronic Funds Transfer scheme.
  • ZA_AC : South African Authenticated Collections scheme.
  • ZA_RMS: South African Registered Mandate Service scheme.
  • CBPR_PLUS: Cross-Border Payments and Reporting Plus.
Enum"ZA_RTC""ZA_RPP""ZA_EFT""ZA_AC""ZA_RMS""CBPR_PLUS"
Discriminator
paymentScheme.​schemeDataobject(ZaRppSchemeData)
refundReferencestring

An explanation of the transaction, as assigned by the refund initiator, to unambiguously refer to this refund payment. This value will be used as the transaction reference if the clearing scheme supports it.

schemastringrequired
Value"RefundInitiationRequest"
Important

You must either:

  • Omit the debtorAccount field entirely, OR
  • Populate ALL debtorAccount fields.

(See the Debtor Account note above.)

  1. Electrum checks the RTP store to determine whether or not the prior RTP exists, if it has been paid, and what the amount was.

  2. Upon successful validation of the refund pre-conditions, clearing begins in the form of an outbound (pay-by-account, or PBAC) PayShap transaction.

    • Electrum sends messages to the sponsor bank to reserve funds for clearing of the refund.
    • If funds reservation is successful then Electrum initiates clearing with BankservAfrica.
  3. Once the refund has been successfully processed, Electrum sends an outboundRefundInitiationResponse message (PaymentStatusReport schema) to you.

RequestToPayResponse Schema
messageIdentifiersobject(MessageIdentifiers)required

Holds a point-to-point unique message identification string as well as a message's creation date time.

messageIdentifiers.​creationDateTimestring(date-time)required

The date and time at which the message was created, in senders local timezone or UTC. The date must be formatted as defined by date-time in RFC3339

messageIdentifiers.​messageIdentificationstring<= 35 charactersrequired

A reference used to unambiguously identify the message between the sending and receiving party. Take note that this uniquely identifies a single message in a potentially multi-message exchange to complete a payment.

supplementaryDataobject(SupplementaryData)

A list of key-value pairs to support adding any supplementary/additional data to an Electrum Regulated Payments API message.

originalMessageIdentifiersobject(MessageIdentifiers)required

Holds a point-to-point unique message identification string as well as a message's creation date time.

originalMessageIdentifiers.​creationDateTimestring(date-time)required

The date and time at which the message was created, in senders local timezone or UTC. The date must be formatted as defined by date-time in RFC3339

originalMessageIdentifiers.​messageIdentificationstring<= 35 charactersrequired

A reference used to unambiguously identify the message between the sending and receiving party. Take note that this uniquely identifies a single message in a potentially multi-message exchange to complete a payment.

transactionIdentifiersobject(TransactionIdentifiers)required

Holds a series of identifiers to identify the transaction or an individual message that is part of a transaction.

transactionIdentifiers.​endToEndIdentificationstring<= 35 charactersrequired

Unique identification, as assigned by the initiating party, to unambiguously identify the transaction. This identification is passed on, unchanged, throughout the entire end-to-end chain. Note: this is distinct from the UETR.

transactionIdentifiers.​instructionIdentificationstring<= 35 characters

Unique identification, as assigned by an instructing party for an instructed party, to unambiguously identify the instruction. The instruction identification is a point to point reference that can be used between the instructing party and the instructed party to refer to the individual instruction. It can be included in several messages related to the instruction.

transactionIdentifiers.​transactionIdentificationstring<= 35 characters

Unique identification, as assigned by the first instructing agent, to unambiguously identify the transaction that is passed on, unchanged, throughout the entire interbank chain. Usage: The transaction identification can be used for reconciliation, tracking or to link tasks relating to the transaction on the interbank level. Usage: The instructing agent has to make sure that the transaction identification is unique for a pre-agreed period.

transactionIdentifiers.​uetrstring(UUID)required

Universally unique identifier to provide an end-to-end reference of a payment transaction. This identifier remains the same for all messages related to the same transaction.

instructedAgentobject(InstitutionIdentification)
instructingAgentobject(InstitutionIdentification)
statusobject(Status)required
status.​outcomestringrequired
  • APPROVED: The instruction has been approved.
  • CANCELLED: The instruction has been cancelled.
  • PENDING: The instruction is pending.
  • REJECTED: The instruction has been rejected.
Enum"APPROVED""CANCELLED""PENDING""REJECTED"
status.​reasonInfoArray of objects(StatusReasonInfo)non-empty

A list of StatusReasonInfo values providing detailed reason information for the outcome.

mandateInformationobject(MandateInformation)

Provides details of the direct debit mandate signed between the creditor and the debtor.

NOTE: This model is a work in progress and may change. In particular, it lacks properties relating to mandate amendments which we may need in the future. Note also that this model is not relevant to the ZA_EFT scheme, and therefore Electrum will not do any special processing for these fields for EFT (e.g. Electrum cannot honour tracking days for EFT payments).

originalTransactionDataobject(OriginalTransactionData)

Contains key elements related to the original transaction that is being referred to.

paymentSchemeobject(PaymentStatusReportPaymentScheme)required

Designates which scheme a payment status report is associated with and describes scheme-specific information for the payment status report.

paymentScheme.​schemastringrequired
Discriminator
schemastringrequired
Value"PaymentStatusReport"
  1. Electrum updates the status of the original RTP transaction in the RTP Store to REFUNDED. This prevents the processing of additional refunds for the same transaction.

Error Handling

Timeout at Corporate Client

refund timeout at CC

If Electrum does not receive and/or acknowledge your outboundRefundInitiation request with an ACK (HTTP 2xx response), then a timeout error will occur at your system. You can retry the same transaction, and if you receive an ACK from Electrum then the standard success flow will follow.

Corporate Client sends Multiple Refund Initiation Requests

refund mutliple requests

If you have received an ACK from Electrum in response to an outboundRefundInitiation message, but you send the outboundRefundInitiation message again, then Electrum will ACK the second request similarly. However the refund will be processed according to the first request. No refund will be processed for the second request - no refund would be possible as the status of the original RTP would have been updated after the first successful refund request.

Error at Sponsor Bank During Funds Reservation

refund error during reservation

If an error occurs at the sponsor bank and the funds reservation is unsuccessful (for example, there are insufficient funds in the account to complete the payment), then Electrum will send a negative outboundRefundInitiationResponse, with status.outcome set to REJECTED and a reason for the error (e.g., AM04 (insufficient funds)), to you.

Error at BankservAfrica

refund error at BSA

If an error occurs at BankservAfrica and the clearing step is unsuccessful, then BankservAfrica will notify Electrum. Electrum will send a negative outboundRefundInitiationResponse to you.

Timeout At Electrum

refund timeout at Electrum

If Electrum does not receive an ACK after sending an outboundRefundInitiationResponse message to you, then a timeout will occur at Electrum. Electrum will continue to send the outboundRefundInitiationResponse message to you, via a store-and-forward queue, until you acknowledge that you have received it.

Error at RTP Store

refund error at rtp store

An error occurs when Electrum checks the RTP Store to determine the validity of the original RTP. This could be because:

  • The RTP does not exist (the UETR may have been input incorrectly).
  • The RTP exists but is not in a state that allows for refunds, i.e., is not in a PAID state.
  • The RTP exists but the requested refund amount is greater than the RTP paid amount.

In each of these cases the refund request will not be processed. Electrum will send a negative outboundRefundInitiationResponse to you.