taler-docs

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

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     }