diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-04-23 14:40:05 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-04-23 14:40:05 +0200 |
commit | 4b7d9f5e19e9f28ec1163f3b6e5c00f0805e6221 (patch) | |
tree | 396b8ddf6bf4b074d85737a27cec8a58a16237cf /src | |
parent | f8cb45f17a4bd9f9a4b68a4427ec485984703d33 (diff) |
modernize POST /transfers API
Diffstat (limited to 'src')
-rw-r--r-- | src/include/taler_merchant_service.h | 89 | ||||
-rw-r--r-- | src/lib/merchant_api_post_transfers.c | 120 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_post_transfers.c | 36 |
3 files changed, 142 insertions, 103 deletions
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 49bc83fd..92e18335 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -2898,31 +2898,88 @@ struct TALER_MERCHANT_TrackTransferDetail }; + +/** + * @brief Response to a POST /transfers operation from a merchant's backend. + */ +struct TALER_MERCHANT_PostTransfersResponse +{ + /** + * HTTP response details + */ + struct TALER_MERCHANT_HttpResponse hr; + + /** + * Details depending on HTTP status. + */ + union + { + + /** + * Details in case of success (#MHD_HTTP_OK). + */ + struct + { + + /** + * when did the transfer happen (according to the exchange) + */ + struct GNUNET_TIME_Timestamp execution_time; + + /** + * total amount of the wire transfer + */ + struct TALER_Amount total_amount; + + /** + * how much did the exchange charge in terms of wire fees + */ + struct TALER_Amount wire_fee; + + /** + * Length of the @e details array + */ + unsigned int details_length; + + /** + * array with details about the combined transactions + */ + const struct TALER_MERCHANT_TrackTransferDetail *details; + } success; + + /** + * Details if we got an #MHD_HTTP_BAD_GATEWAY. + */ + struct + { + /** + * HTTP status of the exchange (or 0 if not available). + */ + unsigned int exchange_http_status; + + /** + * Error code of the exchange (or TALER_EC_NONE if not available). + */ + enum TALER_ErrorCode exchange_ec; + + } bad_gateway; + + } details; + +}; + + /** * Callbacks of this type are used to work the result of submitting a * POST /transfers request to a merchant * * @param cls closure - * @param hr HTTP response details - * @param execution_time when did the transfer happen (according to the exchange), - * #GNUNET_TIME_UNIT_FOREVER_ABS if the transfer did not yet happen or if - * we have no data from the exchange about it - * @param total_amount total amount of the wire transfer, or NULL if the exchange did - * not provide any details - * @param wire_fee how much did the exchange charge in terms of wire fees, or NULL - * if the exchange did not provide any details - * @param details_length length of the @a details array - * @param details array with details about the combined transactions + * @param ptr response details */ typedef void (*TALER_MERCHANT_PostTransfersCallback) ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - struct GNUNET_TIME_Timestamp execution_time, - const struct TALER_Amount *total_amount, - const struct TALER_Amount *wire_fee, - unsigned int details_length, - const struct TALER_MERCHANT_TrackTransferDetail details[]); + const struct TALER_MERCHANT_PostTransfersResponse *ptr); /** diff --git a/src/lib/merchant_api_post_transfers.c b/src/lib/merchant_api_post_transfers.c index 450b46d9..2a1a3f68 100644 --- a/src/lib/merchant_api_post_transfers.c +++ b/src/lib/merchant_api_post_transfers.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,68 +85,68 @@ handle_post_transfers_finished (void *cls, const void *response) { struct TALER_MERCHANT_PostTransfersHandle *pth = cls; - const json_t *json = response; - json_t *deposit_sum = NULL; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_PostTransfersResponse ptr = { + .hr.reply = response, + .hr.http_status = (unsigned int) response_code }; pth->job = NULL; switch (response_code) { case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: { - struct TALER_Amount total; - struct TALER_Amount wire_fee; - struct GNUNET_TIME_Timestamp execution_time; json_t *deposit_sums; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount_any ("total", - &total), - TALER_JSON_spec_amount_any ("wire_fee", - &wire_fee), - GNUNET_JSON_spec_timestamp ("execution_time", - &execution_time), + TALER_JSON_spec_amount_any ( + "total", + &ptr.details.success.total_amount), + TALER_JSON_spec_amount_any ( + "wire_fee", + &ptr.details.success.wire_fee), + GNUNET_JSON_spec_timestamp ( + "execution_time", + &ptr.details.success.execution_time), GNUNET_JSON_spec_json ("deposit_sums", &deposit_sums), GNUNET_JSON_spec_end () }; if (GNUNET_OK != - GNUNET_JSON_parse (json, + GNUNET_JSON_parse (ptr.hr.reply, spec, NULL, NULL)) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + ptr.hr.http_status = 0; + ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + } + if (! json_is_array (deposit_sums)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + ptr.hr.http_status = 0; + ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } - else { - size_t deposit_sums_length; struct TALER_MERCHANT_TrackTransferDetail *details; unsigned int i; bool ok; + json_t *deposit_sum; - if (! json_is_array (deposit_sums)) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } - deposit_sums_length = json_array_size (deposit_sums); - details = GNUNET_new_array (deposit_sums_length, + ptr.details.success.details_length + = json_array_size (deposit_sums); + details = GNUNET_new_array (ptr.details.success.details_length, struct TALER_MERCHANT_TrackTransferDetail); + ptr.details.success.details = details; ok = true; json_array_foreach (deposit_sums, i, deposit_sum) { - struct TALER_MERCHANT_TrackTransferDetail *d = &details[i]; + struct TALER_MERCHANT_TrackTransferDetail *d + = &details[i]; struct GNUNET_JSON_Specification ispec[] = { GNUNET_JSON_spec_string ("order_id", &d->order_id), @@ -173,17 +173,12 @@ handle_post_transfers_finished (void *cls, GNUNET_break_op (0); GNUNET_free (details); GNUNET_JSON_parse_free (spec); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + ptr.hr.http_status = 0; + ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } pth->cb (pth->cb_cls, - &hr, - execution_time, - &total, - &wire_fee, - deposit_sums_length, - details); + &ptr); GNUNET_free (details); GNUNET_JSON_parse_free (spec); TALER_MERCHANT_transfers_post_cancel (pth); @@ -193,8 +188,8 @@ handle_post_transfers_finished (void *cls, case MHD_HTTP_ACCEPTED: break; case MHD_HTTP_UNAUTHORIZED: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ptr.hr.ec = TALER_JSON_get_error_code (ptr.hr.reply); + ptr.hr.hint = TALER_JSON_get_error_hint (ptr.hr.reply); /* Nothing really to verify, merchant says we need to authenticate. */ break; case MHD_HTTP_NOT_FOUND: @@ -202,20 +197,20 @@ handle_post_transfers_finished (void *cls, happen, we should pass the JSON reply to the application */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Did not find any data\n"); - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ptr.hr.ec = TALER_JSON_get_error_code (ptr.hr.reply); + ptr.hr.hint = TALER_JSON_get_error_hint (ptr.hr.reply); 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); + ptr.hr.ec = TALER_JSON_get_error_code (ptr.hr.reply); + ptr.hr.hint = TALER_JSON_get_error_hint (ptr.hr.reply); break; case MHD_HTTP_BAD_GATEWAY: /* Exchange had an 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); + ptr.hr.ec = TALER_JSON_get_error_code (ptr.hr.reply); + ptr.hr.hint = TALER_JSON_get_error_hint (ptr.hr.reply); { uint32_t eec; uint32_t ehc; @@ -228,16 +223,22 @@ handle_post_transfers_finished (void *cls, }; if (GNUNET_OK != - GNUNET_JSON_parse (deposit_sum, + GNUNET_JSON_parse (ptr.hr.reply, ispec, NULL, NULL)) { GNUNET_break_op (0); + ptr.details.bad_gateway.exchange_http_status = 0; + ptr.details.bad_gateway.exchange_ec = TALER_EC_NONE; break; } else { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + ptr.details.bad_gateway.exchange_http_status + = (unsigned int) ehc; + ptr.details.bad_gateway.exchange_ec + = (enum TALER_ErrorCode) eec; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Exchange returned %u/%u\n", (unsigned int) eec, (unsigned int) ehc); @@ -247,28 +248,23 @@ handle_post_transfers_finished (void *cls, case MHD_HTTP_GATEWAY_TIMEOUT: /* 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); + ptr.hr.ec = TALER_JSON_get_error_code (ptr.hr.reply); + ptr.hr.hint = TALER_JSON_get_error_hint (ptr.hr.reply); break; default: /* unexpected response code */ GNUNET_break_op (0); - TALER_MERCHANT_parse_error_details_ (json, + TALER_MERCHANT_parse_error_details_ (ptr.hr.reply, response_code, - &hr); + &ptr.hr); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d\n", - (unsigned int) response_code, - (int) hr.ec); + (unsigned int) ptr.hr.http_status, + (int) ptr.hr.ec); break; } pth->cb (pth->cb_cls, - &hr, - GNUNET_TIME_UNIT_FOREVER_TS, - NULL, - NULL, - 0, - NULL); + &ptr); TALER_MERCHANT_transfers_post_cancel (pth); } diff --git a/src/testing/testing_api_cmd_post_transfers.c b/src/testing/testing_api_cmd_post_transfers.c index 4cff2348..9a01d2d5 100644 --- a/src/testing/testing_api_cmd_post_transfers.c +++ b/src/testing/testing_api_cmd_post_transfers.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 @@ -126,48 +126,34 @@ struct PostTransfersState * Callback for a POST /transfers operation. * * @param cls closure for this function - * @param hr HTTP response details - * @param execution_time when did the transfer happen (according to the exchange), - * #GNUNET_TIME_UNIT_FOREVER_ABS if the transfer did not yet happen or if - * we have no data from the exchange about it - * @param total_amount total amount of the wire transfer, or NULL if the exchange did - * not provide any details - * @param wire_fee how much did the exchange charge in terms of wire fees, or NULL - * if the exchange did not provide any details - * @param details_length length of the @a details array - * @param details array with details about the combined transactions + * @param ptr response details */ static void transfers_cb (void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - struct GNUNET_TIME_Timestamp execution_time, - const struct TALER_Amount *total_amount, - const struct TALER_Amount *wire_fee, - unsigned int details_length, - const struct TALER_MERCHANT_TrackTransferDetail details[]) + const struct TALER_MERCHANT_PostTransfersResponse *ptr) { struct PostTransfersState *pts = cls; pts->pth = NULL; - if (pts->http_status != hr->http_status) + if (pts->http_status != ptr->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u (%d) to command %s\n", - hr->http_status, - (int) hr->ec, + ptr->hr.http_status, + (int) ptr->hr.ec, TALER_TESTING_interpreter_get_current_label (pts->is)); TALER_TESTING_interpreter_fail (pts->is); return; } - switch (hr->http_status) + switch (ptr->hr.http_status) { case MHD_HTTP_OK: { - pts->execution_time = execution_time; - pts->wire_fee = *wire_fee; + pts->execution_time = ptr->details.success.execution_time; + pts->wire_fee = ptr->details.success.wire_fee; fprintf (stderr, "FIXME"); - json_dumpf (hr->reply, + json_dumpf (ptr->hr.reply, stderr, 0); #if FIXME_WRITE_PROPPER_CHECK_OF_RETURNED_DATA_HERE @@ -316,7 +302,7 @@ transfers_cb (void *cls, GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unhandled HTTP status %u for POST /transfers.\n", - hr->http_status); + ptr->hr.http_status); } TALER_TESTING_interpreter_next (pts->is); } |