taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

post-private-orders-ORDER_ID-refund-external.rst (5431B)


      1 .. http:post:: [/instances/$INSTANCE]/private/orders/$ORDER_ID/refund-external
      2 
      3   Record a refund that was settled outside of Taler, for example a cash or
      4   card return.  Unlike Taler refunds, this is a bookkeeping entry only: the
      5   point-of-sale or external payment integration performs the actual return of
      6   funds, and no wallet pickup step exists or is needed.  The recorded entries
      7   are exposed through the order status as ``refunds_external``.
      8 
      9   Since protocol **vDonauReceipts**, an external refund, like a Taler refund,
     10   ends the wallet's ability to replay its payment request.  Donation receipts
     11   that the Donau had not yet issued for the order are then never issued.
     12 
     13   External refunds are available for any *paid* order, including pure Taler
     14   orders without ``amount_external``.  This is relevant because Taler refunds
     15   are constrained by the contract's refund deadline; once it has passed, the
     16   amount can only be returned through an external method, which is recorded
     17   here.
     18 
     19   The refund channel does not need to match the payment channel.  The backend
     20   validates external refunds against the order total: the cumulative
     21   externally refunded amount must not exceed the full order total (the Taler
     22   ``amount`` plus all ``amount_external`` entries) minus the amount already
     23   refunded through Taler, and must use the currency of the order.
     24 
     25   Each external refund is identified by an ``id`` chosen by the merchant and
     26   unique within the order.  Recording a refund under an ``id`` that already
     27   exists is *idempotent* if the request body is identical, which makes it safe
     28   for a point-of-sale application to retry after a network failure without
     29   consuming the refundable amount twice.  Reusing an existing ``id`` with a
     30   different body is refused as a conflict.
     31 
     32   The identifier is mandatory: a recorded external refund cannot be removed,
     33   so a duplicate would permanently consume part of the amount that may still
     34   be refunded for the order.
     35 
     36   **Required permission:** ``orders-refund`` (see :ref:`Scopes <merchant-api-scopes>`)
     37 
     38   Since protocol **v42**.
     39 
     40   **Request:**
     41 
     42   The request body is an `ExternalRefundRequest` object.
     43 
     44   **Response:**
     45 
     46   :http:statuscode:`200 OK`:
     47     The external refund was recorded, or had already been recorded with
     48     an identical request body.  The response is an
     49     `ExternalRefundResponse` object containing the identifier of the
     50     refund.
     51   :http:statuscode:`400 Bad Request`:
     52     The request body is malformed, for example the ``method`` is empty,
     53     is ``taler``, contains characters other than ASCII alphanumerics
     54     and ``-``, or the ``id`` is empty.
     55     Returned with ``TALER_EC_GENERIC_PARAMETER_MALFORMED``.
     56   :http:statuscode:`401 Unauthorized`:
     57     The request is unauthorized.
     58   :http:statuscode:`404 Not found`:
     59     The order is unknown to the merchant.
     60     Returned with ``TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN``.
     61   :http:statuscode:`409 Conflict`:
     62     The external refund could not be recorded.
     63     Returned with
     64     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_ORDER_UNPAID``
     65     if the order is not paid,
     66     ``TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH``
     67     if the refund uses a different currency than the order, or
     68     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_EXTERNAL_INCONSISTENT_AMOUNT``
     69     if the cumulative external refunds would exceed the order total minus
     70     the amount already refunded through Taler, or
     71     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ID_REFUND_EXTERNAL_ALREADY_EXISTS``
     72     if an external refund with the same ``id`` was already recorded for
     73     this order with different details.
     74   :http:statuscode:`500 Internal Server Error`:
     75     The server experienced an internal failure.
     76     Returned with ``TALER_EC_GENERIC_DB_START_FAILED``,
     77     ``TALER_EC_GENERIC_DB_FETCH_FAILED``,
     78     ``TALER_EC_GENERIC_DB_STORE_FAILED``,
     79     ``TALER_EC_GENERIC_DB_COMMIT_FAILED``,
     80     ``TALER_EC_GENERIC_DB_SOFT_FAILURE``,
     81     ``TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH`` or
     82     ``TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID``.
     83 
     84   **Details:**
     85 
     86   .. ts:def:: ExternalRefundRequest
     87 
     88     interface ExternalRefundRequest {
     89       // Method by which the funds were returned to the customer,
     90       // for example "cash" or "card". May differ from the methods used
     91       // to pay the order. Must be a stable, non-empty identifier of
     92       // ASCII alphanumerics and "-", and must never be "taler".
     93       method: string;
     94 
     95       // Identifier of this refund within the order, chosen by the
     96       // merchant. Must be non-empty. Re-using an identifier with an
     97       // identical request body is idempotent; re-using it with
     98       // different details is a conflict.
     99       id: string;
    100 
    101       // Optionally, the ``id`` of the ``amount_external`` entry this
    102       // refund reverses, when the refund maps to a specific original
    103       // payment (for example a card transaction reversal).
    104       payment_id?: string;
    105 
    106       // Amount returned to the customer via the external method.
    107       // Must use the currency of the order.
    108       amount: Amount;
    109 
    110       // Human-readable refund justification, mirroring Taler refunds.
    111       reason: string;
    112     }
    113 
    114   .. ts:def:: ExternalRefundResponse
    115 
    116     interface ExternalRefundResponse {
    117       // Identifier of the recorded external refund within the order,
    118       // as given in the request. Can be used to reference the refund
    119       // later.
    120       refund_id: string;
    121     }