diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-12-28 15:00:36 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-12-28 15:00:36 +0100 |
commit | a7b2d842a460c880ec9811312f129a4b87505615 (patch) | |
tree | bf6776b15a4e1c936cb838de6ebfd75b80ec9c9c /src/lib/merchant_api_pay.c | |
parent | d0e409d0cdebd579773757b52937361de2a3d0ef (diff) | |
download | merchant-a7b2d842a460c880ec9811312f129a4b87505615.tar.gz merchant-a7b2d842a460c880ec9811312f129a4b87505615.tar.bz2 merchant-a7b2d842a460c880ec9811312f129a4b87505615.zip |
implement TALER_MERCHANT_pay_abort() -- first version, lacks signature verification
Diffstat (limited to 'src/lib/merchant_api_pay.c')
-rw-r--r-- | src/lib/merchant_api_pay.c | 690 |
1 files changed, 511 insertions, 179 deletions
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c index bfb1ae85..276680e2 100644 --- a/src/lib/merchant_api_pay.c +++ b/src/lib/merchant_api_pay.c @@ -54,16 +54,31 @@ struct TALER_MERCHANT_Pay struct GNUNET_CURL_Job *job; /** - * Function to call with the result. + * Function to call with the result in "pay" @e mode. */ - TALER_MERCHANT_PayCallback cb; + TALER_MERCHANT_PayCallback pay_cb; /** - * Closure for @a cb. + * Closure for @a pay_cb. */ - void *cb_cls; + void *pay_cb_cls; /** + * Function to call with the result in "abort-refund" @e mode. + */ + TALER_MERCHANT_PayRefundCallback abort_cb; + + /** + * Closure for @a abort_cb. + */ + void *abort_cb_cls; + + /** + * Operational mode, either "pay" or "abort-refund". + */ + const char *mode; + + /** * Reference to the execution context. */ struct GNUNET_CURL_Context *ctx; @@ -82,6 +97,77 @@ struct TALER_MERCHANT_Pay /** + * Check that the response for a /pay refund is well-formed, + * and call the application callback with the result if it is + * OK. Otherwise returns #GNUNET_SYSERR. + * + * @param ph handle to operation that created the reply + * @param json the reply to parse + * @return #GNUNET_OK on success + */ +static int +check_abort_refund (struct TALER_MERCHANT_Pay *ph, + const json_t *json) +{ + json_t *refunds; + unsigned int num_refunds; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("refunds", &refunds), + GNUNET_JSON_spec_end() + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (json, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + num_refunds = json_array_size (refunds); + if (num_refunds != ph->num_coins) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + return GNUNET_SYSERR; + } + { + struct TALER_MerchantSignatureP sigs[num_refunds]; + + for (unsigned int i=0;i<num_refunds;i++) + { + struct TALER_MerchantSignatureP *sig = &sigs[i]; + json_t *deposit = json_array_get (refunds, i); + struct GNUNET_JSON_Specification spec_detail[] = { + GNUNET_JSON_spec_fixed_auto ("sig", sig), + GNUNET_JSON_spec_end() + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (deposit, + spec_detail, + NULL, NULL)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + return GNUNET_SYSERR; + } + } + /* FIXME: check that signature is valid! */ + ph->abort_cb (ph->abort_cb_cls, + MHD_HTTP_OK, + TALER_EC_NONE, + num_refunds, + sigs, + json); + ph->abort_cb = NULL; + } + GNUNET_JSON_parse_free (spec); + return GNUNET_OK; +} + + +/** * We got a 403 response back from the exchange (or the merchant). * Now we need to check the provided cryptographic proof that the * coin was actually already spent! @@ -196,199 +282,144 @@ handle_pay_finished (void *cls, struct TALER_MERCHANT_Pay *ph = cls; ph->job = NULL; - switch (response_code) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "/pay completed with response code %u\n", + (unsigned int) response_code); + if (0 == strcasecmp (ph->mode, + "pay")) { - case 0: - break; - case MHD_HTTP_OK: - break; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the merchant is buggy - (or API version conflict); just pass JSON reply to the application */ - break; - case MHD_HTTP_FORBIDDEN: - if (GNUNET_OK != check_forbidden (ph, - json)) + switch (response_code) { - GNUNET_break_op (0); + case 0: + break; + case MHD_HTTP_OK: + break; + case MHD_HTTP_BAD_REQUEST: + /* This should never happen, either us or the merchant is buggy + (or API version conflict); just pass JSON reply to the application */ + break; + case MHD_HTTP_FORBIDDEN: + if (GNUNET_OK != check_forbidden (ph, + json)) + { + GNUNET_break_op (0); + response_code = 0; + } + break; + case MHD_HTTP_UNAUTHORIZED: + /* Nothing really to verify, merchant says one of the signatures is + invalid; as we checked them, this should never happen, we + should pass the JSON reply to the application */ + break; + case MHD_HTTP_NOT_FOUND: + /* Nothing really to verify, this should never + happen, we should pass the JSON reply to the application */ + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + /* Server had an internal issue; we should retry, but this API + leaves this to the application */ + break; + default: + /* unexpected response code */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u\n", + (unsigned int) response_code); + GNUNET_break (0); response_code = 0; - } - break; - case MHD_HTTP_UNAUTHORIZED: - /* Nothing really to verify, merchant says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u\n", - (unsigned int) response_code); - GNUNET_break (0); - response_code = 0; - break; + break; + } + ph->pay_cb (ph->pay_cb_cls, + response_code, + TALER_JSON_get_error_code (json), + json); } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "/pay completed with response code %u\n", - (unsigned int) response_code); - ph->cb (ph->cb_cls, - response_code, - TALER_JSON_get_error_code (json), - json); - TALER_MERCHANT_pay_cancel (ph); -} - - -/** - * Pay a merchant. API for wallets that have the coin's private keys. - * _NOTE_: this function does NOT calculate each coin amount in order - * to match the contract total price. This calculation is to be made - * by the logic using this library. - * - * @param ctx the execution loop context - * @param merchant_uri base URI of the merchant's backend - * @param instance which merchant instance will receive this payment - * @param h_contract_terms hashcode of the proposal being paid - * @param amount total value of the contract to be paid to the merchant - * @param max_fee maximum fee covered by the merchant (according to the contract) - * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) - * @param merchant_sig signature from the merchant over the original contract - * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant - * @param refund_deadline date until which the merchant can issue a refund to the customer via the merchant (can be zero if refunds are not allowed) - * @param pay_deadline maximum time limit to pay for this contract - * @param h_wire hash of the merchant’s account details - * @param order_id order id of the proposal being paid - * @param num_coins number of coins used to pay - * @param coins array of coins we use to pay - * @param pay_cb the callback to call when a reply for this request is available - * @param pay_cb_cls closure for @a pay_cb - * @return a handle for this request - */ -struct TALER_MERCHANT_Pay * -TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx, - const char *merchant_uri, - const char *instance, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_Amount *amount, - const struct TALER_Amount *max_fee, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_MerchantSignatureP *merchant_sig, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund_deadline, - struct GNUNET_TIME_Absolute pay_deadline, - const struct GNUNET_HashCode *h_wire, - const char *order_id, - unsigned int num_coins, - const struct TALER_MERCHANT_PayCoin *coins, - TALER_MERCHANT_PayCallback pay_cb, - void *pay_cb_cls) -{ - struct TALER_DepositRequestPS dr; - struct TALER_MERCHANT_PaidCoin pc[num_coins]; - - (void) GNUNET_TIME_round_abs (×tamp); - (void) GNUNET_TIME_round_abs (&pay_deadline); - (void) GNUNET_TIME_round_abs (&refund_deadline); - - if (GNUNET_YES != - TALER_amount_cmp_currency (amount, - max_fee)) - { - GNUNET_break (0); - return NULL; - } - - dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); - dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS)); - dr.h_contract_terms = *h_contract_terms; - dr.h_wire = *h_wire; - dr.timestamp = GNUNET_TIME_absolute_hton (timestamp); - dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline); - dr.merchant = *merchant_pub; - for (unsigned int i=0;i<num_coins;i++) + else { - const struct TALER_MERCHANT_PayCoin *coin = &coins[i]; - struct TALER_MERCHANT_PaidCoin *p = &pc[i]; - struct TALER_Amount fee; - - /* prepare 'dr' for this coin to generate coin signature */ - GNUNET_CRYPTO_eddsa_key_get_public (&coin->coin_priv.eddsa_priv, - &dr.coin_pub.eddsa_pub); - TALER_amount_hton (&dr.amount_with_fee, - &coin->amount_with_fee); - if (GNUNET_SYSERR == - TALER_amount_subtract (&fee, - &coin->amount_with_fee, - &coin->amount_without_fee)) + GNUNET_assert (0 == strcasecmp (ph->mode, + "abort-refund")); + + switch (response_code) { - /* Integer underflow, fee larger than total amount? - This should not happen (client violated API!) */ + case 0: + break; + case MHD_HTTP_OK: + if (GNUNET_OK == + check_abort_refund (ph, + json)) + { + TALER_MERCHANT_pay_cancel (ph); + return; + } + response_code = 0; + break; + case MHD_HTTP_BAD_REQUEST: + /* This should never happen, either us or the merchant is buggy + (or API version conflict); just pass JSON reply to the application */ + break; + case MHD_HTTP_FORBIDDEN: + break; + case MHD_HTTP_UNAUTHORIZED: + /* Nothing really to verify, merchant says one of the signatures is + invalid; as we checked them, this should never happen, we + should pass the JSON reply to the application */ + break; + case MHD_HTTP_NOT_FOUND: + /* Nothing really to verify, this should never + happen, we should pass the JSON reply to the application */ + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + /* Server had an internal issue; we should retry, but this API + leaves this to the application */ + break; + default: + /* unexpected response code */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u\n", + (unsigned int) response_code); GNUNET_break (0); - return NULL; - } - TALER_amount_hton (&dr.deposit_fee, - &fee); - { - TALER_LOG_DEBUG ("... amount_with_fee was %s\n", - TALER_amount2s (&coin->amount_with_fee)); - TALER_LOG_DEBUG ("... fee was %s\n", - TALER_amount2s (&fee)); - } - - GNUNET_CRYPTO_eddsa_sign (&coin->coin_priv.eddsa_priv, - &dr.purpose, - &p->coin_sig.eddsa_signature); - p->denom_pub = coin->denom_pub; - p->denom_sig = coin->denom_sig; - p->denom_value = coin->denom_value; - p->coin_pub = dr.coin_pub; - p->amount_with_fee = coin->amount_with_fee; - p->amount_without_fee = coin->amount_without_fee; - p->exchange_url = coin->exchange_url; + response_code = 0; + break; + } + ph->abort_cb (ph->abort_cb_cls, + response_code, + TALER_JSON_get_error_code (json), + 0, + NULL, + json); } - return TALER_MERCHANT_pay_frontend (ctx, - merchant_uri, - merchant_pub, - order_id, - num_coins, - pc, - pay_cb, - pay_cb_cls); + + TALER_MERCHANT_pay_cancel (ph); } /** - * Pay a merchant. API for frontends talking to backends. Here, - * the frontend does not have the coin's private keys, but just - * the public keys and signatures. Note the subtle difference - * in the type of @a coins compared to #TALER_MERCHANT_pay(). + * Issue /pay request. Generic version for the various + * variants of the API. * * @param ctx the execution loop context - * @param merchant_uri base URI of the merchant's backend + * @param merchant_url base URL of the merchant's backend * @param merchant_pub public key of the merchant * @param num_coins number of coins used to pay * @param coins array of coins we use to pay + * @param mode mode string to use ("pay" or "abort-refund"). * @param pay_cb the callback to call when a reply for this request is available * @param pay_cb_cls closure for @a pay_cb + * @param abort_cb callback to call for the abort-refund variant + * @param abort_cb_cls closure for @a abort_cb * @return a handle for this request */ -struct TALER_MERCHANT_Pay * -TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx, - const char *merchant_uri, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *order_id, - unsigned int num_coins, - const struct TALER_MERCHANT_PaidCoin *coins, - TALER_MERCHANT_PayCallback pay_cb, - void *pay_cb_cls) +static struct TALER_MERCHANT_Pay * +request_pay_generic (struct GNUNET_CURL_Context *ctx, + const char *merchant_url, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *order_id, + unsigned int num_coins, + const struct TALER_MERCHANT_PaidCoin *coins, + const char *mode, + TALER_MERCHANT_PayCallback pay_cb, + void *pay_cb_cls, + TALER_MERCHANT_PayRefundCallback abort_cb, + void *abort_cb_cls) { struct TALER_MERCHANT_Pay *ph; json_t *pay_obj; @@ -465,10 +496,12 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx, } pay_obj = json_pack ("{" + " s:s," /* mode */ " s:o," /* coins */ " s:s," /* order_id */ " s:o," /* merchant_pub */ "}", + "mode", mode, "coins", j_coins, "order_id", order_id, "merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub)); @@ -479,9 +512,12 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx, } ph = GNUNET_new (struct TALER_MERCHANT_Pay); ph->ctx = ctx; - ph->cb = pay_cb; - ph->cb_cls = pay_cb_cls; - ph->url = MAH_path_to_url_ (merchant_uri, + ph->mode = mode; + ph->abort_cb = abort_cb; + ph->abort_cb_cls = abort_cb_cls; + ph->pay_cb = pay_cb; + ph->pay_cb_cls = pay_cb_cls; + ph->url = MAH_path_to_url_ (merchant_url, "/pay"); ph->num_coins = num_coins; ph->coins = GNUNET_new_array (num_coins, @@ -517,6 +553,302 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx, /** + * Pay a merchant. API for wallets that have the coin's private keys. + * _NOTE_: this function does NOT calculate each coin amount in order + * to match the contract total price. This calculation is to be made + * by the logic using this library. + * + * @param ctx the execution loop context + * @param merchant_url base URL of the merchant's backend + * @param instance which merchant instance will receive this payment + * @param h_contract_terms hashcode of the proposal being paid + * @param amount total value of the contract to be paid to the merchant + * @param max_fee maximum fee covered by the merchant (according to the contract) + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param merchant_sig signature from the merchant over the original contract + * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant + * @param refund_deadline date until which the merchant can issue a refund to the customer via the merchant (can be zero if refunds are not allowed) + * @param pay_deadline maximum time limit to pay for this contract + * @param h_wire hash of the merchant’s account details + * @param order_id order id of the proposal being paid + * @param num_coins number of coins used to pay + * @param coins array of coins we use to pay + * @param pay_cb the callback to call when a reply for this request is available + * @param pay_cb_cls closure for @a pay_cb + * @return a handle for this request + */ +static struct TALER_MERCHANT_Pay * +prepare_pay_generic (struct GNUNET_CURL_Context *ctx, + const char *merchant_url, + const char *instance, + const struct GNUNET_HashCode *h_contract_terms, + const struct TALER_Amount *amount, + const struct TALER_Amount *max_fee, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig, + struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Absolute refund_deadline, + struct GNUNET_TIME_Absolute pay_deadline, + const struct GNUNET_HashCode *h_wire, + const char *order_id, + unsigned int num_coins, + const struct TALER_MERCHANT_PayCoin *coins, + const char *mode, + TALER_MERCHANT_PayCallback pay_cb, + void *pay_cb_cls, + TALER_MERCHANT_PayRefundCallback abort_cb, + void *abort_cb_cls) +{ + struct TALER_DepositRequestPS dr; + struct TALER_MERCHANT_PaidCoin pc[num_coins]; + + (void) GNUNET_TIME_round_abs (×tamp); + (void) GNUNET_TIME_round_abs (&pay_deadline); + (void) GNUNET_TIME_round_abs (&refund_deadline); + + if (GNUNET_YES != + TALER_amount_cmp_currency (amount, + max_fee)) + { + GNUNET_break (0); + return NULL; + } + + dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); + dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS)); + dr.h_contract_terms = *h_contract_terms; + dr.h_wire = *h_wire; + dr.timestamp = GNUNET_TIME_absolute_hton (timestamp); + dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline); + dr.merchant = *merchant_pub; + for (unsigned int i=0;i<num_coins;i++) + { + const struct TALER_MERCHANT_PayCoin *coin = &coins[i]; + struct TALER_MERCHANT_PaidCoin *p = &pc[i]; + struct TALER_Amount fee; + + /* prepare 'dr' for this coin to generate coin signature */ + GNUNET_CRYPTO_eddsa_key_get_public (&coin->coin_priv.eddsa_priv, + &dr.coin_pub.eddsa_pub); + TALER_amount_hton (&dr.amount_with_fee, + &coin->amount_with_fee); + if (GNUNET_SYSERR == + TALER_amount_subtract (&fee, + &coin->amount_with_fee, + &coin->amount_without_fee)) + { + /* Integer underflow, fee larger than total amount? + This should not happen (client violated API!) */ + GNUNET_break (0); + return NULL; + } + TALER_amount_hton (&dr.deposit_fee, + &fee); + { + TALER_LOG_DEBUG ("... amount_with_fee was %s\n", + TALER_amount2s (&coin->amount_with_fee)); + TALER_LOG_DEBUG ("... fee was %s\n", + TALER_amount2s (&fee)); + } + + GNUNET_CRYPTO_eddsa_sign (&coin->coin_priv.eddsa_priv, + &dr.purpose, + &p->coin_sig.eddsa_signature); + p->denom_pub = coin->denom_pub; + p->denom_sig = coin->denom_sig; + p->denom_value = coin->denom_value; + p->coin_pub = dr.coin_pub; + p->amount_with_fee = coin->amount_with_fee; + p->amount_without_fee = coin->amount_without_fee; + p->exchange_url = coin->exchange_url; + } + return request_pay_generic (ctx, + merchant_url, + merchant_pub, + order_id, + num_coins, + pc, + mode, + pay_cb, + pay_cb_cls, + abort_cb, + abort_cb_cls); +} + + +/** + * Pay a merchant. API for wallets that have the coin's private keys. + * _NOTE_: this function does NOT calculate each coin amount in order + * to match the contract total price. This calculation is to be made + * by the logic using this library. + * + * @param ctx the execution loop context + * @param merchant_url base URL of the merchant's backend + * @param instance which merchant instance will receive this payment + * @param h_contract_terms hashcode of the proposal being paid + * @param amount total value of the contract to be paid to the merchant + * @param max_fee maximum fee covered by the merchant (according to the contract) + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param merchant_sig signature from the merchant over the original contract + * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant + * @param refund_deadline date until which the merchant can issue a refund to the customer via the merchant (can be zero if refunds are not allowed) + * @param pay_deadline maximum time limit to pay for this contract + * @param h_wire hash of the merchant’s account details + * @param order_id order id of the proposal being paid + * @param num_coins number of coins used to pay + * @param coins array of coins we use to pay + * @param pay_cb the callback to call when a reply for this request is available + * @param pay_cb_cls closure for @a pay_cb + * @return a handle for this request + */ +struct TALER_MERCHANT_Pay * +TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx, + const char *merchant_url, + const char *instance, + const struct GNUNET_HashCode *h_contract_terms, + const struct TALER_Amount *amount, + const struct TALER_Amount *max_fee, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig, + struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Absolute refund_deadline, + struct GNUNET_TIME_Absolute pay_deadline, + const struct GNUNET_HashCode *h_wire, + const char *order_id, + unsigned int num_coins, + const struct TALER_MERCHANT_PayCoin *coins, + TALER_MERCHANT_PayCallback pay_cb, + void *pay_cb_cls) +{ + return prepare_pay_generic (ctx, + merchant_url, + instance, + h_contract_terms, + amount, + max_fee, + merchant_pub, + merchant_sig, + timestamp, + refund_deadline, + pay_deadline, + h_wire, + order_id, + num_coins, + coins, + "pay", + pay_cb, + pay_cb_cls, + NULL, + NULL); +} + + +/** + * Run a payment abort operation, asking for refunds for coins + * that were previously spend on a /pay that failed to go through. + * + * @param ctx execution context + * @param merchant_url base URL of the merchant + * @param instance which merchant instance will receive this payment + * @param h_wire hash of the merchant’s account details + * @param h_contract hash of the contact of the merchant with the customer + * @param transaction_id transaction id for the transaction between merchant and customer + * @param amount total value of the contract to be paid to the merchant + * @param max_fee maximum fee covered by the merchant (according to the contract) + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param merchant_sig signature from the merchant over the original contract + * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant + * @param refund_deadline date until which the merchant can issue a refund to the customer via the merchant (can be zero if refunds are not allowed) + * @param pay_deadline maximum time limit to pay for this contract + * @param num_coins number of coins used to pay + * @param coins array of coins we use to pay + * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key. + * @param payref_cb the callback to call when a reply for this request is available + * @param payref_cb_cls closure for @a pay_cb + * @return a handle for this request + */ +struct TALER_MERCHANT_Pay * +TALER_MERCHANT_pay_abort (struct GNUNET_CURL_Context *ctx, + const char *merchant_url, + const char *instance, + const struct GNUNET_HashCode *h_contract, + const struct TALER_Amount *amount, + const struct TALER_Amount *max_fee, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig, + struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Absolute refund_deadline, + struct GNUNET_TIME_Absolute pay_deadline, + const struct GNUNET_HashCode *h_wire, + const char *order_id, + unsigned int num_coins, + const struct TALER_MERCHANT_PayCoin *coins, + TALER_MERCHANT_PayRefundCallback payref_cb, + void *payref_cb_cls) +{ + return prepare_pay_generic (ctx, + merchant_url, + instance, + h_contract, + amount, + max_fee, + merchant_pub, + merchant_sig, + timestamp, + refund_deadline, + pay_deadline, + h_wire, + order_id, + num_coins, + coins, + "abort-refund", + NULL, + NULL, + payref_cb, + payref_cb_cls); +} + + +/** + * PAY a merchant. API for frontends talking to backends. Here, + * the frontend does not have the coin's private keys, but just + * the public keys and signatures. Note the subtle difference + * in the type of @a coins compared to #TALER_MERCHANT_pay(). + * + * @param ctx the execution loop context + * @param merchant_url base URL of the merchant's backend + * @param merchant_pub public key of the merchant + * @param num_coins number of coins used to pay + * @param coins array of coins we use to pay + * @param pay_cb the callback to call when a reply for this request is available + * @param pay_cb_cls closure for @a pay_cb + * @return a handle for this request + */ +struct TALER_MERCHANT_Pay * +TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx, + const char *merchant_url, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *order_id, + unsigned int num_coins, + const struct TALER_MERCHANT_PaidCoin *coins, + TALER_MERCHANT_PayCallback pay_cb, + void *pay_cb_cls) +{ + return request_pay_generic (ctx, + merchant_url, + merchant_pub, + order_id, + num_coins, + coins, + "pay", + pay_cb, + pay_cb_cls, + NULL, + NULL); +} + + +/** * Cancel a pay permission request. This function cannot be used * on a request handle if a response is already served for it. * |