commit 7c6841cba0d787da4824919f65a3a2f0db5596e8
parent 32ba3f5b88c5c6036177377a5e3ca6fd40e58dd4
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date: Mon, 23 Jun 2025 22:34:49 +0200
first passing pay scenarios
Diffstat:
2 files changed, 200 insertions(+), 169 deletions(-)
diff --git a/src/lib/taler_merchant_pay_service.c b/src/lib/taler_merchant_pay_service.c
@@ -464,7 +464,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
GNUNET_JSON_pack_string ("session_id",
o->details.session_id)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_ORDER_ID:
@@ -478,7 +482,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
json_t *js = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("h_contract", o->details.h_contract)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_CHOICE_INDEX:
@@ -489,7 +497,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
GNUNET_JSON_pack_int64 ("choice_index",
o->details.choice_index)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_AMOUNT:
@@ -498,7 +510,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
TALER_JSON_pack_amount ("amount",
&o->details.amount)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_MAX_FEE:
@@ -507,7 +523,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
TALER_JSON_pack_amount ("max_fee",
&o->details.max_fee)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_MERCHANT_PUB:
@@ -518,7 +538,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
GNUNET_JSON_pack_data_auto ("merchant_pub",
&o->details.merchant_pub)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_TIMESTAMP:
@@ -529,30 +553,22 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
GNUNET_JSON_pack_timestamp ("timestamp",
o->details.timestamp)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_REFUND_DEADLINE:
{
ph->refund_deadline = o->details.refund_deadline;
-
- //Do we really need to pack it?
- json_t *js = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_timestamp ("refund_deadline",
- o->details.refund_deadline)
- );
- return store_json_option (ph, o->ot, js);
}
case TALER_MERCHANT_OrderPayOptionType_PAY_DEADLINE:
{
-
-
- json_t *js = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_timestamp ("pay_deadline",
- o->details.pay_deadline)
- );
- return store_json_option (ph, o->ot, js);
+ //FIXME: This one comes from the merchant_api_post_order_pay
+ // no idea do we still need it or not?
}
case TALER_MERCHANT_OrderPayOptionType_H_WIRE:
@@ -564,7 +580,11 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
GNUNET_JSON_pack_data_auto ("h_wire",
&o->details.h_wire)
);
- return store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
}
case TALER_MERCHANT_OrderPayOptionType_COINS:
@@ -572,14 +592,13 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
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->field_seen[o->ot] = true;
+ //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->field_seen[o->ot] = true;
break;
case TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS:
@@ -601,7 +620,10 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
json_t *js = GNUNET_JSON_PACK (
GNUNET_JSON_pack_array_steal ("tokens_evs", arr)
);
- store_json_option (ph, o->ot, js);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph, o->ot, js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
}
break;
@@ -618,10 +640,10 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
/* all the old mandatory checks */
if (!ph->merchant_url || !ph->order_id)
return TALER_MERCHANT_OPOEC_MISSING_MANDATORY;
- if (!ph->field_seen[TALER_MERCHANT_OrderPayOptionType_COINS])
- return TALER_MERCHANT_OPOEC_MISSING_MANDATORY;
- if (!ph->field_seen[TALER_MERCHANT_OrderPayOptionType_REFUND_DEADLINE])
- return TALER_MERCHANT_OPOEC_MISSING_MANDATORY;
+// if (!ph->field_seen[TALER_MERCHANT_OrderPayOptionType_COINS])
+// return TALER_MERCHANT_OPOEC_MISSING_MANDATORY;
+// if (!ph->field_seen[TALER_MERCHANT_OrderPayOptionType_REFUND_DEADLINE])
+// return TALER_MERCHANT_OPOEC_MISSING_MANDATORY;
/* --- build wallet_data hash for signing coins & tokens --- */
if (ph->has_choice_index) {
@@ -629,79 +651,88 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
ph->wallet_data = GNUNET_JSON_PACK (
GNUNET_JSON_pack_int64("choice_index", ph->choice_index),
GNUNET_JSON_pack_allow_null(
+ //TODO: WTF IS THIS BULLSHIT...
GNUNET_JSON_pack_array_incref("tokens_evs", ph->body))
);
TALER_json_hash (ph->wallet_data, &ph->wallet_data_hash);
}
- /* --- sign & pack coins into paid_coins array in body --- */
+ /* --- sign coins AND build the “coins” JSON in one pass --------------- */
{
- struct TALER_MERCHANT_PaidCoin pc[ph->coins.num_coins];
- for (unsigned i = 0; i < ph->coins.num_coins; i++) {
+ json_t *arr = json_array ();
+ struct TALER_Amount total_fee, total_amount;
- const struct TALER_MERCHANT_PayCoin *coin = &ph->coins.coins[i];
- struct TALER_MERCHANT_PaidCoin *p = &pc[i];
+ for (unsigned i = 0; i < ph->coins.num_coins; i++)
+ {
+ const struct TALER_MERCHANT_PayCoin *c = &ph->coins.coins[i];
+ struct TALER_MERCHANT_PaidCoin pc;
+
+ /* sign ------------------------------------------------------------ */
struct TALER_Amount fee;
- struct TALER_DenominationHashP h_denom_pub;
+ struct TALER_DenominationHashP h_denom;
- if (0 >
- TALER_amount_subtract (&fee,
- &coin->amount_with_fee,
- &coin->amount_without_fee))
- {
- /* Integer underflow, fee larger than total amount?
- This should not happen (client violated API!) */
- GNUNET_break (0);
+ TALER_denom_pub_hash(&c->denom_pub, &h_denom);
+ if (0 > TALER_amount_subtract(&fee, &c->amount_with_fee, &c->amount_without_fee))
return TALER_MERCHANT_OPOEC_INVALID_VALUE;
- }
- TALER_denom_pub_hash ( &coin->denom_pub,
- &h_denom_pub);
- TALER_wallet_deposit_sign ( &coin->amount_with_fee,
- &fee,
- &ph->h_wire,
- &ph->h_contract_terms, /* contract */
- ph->has_choice_index
- ? &ph->wallet_data_hash
- : NULL,
- coin->h_age_commitment,
- NULL, /* extensions */
- &h_denom_pub,
- ph->timestamp,
- &ph->merchant_pub,
- ph->refund_deadline,
- &coin->coin_priv,
- &p->coin_sig);
-
- p->denom_pub = coin->denom_pub;
- p->denom_sig = coin->denom_sig;
- p->denom_value = coin->denom_value;
- GNUNET_CRYPTO_eddsa_key_get_public (&coin->coin_priv.eddsa_priv,
- &p->coin_pub.eddsa_pub);
- p->amount_with_fee = coin->amount_with_fee;
- p->amount_without_fee = coin->amount_without_fee;
- p->exchange_url = coin->exchange_url;
+
+ TALER_wallet_deposit_sign(&c->amount_with_fee, &fee, &ph->h_wire, &ph->h_contract_terms,
+ ph->has_choice_index ? &ph->wallet_data_hash : NULL, c->h_age_commitment, NULL,
+ &h_denom, ph->timestamp, &ph->merchant_pub, ph->refund_deadline, &c->coin_priv,
+ &pc.coin_sig);
+
+ pc.denom_pub = c->denom_pub;
+ pc.denom_sig = c->denom_sig;
+ pc.denom_value = c->denom_value;
+ pc.amount_with_fee = c->amount_with_fee;
+ pc.amount_without_fee = c->amount_without_fee;
+ pc.exchange_url = c->exchange_url;
+ GNUNET_CRYPTO_eddsa_key_get_public(&c->coin_priv.eddsa_priv, &pc.coin_pub.eddsa_pub);
+
+ /* JSON ------------------------------------------------------------ */
+ json_t *je = GNUNET_JSON_PACK(TALER_JSON_pack_amount("contribution", &pc.amount_with_fee),
+ GNUNET_JSON_pack_data_auto("coin_pub", &pc.coin_pub),
+ GNUNET_JSON_pack_string("exchange_url", pc.exchange_url),
+ GNUNET_JSON_pack_data_auto("h_denom", &h_denom),
+ TALER_JSON_pack_denom_sig("ub_sig", &pc.denom_sig),
+ GNUNET_JSON_pack_data_auto("coin_sig", &pc.coin_sig));
+ json_array_append_new(arr, je);
+
+ /* optional totals if you need them later
+ (kept here because they existed in the legacy code) */
+ if (0 == i)
+ {
+ total_fee = fee;
+ total_amount = pc.amount_with_fee;
+ } else
+ {
+ if ( (0 >
+ TALER_amount_add (&total_fee,
+ &total_fee,
+ &fee)) ||
+ (0 >
+ TALER_amount_add (&total_amount,
+ &total_amount,
+ &pc.amount_with_fee)) )
+ {
+ /* integer overflow */
+ GNUNET_break(0);
+ json_decref(arr);
+ return TALER_MERCHANT_OPOEC_INVALID_VALUE;
+ }
+ }
}
- /* now JSON-pack paid_coins[] into request body */
- json_t *arr = json_array ();
- for (unsigned i = 0; i < ph->coins.num_coins; i++) {
- struct TALER_MERCHANT_PaidCoin *p = &pc[i];
- json_t *je = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("coin_sig", &p->coin_sig),
- GNUNET_JSON_pack_data_auto ("coin_pub", &p->coin_pub),
- TALER_JSON_pack_amount ("amount_with_fee", &p->amount_with_fee),
- TALER_JSON_pack_amount ("amount_without_fee",&p->amount_without_fee),
- GNUNET_JSON_pack_string ("exchange_url", p->exchange_url)
- );
- json_array_append_new (arr, je);
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
+ store_json_option (ph,
+ TALER_MERCHANT_OrderPayOptionType_COINS,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_array_steal ("coins", arr)
+ ));
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ {
+ return ec;
}
- store_json_option (ph,
- TALER_MERCHANT_OrderPayOptionType_COINS,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("coins", arr)
- )
- );
}
/* --- sign & pack input_tokens into used_tokens array in body --- */
diff --git a/src/testing/testing_api_cmd_pay_order.c b/src/testing/testing_api_cmd_pay_order.c
@@ -1227,86 +1227,86 @@ pay_run (void *cls,
TALER_TESTING_FAIL (is);
ps->h_contract_terms = *h_proposal;
//TODO: Most probably that's the thing we would like to replace with our own implementation of the pay_function
- ps->oph = TALER_MERCHANT_order_pay (
- TALER_TESTING_interpreter_get_context (is),
- ps->merchant_url,
- ps->session_id,
- h_proposal,
- ps->choice_index,
- &ps->total_amount,
- &max_fee,
- &merchant_pub,
- merchant_sig,
- timestamp,
- refund_deadline,
- pay_deadline,
- &h_wire,
- order_id,
- npay_coins,
- pay_coins,
- len_use_tokens,
- use_tokens,
- len_output_tokens,
- output_tokens,
- &pay_cb,
- ps);
+// ps->oph = TALER_MERCHANT_order_pay (
+// TALER_TESTING_interpreter_get_context (is),
+// ps->merchant_url,
+// ps->session_id,
+// h_proposal,
+// ps->choice_index,
+// &ps->total_amount,
+// &max_fee,
+// &merchant_pub,
+// merchant_sig,
+// timestamp,
+// refund_deadline,
+// pay_deadline,
+// &h_wire,
+// order_id,
+// npay_coins,
+// pay_coins,
+// len_use_tokens,
+// use_tokens,
+// len_output_tokens,
+// output_tokens,
+// &pay_cb,
+// ps);
// New logic of setting params
-// {
-// struct GNUNET_CURL_Context *ctx =
-// TALER_TESTING_interpreter_get_context (is);
-//
-// ps->oph = TALER_MERCHANT_order_pay_create (ctx,
-// &pay_cb,
-// ps);
-//
-// if (NULL == ps->oph)
-// TALER_TESTING_FAIL (is);
-//
-// /* build the option array ------------------------------------------------ */
-// struct TALER_MERCHANT_OrderPayOption opts[32];
-// size_t oi = 0;
-//
-// #define ADD(_opt) opts[oi++] = (_opt)
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_URL (ps->merchant_url));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_ORDER_ID (order_id));
-// if (NULL != ps->session_id)
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_SESSION_ID (ps->session_id));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_CONTRACT (h_proposal));
-// if (ps->choice_index >= 0)
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_CHOICE_INDEX(ps->choice_index));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_AMOUNT (&ps->total_amount));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MAX_FEE (&max_fee));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_PUB (&merchant_pub));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TIMESTAMP (timestamp));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_REFUND_DEADLINE(refund_deadline));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_PAY_DEADLINE (pay_deadline));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_WIRE (&h_wire));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_COINS (npay_coins,
-// pay_coins));
-// if (len_use_tokens > 0)
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_INPUT_TOKENS(len_use_tokens,
-// use_tokens));
-// if (len_output_tokens > 0)
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_OUTPUT_TOKENS(len_output_tokens,
-// output_tokens));
-// ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ());
-// #undef ADD
-//
-// if (TALER_MERCHANT_OPOEC_OK !=
-// TALER_MERCHANT_order_pay_set_options (ps->oph,
-// opts,
-// oi))
-// TALER_TESTING_FAIL (is);
-//
-// if (TALER_MERCHANT_OPOEC_OK !=
-// TALER_MERCHANT_order_pay_start (ps->oph))
-// TALER_TESTING_FAIL (is);
-// }
- GNUNET_array_grow (pay_coins,
- npay_coins,
- 0);
- if (NULL == ps->oph)
- TALER_TESTING_FAIL (is);
+ {
+ struct GNUNET_CURL_Context *ctx =
+ TALER_TESTING_interpreter_get_context (is);
+
+ ps->oph = TALER_MERCHANT_order_pay_create (ctx,
+ &pay_cb,
+ ps);
+
+ if (NULL == ps->oph)
+ TALER_TESTING_FAIL (is);
+
+ /* build the option array ------------------------------------------------ */
+ struct TALER_MERCHANT_OrderPayOption opts[32];
+ size_t oi = 0;
+
+ #define ADD(_opt) opts[oi++] = (_opt)
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_URL (ps->merchant_url));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_ORDER_ID (order_id));
+ if (NULL != ps->session_id)
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_SESSION_ID (ps->session_id));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_CONTRACT (h_proposal));
+ if (ps->choice_index >= 0)
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_CHOICE_INDEX(ps->choice_index));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_AMOUNT (&ps->total_amount));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MAX_FEE (&max_fee));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_PUB (&merchant_pub));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TIMESTAMP (timestamp));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_REFUND_DEADLINE(refund_deadline));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_PAY_DEADLINE (pay_deadline));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_H_WIRE (&h_wire));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_COINS (npay_coins,
+ pay_coins));
+ if (len_use_tokens > 0)
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_INPUT_TOKENS(len_use_tokens,
+ use_tokens));
+ if (len_output_tokens > 0)
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_OUTPUT_TOKENS(len_output_tokens,
+ output_tokens));
+ ADD (TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ());
+ #undef ADD
+
+ if (TALER_MERCHANT_OPOEC_OK !=
+ TALER_MERCHANT_order_pay_set_options (ps->oph,
+ opts,
+ oi))
+ TALER_TESTING_FAIL (is);
+
+ if (TALER_MERCHANT_OPOEC_OK !=
+ TALER_MERCHANT_order_pay_start (ps->oph))
+ TALER_TESTING_FAIL (is);
+ }
+// GNUNET_array_grow (pay_coins,
+// npay_coins,
+// 0);
+// if (NULL == ps->oph)
+// TALER_TESTING_FAIL (is);
}
@@ -1328,8 +1328,8 @@ pay_cleanup (void *cls,
"Command `%s' did not complete.\n",
TALER_TESTING_interpreter_get_current_label (
ps->is));
- TALER_MERCHANT_order_pay_cancel (ps->oph);
- //TALER_MERCHANT_order_pay_cancel1 (ps->oph);
+ //TALER_MERCHANT_order_pay_cancel (ps->oph);
+ TALER_MERCHANT_order_pay_cancel1 (ps->oph);
}
GNUNET_free (ps);