diff options
Diffstat (limited to 'src/lib/exchange_api_refund.c')
-rw-r--r-- | src/lib/exchange_api_refund.c | 551 |
1 files changed, 136 insertions, 415 deletions
diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c index f83a2985a..9159b55f2 100644 --- a/src/lib/exchange_api_refund.c +++ b/src/lib/exchange_api_refund.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -39,9 +39,9 @@ struct TALER_EXCHANGE_RefundHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -70,9 +70,33 @@ struct TALER_EXCHANGE_RefundHandle void *cb_cls; /** - * Information the exchange should sign in response. + * Hash over the proposal data to identify the contract + * which is being refunded. */ - struct TALER_RefundConfirmationPS depconf; + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * The coin's public key. This is the value that must have been + * signed (blindly) by the Exchange. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * The Merchant's public key. Allows the merchant to later refund + * the transaction or to inquire about the wire transfer identifier. + */ + struct TALER_MerchantPublicKeyP merchant; + + /** + * Merchant-generated transaction ID for the refund. + */ + uint64_t rtransaction_id; + + /** + * Amount to be refunded, including refund fee charged by the + * exchange to the customer. + */ + struct TALER_Amount refund_amount; }; @@ -87,16 +111,17 @@ struct TALER_EXCHANGE_RefundHandle * @param[out] exchange_sig set to the exchange's signature * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not */ -static int +static enum GNUNET_GenericReturnValue verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, const json_t *json, struct TALER_ExchangePublicKeyP *exchange_pub, struct TALER_ExchangeSignatureP *exchange_sig) { - const struct TALER_EXCHANGE_Keys *key_state; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("exchange_sig", exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", exchange_pub), + GNUNET_JSON_spec_fixed_auto ("exchange_sig", + exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", + exchange_pub), GNUNET_JSON_spec_end () }; @@ -108,19 +133,22 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, GNUNET_break_op (0); return GNUNET_SYSERR; } - key_state = TALER_EXCHANGE_get_keys (rh->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (rh->keys, exchange_pub)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND, - &rh->depconf, - &exchange_sig->eddsa_signature, - &exchange_pub->eddsa_pub)) + TALER_exchange_online_refund_confirmation_verify ( + &rh->h_contract_terms, + &rh->coin_pub, + &rh->merchant, + rh->rtransaction_id, + &rh->refund_amount, + exchange_pub, + exchange_sig)) { GNUNET_break_op (0); return GNUNET_SYSERR; @@ -130,282 +158,6 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, /** - * Verify that the information in the "409 Conflict" response - * from the exchange is valid and indeed shows that the refund - * amount requested is too high. - * - * @param[in,out] rh refund handle (refund fee added) - * @param json json reply with the coin transaction history - * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not - */ -static int -verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh, - const json_t *json) -{ - json_t *history; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("history", - &history), - GNUNET_JSON_spec_end () - }; - size_t len; - struct TALER_Amount dtotal; - bool have_deposit; - struct TALER_Amount rtotal; - bool have_refund; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - len = json_array_size (history); - if (0 == len) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - have_deposit = false; - have_refund = false; - for (size_t off = 0; off<len; off++) - { - json_t *transaction; - struct TALER_Amount amount; - const char *type; - struct GNUNET_JSON_Specification spec_glob[] = { - TALER_JSON_spec_amount_any ("amount", - &amount), - GNUNET_JSON_spec_string ("type", - &type), - GNUNET_JSON_spec_end () - }; - - transaction = json_array_get (history, - off); - if (GNUNET_OK != - GNUNET_JSON_parse (transaction, - spec_glob, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (0 == strcasecmp (type, - "DEPOSIT")) - { - struct TALER_DepositRequestPS dr = { - .purpose.size = htonl (sizeof (dr)), - .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT), - .coin_pub = rh->depconf.coin_pub - }; - struct TALER_CoinSpendSignatureP sig; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("coin_sig", - &sig), - GNUNET_JSON_spec_fixed_auto ("h_contract_terms", - &dr.h_contract_terms), - GNUNET_JSON_spec_fixed_auto ("h_wire", - &dr.h_wire), - GNUNET_JSON_spec_fixed_auto ("h_denom_pub", - &dr.h_denom_pub), - TALER_JSON_spec_absolute_time_nbo ("timestamp", - &dr.wallet_timestamp), - TALER_JSON_spec_absolute_time_nbo ("refund_deadline", - &dr.refund_deadline), - TALER_JSON_spec_amount_any_nbo ("deposit_fee", - &dr.deposit_fee), - GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &dr.merchant), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (transaction, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - TALER_amount_hton (&dr.amount_with_fee, - &amount); - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT, - &dr, - &sig.eddsa_signature, - &rh->depconf.coin_pub.eddsa_pub)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ( (0 != GNUNET_memcmp (&rh->depconf.h_contract_terms, - &dr.h_contract_terms)) || - (0 != GNUNET_memcmp (&rh->depconf.merchant, - &dr.merchant)) ) - { - /* deposit information is about a different merchant/contract */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (have_deposit) - { - /* this cannot really happen, but we conservatively support it anyway */ - if (GNUNET_YES != - TALER_amount_cmp_currency (&amount, - &dtotal)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - GNUNET_break (0 <= - TALER_amount_add (&dtotal, - &dtotal, - &amount)); - } - else - { - dtotal = amount; - have_deposit = true; - } - } - else if (0 == strcasecmp (type, - "REFUND")) - { - struct TALER_MerchantSignatureP sig; - struct TALER_Amount refund_fee; - struct TALER_Amount sig_amount; - struct TALER_RefundRequestPS rr = { - .purpose.size = htonl (sizeof (rr)), - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .coin_pub = rh->depconf.coin_pub - }; - struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount_any ("refund_fee", - &refund_fee), - GNUNET_JSON_spec_fixed_auto ("merchant_sig", - &sig), - GNUNET_JSON_spec_fixed_auto ("h_contract_terms", - &rr.h_contract_terms), - GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &rr.merchant), - GNUNET_JSON_spec_uint64 ("rtransaction_id", - &rr.rtransaction_id), /* Note: converted to NBO below */ - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (transaction, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (0 > - TALER_amount_add (&sig_amount, - &refund_fee, - &amount)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - TALER_amount_hton (&rr.refund_amount, - &sig_amount); - rr.rtransaction_id = GNUNET_htonll (rr.rtransaction_id); - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &sig.eddsa_sig, - &rr.merchant.eddsa_pub)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ( (0 != GNUNET_memcmp (&rh->depconf.h_contract_terms, - &rr.h_contract_terms)) || - (0 != GNUNET_memcmp (&rh->depconf.merchant, - &rr.merchant)) ) - { - /* refund is about a different merchant/contract */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (rr.rtransaction_id == rh->depconf.rtransaction_id) - { - /* Eh, this shows either a dependency failure or idempotency, - but must not happen in a conflict reply. Fail! */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - if (have_refund) - { - if (GNUNET_YES != - TALER_amount_cmp_currency (&amount, - &rtotal)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - GNUNET_break (0 <= - TALER_amount_add (&rtotal, - &rtotal, - &amount)); - } - else - { - rtotal = amount; - have_refund = true; - } - } - else - { - /* unexpected type, new version on server? */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected type `%s' in response for exchange refund\n", - type); - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - } - - { - struct TALER_Amount amount; - - TALER_amount_ntoh (&amount, - &rh->depconf.refund_amount); - if (have_refund) - { - if (0 > - TALER_amount_add (&rtotal, - &rtotal, - &amount)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - } - else - { - rtotal = amount; - } - } - if (-1 == TALER_amount_cmp (&dtotal, - &rtotal)) - { - /* dtotal < rtotal: good! */ - return GNUNET_OK; - } - /* this fails to prove a conflict */ - GNUNET_break_op (0); - return GNUNET_SYSERR; -} - - -/** * Verify that the information on the "412 Dependency Failed" response * from the exchange is valid and indeed shows that there is a refund * transaction ID reuse going on. @@ -414,14 +166,15 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh, * @param json json reply with the signature * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not */ -static int +static enum GNUNET_GenericReturnValue verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, const json_t *json) { - json_t *h; + const json_t *h; json_t *e; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("history", &h), + GNUNET_JSON_spec_array_const ("history", + &h), GNUNET_JSON_spec_end () }; @@ -433,8 +186,7 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, GNUNET_break_op (0); return GNUNET_SYSERR; } - if ( (! json_is_array (h)) || - (1 != json_array_size (h) ) ) + if (1 != json_array_size (h)) { GNUNET_break_op (0); return GNUNET_SYSERR; @@ -445,13 +197,10 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, const char *type; struct TALER_MerchantSignatureP sig; struct TALER_Amount refund_fee; - struct TALER_RefundRequestPS rr = { - .purpose.size = htonl (sizeof (rr)), - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .coin_pub = rh->depconf.coin_pub - }; + struct TALER_PrivateContractHashP h_contract_terms; uint64_t rtransaction_id; - struct GNUNET_JSON_Specification spec[] = { + struct TALER_MerchantPublicKeyP merchant_pub; + struct GNUNET_JSON_Specification ispec[] = { TALER_JSON_spec_amount_any ("amount", &amount), GNUNET_JSON_spec_string ("type", @@ -461,9 +210,9 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, GNUNET_JSON_spec_fixed_auto ("merchant_sig", &sig), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", - &rr.h_contract_terms), + &h_contract_terms), GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &rr.merchant), + &merchant_pub), GNUNET_JSON_spec_uint64 ("rtransaction_id", &rtransaction_id), GNUNET_JSON_spec_end () @@ -471,31 +220,30 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, if (GNUNET_OK != GNUNET_JSON_parse (e, - spec, + ispec, NULL, NULL)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - rr.rtransaction_id = GNUNET_htonll (rtransaction_id); - TALER_amount_hton (&rr.refund_amount, - &amount); if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &sig.eddsa_sig, - &rh->depconf.merchant.eddsa_pub)) + TALER_merchant_refund_verify (&rh->coin_pub, + &h_contract_terms, + rtransaction_id, + &amount, + &merchant_pub, + &sig)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - if ( (rr.rtransaction_id != rh->depconf.rtransaction_id) || - (0 != GNUNET_memcmp (&rh->depconf.h_contract_terms, - &rr.h_contract_terms)) || - (0 != GNUNET_memcmp (&rh->depconf.merchant, - &rr.merchant)) || - (0 == TALER_amount_cmp_nbo (&rh->depconf.refund_amount, - &rr.refund_amount)) ) + if ( (rtransaction_id != rh->rtransaction_id) || + (0 != GNUNET_memcmp (&rh->h_contract_terms, + &h_contract_terms)) || + (0 != GNUNET_memcmp (&rh->merchant, + &merchant_pub)) || + (0 == TALER_amount_cmp (&rh->refund_amount, + &amount)) ) { GNUNET_break_op (0); return GNUNET_SYSERR; @@ -519,37 +267,28 @@ handle_refund_finished (void *cls, const void *response) { struct TALER_EXCHANGE_RefundHandle *rh = cls; - struct TALER_ExchangePublicKeyP exchange_pub; - struct TALER_ExchangeSignatureP exchange_sig; - struct TALER_ExchangePublicKeyP *ep = NULL; - struct TALER_ExchangeSignatureP *es = NULL; const json_t *j = response; - struct TALER_EXCHANGE_HttpResponse hr = { - .reply = j, - .http_status = (unsigned int) response_code + struct TALER_EXCHANGE_RefundResponse rr = { + .hr.reply = j, + .hr.http_status = (unsigned int) response_code }; rh->job = NULL; switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: if (GNUNET_OK != verify_refund_signature_ok (rh, j, - &exchange_pub, - &exchange_sig)) + &rr.details.ok.exchange_pub, + &rr.details.ok.exchange_sig)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE; - } - else - { - ep = &exchange_pub; - es = &exchange_sig; + rr.hr.http_status = 0; + rr.hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE; } break; case MHD_HTTP_BAD_REQUEST: @@ -557,42 +296,36 @@ handle_refund_finished (void *cls, (or API version conflict); also can happen if the currency differs (which we should obviously never support). Just pass JSON reply to the application */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_FORBIDDEN: /* Nothing really to verify, exchange says one of the signatures is invalid; as we checked them, this should never happen, we should pass the JSON reply to the application */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_NOT_FOUND: /* Nothing really to verify, this should never happen, we should pass the JSON reply to the application */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_CONFLICT: /* Requested total refunds exceed deposited amount */ - if (GNUNET_OK != - verify_conflict_history_ok (rh, - j)) - { - GNUNET_break (0); - hr.http_status = 0; - hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE; - hr.hint = "conflict information provided by exchange is invalid"; - break; - } - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_GONE: /* Kind of normal: the money was already sent to the merchant (it was too late for the refund). */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); + break; + case MHD_HTTP_FAILED_DEPENDENCY: + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_PRECONDITION_FAILED: if (GNUNET_OK != @@ -600,89 +333,80 @@ handle_refund_finished (void *cls, j)) { GNUNET_break (0); - hr.http_status = 0; - hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE; - hr.hint = "failed precondition proof returned by exchange is invalid"; + rr.hr.http_status = 0; + rr.hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE; + rr.hr.hint = "failed precondition proof returned by exchange is invalid"; break; } /* Two different refund requests were made about the same deposit, but carrying identical refund transaction ids. */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_INTERNAL_SERVER_ERROR: /* Server had an internal issue; we should retry, but this API leaves this to the application */ - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); break; default: /* unexpected response code */ GNUNET_break_op (0); - hr.ec = TALER_JSON_get_error_code (j); - hr.hint = TALER_JSON_get_error_hint (j); + rr.hr.ec = TALER_JSON_get_error_code (j); + rr.hr.hint = TALER_JSON_get_error_hint (j); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d for exchange refund\n", (unsigned int) response_code, - hr.ec); + rr.hr.ec); break; } rh->cb (rh->cb_cls, - &hr, - ep, - es); + &rr); TALER_EXCHANGE_refund_cancel (rh); } struct TALER_EXCHANGE_RefundHandle * -TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_Amount *amount, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - const struct TALER_MerchantPrivateKeyP *merchant_priv, - TALER_EXCHANGE_RefundCallback cb, - void *cb_cls) +TALER_EXCHANGE_refund ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_Amount *amount, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t rtransaction_id, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + TALER_EXCHANGE_RefundCallback cb, + void *cb_cls) { - struct TALER_RefundRequestPS rr = { - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .purpose.size = htonl (sizeof (rr)), - .h_contract_terms = *h_contract_terms, - .rtransaction_id = GNUNET_htonll (rtransaction_id), - .coin_pub = *coin_pub - }; + struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantSignatureP merchant_sig; struct TALER_EXCHANGE_RefundHandle *rh; - struct GNUNET_CURL_Context *ctx; json_t *refund_obj; CURL *eh; char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, - &rr.merchant.eddsa_pub); - TALER_amount_hton (&rr.refund_amount, - amount); - GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, - &rr, - &merchant_sig.eddsa_sig); - - + &merchant_pub.eddsa_pub); + TALER_merchant_refund_sign (coin_pub, + h_contract_terms, + rtransaction_id, + amount, + merchant_priv, + &merchant_sig); { char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char *end; - end = GNUNET_STRINGS_data_to_string (coin_pub, - sizeof (struct - TALER_CoinSpendPublicKeyP), - pub_str, - sizeof (pub_str)); + end = GNUNET_STRINGS_data_to_string ( + coin_pub, + sizeof (struct TALER_CoinSpendPublicKeyP), + pub_str, + sizeof (pub_str)); *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/coins/%s/refund", + "coins/%s/refund", pub_str); } refund_obj = GNUNET_JSON_PACK ( @@ -693,30 +417,26 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, GNUNET_JSON_pack_uint64 ("rtransaction_id", rtransaction_id), GNUNET_JSON_pack_data_auto ("merchant_pub", - &rr.merchant), + &merchant_pub), GNUNET_JSON_pack_data_auto ("merchant_sig", &merchant_sig)); rh = GNUNET_new (struct TALER_EXCHANGE_RefundHandle); - rh->exchange = exchange; rh->cb = cb; rh->cb_cls = cb_cls; - rh->url = TEAH_path_to_url (exchange, - arg_str); + rh->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == rh->url) { json_decref (refund_obj); GNUNET_free (rh); return NULL; } - rh->depconf.purpose.size = htonl (sizeof (struct TALER_RefundConfirmationPS)); - rh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND); - rh->depconf.h_contract_terms = *h_contract_terms; - rh->depconf.coin_pub = *coin_pub; - rh->depconf.merchant = rr.merchant; - rh->depconf.rtransaction_id = GNUNET_htonll (rtransaction_id); - TALER_amount_hton (&rh->depconf.refund_amount, - amount); - + rh->h_contract_terms = *h_contract_terms; + rh->coin_pub = *coin_pub; + rh->merchant = merchant_pub; + rh->rtransaction_id = rtransaction_id; + rh->refund_amount = *amount; eh = TALER_EXCHANGE_curl_easy_get_ (rh->url); if ( (NULL == eh) || (GNUNET_OK != @@ -736,7 +456,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for refund: `%s'\n", rh->url); - ctx = TEAH_handle_to_context (exchange); + rh->keys = TALER_EXCHANGE_keys_incref (keys); rh->job = GNUNET_CURL_job_add2 (ctx, eh, rh->ctx.headers, @@ -756,6 +476,7 @@ TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund) } GNUNET_free (refund->url); TALER_curl_easy_post_finished (&refund->ctx); + TALER_EXCHANGE_keys_decref (refund->keys); GNUNET_free (refund); } |