taler-docs

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

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


      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 
     32   :http:statuscode:`402 Payment required`:
     33     There used to be a sufficient payment, but due to refunds the amount effectively
     34     paid is no longer sufficient. (If the amount is generally insufficient, we
     35     return "400 Bad Request", only if this is because of refunds we return 402.)
     36   :http:statuscode:`403 Forbidden`:
     37     One of the coin signatures was not valid.
     38   :http:statuscode:`404 Not found`:
     39     The merchant backend could not find the order
     40     or the instance or a token family or
     41     the Donau charity specified in
     42     the contract and thus cannot process the payment.
     43     Applicable error codes:
     44 
     45     * ``MERCHANT_GENERIC_TOKEN_KEY_UNKNOWN``
     46     * ``MERCHANT_GENERIC_ORDER_UNKNOWN``
     47     * ``MERCHANT_GENERIC_DONAU_CHARITY_UNKNOWN``
     48     * ``MERCHANT_GENERIC_INSTANCE_UNKNOWN``
     49 
     50   :http:statuscode:`408 Request timeout`:
     51     The backend took too long to process the request. Likely the merchant's connection
     52     to the exchange timed out. Try again.
     53     Applicable error codes:
     54 
     55     * ``MERCHANT_GENERIC_EXCHANGE_TIMEOUT``
     56 
     57   :http:statuscode:`409 Conflict`:
     58     The exchange rejected the payment because a coin was already spent (or
     59     used in a different way for the same purchase previously), or
     60     the merchant rejected the payment because the order was already fully paid
     61     (and then return signatures with refunds). If a coin was already spent
     62     (this includes re-using the same coin after a refund),
     63     the response will include the ``exchange_url`` for which the payment failed,
     64     in addition to the response from the exchange to the ``/batch-deposit`` request.
     65     Applicable error codes:
     66 
     67     * ``MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS``:  Exchange reported insufficient
     68       funds for one of the coins.
     69 
     70   :http:statuscode:`410 Gone`:
     71     The offer has expired and is no longer available or
     72     the provided payment has expired.
     73     Applicable error codes:
     74 
     75     * ``MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_DEPOSIT_EXPIRED``: payment expired
     76     * ``MERCHANT_POST_ORDERS_ID_PAY_OFFER_EXPIRED``: offer expired
     77 
     78   :http:statuscode:`412 Precondition failed`:
     79     The given exchange is not acceptable for this merchant, as it is not in the
     80     list of accepted exchanges and not audited by an approved auditor.
     81     TODO: Status code may be changed to 409 in the future as 412 is technically wrong.
     82   :http:statuscode:`451 Unavailable for Legal Reasons`:
     83     The exchange has rejected the deposit by the merchant
     84     for legal reasons. This is **not** exactly a client
     85     failure (and possibly nobody's fault except for the
     86     regulator). In any case, the wallet should refresh
     87     the deposited coins of the affected exchange and
     88     may try to pay with coins from another exchange if
     89     possible (it has such coins and the merchant accepts
     90     coins from another exchange).
     91     The body is a `PaymentDeniedLegallyResponse` with
     92     details about the failure.
     93     Since protocol **v17**.
     94   :http:statuscode:`501 Not implemented`:
     95     This is returned if an optional feature required to
     96     process this particular payment is no longer implemented.
     97     This should only be possible if a different version
     98     of the backend software was deployed between order
     99     creation and payment.
    100 
    101     Applicable error codes:
    102 
    103     * ``MERCHANT_GENERIC_DONAU_NOT_CONFIGURED``: returned if donations are not supported
    104     * ``MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE``: usually returned if a token type is not supported
    105 
    106   :http:statuscode:`502 Bad gateway`:
    107     The merchant's interaction with the exchange failed in some way.
    108     The client might want to try again later.
    109     This includes failures such as the denomination key of a coin not being
    110     known to the exchange as far as the merchant can tell.
    111     Applicable error codes:
    112 
    113     * ``MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS``
    114     * ``MERCHANT_GENERIC_EXCHANGE_REPLY_MALFORMED``
    115 
    116   :http:statuscode:`504 Gateway timeout`:
    117     The merchant's interaction with the exchange took too long.
    118     The client might want to try again later.
    119 
    120   The backend will return verbatim the error codes received from the exchange's
    121   :ref:`deposit <deposit>` API.  If the wallet made a mistake, like by
    122   double-spending for example, the frontend should pass the reply verbatim to
    123   the browser/wallet.  If the payment was successful, the frontend MAY use
    124   this to trigger some business logic.
    125 
    126   **Details:**
    127 
    128   .. ts:def:: PaymentResponse
    129 
    130     interface PaymentResponse {
    131       // Signature on ``TALER_PaymentResponsePS`` with the public
    132       // key of the merchant instance.
    133       sig: EddsaSignature;
    134 
    135       // Text to be shown to the point-of-sale staff as a proof of
    136       // payment.
    137       pos_confirmation?: string;
    138 
    139       // Signed tokens. Returned in the same order as the
    140       // token envelopes were provided in the request. Specifically,
    141       // the order will follow the order of the outputs from the
    142       // contract terms, and then within each output follow the
    143       // order in which the ``wallet_data`` contained the respective
    144       // blinded envelopes.  The donation tokens will be present
    145       // at the offset matching the place where a donation receipt
    146       // was indicated in the outputs array, and of course be skipped
    147       // if the ``PayWalletData`` did not have a ``donau`` field.
    148       // @since protocol **v21**
    149       token_sigs?: SignedTokenEnvelope[];
    150 
    151     }
    152 
    153   .. ts:def:: PayRequest
    154 
    155     interface PayRequest {
    156       // The coins used to make the payment.
    157       coins: CoinPaySig[];
    158 
    159       // Input tokens required by choice indicated by ``choice_index``.
    160       // @since protocol **v21**
    161       tokens?: TokenUseSig[];
    162 
    163       // Custom inputs from the wallet for the contract.
    164       wallet_data?: PayWalletData;
    165 
    166       // The session for which the payment is made (or replayed).
    167       // Only set for session-based payments.
    168       session_id?: string;
    169 
    170     }
    171 
    172   .. ts:def:: SignedTokenEnvelope
    173 
    174     interface SignedTokenEnvelope {
    175 
    176       // Blind signature made by the merchant.
    177       blind_sig: TokenIssueBlindSig;
    178 
    179     }
    180 
    181   .. ts:def:: TokenIssueBlindSig
    182 
    183     type TokenIssueBlindSig = RSATokenIssueBlindSig | CSTokenIssueBlindSig;
    184 
    185   .. ts:def:: RSATokenIssueBlindSig
    186 
    187     interface RSATokenIssueBlindSig {
    188       cipher: "RSA";
    189 
    190       // (blinded) RSA signature
    191       blinded_rsa_signature: BlindedRsaSignature;
    192     }
    193 
    194   .. ts:def:: CSTokenIssueBlindSig
    195 
    196     interface CSTokenIssueBlindSig {
    197       cipher: "CS";
    198 
    199       // Signer chosen bit value, 0 or 1, used
    200       // in Clause Blind Schnorr to make the
    201       // ROS problem harder.
    202       b: Integer;
    203 
    204       // Blinded scalar calculated from c_b.
    205       s: Cs25519Scalar;
    206 
    207     }
    208 
    209   .. ts:def:: PayWalletData
    210 
    211     interface PayWalletData {
    212       // Index of the selected choice within the ``choices`` array of
    213       // the contract terms.
    214       // @since protocol **v21**
    215       choice_index?: Integer;
    216 
    217       // Array of output tokens to be (blindly) signed by the merchant.
    218       // Output tokens specified in choice indicated by ``choice_index``.
    219       // @since protocol **v21**
    220       tokens_evs?: TokenEnvelope[];
    221 
    222       // Request for donation receipts to be issued.
    223       // @since protocol **v21**
    224       donau?: DonationRequestData;
    225     }
    226 
    227   .. ts:def:: DonationRequestData
    228 
    229     interface DonationRequestData {
    230       // Base URL of the selected Donau
    231       url: string;
    232 
    233       // Year for which the donation receipts are expected.
    234       // Also determines which keys are used to sign the
    235       // blinded donation receipts.
    236       year: Integer;
    237 
    238       // Array of blinded donation receipts to sign.
    239       // Must NOT be empty (if no donation receipts
    240       // are desired, just leave the entire ``donau``
    241       // argument blank).
    242       budikeypairs: BlindedDonationReceiptKeyPair[];
    243     }
    244 
    245   .. ts:def:: CoinPaySig
    246 
    247     interface CoinPaySig {
    248       // Signature by the coin.
    249       coin_sig: EddsaSignature;
    250 
    251       // Public key of the coin being spent.
    252       coin_pub: EddsaPublicKey;
    253 
    254       // Signature made by the denomination public key.
    255       ub_sig: UnblindedSignature;
    256 
    257       // The hash of the denomination public key associated with this coin.
    258       h_denom: HashCode;
    259 
    260       // The amount that is subtracted from this coin with this payment.
    261       contribution: Amount;
    262 
    263       // URL of the exchange this coin was withdrawn from.
    264       exchange_url: string;
    265 
    266       // Signature affirming the posession of the
    267       // respective private key proving that the payer
    268       // is old enough. Only provided if the paid contract
    269       // has an age restriction and the coin is
    270       // age-restricted.
    271       minimum_age_sig?: EddsaSignature;
    272 
    273       // Age commitment vector of the coin.
    274       // Only provided if the paid contract
    275       // has an age restriction and the coin is
    276       // age-restricted.
    277       age_commitment?: Edx25519PublicKey[];
    278 
    279       // Hash over the agge commitment vector of the coin.
    280       // Only provided if the paid contract
    281       // does NOT have an age restriction and the coin is
    282       // age-restricted.
    283       h_age_commitment?: AgeCommitmentHash;
    284     }
    285 
    286   .. ts:def:: TokenUseSig
    287 
    288     interface TokenUseSig {
    289 
    290       // Signature on ``TALER_TokenUseRequestPS`` with the token use key of
    291       // the token being used in this request.
    292       token_sig: EddsaSignature;
    293 
    294       // Token use public key.
    295       token_pub: EddsaPublicKey;
    296 
    297       // Unblinded signature on ``TALER_TokenIssueRequestPS`` with the token
    298       // issue public key of the merchant.
    299       ub_sig: UnblindedSignature;
    300 
    301       // Hash of the token issue public key associated with this token.
    302       h_issue: HashCode;
    303     }
    304 
    305   .. ts:def:: TokenEnvelope
    306 
    307     // This type depends on the cipher used to sign token families. This is
    308     // configured by the merchant and defined for each token family in the
    309     // contract terms.
    310     type TokenEnvelope = RSATokenEnvelope | CSTokenEnvelope;
    311 
    312   .. ts:def:: RSATokenEnvelope
    313 
    314     interface RSATokenEnvelope {
    315 
    316       // RSA is used for the blind signature.
    317       cipher: "RSA";
    318 
    319       // Blinded signature of the token's `public EdDSA key <eddsa-token-pub>`.
    320       rsa_blinded_pub: BlindedRsaSignature;
    321 
    322     }
    323 
    324   .. ts:def:: CSTokenEnvelope
    325 
    326     interface CSTokenEnvelope {
    327       // Blind Clause-Schnorr signature scheme is used for the blind signature.
    328       // See https://taler.net/papers/cs-thesis.pdf for details.
    329       cipher: "CS";
    330 
    331       // Public nonce
    332       cs_nonce: string;      // Crockford `Base32` encoded
    333 
    334       // Two Curve25519 scalars, each representing a blinded challenge
    335       cs_blinded_c0: string; // Crockford `Base32` encoded
    336       cs_blinded_c1: string; // Crockford `Base32` encoded
    337     }
    338 
    339   .. ts:def:: PaymentDeniedLegallyResponse
    340 
    341     interface PaymentDeniedLegallyResponse {
    342 
    343       // Numeric `error code <error-codes>` unique to the condition.
    344       // Error code, must be
    345       // TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LEGALLY_REFUSED.
    346       code: Integer;
    347 
    348       // Base URL of the exchanges that denied the payment.
    349       // The wallet should refresh the coins from these
    350       // exchanges, but may try to pay with coins from
    351       // other exchanges.
    352       exchange_base_urls: string[];
    353 
    354     }