merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/backend/taler-merchant-httpd_post-orders-ID-pay.c | 4++--
Msrc/include/taler_merchant_pay_service.h | 26++++++++++++++++++++++++++
Msrc/lib/taler_merchant_pay_service.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/testing/testing_api_cmd_pay_order.c | 49++++++++++++++++++++++++++++++++++++++++++++-----
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