post-orders-ORDER_ID-pay.rst (17741B)
1 .. http:post:: [/instances/$INSTANCE]/orders/$ORDER_ID/pay 2 3 Pay for an order by giving a deposit permission for coins. Typically used by 4 the customer's wallet. Note that this request does not include the 5 usual ``h_contract`` argument to authenticate the wallet, as the hash of 6 the contract is implied by the signatures of the coins. Furthermore, this 7 API doesn't really return useful information about the order. 8 9 **Request:** 10 11 The request must be a `pay request <PayRequest>`. 12 13 **Response:** 14 15 :http:statuscode:`200 OK`: 16 The exchange accepted all of the coins. 17 The body is a `payment response <PaymentResponse>`. 18 The ``frontend`` should now fulfill the contract. 19 Note that it is possible that refunds have been granted. 20 :http:statuscode:`400 Bad request`: 21 Either the client request is malformed or some specific processing error 22 happened that may be the fault of the client as detailed in the JSON body 23 of the response. 24 This includes the case where the payment is insufficient (sum is below 25 the required total amount, for example because the wallet calculated the 26 fees wrong). 27 Applicable error codes: 28 29 * ``MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND``: Wallet tried 30 to pay with a non-existent denomination. 31 * ``MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED``: The 32 denomination used for payment has expired for deposits. 33 * ``MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING``: An age commitment 34 is required but was not provided. 35 * ``MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH``: The age 36 commitment has the wrong number of public keys. 37 * ``MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED``: The age 38 verification signature is invalid. 39 * ``MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING``: The age 40 commitment hash is required but was not provided. 41 * ``MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT``: The total payment 42 amount is insufficient to cover the order. 43 * ``MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES``: The payment 44 is insufficient because fees exceed what is covered. 45 * ``MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ISSUE_SIG_INVALID``: A token issue 46 signature is invalid. 47 * ``MERCHANT_POST_ORDERS_ID_PAY_TOKEN_USE_SIG_INVALID``: A token use 48 signature is invalid. 49 * ``MERCHANT_POST_ORDERS_ID_PAY_TOKEN_COUNT_MISMATCH``: The number of 50 input tokens does not match the expected count. 51 * ``MERCHANT_POST_ORDERS_ID_PAY_TOKEN_ENVELOPE_COUNT_MISMATCH``: The number 52 of output token envelopes does not match the expected count. 53 * ``MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_OUT_OF_BOUNDS``: The 54 ``choice_index`` in the wallet data is out of range. 55 * ``MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISSING``: The 56 ``choice_index`` is required but was not provided. 57 * ``MERCHANT_GENERIC_EXCHANGE_UNTRUSTED``: The exchange used for a coin 58 is not trusted by this merchant. 59 * ``MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW``: Payment amount overflowed. 60 * ``MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT``: Fees exceed the payment. 61 * ``MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED``: Adding wire fees failed. 62 * ``MERCHANT_POST_ORDERS_ID_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE``: Refund deadline past wire deadline. 63 * ``MERCHANT_POST_ORDERS_ID_PAY_WIRE_HASH_UNKNOWN``: Wire hash unknown. 64 * ``MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED``: Wire method unsupported. 65 * ``GENERIC_PARAMETER_MALFORMED``: A request parameter is malformed. 66 67 :http:statuscode:`402 Payment required`: 68 There used to be a sufficient payment, but due to refunds the amount effectively 69 paid is no longer sufficient. (If the amount is generally insufficient, we 70 return "400 Bad Request", only if this is because of refunds we return 402.) 71 Returned with ``TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDED``. 72 :http:statuscode:`403 Forbidden`: 73 One of the coin signatures was not valid. 74 :http:statuscode:`404 Not found`: 75 The merchant backend could not find the order 76 or the instance or a token family or 77 the Donau charity specified in 78 the contract and thus cannot process the payment. 79 Applicable error codes: 80 81 * ``MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN`` 82 * ``MERCHANT_GENERIC_ORDER_UNKNOWN`` 83 * ``MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN`` 84 * ``MERCHANT_GENERIC_INSTANCE_UNKNOWN`` 85 86 :http:statuscode:`408 Request timeout`: 87 The backend took too long to process the request. Likely the merchant's connection 88 to the exchange timed out. Try again. 89 Applicable error codes: 90 91 * ``MERCHANT_GENERIC_EXCHANGE_TIMEOUT`` 92 93 :http:statuscode:`409 Conflict`: 94 The exchange rejected the payment because a coin was already spent (or 95 used in a different way for the same purchase previously), or 96 the merchant rejected the payment because the order was already fully paid 97 (and then return signatures with refunds). If a coin was already spent 98 (this includes re-using the same coin after a refund), 99 the response will include the ``exchange_url`` for which the payment failed, 100 in addition to the response from the exchange to the :http:post:`/batch-deposit </batch-deposit>` request. 101 Applicable error codes: 102 103 * ``MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS``: Exchange reported insufficient 104 funds for one of the coins. 105 * ``MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISMATCH``: The order was 106 already paid, but completing a different choice than the one given in 107 this request, so the request does not describe the payment that was 108 made. The response is an `AlreadyPaidChoiceResponse` and contains the 109 ``choice_index`` the order was actually paid with. 110 Since protocol **vMixedPayments**. 111 * ``MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID``: The order was already 112 fully paid by another wallet. The response includes refund signatures 113 for the coins. 114 * ``MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID``: A token was already used 115 in a previous payment. 116 * ``MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH``: The donation 117 amount does not match the expected amount or exceeds the yearly limit. 118 * ``MERCHANT_GENERIC_CURRENCY_MISMATCH``: Coin currency does not match 119 the expected payment currency. 120 121 :http:statuscode:`410 Gone`: 122 The offer has expired and is no longer available or 123 the provided payment has expired. 124 Applicable error codes: 125 126 * ``MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED``: payment expired 127 * ``MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED``: offer expired 128 129 :http:statuscode:`412 Precondition failed`: 130 The given exchange is not acceptable for this merchant, as it is not in the 131 list of accepted exchanges and not audited by an approved auditor. 132 TODO: Status code may be changed to 409 in the future as 412 is technically wrong. 133 :http:statuscode:`413 Request entity too large`: 134 The uploaded body is to long, it exceeds the size limit. 135 Returned with an error code of 136 ``TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT``. 137 :http:statuscode:`451 Unavailable for Legal Reasons`: 138 The exchange has rejected the deposit by the merchant 139 for legal reasons. This is **not** exactly a client 140 failure (and possibly nobody's fault except for the 141 regulator). In any case, the wallet should refresh 142 the deposited coins of the affected exchange and 143 may try to pay with coins from another exchange if 144 possible (it has such coins and the merchant accepts 145 coins from another exchange). 146 The body is a `PaymentDeniedLegallyResponse` with 147 details about the failure. 148 Since protocol **v17**. 149 Returned with ``TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED`` or 150 ``TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION``. 151 :http:statuscode:`501 Not implemented`: 152 This is returned if an optional feature required to 153 process this particular payment is no longer implemented. 154 This should only be possible if a different version 155 of the backend software was deployed between order 156 creation and payment. 157 158 Applicable error codes: 159 160 * ``MERCHANT_GENERIC_DONAU_NOT_CONFIGURED``: returned if donations are not supported 161 * ``MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE``: usually returned if a token type is not supported 162 163 :http:statuscode:`502 Bad gateway`: 164 The merchant's interaction with the exchange failed in some way. 165 The client might want to try again later. 166 This includes failures such as the denomination key of a coin not being 167 known to the exchange as far as the merchant can tell. 168 Applicable error codes: 169 170 * ``MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS`` 171 * ``MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED`` 172 * ``MERCHANT_GENERIC_DONAU_INVALID_RESPONSE`` 173 174 :http:statuscode:`500 Internal Server Error`: 175 The server experienced an internal failure. 176 Returned with ``TALER_EC_GENERIC_DB_STORE_FAILED``, 177 ``TALER_EC_GENERIC_DB_FETCH_FAILED``, 178 ``TALER_EC_GENERIC_DB_START_FAILED``, 179 ``TALER_EC_GENERIC_DB_COMMIT_FAILED``, 180 ``TALER_EC_GENERIC_DB_SOFT_FAILURE``, 181 ``TALER_EC_GENERIC_DB_INVARIANT_FAILURE``, 182 ``TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE``, 183 ``TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH`` or 184 ``TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID``. 185 :http:statuscode:`504 Gateway timeout`: 186 The merchant's interaction with the exchange took too long. 187 The client might want to try again later. 188 189 The backend will return verbatim the error codes received from the exchange's 190 :ref:`deposit <deposit>` API. If the wallet made a mistake, like by 191 double-spending for example, the frontend should pass the reply verbatim to 192 the browser/wallet. If the payment was successful, the frontend MAY use 193 this to trigger some business logic. 194 195 **Details:** 196 197 .. ts:def:: AlreadyPaidChoiceResponse 198 199 interface AlreadyPaidChoiceResponse { 200 // Error code identifying the conflict, always 201 // ``MERCHANT_POST_ORDERS_ID_PAY_CHOICE_INDEX_MISMATCH``. 202 code: number; 203 204 // Index of the choice within the ``choices`` array of the 205 // contract terms that the order was actually paid with. A client 206 // that wants to refer to the payment that was made has to use 207 // this choice instead of the one it asked for. 208 choice_index: Integer; 209 } 210 211 .. ts:def:: PaymentResponse 212 213 interface PaymentResponse { 214 // Signature on ``TALER_PaymentResponsePS`` with the public 215 // key of the merchant instance. 216 sig: EddsaSignature; 217 218 // Text to be shown to the point-of-sale staff as a proof of 219 // payment. 220 // For OTP devices using a challenge-signature algorithm 221 // ("ECDSA_CHALLENGE" or "EDDSA_CHALLENGE"), contains the 222 // Crockford Base32 encoded signature over the hash of the 223 // order's challenge, made with the device private key. 224 // Since protocol **vChallengeConfirmation**. 225 pos_confirmation?: string; 226 227 // Signed tokens. Returned in the same order as the 228 // token envelopes were provided in the request. Specifically, 229 // the order will follow the order of the outputs from the 230 // contract terms, and then within each output follow the 231 // order in which the ``wallet_data`` contained the respective 232 // blinded envelopes. The donation tokens will be present 233 // at the offset matching the place where a donation receipt 234 // was indicated in the outputs array, and of course be skipped 235 // if the `PayWalletData` did not have a ``donau`` field. 236 // @since protocol **v21** 237 token_sigs?: SignedTokenEnvelope[]; 238 239 } 240 241 .. ts:def:: PayRequest 242 243 interface PayRequest { 244 // The coins used to make the payment. 245 coins: CoinPaySig[]; 246 247 // Input tokens required by choice indicated by ``choice_index``. 248 // @since protocol **v21** 249 tokens?: TokenUseSig[]; 250 251 // Custom inputs from the wallet for the contract. 252 wallet_data?: PayWalletData; 253 254 // The session for which the payment is made (or replayed). 255 // Only set for session-based payments. The empty session ID 256 // is treated like the field being absent (wallets do send it 257 // that way). 258 session_id?: SessionID; 259 260 } 261 262 .. ts:def:: SignedTokenEnvelope 263 264 interface SignedTokenEnvelope { 265 266 // Blind signature made by the merchant. 267 blind_sig: TokenIssueBlindSig; 268 269 } 270 271 .. ts:def:: TokenIssueBlindSig 272 273 type TokenIssueBlindSig = RSATokenIssueBlindSig | CSTokenIssueBlindSig; 274 275 .. ts:def:: RSATokenIssueBlindSig 276 277 interface RSATokenIssueBlindSig { 278 cipher: "RSA"; 279 280 // (blinded) RSA signature 281 blinded_rsa_signature: BlindedRsaSignature; 282 } 283 284 .. ts:def:: CSTokenIssueBlindSig 285 286 interface CSTokenIssueBlindSig { 287 cipher: "CS"; 288 289 // Signer chosen bit value, 0 or 1, used 290 // in Clause Blind Schnorr to make the 291 // ROS problem harder. 292 b: Integer; 293 294 // Blinded scalar calculated from c_b. 295 s: Cs25519Scalar; 296 297 } 298 299 .. ts:def:: PayWalletData 300 301 interface PayWalletData { 302 // Index of the selected choice within the ``choices`` array of 303 // the contract terms. 304 // @since protocol **v21** 305 choice_index?: Integer; 306 307 // Array of output tokens to be (blindly) signed by the merchant. 308 // Output tokens specified in choice indicated by ``choice_index``. 309 // @since protocol **v21** 310 tokens_evs?: TokenEnvelope[]; 311 312 // Request for donation receipts to be issued. 313 // @since protocol **v21** 314 donau?: DonationRequestData; 315 } 316 317 .. ts:def:: DonationRequestData 318 319 interface DonationRequestData { 320 // Base URL of the selected Donau 321 url: WebURL; 322 323 // Year for which the donation receipts are expected. 324 // Also determines which keys are used to sign the 325 // blinded donation receipts. 326 year: Integer; 327 328 // Array of blinded donation receipts to sign. 329 // Must NOT be empty (if no donation receipts 330 // are desired, just leave the entire ``donau`` 331 // argument blank). 332 budikeypairs: BlindedDonationReceiptKeyPair[]; 333 } 334 335 .. ts:def:: CoinPaySig 336 337 interface CoinPaySig { 338 // Signature by the coin. 339 coin_sig: EddsaSignature; 340 341 // Public key of the coin being spent. 342 coin_pub: EddsaPublicKey; 343 344 // Signature made by the denomination public key. 345 ub_sig: UnblindedSignature; 346 347 // The hash of the denomination public key associated with this coin. 348 h_denom: HashCode; 349 350 // The amount that is subtracted from this coin with this payment. 351 contribution: Amount; 352 353 // URL of the exchange this coin was withdrawn from. 354 exchange_url: WebURL; 355 356 // Signature affirming the posession of the 357 // respective private key proving that the payer 358 // is old enough. Only provided if the paid contract 359 // has an age restriction and the coin is 360 // age-restricted. 361 minimum_age_sig?: EddsaSignature; 362 363 // Age commitment vector of the coin. 364 // Only provided if the paid contract 365 // has an age restriction and the coin is 366 // age-restricted. 367 age_commitment?: Edx25519PublicKey[]; 368 369 // Hash over the agge commitment vector of the coin. 370 // Only provided if the paid contract 371 // does NOT have an age restriction and the coin is 372 // age-restricted. 373 h_age_commitment?: AgeCommitmentHash; 374 } 375 376 .. ts:def:: TokenUseSig 377 378 interface TokenUseSig { 379 380 // Signature on ``TALER_TokenUseRequestPS`` with the token use key of 381 // the token being used in this request. 382 token_sig: EddsaSignature; 383 384 // Token use public key. 385 token_pub: EddsaPublicKey; 386 387 // Unblinded signature on ``TALER_TokenIssueRequestPS`` with the token 388 // issue public key of the merchant. 389 ub_sig: UnblindedSignature; 390 391 // Hash of the token issue public key associated with this token. 392 h_issue: HashCode; 393 } 394 395 .. ts:def:: TokenEnvelope 396 397 // This type depends on the cipher used to sign token families. This is 398 // configured by the merchant and defined for each token family in the 399 // contract terms. 400 type TokenEnvelope = RSATokenEnvelope | CSTokenEnvelope; 401 402 .. ts:def:: RSATokenEnvelope 403 404 interface RSATokenEnvelope { 405 406 // RSA is used for the blind signature. 407 cipher: "RSA"; 408 409 // Blinded signature of the token's `public EdDSA key <eddsa-token-pub>`. 410 rsa_blinded_pub: BlindedRsaSignature; 411 412 } 413 414 .. ts:def:: CSTokenEnvelope 415 416 interface CSTokenEnvelope { 417 // Blind Clause-Schnorr signature scheme is used for the blind signature. 418 // See https://taler.net/papers/cs-thesis.pdf for details. 419 cipher: "CS"; 420 421 // Public nonce 422 cs_nonce: string; // Crockford `Base32` encoded 423 424 // Two Curve25519 scalars, each representing a blinded challenge 425 cs_blinded_c0: string; // Crockford `Base32` encoded 426 cs_blinded_c1: string; // Crockford `Base32` encoded 427 } 428 429 .. ts:def:: PaymentDeniedLegallyResponse 430 431 interface PaymentDeniedLegallyResponse { 432 433 // Numeric `error code <error-codes>` unique to the condition. 434 // Error code, must be 435 // TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED. 436 code: Integer; 437 438 // Base URL of the exchanges that denied the payment. 439 // The wallet should refresh the coins from these 440 // exchanges, but may try to pay with coins from 441 // other exchanges. 442 exchange_base_urls: WebURL[]; 443 444 }