commit 1ce3a590dbe9d11b39e5da4ee61f393edaa90267
parent 48c7e1216fae9abb21c94d2c0ded328d05f1db01
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date: Sun, 29 Jun 2025 14:43:33 +0200
donau logic integrated to tests, tests still passing, last thing to test for correctness of pay for donau order
Diffstat:
4 files changed, 132 insertions(+), 36 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -3828,12 +3828,12 @@ phase_parse_wallet_data (struct PayContext *pc)
NULL),
/* "donation_year" is optional (parsed as uint64_t) */
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_uint64 ("year",
+ GNUNET_JSON_spec_uint64 ("donau_year",
&donation_year_tmp),
NULL),
/* "budikeypairs" is optional (a JSON array) */
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_array_const ("budikeypairs",
+ GNUNET_JSON_spec_array_const ("donau_budikeypairs",
&budikeypairs),
NULL),
/* ---------------------------------------------------------- */
diff --git a/src/include/taler_merchant_pay_service.h b/src/include/taler_merchant_pay_service.h
@@ -68,6 +68,9 @@ enum TALER_MERCHANT_OrderPayOptionType
TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS,
TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS,
TALER_MERCHANT_OrderPayOptionType_WALLET_DATA, //Used privately so no #define is present for it
+ TALER_MERCHANT_OrderPayOptionType_DONAU_URL,
+ TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR,
+ TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS,
/*New objects go in here*/
TALER_MERCHANT_OrderPayOptionType_LENGTH
};
@@ -104,6 +107,11 @@ struct TALER_MERCHANT_OrderPayOption
unsigned int num_output_tokens;
const struct TALER_MERCHANT_OutputToken *output_tokens;
} output_tokens;
+#ifdef HAVE_DONAU_DONAU_SERVICE_H
+ const char *donau_url;
+ uint64_t donau_year;
+ json_t *donau_budis_json;
+#endif
} details;
};
@@ -219,6 +227,24 @@ enum TALER_MERCHANT_OrderPayOptionErrorCode
.output_tokens = (_otokens) } \
}
+#define TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_URL(_u) \
+ (struct TALER_MERCHANT_OrderPayOption){ \
+ .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_URL,\
+ .details.donau_url = (_u) \
+ }
+
+#define TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_YEAR(_y) \
+ (struct TALER_MERCHANT_OrderPayOption){ \
+ .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR,\
+ .details.donau_year = (_y) \
+ }
+
+#define TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_BUDIS(_js) \
+ (struct TALER_MERCHANT_OrderPayOption){ \
+ .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS, \
+ .details.donau_budis_json = (_js) \
+ }
+
#define TALER_MERCHANT_ORDER_PAY_SET_OPTIONS(ph,...) \
MHD_NOWARN_COMPOUND_LITERALS_ \
TALER_MERCHANT_order_pay_set_options ( \
diff --git a/src/lib/taler_merchant_pay_service.c b/src/lib/taler_merchant_pay_service.c
@@ -481,19 +481,15 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
switch (o->ot)
{
case TALER_MERCHANT_OrderPayOptionType_MERCHANT_URL:
- ph->merchant_url = GNUNET_strdup (o->details.merchant_url);
+ ph->merchant_url = GNUNET_strdup(o->details.merchant_url);
break;
case TALER_MERCHANT_OrderPayOptionType_SESSION_ID:
- ph->session_id = GNUNET_strdup (o->details.session_id);
+ ph->session_id = GNUNET_strdup(o->details.session_id);
/* add straight into JSON body */
{
- json_t *js = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("session_id",
- o->details.session_id)
- );
- enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
- store_json_option (ph, o->ot, js);
+ json_t *js = GNUNET_JSON_PACK(GNUNET_JSON_pack_string("session_id", o->details.session_id));
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec = store_json_option(ph, o->ot, js);
if (TALER_MERCHANT_OPOEC_OK != ec)
return ec;
break;
@@ -514,15 +510,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
}
case TALER_MERCHANT_OrderPayOptionType_CHOICE_INDEX:
- ph->choice_index = o->details.choice_index;
- ph->has_choice_index= true;
+ ph->choice_index = o->details.choice_index;
+ ph->has_choice_index = true;
{
- json_t *js = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_int64 ("choice_index",
- o->details.choice_index)
- );
- enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
- store_json_option (ph, o->ot, js);
+ json_t *js = GNUNET_JSON_PACK(GNUNET_JSON_pack_int64("choice_index", o->details.choice_index));
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec = store_json_option(ph, o->ot, js);
if (TALER_MERCHANT_OPOEC_OK != ec)
return ec;
break;
@@ -577,33 +569,30 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
case TALER_MERCHANT_OrderPayOptionType_COINS:
/* stash for later signing */
- GNUNET_assert (o->details.coins.num_coins >= 0);
+ GNUNET_assert(o->details.coins.num_coins >= 0);
ph->coins.num_coins = o->details.coins.num_coins;
- ph->coins.coins = o->details.coins.coins;
+ ph->coins.coins = o->details.coins.coins;
//ph->field_seen[o->ot] = true;
break;
case TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS:
/* stash for later signing */
ph->input_tokens.num_tokens = o->details.input_tokens.num_tokens;
- ph->input_tokens.tokens = o->details.input_tokens.tokens;
+ ph->input_tokens.tokens = o->details.input_tokens.tokens;
break;
case TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS:
/* store JSON array directly, *and* stash for hash */
- ph->output_tokens.num_output_tokens
- = o->details.output_tokens.num_output_tokens;
- ph->output_tokens.output_tokens
- = o->details.output_tokens.output_tokens;
+ ph->output_tokens.num_output_tokens = o->details.output_tokens.num_output_tokens;
+ ph->output_tokens.output_tokens = o->details.output_tokens.output_tokens;
{
/* build and store tokens_evs */
- json_t *arr = json_array ();
- for (unsigned j = 0; j < ph->output_tokens.num_output_tokens; j++) {
+ json_t *arr = json_array();
+ for (unsigned j = 0; j < ph->output_tokens.num_output_tokens; j++)
+ {
const struct TALER_MERCHANT_OutputToken *otk = &ph->output_tokens.output_tokens[j];
- json_t *je = GNUNET_JSON_PACK (
- TALER_JSON_pack_token_envelope (NULL, &otk->envelope)
- );
- json_array_append_new (arr, je);
+ json_t *je = GNUNET_JSON_PACK(TALER_JSON_pack_token_envelope(NULL, &otk->envelope));
+ json_array_append_new(arr, je);
}
ph->tokens_evs = arr;
@@ -612,6 +601,48 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
}
break;
+#ifdef HAVE_DONAU_DONAU_SERVICE_H
+ /* ---------- Donau ------------ */
+ case TALER_MERCHANT_OrderPayOptionType_DONAU_URL:
+ {
+ json_t *js = GNUNET_JSON_PACK(
+ GNUNET_JSON_pack_string("donau_url",
+ o->details.donau_url)
+ );
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (ec != TALER_MERCHANT_OPOEC_OK)
+ return ec;
+ break;
+ }
+
+ case TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR:
+ {
+ json_t *js = GNUNET_JSON_PACK(
+ GNUNET_JSON_pack_uint64("donau_year",
+ o->details.donau_year)
+ );
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option(ph, o->ot, js);
+ if (ec != TALER_MERCHANT_OPOEC_OK)
+ return ec;
+ break;
+ }
+
+ case TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS:
+ {
+ json_t *js = GNUNET_JSON_PACK(
+ GNUNET_JSON_pack_array_incref("donau_budikeypairs",
+ o->details.donau_budis_json)
+ );
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option(ph, o->ot, js);
+ if (ec != TALER_MERCHANT_OPOEC_OK)
+ return ec;
+ break;
+ }
+#endif /* HAVE_DONAU_DONAU_SERVICE_H */
+
default:
return TALER_MERCHANT_OPOEC_UNKNOWN_OPTION;
}
diff --git a/src/testing/testing_api_cmd_pay_order.c b/src/testing/testing_api_cmd_pay_order.c
@@ -39,6 +39,7 @@
#ifdef HAVE_DONAU_DONAU_SERVICE_H
#include <donau/donau_service.h>
#include <donau/donau_testing_lib.h>
+#include <donau/donau_json_lib.h>
#endif /* HAVE_DONAU_DONAU_SERVICE_H */
#ifdef HAVE_DONAU_DONAU_SERVICE_H
@@ -138,6 +139,10 @@ struct MerchantDonauPayData
*/
unsigned int cs_pending;
+ /**
+ * Budis Key Pairs json
+ */
+ json_t *budis_json;
};
// FIXME: One thing left is to receive the BUDIsKP
@@ -271,9 +276,30 @@ prepare_donau_data (struct TALER_TESTING_Interpreter *is,
GNUNET_break (0);
}
}
- // What to do with the next thing from donau
- // if (0 == ss->cs_pending)
- // phase_two (ss);
+
+ {
+
+ json_t *budikeypairs = json_array ();
+ GNUNET_assert (NULL != budikeypairs);
+
+ for (size_t i = 0; i < ss->num_bkps; i++)
+ {
+ /* One object per BKP, identical layout to parse_json_bkp() */
+ json_t *budikeypair = GNUNET_JSON_PACK (
+ /* donation-unit hash (binary) */
+ GNUNET_JSON_pack_data_auto ("h_donation_unit_pub",
+ &ss->bkps[i].h_donation_unit_pub),
+ /* blinded UDI structure (cipher-aware helper does the heavy lifting) */
+ DONAU_JSON_pack_blinded_donation_identifier ("blinded_udi",
+ &ss->bkps[i].blinded_udi));
+
+ /* steal the reference into the array */
+ GNUNET_assert (0 == json_array_append_new (budikeypairs, budikeypair));
+ }
+
+ ss->budis_json = budikeypairs;
+ }
+
}
return GNUNET_OK;
@@ -1053,8 +1079,12 @@ pay_run (void *cls,
}
#ifdef HAVE_DONAU_DONAU_SERVICE_H
- // FIXME: I suspect we want to call function here that will get the stuff for the donau_data
-
+ if (ps->donau_data.charity_reference != NULL) {
+ if (GNUNET_OK != prepare_donau_data(is, &ps->donau_data)) {
+ TALER_TESTING_FAIL(is);
+ return;
+ }
+ }
#else /* HAVE_DONAU_DONAU_SERVICE_H */
// Theoretically we have thought about paying without donau_url being selected, so could proceed...
// or maybe not
@@ -1297,6 +1327,15 @@ pay_run (void *cls,
if (len_output_tokens > 0)
ADD (TALER_MERCHANT_ORDER_PAY_OPTION_OUTPUT_TOKENS(len_output_tokens,
output_tokens));
+
+#ifdef HAVE_DONAU_DONAU_SERVICE_H
+ if (ps->donau_data.charity_reference) {
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_URL (ps->donau_data.donau_url));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_YEAR (ps->donau_data.year));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_BUDIS(ps->donau_data.budis_json));
+ }
+#endif
+
ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ());
#undef ADD