Refund Payments

Refunding payments automatically after a payment exception scenario occurs.

In the case where a payment exception scenario has taken place, BVNK provides the option to automatically refund the cryptocurrency for merchants who do not want to hold these cryptocurrencies, due to any compliance issues, or for merchants that do not want to internally process any payments that have fallen outside of the agreed upon payment rules.

🚧

Auto Refund does not automatically return the funds to the sender's address.

Instead, it generates a payout and sends a URL via webhook. This URL should be forwarded to the end user, allowing them to provide their address and accept the refund.

How a refund works

Refunds function as an automatically generated payout request, which needs to be sent to the end user to complete. In this case, the user needs to enter their desired wallet address to which they want the funds sent and confirm the payout.

Refund exception scenarios

As stated on the previous pages, the three payment exception scenarios to consider are:

  • Overpayments
  • Underpayments
  • Late payments

These three scenarios are handled separately on a Merchant ID (MID) level. It means that each created MID can be configured to automatically initiate the refund process for one or more of these scenarios. Each scenario handles the refund slightly differently, as explained below.

📘

Contact your Merchant Support or Integration Manager to have the refund options enabled.

Overpayments

When an overpayment has occurred, the status of the transaction is updated from PROCESSING to COMPLETE. This COMPLETE status should be seen as a standard successful payment on the merchant's side.

The original payment amount requested in the invoice is credited to the merchant's wallet as usual. Still, the additional amount of overpaid cryptocurrency is deposited into a holding account, ensuring no impact on the merchant's wallet balance.

This additional amount is then the total amount that will be returned to the sender as an automatically generated payout.

Underpayments

When an underpayment has occurred, the status of the transaction is updated from PROCESSING to UNDERPAID. This UNDERPAID status should be marked as an unsuccessful payment on the merchant's side.

The entire payment amount is deposited into a holding account, ensuring it is not credited to the merchant's wallet.

The full payment amount of the underpayment is then the total amount that will be returned to the sender as an automatically generated payout.

Late payments

In the rare occurrence that a late payment has occurred, the status of the transaction is updated from PENDING to EXPIRED. This EXPIRED status should be marked as an unsuccessful payment on the merchant's side.

The entire payment amount is deposited into a holding account, ensuring it is not credited to the merchant's wallet.

The full payment amount for the late payment is then the total amount that will be returned to the sender as an automatically generated payout.

Refund flow

The ideal flow of an automatically generated refund is given as follows:

  1. The merchant creates the payment request for an end user.
  2. The merchant forwards the payment link returned from BVNK to the end user.
  3. The end user completes the payment by sending funds to the given address.
  4. The total funds amount is too low, too high, or received late, triggering the appropriate refund.
  5. BVNK sends a webhook notification to the merchant, specifying the amount to refund and the URL where it can be claimed.
  6. The merchant notifies the end user about the URL.
  7. The end user navigates to the URL and enters their wallet address.
  8. Once BVNK receives this address, the displayed amount of cryptocurrency is sent through, less the fees.
  9. The merchant receives a relevant webhook that updates the success of the refund payout.
  10. The process is complete.

Expired refund

If the end user never entered their wallet address and confirms the refund within the expiry limit,

  1. The refund will become EXPIRED. The default expiry limit for a refund is set to three months.
  2. When the limit is reached, the total refund amount will be transferred from the held account to the merchant's MID wallet.
  3. A further webhook is sent to the merchant to indicate that the refund has expired and the amounts have been credited to the appropriate wallet.

Refund webhooks

BVNK automatically initiates the refund process, which in effect acts as a payout transaction.

The merchant will receive a refundInitiated event webhook. Pay attention to the following webhook fields:

Webhook fieldDescription
event: refundIntiatedEvent type indicating that the refund has been initiated.
data.uuid: xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxUUID of the refund, different to the linked incoming payment.
data.type: OUTType. For a refund, it is always set to OUT.
data.subType: merchantRefundSubtype indicating it is a Merchant refund.
data.status: PENDINGStatus of a refund. Possible options: EXPIRED or COMPLETE.
data.redirectUrl: https://pay.bvnk.com/payout?uuid=URL to send to the end user, allowing them to enter their address and claim the refund.

If the refund is not claimed and has expired, a statusChanged event webhook is sent to the merchant. The important fields in this webhook are the following:

Webhook fieldDescription
event: statusChangedEvent type indicating that the refund has had its status changed.
data.uuid: xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxMatching UUID of the refund.
data.subType: merchantRefundSubtype indicating it is a Merchant refund.
data.status: EXPIREDFinal state of the expired payment.

{
  "source": "payment",
  "event": "refundInitiated",
  "data": {
    "uuid": "9485895b-c4a3-4885-bcdc-XXXXXXXXXX",
    "merchantDisplayName": "Merchant Name",
    "merchantId": "00a4af9d-ad4b-42d5-bec4-XXXXXXXXXX",
    "dateCreated": 1689264437804,
    "expiryDate": 1689869237804,
    "quoteExpiryDate": null,
    "acceptanceExpiryDate": null,
    "quoteStatus": "TEMPLATE",
    "reference": "REFUND-XXXXX",
    "type": "OUT",
    "subType": "merchantRefund",
    "status": "PENDING",
    "displayCurrency": {
      "currency": "EUR",
      "amount": 24.58,
      "actual": 0
    },
    "walletCurrency": {
      "currency": "ETH",
      "amount": 0.01421,
      "actual": 0
    },
    "paidCurrency": {
      "currency": null,
      "amount": 0,
      "actual": 0
    },
    "feeCurrency": {
      "currency": "EUR",
      "amount": 0.49,
      "actual": 0.49
    },
    "displayRate": null,
    "exchangeRate": null,
    "address": null,
    "returnUrl": "",
    "redirectUrl": "https://pay.sandbox.bvnk.com/payout?uuid=9485895b-c4a3-4885-bcdc-XXXXXXXXXX",
    "transactions": [],
    "refund": {
      "uuid": "309d82fd-e1d4-4354-9015-XXXXXXXXXX",
      "merchantDisplayName": "Merchant Name",
      "merchantId": "00a4af9d-ad4b-42d5-bec4-XXXXXXXXXX",
      "dateCreated": 1689264326000,
      "expiryDate": 1689265526000,
      "quoteExpiryDate": 1689265526000,
      "acceptanceExpiryDate": 1689264363000,
      "quoteStatus": "ACCEPTED",
      "reference": "reference",
      "type": "IN",
      "subType": "merchantPayIn",
      "status": "COMPLETE",
      "displayCurrency": {
        "currency": "EUR",
        "amount": 10,
        "actual": 10
      },
      "walletCurrency": {
        "currency": "EUR",
        "amount": 10,
        "actual": 10
      },
      "paidCurrency": {
        "currency": "ETH",
        "amount": 0.00579,
        "actual": 0.02
      },
      "feeCurrency": {
        "currency": "EUR",
        "amount": 0.1,
        "actual": 0.1
      },
      "displayRate": {
        "base": "ETH",
        "counter": "EUR",
        "rate": 1727.070973981676
      },
      "exchangeRate": {
        "base": "ETH",
        "counter": "EUR",
        "rate": 1727.071668
      },
      "address": {
        "address": "0x434c932fc5e324204c80c1fb15f3a7XXXXX",
        "tag": null,
        "protocol": "ETH",
        "uri": "ethereum:0x434c932fc5e324204c80c1fb15f3a7XXXXX?value=5.79015E+15",
        "alternatives": []
      },
      "returnUrl": "",
      "redirectUrl": "https://pay.sandbox.bvnk.com/payin?uuid=309d82fd-e1d4-4354-9015-XXXXXXXXXX",
      "transactions": [
        {
          "dateCreated": 1689264367000,
          "dateConfirmed": 1689264429000,
          "hash": "0x034612080ab226a5c3254b521f30dafd7df30dd1c1fc35723cf6XXXXX",
          "amount": 0.02,
          "risk": {
            "level": "LOW",
            "resourceName": "UNKNOWN",
            "resourceCategory": "UNKNOWN",
            "alerts": []
          },
          "networkFeeCurrency": "ETH",
          "networkFeeAmount": 0.0000315,
          "sources": [
            "0x4b8b57aa7a92ea959c92aa32a72bbXXXXX3"
          ],
          "displayRate": {
            "base": "ETH",
            "counter": "EUR",
            "rate": 1727.070973981676
          },
          "exchangeRate": {
            "base": "ETH",
            "counter": "EUR",
            "rate": 1727.071668
          }
        }
      ],
      "refund": null,
      "refunds": []
    },
    "refunds": []
  }
}
{
  "source": "payment",
  "event": "statusChanged",
  "data": {
    "uuid": "9485895b-c4a3-4885-bcdc-XXXXXXXXXX",
    "merchantDisplayName": "Merchant Name",
    "merchantId": "00a4af9d-ad4b-42d5-bec4-XXXXXXXXXX",
    "dateCreated": 1689264438000,
    "expiryDate": 1689264510403,
    "quoteExpiryDate": 1689275310395,
    "acceptanceExpiryDate": 1689264540395,
    "quoteStatus": "ACCEPTED",
    "reference": "REFUND-XXXXX",
    "type": "OUT",
    "subType": "merchantRefund",
    "status": "EXPIRED",
    "displayCurrency": {
      "currency": "EUR",
      "amount": 24.58,
      "actual": 0
    },
    "walletCurrency": {
      "currency": "EUR",
      "amount": 23.49968,
      "actual": 23.49968
    },
    "paidCurrency": {
      "currency": null,
      "amount": 0,
      "actual": 0
    },
    "feeCurrency": {
      "currency": "EUR",
      "amount": 0.49,
      "actual": 0.49
    },
    "displayRate": null,
    "exchangeRate": {
      "base": "ETH",
      "counter": "EUR",
      "rate": 1653.7602177875
    },
    "address": null,
    "returnUrl": "",
    "redirectUrl": "https://pay.sandbox.bvnk.com/payout?uuid=9485895b-c4a3-4885-bcdc-XXXXXXXXXX",
    "transactions": [],
    "refund": {
      "uuid": "309d82fd-e1d4-4354-9015-XXXXXXXXXX",
      "merchantDisplayName": "Metallica Inc",
      "merchantId": "00a4af9d-ad4b-42d5-bec4-XXXXXXXXXX",
      "dateCreated": 1689264326000,
      "expiryDate": 1689265526000,
      "quoteExpiryDate": null,
      "acceptanceExpiryDate": null,
      "quoteStatus": "TEMPLATE",
      "reference": "XXXXXXXXXX",
      "type": "IN",
      "subType": "merchantPayIn",
      "status": "COMPLETE",
      "displayCurrency": {
        "currency": "EUR",
        "amount": 10,
        "actual": 10
      },
      "walletCurrency": {
        "currency": "EUR",
        "amount": 10,
        "actual": 10
      },
      "paidCurrency": {
        "currency": "ETH",
        "amount": 0.00579,
        "actual": 0.02
      },
      "feeCurrency": {
        "currency": "EUR",
        "amount": 0.1,
        "actual": 0.1
      },
      "displayRate": {
        "base": "ETH",
        "counter": "EUR",
        "rate": 1727.070973981676
      },
      "exchangeRate": null,
      "address": null,
      "returnUrl": "",
      "redirectUrl": "https://pay.sandbox.bvnk.com/payin?uuid=309d82fd-e1d4-4354-9015-XXXXXXXXXX",
      "transactions": [
        {
          "dateCreated": 1689264367000,
          "dateConfirmed": 1689264429000,
          "hash": "0x034612080ab226a5c3254b521f30dafd7df30dd1c1fc35723cf638XXXXX",
          "amount": 0.02,
          "risk": {
            "level": "LOW",
            "resourceName": "UNKNOWN",
            "resourceCategory": "UNKNOWN",
            "alerts": []
          },
          "networkFeeCurrency": "ETH",
          "networkFeeAmount": 0.0000315,
          "sources": [
            "0x4b8b57aa7a92ea959c92aa32a72bb3dXXXXX7"
          ],
          "displayRate": {
            "base": "ETH",
            "counter": "EUR",
            "rate": 1727.070973981676
          },
          "exchangeRate": {
            "base": "ETH",
            "counter": "EUR",
            "rate": 1727.071668
          }
        }
      ],
      "refund": null,
      "refunds": []
    },
    "refunds": []
  }
}