summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/taler_merchant_service.h89
-rw-r--r--src/lib/merchant_api_post_transfers.c120
-rw-r--r--src/testing/testing_api_cmd_post_transfers.c36
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);
}