taler-docs

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

post-private-orders.rst (10127B)


      1 .. _merchant-post-private-orders:
      2 
      3 .. http:post:: [/instances/$INSTANCE]/private/orders
      4 
      5   Create a new order that a customer can pay for.
      6 
      7   This request is **not** idempotent unless an ``order_id`` is explicitly specified.
      8   However, while repeating without an ``order_id`` will create another order, that is
      9   generally pretty harmless (as long as only one of the orders is returned to the wallet).
     10 
     11   .. note::
     12 
     13     This endpoint does not return a URL to redirect your user to confirm the
     14     payment.  To get this URL use either
     15     :http:get:`[/instances/$INSTANCE]/orders/$ORDER_ID` (with
     16     ``taler_pay_uri`` in the `StatusUnpaidResponse`), or
     17     :http:get:`[/instances/$INSTANCE]/private/orders/$ORDER_ID` with the
     18     ``taler_pay_uri`` in the `CheckPaymentUnpaidResponse`). That said,
     19     it is also possible to construct the URL by combining the base URL
     20     with the information from the `PostOrderResponse`.
     21     The API is structured this way since the payment redirect URL is not
     22     unique for every order: there might be varying parameters such as the
     23     session id.
     24 
     25   **Required permission:** ``orders-write``
     26 
     27   **Request:**
     28 
     29   The request must be a `PostOrderRequest`.
     30 
     31   **Response:**
     32 
     33   :http:statuscode:`200 OK`:
     34     The backend has successfully created the proposal.  The response is a
     35     :ts:type:`PostOrderResponse`.
     36   :http:statuscode:`400 Bad Request`:
     37     The request body is malformed.
     38     Returned with ``TALER_EC_GENERIC_PARAMETER_MALFORMED``,
     39     ``TALER_EC_GENERIC_PARAMETER_MISSING``,
     40     ``TALER_EC_GENERIC_JSON_INVALID``,
     41     ``TALER_EC_GENERIC_VERSION_MALFORMED``,
     42     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_PROPOSAL_PARSE_ERROR``,
     43     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_PAY_DEADLINE_IN_PAST``,
     44     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_DELIVERY_DATE_IN_PAST``,
     45     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_REFUND_DEADLINE_IN_PAST``,
     46     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_WIRE_DEADLINE_IS_NEVER`` or
     47     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_REFUND_AFTER_WIRE_DEADLINE``.
     48   :http:statuscode:`404 Not found`:
     49     Possible reasons are:
     50 
     51     (1) The order given used products from the inventory, but those were
     52         not found in the inventory.
     53     (2) The merchant instance is unknown (including possibly the instance
     54         being not configured for new orders).
     55     (3) The wire method specified is not supported by the backend.
     56     (4) An OTP device ID was specified and is unknown.
     57 
     58     Returned with ``TALER_EC_MERCHANT_GENERIC_PRODUCT_UNKNOWN``,
     59     ``TALER_EC_MERCHANT_GENERIC_OTP_DEVICE_UNKNOWN``,
     60     ``TALER_EC_MERCHANT_GENERIC_MONEY_POT_UNKNOWN``,
     61     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_INSTANCE_CONFIGURATION_LACKS_WIRE`` or
     62     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_SLUG_UNKNOWN``.
     63   :http:statuscode:`409 Conflict`:
     64     A different proposal already exists under the specified order ID,
     65     or the requested currency is not supported by this backend.
     66     Returned with ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS``,
     67     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGES_FOR_WIRE_METHOD`` or
     68     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY``.
     69   :http:statuscode:`410 Gone`:
     70     The order given used products from the inventory that are out of stock.
     71     The response is a :ts:type:`OutOfStockResponse`.
     72   :http:statuscode:`451 Unavailable for Legal Reasons`:
     73     The order could not be created because of legal
     74     reasons, specifically no exchange would accept
     75     a payment at this time because we have not yet
     76     satisfied the respective legal requirements.
     77     The :ref:`KYC status <merchantkycstatus>` API
     78     can be used to determine details about how to
     79     proceed with the KYC process.
     80     Since **v25**, the body is an
     81     `OrderRefusedErrorDetailResponse` with an error
     82     code of ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_AMOUNT_EXCEEDS_LEGAL_LIMITS``.
     83   :http:statuscode:`500 Internal Server Error`:
     84     The server experienced an internal failure.
     85     Returned with ``TALER_EC_GENERIC_DB_STORE_FAILED``,
     86     ``TALER_EC_GENERIC_DB_FETCH_FAILED``,
     87     ``TALER_EC_GENERIC_DB_COMMIT_FAILED``,
     88     ``TALER_EC_GENERIC_DB_SOFT_FAILURE``,
     89     ``TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH``,
     90     ``TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE``,
     91     ``TALER_EC_GENERIC_ALLOCATION_FAILURE``,
     92     ``TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_LOCALTIME``,
     93     ``TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE`` or
     94     ``TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH``.
     95 
     96   **Details:**
     97 
     98   .. ts:def:: PostOrderRequest
     99 
    100     interface PostOrderRequest {
    101       // The order must at least contain the minimal
    102       // order detail, but can override all.
    103       order: Order;
    104 
    105       // If set, the backend will then set the refund deadline to the
    106       // payment deadline plus the specified delay.
    107       // If it's not set, the default value of the backend might be
    108       // used. Note that both this value and the backend default
    109       // will be ignored if ``refund_deadline`` is set in ``order``
    110       // as the ``refund_deadline`` takes precedence.
    111       // A value of "forever" is not allowed.
    112       refund_delay?: RelativeTime;
    113 
    114       // Specifies the payment target preferred by the client. Can be used
    115       // to select among the various (active) wire methods supported by the instance.
    116       payment_target?: string;
    117 
    118       // The session for which the payment is made (or replayed).
    119       // Only set for session-based payments.
    120       // Since protocol **v6**.
    121       session_id?: string;
    122 
    123       // Specifies that some products are to be included in the
    124       // order from the inventory.  For these inventory management
    125       // is performed (so the products must be in stock) and
    126       // details are completed from the product data of the backend.
    127       inventory_products?: MinimalInventoryProduct[];
    128 
    129       // Specifies a lock identifier that was used to
    130       // lock a product in the inventory.  Only useful if
    131       // ``inventory_products`` is set.  Used in case a frontend
    132       // reserved quantities of the individual products while
    133       // the shopping cart was being built.  Multiple UUIDs can
    134       // be used in case different UUIDs were used for different
    135       // products (i.e. in case the user started with multiple
    136       // shopping sessions that were combined during checkout).
    137       lock_uuids?: string[];
    138 
    139       // Should a token for claiming the order be generated?
    140       // False can make sense if the ORDER_ID is sufficiently
    141       // high entropy to prevent adversarial claims (like it is
    142       // if the backend auto-generates one). Default is 'true'.
    143       // Note: This is NOT related to tokens used for subscriptins or discounts.
    144       create_token?: boolean;
    145 
    146       // OTP device ID to associate with the order.
    147       // This parameter is optional.
    148       otp_id?: string;
    149 
    150     }
    151 
    152   .. ts:def:: PostOrderResponse
    153 
    154     interface PostOrderResponse {
    155       // Order ID of the response that was just created.
    156       order_id: string;
    157 
    158       // Deadline when the offer expires; the customer must pay before.
    159       // @since protocol **v21**.
    160       pay_deadline: Timestamp;
    161 
    162       // Token that authorizes the wallet to claim the order.
    163       // Provided only if "create_token" was set to 'true'
    164       // in the request.
    165       token?: ClaimToken;
    166     }
    167 
    168   .. ts:def:: OutOfStockResponse
    169 
    170     interface OutOfStockResponse {
    171 
    172       // Product ID of an out-of-stock item.
    173       product_id: string;
    174 
    175       // Legacy integer quantity requested. Deprecated; see ``unit_requested_quantity``.
    176       requested_quantity: Integer;
    177 
    178       // Requested quantity using "<integer>[.<fraction>]" syntax with up to six fractional digits.
    179       unit_requested_quantity: string;
    180 
    181       // Legacy integer availability (must be below ``requested_quantity``).
    182       available_quantity: Integer;
    183 
    184       // Available quantity using "<integer>[.<fraction>]" syntax with up to six fractional digits.
    185       unit_available_quantity: string;
    186 
    187       // When do we expect the product to be again in stock?
    188       // Optional, not given if unknown.
    189       restock_expected?: Timestamp;
    190     }
    191 
    192 
    193   .. ts:def:: OrderRefusedErrorDetailResponse
    194 
    195     interface OrderRefusedErrorDetailResponse {
    196 
    197       // Numeric `error code <error-codes>` unique to the condition.
    198       // Will be MERCHANT_PRIVATE_POST_ORDERS_AMOUNT_EXCEEDS_LEGAL_LIMITS).
    199       code: ErrorCode;
    200 
    201       // Human-readable description of the error, i.e. "missing parameter", "commitment violation", ...
    202       // Should give a human-readable hint about the error's nature. Optional, may change without notice!
    203       hint?: string;
    204 
    205       // Detail about why a specific exchange was rejected.
    206       // Note that an exchange that was allowed is not listed.
    207       // It is possible that no exchanges were rejected (in which
    208       // case this array would be empty) and still the operation
    209       // failed because the total of the allowed amounts per
    210       // exchange ended up below the order total. Thus, that
    211       // is ultimately always the cause here (as per the code),
    212       // but the *other* reasons why exchanges might have been
    213       // rejected could be enlightening to the user and are
    214       // thus provided here.
    215       exchange_rejections: ExchangeRejectionDetail;
    216     }
    217 
    218   .. ts:def:: ExchangeRejectionDetail
    219 
    220     interface ExchangeRejectionDetail {
    221 
    222       // Base URL of the rejected exchange
    223       exchange_url: string;
    224 
    225       // Numeric `error code <error-codes>` unique to why
    226       // this exchange was not acceptable.
    227       // Can be MERCHANT_GENERIC_CURRENCY_MISMATCH,
    228       // MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED
    229       // (zero deposit limit, likely KYC required),
    230       // MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE
    231       // (we failed to download /keys from the exchange),
    232       // MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED
    233       // (none of our bank accounts has a compatible wire method)
    234       code: ErrorCode;
    235 
    236       // Human-readable description of the error.
    237       // Should give a human-readable hint about the error's nature.
    238       // Optional, may change without notice!
    239       hint?: string;
    240 
    241     }