taler-docs

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

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


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