Purchase refunds

In the context of the ecommpay payment platform, refund is a repayment of the money customer previously paid in a purchase operation. Refund does not apply , if the money were not previously actually transferred from customer to merchant, for example, if customer's money are held as a result of an authorization hold operation, the amount will be returned through releasing the authorization hold, but not through a refund. For more information, see Two-step purchase).

To perform refunds, you can use Gate and/or Dashboard. This section discusses how to perform refunds by using Gate. Note that general information is relevant for both cards and other payment instruments while the technical information applies only to card operations. For technical information about other payment instruments, see Methods.

General information

The payment platform supports refund for one-time purchases and COF purchases. In general, there is no time limit for making a refund after purchase is complete, though some payment methods may impose timeout after which refund may be no longer possible or require additional fee.

To make a refund using Gate, you need to submit the corresponding request to the /v2/payment/{payment_method}/refund endpoint. When doing so, you need to observe all the special aspects and limitations as described in other sections in this documentation.

In general, depending on the refund amount, one of the following operations is performed:

  • reversal—the refund is initiated for the initial purchase amount and before the current business day closing
  • refund—the refund is initiated in either of the following scenarios: the refund is initiated for a fraction of the initial purchase amount on the same business day or the refund is initiated after the purchase business day closing for either fraction or total initial amount.

Though, there is an exception in this rule for the purchases with Visa or American Express cards: operation type depends only on timing:

  • reversal operation is created, if the refund is initiated before the current business day closing.
  • refund operation is created, if the refund is initiated after the current business day is closed.
Note: The business day here is understood as the time period which is used for clearing purposes. Normally, this is 24 hours, though it may be adjusted to account for day-light saving time. Business day start and end times may differ because of different factors, therefore it is advised to contact the ecommpay support to get the most accurate information.

To sum up: refund is supported for one-time and COF purchases, it is started by using a single request which initiates either refund or reversal operation.

Figure: Diagram of relations between request for refund, payment type, and operation


Diagram of relations between request for refund, payment type, and operation

Once a refund is complete, the payment platform sends to the web service a callback with refund completion result and the information about the current purchase status. After refund, purchase status can be one of the following:

  • success—purchase is complete, refund is not performed.
  • reversed—refund is performed in full before the current business day completion.
  • refunded—refund is performed in full after the current business day completion.
  • partially reversed—refund is performed for a fraction of the initial purchase amount before the current business day completion (applicable only to Visa and American Express cards).
  • partially refunded—refund is performed for a fraction of the initial purchase amount. (For Visa and American Express cards, refund is performed after the current business day completion.)
  • scheduled recurring processing—refund is performed for full or partial amount of the initial COF purchase. Note that this does not affect any future COF purchases.

Special aspects

The refund performing period depends on the issuing bank or payment provider which performs the operation, and may take a long time.

Any refund changes the payment amount. The callback includes information about the actual payment amount still available for further refunds. The actual payment amount is calculated as the initial purchase amount minus all the amounts repaid to customer. Suppose that the initial purchase amount is 13.70 USD. Then, if you make a 10.00 USD  refund, the actual payment amount will be 3.70 USD. If you make another refund for 3.70 USD, the actual payment amount will be zero. The rule also applies to any recurrent purchases where the actual payment amount is the total of all purchases minus all refunds.

Depending on payment method, some refund aspects can differ, for instance additional commission may be charged for late refunds. For more information about special refund aspects for specific payment methods, see Methods or contact your account manager at ecommpay.

Limitations

When performing refunds, you need to observe the following limitations:

  • The initial purchase must include at least one money transfer and the purchase status must be one of the following: success, partially paid, scheduled recurring processing, or partially refunded.

    If the initial purchase did not result in any money transfer or if the purchase status is not one of the listed above statuses, the refund request is declined and the payment platform sends to your web service a callback with the 3281 error code.

  • Refund currency must me the same as the initial purchase currency.

    If the currency in your refund request differs from the initial purchase currency, the refund is declined and the payment platform sends to your web service a callback with the 3284 error code. (For more information about error codes, see Information of operations performing.)

  • The time between consecutive attempts to send refund request must not be too small.

    If you send a repeated refund request within two minutes after the previous attempt, the refund will be declined and the payment platform will send your web service a callback with the 3285 error code.

  • The merchant account balance must be adequate to perform the refund.

    To check your account balance, you can use Data API (see Using Data API for details) or Dashboard (see Monitoring balances for details). Alternatively, you can contact your account manager at ecommpay.

  • Specific region requirement for refunds and requirements imposed by payment service providers and payment processors must be observed.

    For example, in Republic of Belarus, only one refund operation is allowed for each purchase. For more information about special refund features of specific payment methods, see Methods or contact your account manager at ecommpay.

  • There must be no chargeback claims pending for the purchase for which refund is requested.

    If there are any chargeback claim pending for the purchase, the refund request is declined and the payment platform sends to your web service a callback with the 3288 error code.

Additionally, the following limitations apply to partial refunds:

  • Partial refund amount cannot exceed the initial purchase amount, otherwise the refund request is declined and the payment platform sends to your web service a callback with the 3283 error code.
  • After processing a partial refund of a card payment, the actual payment amount should be at least 0.01 USD.

    The actual amount is checked on the payment platform side after the refund is initiated, the rates are used if the payment currency is other than USD. If the requirement is not met, the refund request is declined and a callback wit the 3117 error code is sent to the web service.

  • New partial refund can be initiated only if any previous partial refund in complete, otherwise the refund request is declined and the payment platform sends to your web service a callback with the 3285 error code.

For the information about request and callback formats for card operations, see below. For the information about request and callback formats for other payment methods, see Methods.

Request format

Refund request format complies with general request format regulations as described in Interaction concepts, and the target endpoint for the request is /v2/payment/card/refund. The request body must contain the following objects and parameters:

  • general—object with general request information, contains the following parameters:
    • project_id—the project ID obtained from ecommpay
    • payment_id—payment ID for which refund need to be performed
    • signature—signature created after you specify all the required parameters. For more information about signature generation, see Signature generation and verification).
  • payment—object with payment information which contains the following parameters:
    • description—description of the reason for refunding. This parameter is relevant only for refund operations. Passing this parameter does not modify in any way the description of the initial purchase if such description was included in the initial purchase request.

      The description of the reason for refunding can be passed in callbacks as a value of the operation_description parameter. This parameter is not used by default, but it can be added to the data set passed in callbacks upon coordination with the technical support specialists.

The parameter set listed above allows you to make only a full refund. To make a partial refund, you need to add the following parameters in the payment object:

  • amount—refund amount in minor currency units, must be not larger than the actual purchase balance
  • currency — payment currency in the ISO-4217 alpha-3 format, must be same as the initial purchase currency

Additionally, you can use any other parameters as specified in the the Gate API specification.

To sum up: any refund request must include project and payment IDs, signature, refund description, as well as currency code and amount, if required.

Figure: Sample refund request

{
  "general": {
    "project_id": 239,
    "payment_id": "payment2",
    "signature": "of8k9xeKJ7KLTZYO56lCv+f1M0Sf/7eg=="
  },
  "payment": {
    "description": "refund",
// For partial refund:
    "amount": 1000,
    "currency": "USD"
  }
}

Callback format

Callback with refund result complies with general callback format regulations described in Callbacks. The actual payment amount information is contained in the payment object, the information about the amount repaid to the customer is included in the operation object. Also, callback may include refund description in the operation_description object, if the support service have activated this option when onboarding.

Note: If several refunds are performed for a single purchase, each refund operation is assigned a separate identifier. The identifier is placed in the operation_id parameter inside the operation object.

Below, you will find examples of callbacks for two refund scenarios for an initial purchase with amount 13.70 USD:

  1. Partial 10.00 USD refund with the partially refunded status that makes the actual payment amount equal 3.70 USD.
  2. Full 13.70 USD refund with the refunded status that makes the actual payment amount equal 0.00 USD.

Each example shows the purchase description included in the initial payment request and a description of refund reason.

Figure: Sample callback with a partial refund information

{ 
  "project_id":239,
  "payment":{ 
    "id":"payment2",
    "type":"purchase", // Purchase type: one-time purchase
    "status":"partially refunded", // Purchase status after partial return
    "date":"2019-11-13T14:52:14+0000",
    "method":"card",
    "sum":{ 
      "amount":370, // Actual payment amount
      "currency":"USD" // Payment currency code
    },
    "description":"Thai massage session" // Payment description
  },
  "account":{ 
    "number":"431422******0056",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "operation_description":"Deficient service", // Refund reason
  "operation":{ 
    "id":3862,
    "type":"refund", // Operation type
    "status":"success", // Operation status
    "date":"2019-11-13T14:52:15+0000",
    "created_date":"2019-11-13T14:52:12+0000",
    "request_id":"0c4457b5fe8dada59-e7b58eceb8aecfa791-00049391",
    "sum_initial":{ 
      "amount":1000, // Refund amount
      "currency":"USD" // Refund currency code (same as initial purchase currency)
    },
    "sum_converted":{ 
      "amount":1000,
      "currency":"USD"
    },
    "code":"0",
    "message":"Success",
    "provider":{ 
      "id":414,
      "payment_id":"",
      "endpoint_id":414
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

Figure: Sample callback with a full refund information

{ 
  "project_id":239,
  "payment":{
    "id":"payment2",
    "type":"purchase", // Payment type: one-time purchase
    "status":"refunded", // Payment status after full refund
    "date":"2019-11-13T13:52:09+0000",
    "method":"card",
    "sum":{ 
      "amount":0, // Actual payment amount
      "currency":"USD" // Payment currency
    },
    "description":"Thai massage session" // Payment description
  },
  "account":{
    "number":"431422******0056",
    "token":"14c24c8a5384b413f11b2956a82ddaeea609ea49",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "customer":{
    "id":"1478"
  },
  "operation_description":"Service cancellation", // Refund reason
  "operation":{
    "id":3861,
    "type":"refund", // Operation type
    "status":"success", // Operation status
    "date":"2019-11-13T13:52:09+0000",
    "created_date":"2019-11-13T13:52:08+0000",
    "request_id":"67a97cd6b14f1aa0543c81e18cd270b66-aadc6e790206d5-00038611",
    "sum_initial":{ 
      "amount":1370, // Refund amount
      "currency":"USD" // Refund currency code (same as initial purchase currency)
    },
    "sum_converted":{
      "amount":1370,
      "currency":"USD"
    },
    "code":"0",
    "message":"Success",
    "provider":{
      "id":414,
      "payment_id":"",
      "endpoint_id":414
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

Here is a example in which a refund of 7.99 EUR is performed for a COF purchase with multiple purchases totaling 7.99 EUR. This makes the actual payment amount equal to 0.00 EUR. In this case, the payment status does not change because more purchases are expected for the payment. (For more information about payment statuses, see Payment models and statuses.)

Figure: Sample callback with a full refund information for multiple purchases

{ 
  "project_id":239,
  "payment":{ 
    "id":"payment3",
    "type":"recurring", // Payment type: COF purchase
    "status":"scheduled recurring processing", // Payment status after refund
    "date":"2019-11-13T17:23:26+0000",
    "method":"card",
    "sum":{ 
      "amount":0, // Actual payment amount
      "currency":"EUR" // Payment currency
    },
    "description":"Thai massage session" // Payment description
  },
  "account":{ 
    "number":"431422******0056",
    "token":"14c24c8a5384b413f11b2956a82ddaeea609ea49",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "customer":{ 
    "id":"1478"
  },
  "recurring":{ 
    "id":1061,
    "currency":"EUR",
    "valid_thru":"2027-05-31T00:00:00+0000"
  },
  "operation_description":"Refund for payment3 order", // Refund reason
  "operation":{ 
    "id":3861,
    "type":"refund", // Operation type
    "status":"success", // Operation status after successful refund
    "date":"2019-11-13T17:23:26+0000",
    "created_date":"2019-11-13T17:23:25+0000",
    "request_id":"bb36c8b4bce2c4-0198d59676189b0e344d1-00056689",
    "sum_initial":{ 
      "amount":799, // Refund amount
      "currency":"EUR" // Refund currency code (same as initial payment currency)
    },
    "sum_converted":{ 
      "amount":799,
      "currency":"EUR"
    },
    "code":"0",
    "message":"Success",
    "provider":{ 
      "id":414,
      "payment_id":"",
      "endpoint_id":6
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

Here is an example in which a refund of 60.00 USD for a one-time purchase is declined because of insufficient funds on merchant's account. This is indicated by the 3028 error returned by the payment platform. (For more information about error codes, see Information of operations performing.) Note that the amount and status of the payment do not change.

Figure: Sample callback with a refund decline information

{ 
  "project_id":239,
  "payment":{ 
    "id":"payment7",
    "type":"purchase", // Payment type: one-time purchase
    "status":"success", // Payment status after refund decline
    "date":"2019-12-29T15:29:47+0000",
    "method":"card",
    "sum":{ 
      "amount":6000, // Payment amount
      "currency":"USD" // Payment currency
    },
    "description":"Thai massage session" // Payment description
  },
  "account":{ 
    "number":"431422******0056",
    "token":"14c24c8a5384b413f11b2956a82ddaeea609ea49",
    "type":"visa",
    "card_holder":"JUDY DOE",
    "expiry_month":"03",
    "expiry_year":"2023"
  },
  "operation_description":"Error", // Refund reason
  "operation":{ 
    "id":3869,
    "type":"reversal", // Operation type
    "status":"decline", // Payment status after refund decline
    "date":"2019-12-29T15:32:29+0000",
    "created_date":"2019-12-29T15:32:29+0000",
    "request_id":"713446e4b43-06bfc7eed42c4c854697846a-00059692",
    "sum_initial":{ 
      "amount":6000, // Refund amount
      "currency":"USD" // Refund currency code (same as payment currency)
    },
    "sum_converted":{ 
      "amount":6000,
      "currency":"USD"
    },
    "code":"3028", // Error code
    "message":"Insufficient funds on merchant balance", // Error description
    "provider":{ 
      "id":120,
      "payment_id":"",
      "endpoint_id":120
    }
  },
  "signature":"of8k9xerKSK4XL1QFaDH3p9Mh0CIcjmOwSwKJ7KLTZYO56lCv+f1M0Sf/7eg=="
}

Related links