summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <grothoff@gnunet.org>2022-07-23 21:02:26 +0200
committerChristian Grothoff <grothoff@gnunet.org>2022-07-23 21:02:26 +0200
commit60c96242e10b3e2bab8c4a75565767795f79cbd3 (patch)
tree63b0ae7aa59c2ebcc1df18e0e974220f024e2c6d /src
parent02e9d6e2cd9f0b27f1636f4d27f8ca026b837b6f (diff)
downloadmerchant-60c96242e10b3e2bab8c4a75565767795f79cbd3.tar.gz
merchant-60c96242e10b3e2bab8c4a75565767795f79cbd3.tar.bz2
merchant-60c96242e10b3e2bab8c4a75565767795f79cbd3.zip
-improve get tip API, note: long-polling not actually implemented
Diffstat (limited to 'src')
-rw-r--r--src/include/taler_merchant_service.h83
-rw-r--r--src/lib/merchant_api_merchant_get_tip.c137
-rw-r--r--src/testing/testing_api_cmd_merchant_get_tip.c56
3 files changed, 146 insertions, 130 deletions
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index e22e84f0..25ce2a44 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -3549,29 +3549,76 @@ struct TALER_MERCHANT_PickupDetail
/**
+ * Details returned about a tip by the merchant.
+ */
+struct TALER_MERCHANT_TipStatusResponse
+{
+ /**
+ * HTTP status of the response.
+ */
+ struct TALER_MERCHANT_HttpResponse hr;
+
+ /**
+ * Details depending on the HTTP status.
+ */
+ union {
+
+ /**
+ * Details on #MHD_HTTP_OK.
+ */
+ struct {
+
+ /**
+ * Amount that was authorized under this tip
+ */
+ struct TALER_Amount total_authorized;
+
+ /**
+ * Amount that has been picked up
+ */
+ struct TALER_Amount total_picked_up;
+
+ /**
+ * The reason given for the tip
+ */
+ const char *reason;
+
+ /**
+ * Time when the tip will expire
+ */
+ struct GNUNET_TIME_Timestamp expiration;
+
+ /**
+ * reserve which is funding this tip
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Length of the @e pickups array
+ */
+ unsigned int pickups_length;
+
+ /**
+ * array of pickup operations performed for this tip
+ */
+ struct TALER_MERCHANT_PickupDetail *pickups;
+ } success;
+
+ } details;
+
+};
+
+
+/**
* Callback to process a GET /private/tips/$TIP_ID request
*
* @param cls closure
- * @param hr HTTP response details
- * @param total_authorized how many tips were authorized under this tip
- * @param total_picked_up how many tips have been picked up
- * @param reason what was the reason given for the tip
- * @param expiration when the tip will expire
- * @param reserve_pub which reserve is funding this tip
- * @param pickups_length length of the @a pickups array
- * @param pickups array of pickup operations performed for this tip
+ * @param tsr response details
*/
typedef void
(*TALER_MERCHANT_TipMerchantGetCallback) (
void *cls,
- const struct TALER_MERCHANT_HttpResponse *hr,
- const struct TALER_Amount *total_authorized,
- const struct TALER_Amount *total_picked_up,
- const char *reason,
- struct GNUNET_TIME_Timestamp expiration,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- unsigned int pickups_length,
- const struct TALER_MERCHANT_PickupDetail pickups[]);
+ const struct TALER_MERCHANT_TipStatusResponse *tsr);
/**
@@ -3581,6 +3628,8 @@ typedef void
* @param ctx execution context
* @param backend_url base URL of the merchant backend
* @param tip_id which tip should we query
+ * @param min_pick_up minimum amount picked up to notify about
+ * @param lp_timeout how long to wait for @a min_pick_up to be exceeded
* @param pickups whether to fetch associated pickups
* @param cb function to call with the result
* @param cb_cls closure for @a cb
@@ -3590,6 +3639,8 @@ struct TALER_MERCHANT_TipMerchantGetHandle *
TALER_MERCHANT_merchant_tip_get (struct GNUNET_CURL_Context *ctx,
const char *backend_url,
const struct TALER_TipIdentifierP *tip_id,
+ const struct TALER_Amount *min_pick_up,
+ struct GNUNET_TIME_Relative lp_timeout,
bool pickups,
TALER_MERCHANT_TipMerchantGetCallback cb,
void *cb_cls);
diff --git a/src/lib/merchant_api_merchant_get_tip.c b/src/lib/merchant_api_merchant_get_tip.c
index 020167c4..9c21377e 100644
--- a/src/lib/merchant_api_merchant_get_tip.c
+++ b/src/lib/merchant_api_merchant_get_tip.c
@@ -60,20 +60,15 @@ struct TALER_MERCHANT_TipMerchantGetHandle
};
-static int
+static enum GNUNET_GenericReturnValue
parse_pickups (const json_t *pa,
- const struct TALER_Amount *total_authorized,
- const struct TALER_Amount *total_picked_up,
- const char *reason,
- struct GNUNET_TIME_Timestamp expiration,
- const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_MERCHANT_TipStatusResponse *tsr,
struct TALER_MERCHANT_TipMerchantGetHandle *tgh)
{
unsigned int pa_len = json_array_size (pa);
struct TALER_MERCHANT_PickupDetail pickups[pa_len];
size_t index;
json_t *value;
- int ret = GNUNET_OK;
json_array_foreach (pa, index, value)
{
@@ -95,27 +90,14 @@ parse_pickups (const json_t *pa,
NULL))
{
GNUNET_break_op (0);
- ret = GNUNET_SYSERR;
- break;
+ return GNUNET_SYSERR;
}
}
- if (GNUNET_OK == ret)
- {
- struct TALER_MERCHANT_HttpResponse hr = {
- .http_status = MHD_HTTP_OK
- };
-
- tgh->cb (tgh->cb_cls,
- &hr,
- total_authorized,
- total_picked_up,
- reason,
- expiration,
- reserve_pub,
- pa_len,
- pickups);
- }
- return ret;
+ tsr->details.success.pickups_length = pa_len;
+ tsr->details.success.pickups = pickups;
+ tgh->cb (tgh->cb_cls,
+ tsr);
+ return GNUNET_OK;
}
@@ -134,9 +116,9 @@ handle_merchant_tip_get_finished (void *cls,
{
struct TALER_MERCHANT_TipMerchantGetHandle *tgh = cls;
const json_t *json = response;
- struct TALER_MERCHANT_HttpResponse hr = {
- .http_status = (unsigned int) response_code,
- .reply = json
+ struct TALER_MERCHANT_TipStatusResponse tsr = {
+ .hr.http_status = (unsigned int) response_code,
+ .hr.reply = json
};
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -147,22 +129,17 @@ handle_merchant_tip_get_finished (void *cls,
{
case MHD_HTTP_OK:
{
- struct TALER_Amount total_authorized;
- struct TALER_Amount total_picked_up;
- const char *reason;
- struct GNUNET_TIME_Timestamp expiration;
- struct TALER_ReservePublicKeyP reserve_pub;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("total_authorized",
- &total_authorized),
+ &tsr.details.success.total_authorized),
TALER_JSON_spec_amount_any ("total_picked_up",
- &total_picked_up),
+ &tsr.details.success.total_picked_up),
GNUNET_JSON_spec_string ("reason",
- &reason),
+ &tsr.details.success.reason),
GNUNET_JSON_spec_timestamp ("expiration",
- &expiration),
+ &tsr.details.success.expiration),
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
- &reserve_pub),
+ &tsr.details.success.reserve_pub),
GNUNET_JSON_spec_end ()
};
@@ -171,8 +148,8 @@ handle_merchant_tip_get_finished (void *cls,
spec,
NULL, NULL))
{
- hr.http_status = 0;
- hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ tsr.hr.http_status = 0;
+ tsr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
}
else
{
@@ -181,75 +158,55 @@ handle_merchant_tip_get_finished (void *cls,
if (! json_is_array (pickups))
{
tgh->cb (tgh->cb_cls,
- &hr,
- &total_authorized,
- &total_picked_up,
- reason,
- expiration,
- &reserve_pub,
- 0,
- NULL);
+ &tsr);
TALER_MERCHANT_merchant_tip_get_cancel (tgh);
return;
}
- else if (GNUNET_OK == parse_pickups (pickups,
- &total_authorized,
- &total_picked_up,
- reason,
- expiration,
- &reserve_pub,
- tgh))
+ if (GNUNET_OK ==
+ parse_pickups (pickups,
+ &tsr,
+ tgh))
{
GNUNET_JSON_parse_free (spec);
TALER_MERCHANT_merchant_tip_get_cancel (tgh);
return;
}
- else
- {
- hr.http_status = 0;
- hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- }
+ tsr.hr.http_status = 0;
+ tsr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
}
GNUNET_JSON_parse_free (spec);
break;
}
case MHD_HTTP_UNAUTHORIZED:
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
+ tsr.hr.ec = TALER_JSON_get_error_code (json);
+ tsr.hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, merchant says we need to authenticate. */
break;
case MHD_HTTP_NOT_FOUND:
/* legal, can happen if instance or tip reserve is unknown */
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
+ tsr.hr.ec = TALER_JSON_get_error_code (json);
+ tsr.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);
+ tsr.hr.ec = TALER_JSON_get_error_code (json);
+ tsr.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);
+ &tsr.hr);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n",
(unsigned int) response_code,
- (int) hr.ec);
+ (int) tsr.hr.ec);
break;
}
tgh->cb (tgh->cb_cls,
- &hr,
- NULL,
- NULL,
- NULL,
- GNUNET_TIME_UNIT_ZERO_TS,
- NULL,
- 0,
- NULL);
+ &tsr);
TALER_MERCHANT_merchant_tip_get_cancel (tgh);
}
@@ -258,6 +215,8 @@ struct TALER_MERCHANT_TipMerchantGetHandle *
TALER_MERCHANT_merchant_tip_get (struct GNUNET_CURL_Context *ctx,
const char *backend_url,
const struct TALER_TipIdentifierP *tip_id,
+ const struct TALER_Amount *min_pick_up,
+ struct GNUNET_TIME_Relative lp_timeout,
bool pickups,
TALER_MERCHANT_TipMerchantGetCallback cb,
void *cb_cls)
@@ -274,6 +233,7 @@ TALER_MERCHANT_merchant_tip_get (struct GNUNET_CURL_Context *ctx,
{
char res_str[sizeof (*tip_id) * 2];
char arg_str[sizeof (res_str) + 48];
+ char timeout_str[32];
char *end;
end = GNUNET_STRINGS_data_to_string (tip_id,
@@ -285,9 +245,26 @@ TALER_MERCHANT_merchant_tip_get (struct GNUNET_CURL_Context *ctx,
sizeof (arg_str),
"private/tips/%s",
res_str);
+ GNUNET_snprintf (timeout_str,
+ sizeof (timeout_str),
+ "%llu",
+ ((unsigned long long)
+ lp_timeout.rel_value_us /
+ GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us));
tgh->url = TALER_url_join (backend_url,
arg_str,
- "pickups", pickups ? "yes" : NULL,
+ "pickups",
+ pickups
+ ? "yes"
+ : NULL,
+ "min_amount",
+ min_pick_up
+ ? TALER_amount2s (min_pick_up)
+ : NULL,
+ "timeout_ms",
+ GNUNET_TIME_relative_is_zero (lp_timeout)
+ ? NULL
+ : timeout_str,
NULL);
}
if (NULL == tgh->url)
@@ -308,8 +285,8 @@ TALER_MERCHANT_merchant_tip_get (struct GNUNET_CURL_Context *ctx,
void
-TALER_MERCHANT_merchant_tip_get_cancel (struct
- TALER_MERCHANT_TipMerchantGetHandle *tgh)
+TALER_MERCHANT_merchant_tip_get_cancel (
+ struct TALER_MERCHANT_TipMerchantGetHandle *tgh)
{
if (NULL != tgh->job)
{
diff --git a/src/testing/testing_api_cmd_merchant_get_tip.c b/src/testing/testing_api_cmd_merchant_get_tip.c
index 1ea5229d..a8e7a67e 100644
--- a/src/testing/testing_api_cmd_merchant_get_tip.c
+++ b/src/testing/testing_api_cmd_merchant_get_tip.c
@@ -79,25 +79,11 @@ struct MerchantTipGetState
* Callback for a GET /private/tips/$TIP_ID operation.
*
* @param cls closure for this function
- * @param hr http response
- * @param total_authorized the total amount authorized for the tip
- * @param total_picked_up the total amount of the tip that has been picked up
- * @param reason why the tip was authorized
- * @param expiration when the tip will expire
- * @param reserve_pub public key of the reserve the tip is drawing from
- * @param pickups_length number of pickups associated with the tip
- * @param pickups the array of pickups associated with the tip
+ * @param tsr response
*/
static void
merchant_get_tip_cb (void *cls,
- const struct TALER_MERCHANT_HttpResponse *hr,
- const struct TALER_Amount *total_authorized,
- const struct TALER_Amount *total_picked_up,
- const char *reason,
- struct GNUNET_TIME_Timestamp expiration,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- unsigned int pickups_length,
- const struct TALER_MERCHANT_PickupDetail pickups[])
+ const struct TALER_MERCHANT_TipStatusResponse *tsr)
{
struct MerchantTipGetState *gts = cls;
const struct TALER_TESTING_Command *authorize_cmd;
@@ -107,33 +93,33 @@ merchant_get_tip_cb (void *cls,
gts->tip_reference);
gts->tgh = NULL;
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (total_picked_up->currency,
- &expected_total_picked_up));
- if (gts->http_status != hr->http_status)
+ if (gts->http_status != tsr->hr.http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u (%d) to command %s\n",
- hr->http_status,
- (int) hr->ec,
+ tsr->hr.http_status,
+ (int) tsr->hr.ec,
TALER_TESTING_interpreter_get_current_label (gts->is));
TALER_TESTING_interpreter_fail (gts->is);
return;
}
- switch (hr->http_status)
+ switch (tsr->hr.http_status)
{
case MHD_HTTP_OK:
{
const struct TALER_Amount *initial_amount;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (tsr->details.success.total_picked_up.currency,
+ &expected_total_picked_up));
if (GNUNET_OK !=
TALER_TESTING_get_trait_amount (authorize_cmd,
&initial_amount))
TALER_TESTING_FAIL (gts->is);
if ((GNUNET_OK !=
- TALER_amount_cmp_currency (total_authorized,
+ TALER_amount_cmp_currency (&tsr->details.success.total_authorized,
initial_amount)) ||
- (0 != TALER_amount_cmp (total_authorized,
+ (0 != TALER_amount_cmp (&tsr->details.success.total_authorized,
initial_amount)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -149,7 +135,7 @@ merchant_get_tip_cb (void *cls,
TALER_TESTING_get_trait_reason (authorize_cmd,
&justification))
TALER_TESTING_FAIL (gts->is);
- if (0 != strcmp (reason,
+ if (0 != strcmp (tsr->details.success.reason,
*justification))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -168,7 +154,7 @@ merchant_get_tip_cb (void *cls,
TALER_TESTING_FAIL (gts->is);
if (GNUNET_TIME_timestamp_cmp (*tip_expiration,
!=,
- expiration))
+ tsr->details.success.expiration))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Tip authorized expiration does not match\n");
@@ -176,7 +162,7 @@ merchant_get_tip_cb (void *cls,
return;
}
}
- if (pickups_length != gts->pickups_length)
+ if (tsr->details.success.pickups_length != gts->pickups_length)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Length of pickups array does not match\n");
@@ -184,7 +170,7 @@ merchant_get_tip_cb (void *cls,
return;
}
{
- for (unsigned int i = 0; i < pickups_length; ++i)
+ for (unsigned int i = 0; i < gts->pickups_length; ++i)
{
const struct TALER_TESTING_Command *pickup_cmd;
@@ -198,7 +184,7 @@ merchant_get_tip_cb (void *cls,
&num_planchets))
TALER_TESTING_FAIL (gts->is);
- if (*num_planchets != pickups[i].num_planchets)
+ if (*num_planchets != tsr->details.success.pickups[i].num_planchets)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Pickup planchet count does not match\n");
@@ -216,9 +202,9 @@ merchant_get_tip_cb (void *cls,
if ( (GNUNET_OK !=
TALER_amount_cmp_currency (total,
- &pickups[i].requested_amount)) ||
+ &tsr->details.success.pickups[i].requested_amount)) ||
(0 != TALER_amount_cmp (total,
- &pickups[i].requested_amount)))
+ &tsr->details.success.pickups[i].requested_amount)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Pickup planchet sum does not match\n");
@@ -232,10 +218,10 @@ merchant_get_tip_cb (void *cls,
}
if ( (GNUNET_OK !=
TALER_amount_cmp_currency (&expected_total_picked_up,
- total_picked_up)) ||
+ &tsr->details.success.total_picked_up)) ||
(0 !=
TALER_amount_cmp (&expected_total_picked_up,
- total_picked_up)) )
+ &tsr->details.success.total_picked_up)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Tip picked up amount does not match\n");
@@ -280,6 +266,8 @@ merchant_get_tip_run (void *cls,
tgs->tgh = TALER_MERCHANT_merchant_tip_get (is->ctx,
tgs->merchant_url,
tip_id,
+ NULL,
+ GNUNET_TIME_UNIT_ZERO,
tgs->fetch_pickups,
&merchant_get_tip_cb,
tgs);