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 }