diff options
Diffstat (limited to 'src/lib/merchant_api_wallet_post_order_refund.c')
-rw-r--r-- | src/lib/merchant_api_wallet_post_order_refund.c | 287 |
1 files changed, 101 insertions, 186 deletions
diff --git a/src/lib/merchant_api_wallet_post_order_refund.c b/src/lib/merchant_api_wallet_post_order_refund.c index fc4b0abd..e72982f3 100644 --- a/src/lib/merchant_api_wallet_post_order_refund.c +++ b/src/lib/merchant_api_wallet_post_order_refund.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020 Taler Systems SA + Copyright (C) 2020-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -32,6 +32,10 @@ #include <taler/taler_signatures.h> #include <taler/taler_curl_lib.h> +/** + * Maximum number of refunds we return. + */ +#define MAX_REFUNDS 1024 /** * Handle for a (public) POST /orders/ID/refund operation. @@ -71,33 +75,6 @@ struct TALER_MERCHANT_WalletOrderRefundHandle /** - * Convenience function to call the callback in @a owgh with an error code of - * @a ec and the exchange body being set to @a reply. - * - * @param orh handle providing callback - * @param ec error code to return to application - * @param reply JSON reply we got from the exchange, can be NULL - */ -static void -cb_failure (struct TALER_MERCHANT_WalletOrderRefundHandle *orh, - enum TALER_ErrorCode ec, - const json_t *reply) -{ - struct TALER_MERCHANT_HttpResponse hr = { - .ec = ec, - .reply = reply - }; - - orh->cb (orh->cb_cls, - &hr, - NULL, - NULL, - NULL, - 0); -} - - -/** * Callback to process (public) POST /orders/ID/refund response * * @param cls the `struct TALER_MERCHANT_OrderRefundHandle` @@ -111,37 +88,31 @@ handle_refund_finished (void *cls, { struct TALER_MERCHANT_WalletOrderRefundHandle *orh = cls; const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_WalletRefundResponse wrr = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json }; orh->job = NULL; - switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - orh->cb (orh->cb_cls, - &hr, - NULL, - NULL, - NULL, - 0); + wrr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: { - struct TALER_Amount refund_amount; - json_t *refunds; - struct TALER_MerchantPublicKeyP merchant_pub; + const json_t *refunds; unsigned int refund_len; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount_any ("refund_amount", - &refund_amount), - GNUNET_JSON_spec_json ("refunds", - &refunds), - GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &merchant_pub), + TALER_JSON_spec_amount_any ( + "refund_amount", + &wrr.details.ok.refund_amount), + GNUNET_JSON_spec_array_const ( + "refunds", + &refunds), + GNUNET_JSON_spec_fixed_auto ( + "merchant_pub", + &wrr.details.ok.merchant_pub), GNUNET_JSON_spec_end () }; @@ -151,27 +122,21 @@ handle_refund_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - cb_failure (orh, - TALER_EC_GENERIC_REPLY_MALFORMED, - json); - TALER_MERCHANT_wallet_post_order_refund_cancel (orh); - return; + wrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + wrr.hr.http_status = 0; + break; } - - if (! json_is_array (refunds)) + refund_len = json_array_size (refunds); + if ( (json_array_size (refunds) != (size_t) refund_len) || + (refund_len > MAX_REFUNDS) ) { - GNUNET_break_op (0); - cb_failure (orh, - TALER_EC_GENERIC_REPLY_MALFORMED, - json); - GNUNET_JSON_parse_free (spec); - TALER_MERCHANT_wallet_post_order_refund_cancel (orh); - return; + GNUNET_break (0); + wrr.hr.ec = TALER_EC_GENERIC_ALLOCATION_FAILURE; + wrr.hr.http_status = 0; + break; } - - refund_len = json_array_size (refunds); { - struct TALER_MERCHANT_RefundDetail rds[refund_len]; + struct TALER_MERCHANT_RefundDetail rds[GNUNET_NZL (refund_len)]; memset (rds, 0, @@ -183,10 +148,26 @@ handle_refund_finished (void *cls, i); const char *refund_status_type; uint32_t exchange_status; - int ret; + uint32_t eec = 0; struct GNUNET_JSON_Specification espec[] = { + GNUNET_JSON_spec_string ("type", + &refund_status_type), GNUNET_JSON_spec_uint32 ("exchange_status", &exchange_status), + GNUNET_JSON_spec_uint64 ("rtransaction_id", + &rd->rtransaction_id), + GNUNET_JSON_spec_fixed_auto ("coin_pub", + &rd->coin_pub), + TALER_JSON_spec_amount_any ("refund_amount", + &rd->refund_amount), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_object_const ("exchange_reply", + &rd->hr.reply), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_uint32 ("exchange_code", + &eec), + NULL), GNUNET_JSON_spec_end () }; @@ -196,151 +177,85 @@ handle_refund_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - cb_failure (orh, - TALER_EC_GENERIC_REPLY_MALFORMED, - json); - TALER_MERCHANT_wallet_post_order_refund_cancel (orh); - return; + wrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + wrr.hr.http_status = 0; + goto finish; } - if (MHD_HTTP_OK == exchange_status) + rd->hr.http_status = exchange_status; + rd->hr.ec = (enum TALER_ErrorCode) eec; + switch (exchange_status) { - struct GNUNET_JSON_Specification rspec[] = { - GNUNET_JSON_spec_string ("type", - &refund_status_type), - GNUNET_JSON_spec_fixed_auto ("exchange_sig", - &rd->exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", - &rd->exchange_pub), - GNUNET_JSON_spec_uint64 ("rtransaction_id", - &rd->rtransaction_id), - GNUNET_JSON_spec_fixed_auto ("coin_pub", - &rd->coin_pub), - TALER_JSON_spec_amount_any ("refund_amount", - &rd->refund_amount), - GNUNET_JSON_spec_end () - }; - - ret = GNUNET_JSON_parse (jrefund, - rspec, - NULL, NULL); - if (GNUNET_OK == ret) + case MHD_HTTP_OK: { - /* check that type field is correct */ - if (0 != strcmp ("success", refund_status_type)) - { - GNUNET_break_op (0); - ret = GNUNET_SYSERR; - } - } - } - else - { - struct GNUNET_JSON_Specification rspec[] = { - GNUNET_JSON_spec_string ("type", - &refund_status_type), - GNUNET_JSON_spec_fixed_auto ("coin_pub", - &rd->coin_pub), - GNUNET_JSON_spec_uint64 ("rtransaction_id", - &rd->rtransaction_id), - TALER_JSON_spec_amount_any ("refund_amount", - &rd->refund_amount), - GNUNET_JSON_spec_end () - }; - - ret = GNUNET_JSON_parse (jrefund, + struct GNUNET_JSON_Specification rspec[] = { + GNUNET_JSON_spec_fixed_auto ("exchange_sig", + &rd->details.ok.exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", + &rd->details.ok.exchange_pub), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (jrefund, rspec, - NULL, NULL); - if (GNUNET_OK == ret) - { - /* parse optional arguments */ - json_t *jec; - - jec = json_object_get (jrefund, - "exchange_code"); - if (NULL != jec) + NULL, + NULL)) { - if (! json_is_integer (jec)) - { - GNUNET_break_op (0); - ret = GNUNET_SYSERR; - } - else - { - rd->hr.ec = (enum TALER_ErrorCode) json_integer_value (jec); - } + GNUNET_break_op (0); + wrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + wrr.hr.http_status = 0; + goto finish; } - rd->hr.reply = json_object_get (jrefund, - "exchange_reply"); /* check that type field is correct */ - if (0 != strcmp ("failure", refund_status_type)) + if (0 != strcmp ("success", + refund_status_type)) { GNUNET_break_op (0); - ret = GNUNET_SYSERR; + wrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + wrr.hr.http_status = 0; + goto finish; } } - } - if (GNUNET_OK != ret) - { - GNUNET_break_op (0); - cb_failure (orh, - TALER_EC_GENERIC_REPLY_MALFORMED, - json); - TALER_MERCHANT_wallet_post_order_refund_cancel (orh); - return; - } - rd->hr.http_status = exchange_status; - } - - { - struct TALER_MERCHANT_HttpResponse hr = { - .reply = json, - .http_status = MHD_HTTP_OK - }; + break; /* end MHD_HTTP_OK */ + default: + if (0 != strcmp ("failure", + refund_status_type)) + { + GNUNET_break_op (0); + wrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + wrr.hr.http_status = 0; + goto finish; + } + } /* switch on exchange status code */ + } /* for all refunds */ - orh->cb (orh->cb_cls, - &hr, - &refund_amount, - &merchant_pub, - rds, - refund_len); - } - } - GNUNET_JSON_parse_free (spec); - } + wrr.details.ok.refunds = rds; + wrr.details.ok.refunds_length = refund_len; + orh->cb (orh->cb_cls, + &wrr); + TALER_MERCHANT_wallet_post_order_refund_cancel (orh); + return; + } /* end 'rds' scope */ + } /* case MHD_HTTP_OK */ break; case MHD_HTTP_NO_CONTENT: - orh->cb (orh->cb_cls, - &hr, - NULL, - NULL, - NULL, - 0); break; case MHD_HTTP_CONFLICT: case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - orh->cb (orh->cb_cls, - &hr, - NULL, - NULL, - NULL, - 0); + wrr.hr.ec = TALER_JSON_get_error_code (json); + wrr.hr.hint = TALER_JSON_get_error_hint (json); break; default: GNUNET_break_op (0); /* unexpected status code */ TALER_MERCHANT_parse_error_details_ (json, response_code, - &hr); - orh->cb (orh->cb_cls, - &hr, - NULL, - NULL, - NULL, - 0); + &wrr.hr); break; } +finish: + orh->cb (orh->cb_cls, + &wrr); TALER_MERCHANT_wallet_post_order_refund_cancel (orh); } |