taler-docs

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

post-orders-ORDER_ID-pay.rst (16711B)


      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_ALREADY_PAID``: The order was already
    106       fully paid by another wallet. The response includes refund signatures
    107       for the coins.
    108     * ``MERCHANT_POST_ORDERS_ID_PAY_TOKEN_INVALID``: A token was already used
    109       in a previous payment.
    110     * ``MERCHANT_POST_ORDERS_ID_PAY_DONATION_AMOUNT_MISMATCH``: The donation
    111       amount does not match the expected amount or exceeds the yearly limit.
    112     * ``MERCHANT_GENERIC_CURRENCY_MISMATCH``: Coin currency does not match
    113       the expected payment currency.
    114 
    115   :http:statuscode:`410 Gone`:
    116     The offer has expired and is no longer available or
    117     the provided payment has expired.
    118     Applicable error codes:
    119 
    120     * ``MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED``: payment expired
    121     * ``MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED``: offer expired
    122 
    123   :http:statuscode:`412 Precondition failed`:
    124     The given exchange is not acceptable for this merchant, as it is not in the
    125     list of accepted exchanges and not audited by an approved auditor.
    126     TODO: Status code may be changed to 409 in the future as 412 is technically wrong.
    127   :http:statuscode:`413 Request entity too large`:
    128     The uploaded body is to long, it exceeds the size limit.
    129     Returned with an error code of
    130     ``TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT``.
    131   :http:statuscode:`451 Unavailable for Legal Reasons`:
    132     The exchange has rejected the deposit by the merchant
    133     for legal reasons. This is **not** exactly a client
    134     failure (and possibly nobody's fault except for the
    135     regulator). In any case, the wallet should refresh
    136     the deposited coins of the affected exchange and
    137     may try to pay with coins from another exchange if
    138     possible (it has such coins and the merchant accepts
    139     coins from another exchange).
    140     The body is a `PaymentDeniedLegallyResponse` with
    141     details about the failure.
    142     Since protocol **v17**.
    143     Returned with ``TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED`` or
    144     ``TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_TRANSACTION_LIMIT_VIOLATION``.
    145   :http:statuscode:`501 Not implemented`:
    146     This is returned if an optional feature required to
    147     process this particular payment is no longer implemented.
    148     This should only be possible if a different version
    149     of the backend software was deployed between order
    150     creation and payment.
    151 
    152     Applicable error codes:
    153 
    154     * ``MERCHANT_GENERIC_DONAU_NOT_CONFIGURED``: returned if donations are not supported
    155     * ``MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE``: usually returned if a token type is not supported
    156 
    157   :http:statuscode:`502 Bad gateway`:
    158     The merchant's interaction with the exchange failed in some way.
    159     The client might want to try again later.
    160     This includes failures such as the denomination key of a coin not being
    161     known to the exchange as far as the merchant can tell.
    162     Applicable error codes:
    163 
    164     * ``MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS``
    165     * ``MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED``
    166     * ``MERCHANT_GENERIC_DONAU_INVALID_RESPONSE``
    167 
    168   :http:statuscode:`500 Internal Server Error`:
    169     The server experienced an internal failure.
    170     Returned with ``TALER_EC_GENERIC_DB_STORE_FAILED``,
    171     ``TALER_EC_GENERIC_DB_FETCH_FAILED``,
    172     ``TALER_EC_GENERIC_DB_START_FAILED``,
    173     ``TALER_EC_GENERIC_DB_COMMIT_FAILED``,
    174     ``TALER_EC_GENERIC_DB_SOFT_FAILURE``,
    175     ``TALER_EC_GENERIC_DB_INVARIANT_FAILURE``,
    176     ``TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE``,
    177     ``TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH`` or
    178     ``TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID``.
    179   :http:statuscode:`504 Gateway timeout`:
    180     The merchant's interaction with the exchange took too long.
    181     The client might want to try again later.
    182 
    183   The backend will return verbatim the error codes received from the exchange's
    184   :ref:`deposit <deposit>` API.  If the wallet made a mistake, like by
    185   double-spending for example, the frontend should pass the reply verbatim to
    186   the browser/wallet.  If the payment was successful, the frontend MAY use
    187   this to trigger some business logic.
    188 
    189   **Details:**
    190 
    191   .. ts:def:: PaymentResponse
    192 
    193     interface PaymentResponse {
    194       // Signature on ``TALER_PaymentResponsePS`` with the public
    195       // key of the merchant instance.
    196       sig: EddsaSignature;
    197 
    198       // Text to be shown to the point-of-sale staff as a proof of
    199       // payment.
    200       // For OTP devices using a challenge-signature algorithm
    201       // ("ECDSA_CHALLENGE" or "EDDSA_CHALLENGE"), contains the
    202       // Crockford Base32 encoded signature over the hash of the
    203       // order's challenge, made with the device private key.
    204       // Since protocol **vChallengeConfirmation**.
    205       pos_confirmation?: string;
    206 
    207       // Signed tokens. Returned in the same order as the
    208       // token envelopes were provided in the request. Specifically,
    209       // the order will follow the order of the outputs from the
    210       // contract terms, and then within each output follow the
    211       // order in which the ``wallet_data`` contained the respective
    212       // blinded envelopes.  The donation tokens will be present
    213       // at the offset matching the place where a donation receipt
    214       // was indicated in the outputs array, and of course be skipped
    215       // if the `PayWalletData` did not have a ``donau`` field.
    216       // @since protocol **v21**
    217       token_sigs?: SignedTokenEnvelope[];
    218 
    219     }
    220 
    221   .. ts:def:: PayRequest
    222 
    223     interface PayRequest {
    224       // The coins used to make the payment.
    225       coins: CoinPaySig[];
    226 
    227       // Input tokens required by choice indicated by ``choice_index``.
    228       // @since protocol **v21**
    229       tokens?: TokenUseSig[];
    230 
    231       // Custom inputs from the wallet for the contract.
    232       wallet_data?: PayWalletData;
    233 
    234       // The session for which the payment is made (or replayed).
    235       // Only set for session-based payments.
    236       session_id?: string;
    237 
    238     }
    239 
    240   .. ts:def:: SignedTokenEnvelope
    241 
    242     interface SignedTokenEnvelope {
    243 
    244       // Blind signature made by the merchant.
    245       blind_sig: TokenIssueBlindSig;
    246 
    247     }
    248 
    249   .. ts:def:: TokenIssueBlindSig
    250 
    251     type TokenIssueBlindSig = RSATokenIssueBlindSig | CSTokenIssueBlindSig;
    252 
    253   .. ts:def:: RSATokenIssueBlindSig
    254 
    255     interface RSATokenIssueBlindSig {
    256       cipher: "RSA";
    257 
    258       // (blinded) RSA signature
    259       blinded_rsa_signature: BlindedRsaSignature;
    260     }
    261 
    262   .. ts:def:: CSTokenIssueBlindSig
    263 
    264     interface CSTokenIssueBlindSig {
    265       cipher: "CS";
    266 
    267       // Signer chosen bit value, 0 or 1, used
    268       // in Clause Blind Schnorr to make the
    269       // ROS problem harder.
    270       b: Integer;
    271 
    272       // Blinded scalar calculated from c_b.
    273       s: Cs25519Scalar;
    274 
    275     }
    276 
    277   .. ts:def:: PayWalletData
    278 
    279     interface PayWalletData {
    280       // Index of the selected choice within the ``choices`` array of
    281       // the contract terms.
    282       // @since protocol **v21**
    283       choice_index?: Integer;
    284 
    285       // Array of output tokens to be (blindly) signed by the merchant.
    286       // Output tokens specified in choice indicated by ``choice_index``.
    287       // @since protocol **v21**
    288       tokens_evs?: TokenEnvelope[];
    289 
    290       // Request for donation receipts to be issued.
    291       // @since protocol **v21**
    292       donau?: DonationRequestData;
    293     }
    294 
    295   .. ts:def:: DonationRequestData
    296 
    297     interface DonationRequestData {
    298       // Base URL of the selected Donau
    299       url: string;
    300 
    301       // Year for which the donation receipts are expected.
    302       // Also determines which keys are used to sign the
    303       // blinded donation receipts.
    304       year: Integer;
    305 
    306       // Array of blinded donation receipts to sign.
    307       // Must NOT be empty (if no donation receipts
    308       // are desired, just leave the entire ``donau``
    309       // argument blank).
    310       budikeypairs: BlindedDonationReceiptKeyPair[];
    311     }
    312 
    313   .. ts:def:: CoinPaySig
    314 
    315     interface CoinPaySig {
    316       // Signature by the coin.
    317       coin_sig: EddsaSignature;
    318 
    319       // Public key of the coin being spent.
    320       coin_pub: EddsaPublicKey;
    321 
    322       // Signature made by the denomination public key.
    323       ub_sig: UnblindedSignature;
    324 
    325       // The hash of the denomination public key associated with this coin.
    326       h_denom: HashCode;
    327 
    328       // The amount that is subtracted from this coin with this payment.
    329       contribution: Amount;
    330 
    331       // URL of the exchange this coin was withdrawn from.
    332       exchange_url: string;
    333 
    334       // Signature affirming the posession of the
    335       // respective private key proving that the payer
    336       // is old enough. Only provided if the paid contract
    337       // has an age restriction and the coin is
    338       // age-restricted.
    339       minimum_age_sig?: EddsaSignature;
    340 
    341       // Age commitment vector of the coin.
    342       // Only provided if the paid contract
    343       // has an age restriction and the coin is
    344       // age-restricted.
    345       age_commitment?: Edx25519PublicKey[];
    346 
    347       // Hash over the agge commitment vector of the coin.
    348       // Only provided if the paid contract
    349       // does NOT have an age restriction and the coin is
    350       // age-restricted.
    351       h_age_commitment?: AgeCommitmentHash;
    352     }
    353 
    354   .. ts:def:: TokenUseSig
    355 
    356     interface TokenUseSig {
    357 
    358       // Signature on ``TALER_TokenUseRequestPS`` with the token use key of
    359       // the token being used in this request.
    360       token_sig: EddsaSignature;
    361 
    362       // Token use public key.
    363       token_pub: EddsaPublicKey;
    364 
    365       // Unblinded signature on ``TALER_TokenIssueRequestPS`` with the token
    366       // issue public key of the merchant.
    367       ub_sig: UnblindedSignature;
    368 
    369       // Hash of the token issue public key associated with this token.
    370       h_issue: HashCode;
    371     }
    372 
    373   .. ts:def:: TokenEnvelope
    374 
    375     // This type depends on the cipher used to sign token families. This is
    376     // configured by the merchant and defined for each token family in the
    377     // contract terms.
    378     type TokenEnvelope = RSATokenEnvelope | CSTokenEnvelope;
    379 
    380   .. ts:def:: RSATokenEnvelope
    381 
    382     interface RSATokenEnvelope {
    383 
    384       // RSA is used for the blind signature.
    385       cipher: "RSA";
    386 
    387       // Blinded signature of the token's `public EdDSA key <eddsa-token-pub>`.
    388       rsa_blinded_pub: BlindedRsaSignature;
    389 
    390     }
    391 
    392   .. ts:def:: CSTokenEnvelope
    393 
    394     interface CSTokenEnvelope {
    395       // Blind Clause-Schnorr signature scheme is used for the blind signature.
    396       // See https://taler.net/papers/cs-thesis.pdf for details.
    397       cipher: "CS";
    398 
    399       // Public nonce
    400       cs_nonce: string;      // Crockford `Base32` encoded
    401 
    402       // Two Curve25519 scalars, each representing a blinded challenge
    403       cs_blinded_c0: string; // Crockford `Base32` encoded
    404       cs_blinded_c1: string; // Crockford `Base32` encoded
    405     }
    406 
    407   .. ts:def:: PaymentDeniedLegallyResponse
    408 
    409     interface PaymentDeniedLegallyResponse {
    410 
    411       // Numeric `error code <error-codes>` unique to the condition.
    412       // Error code, must be
    413       // TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED.
    414       code: Integer;
    415 
    416       // Base URL of the exchanges that denied the payment.
    417       // The wallet should refresh the coins from these
    418       // exchanges, but may try to pay with coins from
    419       // other exchanges.
    420       exchange_base_urls: string[];
    421 
    422     }