diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-06-03 23:24:31 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-06-03 23:24:31 +0200 |
commit | 7f8c111f1383805d64ab7f754cb6456d3dfb7250 (patch) | |
tree | 4b5561f5e7ed8a07be933ccd6bbd2c8ec29aa0f0 | |
parent | cea5867be3735f7c418a456b93ba9a45535f8cbc (diff) |
address more FIXMEs
-rw-r--r-- | src/include/taler_merchant_service.h | 227 | ||||
-rw-r--r-- | src/lib/merchant_api_get_reserves.c | 1 | ||||
-rw-r--r-- | src/lib/merchant_api_get_transfers.c | 64 | ||||
-rw-r--r-- | src/lib/merchant_api_post_order_abort.c | 74 | ||||
-rw-r--r-- | src/lib/merchant_api_post_order_pay.c | 2 | ||||
-rw-r--r-- | src/lib/merchant_api_post_order_refund.c | 65 | ||||
-rw-r--r-- | src/lib/merchant_api_wallet_post_order_refund.c | 276 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_abort_order.c | 36 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_get_transfers.c | 53 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_refund_order.c | 27 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_wallet_post_orders_refund.c | 47 |
11 files changed, 431 insertions, 441 deletions
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 83035455..cb9edb29 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -2904,24 +2904,58 @@ struct TALER_MERCHANT_AbortedCoin }; -// FIXME: change signature! +/** + * Response to an /orders/$ID/abort request. + */ +struct TALER_MERCHANT_AbortResponse +{ + /** + * HTTP response details + */ + struct TALER_MERCHANT_HttpResponse hr; + + /** + * Details depending on HTTP status code. + */ + union + { + /** + * Details for #MHD_HTTP_OK. + */ + struct + { + + /** + * public key of the merchant + */ + const struct TALER_MerchantPublicKeyP *merchant_pub; + + /** + * size of the @e aborts array + */ + unsigned int num_aborts; + + /** + * merchant signatures refunding coins + */ + const struct TALER_MERCHANT_AbortedCoin *aborts; + } ok; + + } details; +}; + + /** * Callbacks of this type are used to serve the result of submitting a * /orders/$ID/abort request to a merchant. * * @param cls closure - * @param hr HTTP response details - * @param merchant_pub public key of the merchant - * @param num_aborts size of the @a res array, 0 on errors - * @param aborts merchant signatures refunding coins, NULL on errors + * @param ar response details */ typedef void (*TALER_MERCHANT_AbortCallback) ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - const struct TALER_MerchantPublicKeyP *merchant_pub, - unsigned int num_aborts, - const struct TALER_MERCHANT_AbortedCoin aborts[]); + const struct TALER_MERCHANT_AbortResponse *ar); /** @@ -3048,22 +3082,52 @@ TALER_MERCHANT_order_forget_cancel (struct struct TALER_MERCHANT_OrderRefundHandle; -// FIXME: change signature! /** - * Callback to process a POST /orders/ID/refund request + * Response to a POST /orders/$ID/refund request + */ +struct TALER_MERCHANT_RefundResponse +{ + /** + * HTTP response details this request + */ + struct TALER_MERCHANT_HttpResponse hr; + + /** + * Details depending on HTTP status. + */ + union + { + /** + * Details if status is #MHD_HTTP_OK. + */ + struct + { + + /** + * the refund uri offered to the wallet + */ + const char *taler_refund_uri; + + /** + * Hash of the contract a wallet may need to authorize obtaining the HTTP + * response. + */ + struct TALER_PrivateContractHashP h_contract; + } ok; + } details; +}; + + +/** + * Callback to process a POST /orders/$ID/refund request * * @param cls closure - * @param hr HTTP response details this request - * @param taler_refund_uri the refund uri offered to the wallet - * @param h_contract hash of the contract a Browser may need to authorize - * obtaining the HTTP response. + * @param rr response details this request */ typedef void (*TALER_MERCHANT_RefundCallback) ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - const char *taler_refund_uri, - const struct TALER_PrivateContractHashP *h_contract); + const struct TALER_MERCHANT_RefundResponse *rr); /** @@ -3130,39 +3194,87 @@ struct TALER_MERCHANT_RefundDetail struct TALER_Amount refund_amount; /** - * Public key of the exchange affirming the refund, - * only valid if the @e hr http_status is #MHD_HTTP_OK. + * Details depending on exchange HTTP status. */ - struct TALER_ExchangePublicKeyP exchange_pub; + union + { + /** + * Details if exchange status is #MHD_HTTP_OK. + */ + struct + { + /** + * Public key of the exchange affirming the refund, + * only valid if the @e hr http_status is #MHD_HTTP_OK. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Signature of the exchange affirming the refund, + * only valid if the @e hr http_status is #MHD_HTTP_OK. + */ + struct TALER_ExchangeSignatureP exchange_sig; + } ok; + } details; +}; + + +/** + * Response to a POST /orders/$ID/refund request + * for wallet API. + */ +struct TALER_MERCHANT_WalletRefundResponse +{ + /** + * HTTP response details this request + */ + struct TALER_MERCHANT_HttpResponse hr; /** - * Signature of the exchange affirming the refund, - * only valid if the @e hr http_status is #MHD_HTTP_OK. + * Details depending on HTTP status. */ - struct TALER_ExchangeSignatureP exchange_sig; + union + { + /** + * Details if status is #MHD_HTTP_OK. + */ + struct + { + + /** + * Total amount of the refund that was granted + */ + struct TALER_Amount refund_amount; + /** + * public key of the merchant signing the @e refunds + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * array with details about the refunds obtained + */ + const struct TALER_MERCHANT_RefundDetail *refunds; + + /** + * length of the @e refunds array + */ + unsigned int refunds_length; + } ok; + } details; }; -// FIXME: change signature! /** * Callback to process a (public) POST /orders/ID/refund request * * @param cls closure - * @param hr HTTP response details - * @param refund_amount what is the total amount of the refund that was granted - * @param merchant_pub public key of the merchant signing the @a refunds - * @param refunds array with details about the refunds obtained - * @param refunds_length length of the @a refunds array + * @param wrr HTTP response details */ typedef void (*TALER_MERCHANT_WalletRefundCallback) ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - const struct TALER_Amount *refund_amount, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct TALER_MERCHANT_RefundDetail refunds[], - unsigned int refunds_length); + const struct TALER_MERCHANT_WalletRefundResponse *wrr); /** @@ -3403,22 +3515,53 @@ struct TALER_MERCHANT_TransferData }; -// FIXME: change signature! +/** + * Response from a GET /transfers request. + */ +struct TALER_MERCHANT_GetTransfersResponse +{ + /** + * HTTP response details + */ + struct TALER_MERCHANT_HttpResponse hr; + + /** + * Details depending on HTTP status. + */ + union + { + + /** + * Details for status #MHD_HTTP_OK. + */ + struct + { + + /** + * length of the @e transfers array + */ + unsigned int transfers_length; + + /** + * array with details about the transfers we received + */ + const struct TALER_MERCHANT_TransferData *transfers; + } ok; + } details; +}; + + /** * Callbacks of this type are used to work the result of submitting a * GET /transfers request to a merchant * * @param cls closure - * @param hr HTTP response details - * @param transfers_length length of the @a transfers array - * @param transfers array with details about the transfers we received + * @param gtr HTTP response details */ typedef void (*TALER_MERCHANT_GetTransfersCallback) ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - unsigned int transfers_length, - const struct TALER_MERCHANT_TransferData transfers[]); + const struct TALER_MERCHANT_GetTransfersResponse *gtr); /** diff --git a/src/lib/merchant_api_get_reserves.c b/src/lib/merchant_api_get_reserves.c index 9b3b45e9..cf462cfb 100644 --- a/src/lib/merchant_api_get_reserves.c +++ b/src/lib/merchant_api_get_reserves.c @@ -204,7 +204,6 @@ handle_reserves_get_finished (void *cls, "Unexpected response code %u/%d\n", (unsigned int) response_code, (int) hr.ec); - response_code = 0; break; } rgh->cb (rgh->cb_cls, diff --git a/src/lib/merchant_api_get_transfers.c b/src/lib/merchant_api_get_transfers.c index f2f1186d..473d23a2 100644 --- a/src/lib/merchant_api_get_transfers.c +++ b/src/lib/merchant_api_get_transfers.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017, 2020 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 Lesser General Public License as published by the Free Software @@ -81,23 +81,23 @@ handle_transfers_get_finished (void *cls, { struct TALER_MERCHANT_GetTransfersHandle *gth = cls; const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_GetTransfersResponse gtr = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json }; gth->job = NULL; switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + gtr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: { - json_t *transfers; + const json_t *transfers; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("transfers", - &transfers), + GNUNET_JSON_spec_array_const ("transfers", + &transfers), GNUNET_JSON_spec_end () }; @@ -107,11 +107,11 @@ handle_transfers_get_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + gtr.hr.http_status = 0; + gtr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } - else + { size_t tds_length; struct TALER_MERCHANT_TransferData *tds; @@ -119,14 +119,6 @@ handle_transfers_get_finished (void *cls, unsigned int i; bool ok; - if (! json_is_array (transfers)) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } tds_length = json_array_size (transfers); tds = GNUNET_new_array (tds_length, struct TALER_MERCHANT_TransferData); @@ -174,55 +166,51 @@ handle_transfers_get_finished (void *cls, { GNUNET_break_op (0); GNUNET_free (tds); - GNUNET_JSON_parse_free (spec); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + gtr.hr.http_status = 0; + gtr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } + gtr.details.ok.transfers = tds; + gtr.details.ok.transfers_length = tds_length; gth->cb (gth->cb_cls, - &hr, - tds_length, - tds); + >r); GNUNET_free (tds); - GNUNET_JSON_parse_free (spec); TALER_MERCHANT_transfers_get_cancel (gth); return; } } case MHD_HTTP_UNAUTHORIZED: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + gtr.hr.ec = TALER_JSON_get_error_code (json); + gtr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, merchant says we need to authenticate. */ 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 (json); - hr.hint = TALER_JSON_get_error_hint (json); + gtr.hr.ec = TALER_JSON_get_error_code (json); + gtr.hr.hint = TALER_JSON_get_error_hint (json); 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 (json); - hr.hint = TALER_JSON_get_error_hint (json); + gtr.hr.ec = TALER_JSON_get_error_code (json); + gtr.hr.hint = TALER_JSON_get_error_hint (json); break; default: /* unexpected response code */ GNUNET_break_op (0); TALER_MERCHANT_parse_error_details_ (json, response_code, - &hr); + >r.hr); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d\n", (unsigned int) response_code, - (int) hr.ec); - response_code = 0; + (int) gtr.hr.ec); + gtr.hr.http_status = 0; break; } gth->cb (gth->cb_cls, - &hr, - 0, - NULL); + >r); TALER_MERCHANT_transfers_get_cancel (gth); } diff --git a/src/lib/merchant_api_post_order_abort.c b/src/lib/merchant_api_post_order_abort.c index d980ae18..a924119b 100644 --- a/src/lib/merchant_api_post_order_abort.c +++ b/src/lib/merchant_api_post_order_abort.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 Lesser General Public License as @@ -102,17 +102,20 @@ struct TALER_MERCHANT_OrderAbortHandle * OK. Otherwise returns #GNUNET_SYSERR. * * @param oah handle to operation that created the reply + * @param[in] ar abort response, partially initialized * @param json the reply to parse * @return #GNUNET_OK on success */ -static int +static enum GNUNET_GenericReturnValue check_abort_refund (struct TALER_MERCHANT_OrderAbortHandle *oah, + struct TALER_MERCHANT_AbortResponse *ar, 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_json ("refunds", + &refunds), GNUNET_JSON_spec_end () }; @@ -189,18 +192,11 @@ check_abort_refund (struct TALER_MERCHANT_OrderAbortHandle *oah, } } } - { - struct TALER_MERCHANT_HttpResponse hr = { - .reply = json, - .http_status = MHD_HTTP_OK - }; - - oah->abort_cb (oah->abort_cb_cls, - &hr, - &oah->merchant_pub, - num_refunds, - res); - } + ar->details.ok.merchant_pub = &oah->merchant_pub; + ar->details.ok.num_aborts = num_refunds; + ar->details.ok.aborts = res; + oah->abort_cb (oah->abort_cb_cls, + ar); oah->abort_cb = NULL; } GNUNET_JSON_parse_free (spec); @@ -223,9 +219,9 @@ handle_abort_finished (void *cls, { struct TALER_MERCHANT_OrderAbortHandle *oah = cls; const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_AbortResponse ar = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json }; oah->job = NULL; @@ -235,40 +231,41 @@ handle_abort_finished (void *cls, switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + ar.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: if (GNUNET_OK == check_abort_refund (oah, + &ar, json)) { TALER_MERCHANT_order_abort_cancel (oah); return; } - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + ar.hr.http_status = 0; + ar.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_BAD_REQUEST: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ar.hr.ec = TALER_JSON_get_error_code (json); + ar.hr.hint = TALER_JSON_get_error_hint (json); /* 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: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ar.hr.ec = TALER_JSON_get_error_code (json); + ar.hr.hint = TALER_JSON_get_error_hint (json); break; case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ar.hr.ec = TALER_JSON_get_error_code (json); + ar.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, this should never happen, we should pass the JSON reply to the application */ break; case MHD_HTTP_REQUEST_TIMEOUT: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ar.hr.ec = TALER_JSON_get_error_code (json); + ar.hr.hint = TALER_JSON_get_error_hint (json); /* 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 @@ -276,19 +273,19 @@ handle_abort_finished (void *cls, break; case MHD_HTTP_PRECONDITION_FAILED: /* Our *payment* already succeeded fully. */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ar.hr.ec = TALER_JSON_get_error_code (json); + ar.hr.hint = TALER_JSON_get_error_hint (json); break; case MHD_HTTP_INTERNAL_SERVER_ERROR: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ar.hr.ec = TALER_JSON_get_error_code (json); + ar.hr.hint = TALER_JSON_get_error_hint (json); /* Server had an internal issue; we should retry, but this API leaves this to the application */ break; case MHD_HTTP_BAD_GATEWAY: TALER_MERCHANT_parse_error_details_ (json, response_code, - &hr); + &ar.hr); /* Nothing really to verify, the merchant is blaming the exchange. We should pass the JSON reply to the application */ break; @@ -296,19 +293,16 @@ handle_abort_finished (void *cls, /* unexpected response code */ TALER_MERCHANT_parse_error_details_ (json, response_code, - &hr); + &ar.hr); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d\n", (unsigned int) response_code, - (int) hr.ec); + (int) ar.hr.ec); GNUNET_break_op (0); break; } oah->abort_cb (oah->abort_cb_cls, - &hr, - NULL, - 0, - NULL); + &ar); TALER_MERCHANT_order_abort_cancel (oah); } diff --git a/src/lib/merchant_api_post_order_pay.c b/src/lib/merchant_api_post_order_pay.c index aecc9fc4..6cfeb846 100644 --- a/src/lib/merchant_api_post_order_pay.c +++ b/src/lib/merchant_api_post_order_pay.c @@ -493,7 +493,7 @@ handle_pay_finished (void *cls, return; /* ! */ case GNUNET_SYSERR: GNUNET_break_op (0); - response_code = 0; + pr.hr.http_status = 0; break; } break; diff --git a/src/lib/merchant_api_post_order_refund.c b/src/lib/merchant_api_post_order_refund.c index be996dc2..4414bd86 100644 --- a/src/lib/merchant_api_post_order_refund.c +++ b/src/lib/merchant_api_post_order_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 Lesser General Public License as published by the Free Software @@ -85,30 +85,26 @@ handle_refund_finished (void *cls, { struct TALER_MERCHANT_OrderRefundHandle *orh = cls; const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_RefundResponse rr = { + .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); + rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: { - const char *taler_refund_uri; - struct TALER_PrivateContractHashP h_contract; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("taler_refund_uri", - &taler_refund_uri), - GNUNET_JSON_spec_fixed_auto ("h_contract", - &h_contract), + GNUNET_JSON_spec_string ( + "taler_refund_uri", + &rr.details.ok.taler_refund_uri), + GNUNET_JSON_spec_fixed_auto ( + "h_contract", + &rr.details.ok.h_contract), GNUNET_JSON_spec_end () }; @@ -118,51 +114,36 @@ handle_refund_finished (void *cls, NULL, NULL)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - orh->cb (orh->cb_cls, - &hr, - NULL, - NULL); + rr.hr.http_status = 0; + rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } - orh->cb (orh->cb_cls, - &hr, - taler_refund_uri, - &h_contract); - GNUNET_JSON_parse_free (spec); + break; } - break; case MHD_HTTP_UNAUTHORIZED: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + rr.hr.ec = TALER_JSON_get_error_code (json); + rr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, merchant says we need to authenticate. */ break; case MHD_HTTP_FORBIDDEN: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + rr.hr.ec = TALER_JSON_get_error_code (json); + rr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, merchant says we need to authenticate. */ break; case MHD_HTTP_NOT_FOUND: case MHD_HTTP_CONFLICT: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - orh->cb (orh->cb_cls, - &hr, - NULL, - NULL); + rr.hr.ec = TALER_JSON_get_error_code (json); + rr.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); + &rr.hr); break; } + orh->cb (orh->cb_cls, + &rr); TALER_MERCHANT_post_order_refund_cancel (orh); } diff --git a/src/lib/merchant_api_wallet_post_order_refund.c b/src/lib/merchant_api_wallet_post_order_refund.c index fc4b0abd..ed3fc1b8 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 @@ -71,33 +71,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 +84,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 +118,13 @@ 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; - } - - if (! json_is_array (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; + wrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + 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 +136,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 +165,84 @@ 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); + 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); } diff --git a/src/testing/testing_api_cmd_abort_order.c b/src/testing/testing_api_cmd_abort_order.c index c90851f8..58b11308 100644 --- a/src/testing/testing_api_cmd_abort_order.c +++ b/src/testing/testing_api_cmd_abort_order.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2018, 2020 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 @@ -165,48 +165,42 @@ build_coins (struct TALER_MERCHANT_AbortCoin **ac, * in the state. * * @param cls closure. - * @param hr HTTP response - * @param merchant_pub public key of the merchant refunding the - * contract. - * @param num_aborts length of the @a res array - * @param res array containing the abort confirmations + * @param ar response */ static void abort_cb (void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - const struct TALER_MerchantPublicKeyP *merchant_pub, - unsigned int num_aborts, - const struct TALER_MERCHANT_AbortedCoin res[]) + const struct TALER_MERCHANT_AbortResponse *ar) { struct AbortState *as = cls; as->oah = NULL; - if (as->http_status != hr->http_status) + if (as->http_status != ar->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u (%d) to command `%s' (expected %u)\n", - hr->http_status, - (int) hr->ec, + ar->hr.http_status, + (int) ar->hr.ec, TALER_TESTING_interpreter_get_current_label (as->is), as->http_status); TALER_TESTING_FAIL (as->is); } - if ( (MHD_HTTP_OK == hr->http_status) && - (TALER_EC_NONE == hr->ec) ) + if ( (MHD_HTTP_OK == ar->hr.http_status) && + (TALER_EC_NONE == ar->hr.ec) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u refunds\n", - num_aborts); - as->acs_length = num_aborts; - as->acs = GNUNET_new_array (num_aborts, + ar->details.ok.num_aborts); + as->acs_length = ar->details.ok.num_aborts; + as->acs = GNUNET_new_array (as->acs_length, struct TALER_MERCHANT_AbortedCoin); GNUNET_memcpy (as->acs, - res, - num_aborts * sizeof (struct TALER_MERCHANT_AbortedCoin)); + ar->details.ok.aborts, + as->acs_length + * sizeof (struct TALER_MERCHANT_AbortedCoin)); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successful pay-abort (HTTP status: %u)\n", - hr->http_status); + ar->hr.http_status); TALER_TESTING_interpreter_next (as->is); } diff --git a/src/testing/testing_api_cmd_get_transfers.c b/src/testing/testing_api_cmd_get_transfers.c index 33c2d462..50544587 100644 --- a/src/testing/testing_api_cmd_get_transfers.c +++ b/src/testing/testing_api_cmd_get_transfers.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2018, 2020 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 @@ -83,42 +83,40 @@ struct GetTransfersState * Check the result of our GET /transfers request to a merchant * * @param cls closure - * @param hr HTTP response details - * @param transfers_length length of the @a transfers array - * @param transfers array with details about the transfers we received + * @param gtr response details */ static void get_transfers_cb ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - unsigned int transfers_length, - const struct TALER_MERCHANT_TransferData transfers[]) + const struct TALER_MERCHANT_GetTransfersResponse *gtr) { struct GetTransfersState *gts = cls; gts->gth = NULL; - if (gts->http_status != hr->http_status) + if (gts->http_status != gtr->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u (%d) to command %s\n", - hr->http_status, - (int) hr->ec, + gtr->hr.http_status, + (int) gtr->hr.ec, TALER_TESTING_interpreter_get_current_label (gts->is)); TALER_TESTING_interpreter_fail (gts->is); return; } - switch (hr->http_status) + switch (gtr->hr.http_status) { case MHD_HTTP_OK: - if (transfers_length != gts->transfers_length) + if (gtr->details.ok.transfers_length != gts->transfers_length) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Transfers length does not match\n"); TALER_TESTING_interpreter_fail (gts->is); return; } - for (unsigned int i = 0; i < transfers_length; ++i) + for (unsigned int i = 0; i < gtr->details.ok.transfers_length; ++i) { + const struct TALER_MERCHANT_TransferData *transfer + = >r->details.ok.transfers[i]; const struct TALER_TESTING_Command *transfer_cmd; transfer_cmd = TALER_TESTING_interpreter_lookup_command ( @@ -145,7 +143,7 @@ get_transfers_cb ( return; } if (0 != GNUNET_memcmp (wtid, - &transfers[i].wtid)) + &transfer->wtid)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire transfer id does not match\n"); @@ -154,7 +152,7 @@ get_transfers_cb ( } TALER_TESTING_cmd_merchant_post_transfer_set_serial ( (struct TALER_TESTING_Command *) transfer_cmd, - transfers[i].credit_serial); + transfer->credit_serial); } { const char **payto_uri; @@ -169,12 +167,12 @@ get_transfers_cb ( return; } if (0 != strcmp (*payto_uri, - transfers[i].payto_uri)) + transfer->payto_uri)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire transfer payto uri does not match: %s != %s\n", *payto_uri, - transfers[i].payto_uri); + transfer->payto_uri); TALER_TESTING_interpreter_fail (gts->is); return; } @@ -193,9 +191,9 @@ get_transfers_cb ( } if ( (GNUNET_OK != TALER_amount_cmp_currency (credit_amount, - &transfers[i].credit_amount)) || + &transfer->credit_amount)) || (0 != TALER_amount_cmp (credit_amount, - &transfers[i].credit_amount))) + &transfer->credit_amount))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire transfer credit amount does not match\n"); @@ -216,7 +214,7 @@ get_transfers_cb ( return; } if (0 != strcmp (*exchange_url, - transfers[i].exchange_url)) + transfer->exchange_url)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire transfer exchange url does not match\n"); @@ -228,7 +226,9 @@ get_transfers_cb ( break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Unhandled HTTP status.\n"); + "Unhandled HTTP status %u.\n", + gtr->hr.http_status); + break; } TALER_TESTING_interpreter_next (gts->is); } @@ -290,11 +290,12 @@ get_transfers_cleanup (void *cls, struct TALER_TESTING_Command -TALER_TESTING_cmd_merchant_get_transfers (const char *label, - const char *merchant_url, - const char *payto_uri, - unsigned int http_code, - ...) +TALER_TESTING_cmd_merchant_get_transfers ( + const char *label, + const char *merchant_url, + const char *payto_uri, + unsigned int http_code, + ...) { struct GetTransfersState *gts; diff --git a/src/testing/testing_api_cmd_refund_order.c b/src/testing/testing_api_cmd_refund_order.c index 0f94622c..cac965c5 100644 --- a/src/testing/testing_api_cmd_refund_order.c +++ b/src/testing/testing_api_cmd_refund_order.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2019 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 @@ -76,39 +76,34 @@ struct RefundState * if the HTTP response code is the one expected. * * @param cls closure - * @param hr HTTP response - * @param taler_refund_uri the refund uri offered to the wallet - * @param h_contract hash of the contract a Browser may need to authorize - * obtaining the HTTP response. + * @param rr response */ static void refund_cb (void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - const char *taler_refund_uri, - const struct TALER_PrivateContractHashP *h_contract) + const struct TALER_MERCHANT_RefundResponse *rr) { struct RefundState *ris = cls; - (void) h_contract; ris->orh = NULL; - if (ris->http_code != hr->http_status) + if (ris->http_code != rr->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected status %u, got %u(%d) for refund increase\n", ris->http_code, - hr->http_status, - (int) hr->ec); + rr->hr.http_status, + (int) rr->hr.ec); TALER_TESTING_FAIL (ris->is); } - switch (hr->http_status) + switch (rr->hr.http_status) { case MHD_HTTP_OK: { struct TALER_MERCHANT_RefundUriData rud; if (GNUNET_OK != - TALER_MERCHANT_parse_refund_uri (taler_refund_uri, - &rud)) + TALER_MERCHANT_parse_refund_uri ( + rr->details.ok.taler_refund_uri, + &rud)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Taler refund uri is malformed\n"); @@ -165,7 +160,7 @@ refund_cb (void *cls, default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unhandled HTTP status %u for refund order.\n", - hr->http_status); + rr->hr.http_status); } TALER_TESTING_interpreter_next (ris->is); } diff --git a/src/testing/testing_api_cmd_wallet_post_orders_refund.c b/src/testing/testing_api_cmd_wallet_post_orders_refund.c index b9e7981f..fff3bb33 100644 --- a/src/testing/testing_api_cmd_wallet_post_orders_refund.c +++ b/src/testing/testing_api_cmd_wallet_post_orders_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 General Public License as @@ -76,44 +76,39 @@ struct WalletRefundState * if the HTTP response code is the one expected. * * @param cls closure - * @param hr HTTP response - * @param refund_amount refund amount - * @param merchant_pub public key of the merchant giving the refund - * @param refunds the given refunds - * @param refunds_length how many refunds were given + * @param wrr response */ static void refund_cb ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - const struct TALER_Amount *refund_amount, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct TALER_MERCHANT_RefundDetail refunds[], - unsigned int refunds_length) + const struct TALER_MERCHANT_WalletRefundResponse *wrr) { struct WalletRefundState *wrs = cls; wrs->orh = NULL; - if (wrs->http_code != hr->http_status) + if (wrs->http_code != wrr->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected status %u, got %u(%d) for refund increase\n", wrs->http_code, - hr->http_status, - (int) hr->ec); + wrr->hr.http_status, + (int) wrr->hr.ec); TALER_TESTING_FAIL (wrs->is); } - switch (hr->http_status) + switch (wrr->hr.http_status) { case MHD_HTTP_OK: { struct TALER_Amount refunded_total; - if (refunds_length > 0) + if (wrr->details.ok.refunds_length > 0) GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (refunds[0].refund_amount.currency, - &refunded_total)); - for (unsigned int i = 0; i < refunds_length; ++i) + TALER_amount_set_zero ( + wrr->details.ok.refunds[0].refund_amount.currency, + &refunded_total)); + for (unsigned int i = 0; i < wrr->details.ok.refunds_length; ++i) { + const struct TALER_MERCHANT_RefundDetail *refund + = &wrr->details.ok.refunds[wrr->details.ok.refunds_length - 1 - i]; const struct TALER_TESTING_Command *refund_cmd; const struct TALER_Amount *expected_amount; @@ -133,13 +128,12 @@ refund_cb ( /* The most recent refunds are returned first */ GNUNET_assert (0 <= TALER_amount_add (&refunded_total, &refunded_total, - &refunds[refunds_length - 1 - - i].refund_amount)); - if ((GNUNET_OK != - TALER_amount_cmp_currency (expected_amount, - &refunded_total)) || - (0 != TALER_amount_cmp (expected_amount, - &refunded_total))) + &refund->refund_amount)); + if ( (GNUNET_OK != + TALER_amount_cmp_currency (expected_amount, + &refunded_total)) || + (0 != TALER_amount_cmp (expected_amount, + &refunded_total)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Refund amounts do not match\n"); @@ -150,7 +144,6 @@ refund_cb ( } break; default: - break; } TALER_TESTING_interpreter_next (wrs->is); |