merchant

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

commit 81959db474fbd3fab4b7e5e73d07d86a5ad751d1
parent 22350d314c0437888ad76fa4cb7b8639807c59b3
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon, 25 May 2026 21:45:06 +0200

fix bugs from major refactoring

Diffstat:
Msrc/backend/taler-merchant-httpd_get-orders-ORDER_ID.c | 71++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/backend/taler-merchant-httpd_get-private-orders-ORDER_ID.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/backend/taler-merchant-httpd_post-private-orders.c | 9+++++++--
Msrc/include/taler/taler_merchant_util.h | 2+-
Msrc/testing/test_merchant_mfa.sh | 83+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/testing/test_merchant_statistics.sh | 4++--
Msrc/util/base_terms_parse.c | 9++++++---
Msrc/util/base_terms_serialize.c | 2+-
Msrc/util/contract_serialize.c | 4++--
Msrc/util/order_choice_parse.c | 11+++++++++++
Msrc/util/test_contract.c | 19+++++++++----------
11 files changed, 199 insertions(+), 98 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_get-orders-ORDER_ID.c b/src/backend/taler-merchant-httpd_get-orders-ORDER_ID.c @@ -154,6 +154,13 @@ struct GetOrderData struct TALER_MERCHANT_Contract *contract_terms; /** + * Parsed proto contract terms, NULL when parsing failed. + * Careful, aliased with pc in @e contract_terms if @e contract_terms is + * not NULL! + */ + struct TALER_MERCHANT_ProtoContract *pc; + + /** * Order of the payment we are checking. NULL when we have a contract. */ json_t *order_json; @@ -247,11 +254,6 @@ struct GetOrderData bool generate_html; /** - * Did we parse the contract terms? - */ - bool contract_parsed; - - /** * Did we parse the order? */ bool order_parsed; @@ -330,7 +332,6 @@ suspend_god (struct GetOrderData *god) { json_decref (god->contract_terms_json); god->contract_terms_json = NULL; - god->contract_parsed = false; } if (NULL != god->order_json) { @@ -342,6 +343,12 @@ suspend_god (struct GetOrderData *god) { TALER_MERCHANT_contract_free (god->contract_terms); god->contract_terms = NULL; + god->pc = NULL; + } + if (NULL != god->pc) + { + TALER_MERCHANT_proto_contract_free (god->pc); + god->pc = NULL; } if (NULL != god->order) { @@ -350,7 +357,6 @@ suspend_god (struct GetOrderData *god) } god->ct = NULL; /* ensure not dangling */ GNUNET_assert (! god->suspended); - god->contract_parsed = false; god->contract_match = false; god->token_match = false; god->contract_available = false; @@ -781,18 +787,37 @@ phase_parse_contract (struct GetOrderData *god) GNUNET_break (NULL == god->order); if (NULL != god->contract_terms_json) { - god->contract_terms = TALER_MERCHANT_contract_parse ( - god->contract_terms_json); - if (NULL == god->contract_terms) + if (NULL == + json_object_get (god->contract_terms_json, + "nonce")) { - phase_fail (god, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, - god->order_id); - return; + god->pc = TALER_MERCHANT_proto_contract_parse ( + god->contract_terms_json); + if (NULL == god->pc) + { + phase_fail (god, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, + god->order_id); + return; + } + god->ct = god->pc->base; + } + else + { + god->contract_terms = TALER_MERCHANT_contract_parse ( + god->contract_terms_json); + if (NULL == god->contract_terms) + { + phase_fail (god, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, + god->order_id); + return; + } + god->pc = god->contract_terms->pc; + god->ct = god->contract_terms->pc->base; } - god->contract_parsed = true; - god->ct = god->contract_terms->pc->base; } if (NULL != god->order_json) { @@ -810,7 +835,7 @@ phase_parse_contract (struct GetOrderData *god) god->ct = god->order->base; } GNUNET_assert ( (NULL != god->order) || - (NULL != god->contract_terms) ); + (NULL != god->pc) ); if ( (NULL != god->session_id) && (NULL != god->ct->fulfillment_url) && @@ -1375,8 +1400,8 @@ phase_check_refunded (struct GetOrderData *god) switch (god->ct->version) { case TALER_MERCHANT_CONTRACT_VERSION_0: - refund_amount = god->contract_terms->pc->details.v0.brutto; - refund_currency = god->contract_terms->pc->details.v0.brutto.currency; + refund_amount = god->pc->details.v0.brutto; + refund_currency = god->pc->details.v0.brutto.currency; break; case TALER_MERCHANT_CONTRACT_VERSION_1: if (god->choice_index < 0) @@ -1386,8 +1411,8 @@ phase_check_refunded (struct GetOrderData *god) return false; } GNUNET_assert (god->choice_index < - god->contract_terms->pc->details.v1.choices_len); - refund_currency = god->contract_terms->pc->details.v1.choices[ + god->pc->details.v1.choices_len); + refund_currency = god->pc->details.v1.choices[ god->choice_index].amount.currency; GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (refund_currency, @@ -1571,7 +1596,7 @@ phase_return_status (struct GetOrderData *god) GNUNET_assert (NULL != god->contract_terms_json); GNUNET_assert (NULL != god->contract_terms); - uri = make_taler_refund_uri (god->contract_terms->pc->merchant_base_url, + uri = make_taler_refund_uri (god->pc->merchant_base_url, god->order_id); if (NULL == uri) { diff --git a/src/backend/taler-merchant-httpd_get-private-orders-ORDER_ID.c b/src/backend/taler-merchant-httpd_get-private-orders-ORDER_ID.c @@ -263,6 +263,12 @@ struct GetOrderRequestContext struct TALER_MERCHANT_Contract *contract_terms; /** + * Proto-contract. Be careful: do NOT free this + * if @e contract_terms is not NULL! + */ + struct TALER_MERCHANT_ProtoContract *pc; + + /** * Order terms of the payment we are checking. NULL when we have * a contract. */ @@ -549,6 +555,12 @@ gorc_cleanup (void *cls) { TALER_MERCHANT_contract_free (gorc->contract_terms); gorc->contract_terms = NULL; + gorc->pc = NULL; /* was an alias! */ + } + if (NULL != gorc->pc) + { + TALER_MERCHANT_proto_contract_free (gorc->pc); + gorc->pc = NULL; } if (NULL != gorc->order) { @@ -801,39 +813,64 @@ phase_parse_contract (struct GetOrderRequestContext *gorc) if ( (NULL == gorc->contract_terms) && (NULL != gorc->contract_terms_json) ) { - gorc->contract_terms = TALER_MERCHANT_contract_parse ( - gorc->contract_terms_json); + if (NULL == + json_object_get (gorc->contract_terms_json, + "nonce")) + { + /* only have a proto contract */ + gorc->pc = TALER_MERCHANT_proto_contract_parse ( + gorc->contract_terms_json); - if (NULL == gorc->contract_terms) + if (NULL == gorc->pc) + { + GNUNET_break (0); + phase_end (gorc, + TALER_MHD_reply_with_error ( + gorc->sc.con, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, + hc->infix)); + return; + } + gorc->ct = gorc->pc->base; + gorc->timestamp = gorc->pc->timestamp; + } + else { - GNUNET_break (0); - phase_end (gorc, - TALER_MHD_reply_with_error ( - gorc->sc.con, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, - hc->infix)); - return; + gorc->contract_terms = TALER_MERCHANT_contract_parse ( + gorc->contract_terms_json); + gorc->pc = gorc->contract_terms->pc; + if (NULL == gorc->contract_terms) + { + GNUNET_break (0); + phase_end (gorc, + TALER_MHD_reply_with_error ( + gorc->sc.con, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID, + hc->infix)); + return; + } + gorc->ct = gorc->contract_terms->pc->base; + gorc->timestamp = gorc->contract_terms->pc->timestamp; } - gorc->ct = gorc->contract_terms->pc->base; - gorc->timestamp = gorc->contract_terms->pc->timestamp; } switch (gorc->ct->version) { case TALER_MERCHANT_CONTRACT_VERSION_0: gorc->contract_amount - = (NULL != gorc->contract_terms) - ? gorc->contract_terms->pc->details.v0.brutto + = (NULL != gorc->pc) + ? gorc->pc->details.v0.brutto : gorc->order->details.v0.brutto; break; case TALER_MERCHANT_CONTRACT_VERSION_1: if (gorc->choice_index >= 0) { if (gorc->choice_index >= - (NULL != gorc->contract_terms) - ? gorc->contract_terms->pc->details.v1.choices_len - : gorc->order->details.v1.choices_len) + ( (NULL != gorc->pc) + ? gorc->pc->details.v1.choices_len + : gorc->order->details.v1.choices_len) ) { GNUNET_break (0); phase_end (gorc, @@ -845,8 +882,8 @@ phase_parse_contract (struct GetOrderRequestContext *gorc) return; } gorc->contract_amount = - (NULL != gorc->contract_terms) - ? gorc->contract_terms->pc->details.v1.choices[gorc->choice_index].amount + (NULL != gorc->pc) + ? gorc->pc->details.v1.choices[gorc->choice_index].amount : gorc->order->details.v1.choices[gorc->choice_index].amount; } else @@ -885,7 +922,7 @@ phase_parse_contract (struct GetOrderRequestContext *gorc) } GNUNET_assert ( (NULL != gorc->contract_terms_json) || (NULL != gorc->order_json) ); - GNUNET_assert ( (NULL != gorc->contract_terms) || + GNUNET_assert ( (NULL != gorc->pc) || (NULL != gorc->order) ); gorc->phase++; } @@ -1138,8 +1175,8 @@ phase_check_repurchase (struct GetOrderRequestContext *gorc) GNUNET_JSON_pack_string ("summary", gorc->ct->summary), GNUNET_JSON_pack_timestamp ("pay_deadline", - NULL != gorc->contract_terms - ? gorc->contract_terms->pc->pay_deadline + NULL != gorc->pc + ? gorc->pc->pay_deadline : gorc->order->pay_deadline), GNUNET_JSON_pack_timestamp ("creation_time", gorc->timestamp)); diff --git a/src/backend/taler-merchant-httpd_post-private-orders.c b/src/backend/taler-merchant-httpd_post-private-orders.c @@ -2140,6 +2140,9 @@ phase_serialize_order (struct OrderContext *oc) } oc->serialize_order.contract = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ( + "order_id", + oc->parse_order.order->order_id), GNUNET_JSON_pack_object_steal ( NULL, TALER_MERCHANT_base_terms_serialize (oc->parse_order.order->base)), @@ -3531,8 +3534,10 @@ phase_parse_choices (struct OrderContext *oc) cchoice->amount = ochoice->amount; cchoice->tip = ochoice->tip; cchoice->no_tip = ochoice->no_tip; - cchoice->description = GNUNET_strdup (ochoice->description); - cchoice->description_i18n = json_incref (ochoice->description_i18n); + if (NULL != ochoice->description) + cchoice->description = GNUNET_strdup (ochoice->description); + if (NULL != ochoice->description_i18n) + cchoice->description_i18n = json_incref (ochoice->description_i18n); cchoice->max_fee = ochoice->max_fee; /* convert inputs */ diff --git a/src/include/taler/taler_merchant_util.h b/src/include/taler/taler_merchant_util.h @@ -1419,7 +1419,7 @@ struct TALER_MERCHANT_ContractBaseTerms uint8_t minimum_age; /** - * Default money pot to use for this product, applies to the + * Default money pot to use for this order, applies to the * amount remaining that was not claimed by money pots of * products or taxes. Not useful to wallets, only for * merchant-internal accounting. If zero, the remaining diff --git a/src/testing/test_merchant_mfa.sh b/src/testing/test_merchant_mfa.sh @@ -60,7 +60,7 @@ echo -n "Self-provision instance ..." STATUS=$(curl -H "Content-Type: application/json" -X POST \ http://localhost:9966/instances \ - -d '{"auth":{"method":"token", "password":"pass1234"},"id":"self","name":"default","phone_number":"1234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ + -d '{"auth":{"method":"token", "password":"pass1234"},"id":"self","name":"default","phone_number":"+4171234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") @@ -81,19 +81,19 @@ STATUS=$(curl -H "Content-Type: application/json" -X POST \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") -if [ "$STATUS" != "204" ] +if [ "$STATUS" != "200" ] then jq < "$LAST_RESPONSE" - exit_fail "Expected 204 OK. Got: $STATUS" + exit_fail "Expected 200 OK. Got: $STATUS" fi echo "OK" -TAN=$(cat /tmp/test-merchant-sms-tan.txt | head -n1) -ADDR=$(cat /tmp/test-merchant-sms-address.txt) +TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1 | awk '{print $1}') +ADDR=$(cat /tmp/test-merchant-email-address.txt) -if [ "$ADDR" != "1234" ] +if [ "$ADDR" != "self@example.com" ] then - exit_fail "Expected address '1234'. Got: $ADDR" + exit_fail "Expected address 'self@example.com'. Got: $ADDR" fi echo -n "Sending challenge $C1 solution " @@ -120,14 +120,14 @@ STATUS=$(curl -H "Content-Type: application/json" -X POST \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") -if [ "$STATUS" != "204" ] +if [ "$STATUS" != "200" ] then jq < "$LAST_RESPONSE" - exit_fail "Expected 204 OK. Got: $STATUS" + exit_fail "Expected 200 OK. Got: $STATUS" fi echo "OK" -TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1) +TAN=$(cat /tmp/test-merchant-sms-tan.txt | head -n1 | awk '{print $1}') echo -n "Sending challenge $C2 solution " @@ -152,7 +152,7 @@ STATUS=$(curl \ -H "Taler-Challenge-Ids: $C1,$C2" \ -X POST \ http://localhost:9966/instances \ - -d '{"auth":{"method":"external"},"id":"self","name":"change","phone_number":"1234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ + -d '{"auth":{"method":"external"},"id":"self","name":"change","phone_number":"+4171234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") @@ -172,7 +172,7 @@ STATUS=$(curl \ -H "Taler-Challenge-Ids: $C1,$C2" \ -X POST \ http://localhost:9966/instances \ - -d '{"auth":{"method":"token", "password":"pass1234"},"id":"self","name":"default","phone_number":"1234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ + -d '{"auth":{"method":"token", "password":"pass1234"},"id":"self","name":"default","phone_number":"+4171234","email":"self@example.com","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") @@ -202,7 +202,7 @@ fi echo " OK" -echo -n "Trigger MFA to add bank account with 2-FA authorization " +echo -n "Do NOT Trigger MFA to add first bank account " STATUS=$(curl \ -H "Content-Type: application/json" \ -X POST \ @@ -212,6 +212,25 @@ STATUS=$(curl \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") +if [ "$STATUS" != "200" ] +then + jq < "$LAST_RESPONSE" + exit_fail "Expected 200 OK. Got: $STATUS" +fi + +echo " OK" + + +echo -n "Trigger MFA to add 2nd bank account with 2-FA authorization " +STATUS=$(curl \ + -H "Content-Type: application/json" \ + -X POST \ + -H 'Authorization: Bearer secret-token:pass1234' \ + http://localhost:9966/instances/self/private/accounts \ + -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/45?receiver-name=user45"}' \ + -w "%{http_code}" -s \ + -o "$LAST_RESPONSE") + if [ "$STATUS" != "202" ] then jq < "$LAST_RESPONSE" @@ -221,8 +240,10 @@ fi echo " OK" -C1=$(jq -r .challenges[1].challenge_id < "$LAST_RESPONSE") +C1=$(jq -r .challenges[0].challenge_id < "$LAST_RESPONSE") +# Delete old TANs. +rm /tmp/test-merchant-*-tan.txt echo -n "Requesting challenge $C1 " STATUS=$(curl -H "Content-Type: application/json" -X POST \ @@ -231,19 +252,19 @@ STATUS=$(curl -H "Content-Type: application/json" -X POST \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") -if [ "$STATUS" != "204" ] +if [ "$STATUS" != "200" ] then jq < "$LAST_RESPONSE" - exit_fail "Expected 204 OK. Got: $STATUS" + exit_fail "Expected 200 OK. Got: $STATUS" fi echo "OK" -TAN=$(cat /tmp/test-merchant-sms-tan.txt | head -n1) -ADDR=$(cat /tmp/test-merchant-sms-address.txt) +TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1 | awk '{print $1}') +ADDR=$(cat /tmp/test-merchant-email-address.txt) -if [ "$ADDR" != "1234" ] +if [ "$ADDR" != "self@example.com" ] then - exit_fail "Expected address '1234'. Got: $ADDR" + exit_fail "Expected address 'self@example.com'. Got: $ADDR" fi echo -n "Sending challenge $C1 solution " @@ -263,14 +284,14 @@ then fi echo "OK" -echo -n "Finally, add bank account " +echo -n "Finally, add 2nd bank account " STATUS=$(curl \ -X POST \ -H "Content-Type: application/json" \ -H "Taler-Challenge-Ids: $C1" \ -H 'Authorization: Bearer secret-token:pass1234' \ http://localhost:9966/instances/self/private/accounts \ - -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/44?receiver-name=user44"}' \ + -d '{"payto_uri":"payto://x-taler-bank/localhost:8082/45?receiver-name=user45"}' \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") @@ -311,19 +332,19 @@ STATUS=$(curl -H "Content-Type: application/json" -X POST \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") -if [ "$STATUS" != "204" ] +if [ "$STATUS" != "200" ] then jq < "$LAST_RESPONSE" - exit_fail "Expected 204 OK. Got: $STATUS" + exit_fail "Expected 200 OK. Got: $STATUS" fi echo "OK" -TAN=$(cat /tmp/test-merchant-sms-tan.txt | head -n1) -ADDR=$(cat /tmp/test-merchant-sms-address.txt) +TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1 | awk '{print $1}') +ADDR=$(cat /tmp/test-merchant-email-address.txt) -if [ "$ADDR" != "1234" ] +if [ "$ADDR" != "self@example.com" ] then - exit_fail "Expected address '1234'. Got: $ADDR" + exit_fail "Expected address 'self@example.com'. Got: $ADDR" fi echo -n "Sending challenge $C1 solution " @@ -350,14 +371,14 @@ STATUS=$(curl -H "Content-Type: application/json" -X POST \ -w "%{http_code}" -s \ -o "$LAST_RESPONSE") -if [ "$STATUS" != "204" ] +if [ "$STATUS" != "200" ] then jq < "$LAST_RESPONSE" - exit_fail "Expected 204 OK. Got: $STATUS" + exit_fail "Expected 200 OK. Got: $STATUS" fi echo "OK" -TAN=$(cat /tmp/test-merchant-email-tan.txt | head -n1) +TAN=$(cat /tmp/test-merchant-sms-tan.txt | head -n1 | awk '{print $1}') echo -n "Sending challenge $C2 solution " diff --git a/src/testing/test_merchant_statistics.sh b/src/testing/test_merchant_statistics.sh @@ -171,7 +171,7 @@ echo "OK" echo -n "Creating money pot..." STATUS=$(curl 'http://localhost:9966/private/pots' \ - -d '{"description":"First pot","pot_name":"#1"}' \ + -d '{"description":"First pot","pot_name":"pot1"}' \ -w "%{http_code}" -s -o "$LAST_RESPONSE") if [ "$STATUS" != "200" ] @@ -247,7 +247,7 @@ echo "OK" echo -n "Patching money pot ..." STATUS=$(curl "http://localhost:9966/private/pots/$MONEY_POT" -X PATCH \ - -d '{"description":"Updated pot","expected_pot_totals":[],"new_pot_totals":["KUDOS:23"],"pot_name":"#1p"}' \ + -d '{"description":"Updated pot","expected_pot_totals":[],"new_pot_totals":["KUDOS:23"],"pot_name":"pot1p"}' \ -w "%{http_code}" -s -o "$LAST_RESPONSE") if [ "$STATUS" != "204" ] diff --git a/src/util/base_terms_parse.c b/src/util/base_terms_parse.c @@ -37,8 +37,10 @@ TALER_MERCHANT_base_terms_parse ( struct TALER_MERCHANT_ContractBaseTerms *ct = GNUNET_new (struct TALER_MERCHANT_ContractBaseTerms); struct GNUNET_JSON_Specification espec[] = { - TALER_MERCHANT_spec_contract_version ("version", - &ct->version), + GNUNET_JSON_spec_mark_optional ( + TALER_MERCHANT_spec_contract_version ("version", + &ct->version), + NULL), GNUNET_JSON_spec_string_copy ("summary", &ct->summary), /* FIXME: do i18n_str validation in the future */ @@ -87,7 +89,7 @@ TALER_MERCHANT_base_terms_parse ( &ct->minimum_age), NULL), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_uint64 ("default_money_pot", + GNUNET_JSON_spec_uint64 ("order_default_money_pot", &ct->default_money_pot), NULL), GNUNET_JSON_spec_end () @@ -98,6 +100,7 @@ TALER_MERCHANT_base_terms_parse ( GNUNET_assert (NULL != input); ct->max_pickup_time = GNUNET_TIME_UNIT_FOREVER_TS; + ct->version = TALER_MERCHANT_CONTRACT_VERSION_0; res = GNUNET_JSON_parse (input, espec, &ename, diff --git a/src/util/base_terms_serialize.c b/src/util/base_terms_serialize.c @@ -77,7 +77,7 @@ TALER_MERCHANT_base_terms_serialize ( ? GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("dummy", NULL)) - : GNUNET_JSON_pack_uint64 ("default_money_pot", + : GNUNET_JSON_pack_uint64 ("order_default_money_pot", ct->default_money_pot), GNUNET_TIME_absolute_is_never (ct->max_pickup_time.abs_time) ? GNUNET_JSON_pack_allow_null ( diff --git a/src/util/contract_serialize.c b/src/util/contract_serialize.c @@ -133,10 +133,10 @@ success: } return GNUNET_JSON_PACK ( - GNUNET_JSON_pack_object_steal (NULL, - bj), GNUNET_JSON_pack_string ("order_id", pc->order_id), + GNUNET_JSON_pack_object_steal (NULL, + bj), GNUNET_JSON_pack_timestamp ("timestamp", pc->timestamp), GNUNET_JSON_pack_timestamp ("refund_deadline", diff --git a/src/util/order_choice_parse.c b/src/util/order_choice_parse.c @@ -291,6 +291,17 @@ parse_order_choices ( GNUNET_break_op (0); return GNUNET_SYSERR; } + if ( (! choice->no_fee) && + (GNUNET_OK != + TALER_amount_cmp_currency (&choice->amount, + &choice->max_fee)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fee currency does not match amount currency in choice #%u\n", + i); + GNUNET_break_op (0); + return GNUNET_SYSERR; + } if ( (! choice->no_tip) && (GNUNET_OK != TALER_amount_cmp_currency (&choice->amount, diff --git a/src/util/test_contract.c b/src/util/test_contract.c @@ -61,7 +61,7 @@ const char *contract_common = "{\n" " \"exchanges\": [],\n" " \"delivery_location\": {},\n" // TODO " \"delivery_date\": {\"t_s\": 1736174497},\n" - " \"nonce\": \"\",\n" // TODO + " \"nonce\": \"test-nonce\",\n" " \"auto_refund\": {\"d_us\": \"forever\"},\n" " \"extra\": {\n" " \"key0\": \"value0\",\n" @@ -181,12 +181,11 @@ main (int argc, GNUNET_assert (0 == json_object_update_new (v0, common)); - v0_parsed = TALER_MERCHANT_contract_parse (v0, false); + v0_parsed = TALER_MERCHANT_contract_parse (v0); GNUNET_assert (NULL != v0_parsed); - v0_serialized = TALER_MERCHANT_contract_serialize (v0_parsed, false); + v0_serialized = TALER_MERCHANT_contract_serialize (v0_parsed); GNUNET_assert (NULL != v0_serialized); - GNUNET_assert (1 == json_equal (v0, v0_serialized)); json_decref (v0_serialized); @@ -208,20 +207,20 @@ main (int argc, GNUNET_assert (0 == json_object_update_new (v1, common)); - v1_parsed = TALER_MERCHANT_contract_parse (v1, false); + v1_parsed = TALER_MERCHANT_contract_parse (v1); GNUNET_assert (NULL != v1_parsed); - v1_serialized = TALER_MERCHANT_contract_serialize (v1_parsed, false); + v1_serialized = TALER_MERCHANT_contract_serialize (v1_parsed); GNUNET_assert (NULL != v1_serialized); GNUNET_assert (1 == json_equal (v1, v1_serialized)); for (unsigned int i = 0; - i < v1_parsed->details.v1.token_authorities_len; + i < v1_parsed->pc->details.v1.token_authorities_len; i++) { struct TALER_MERCHANT_ContractTokenFamily *in = - &v1_parsed->details.v1.token_authorities[i]; + &v1_parsed->pc->details.v1.token_authorities[i]; for (unsigned int j = 0; j < in->keys_len; j++) { struct TALER_MERCHANT_ContractTokenFamilyKey *inkey = &in->keys[j]; @@ -230,8 +229,8 @@ main (int argc, GNUNET_assert (GNUNET_OK == TALER_MERCHANT_find_token_family_key ( in->slug, inkey->valid_after, - v1_parsed->details.v1.token_authorities, - v1_parsed->details.v1.token_authorities_len, + v1_parsed->pc->details.v1.token_authorities, + v1_parsed->pc->details.v1.token_authorities_len, &out, &outkey)); GNUNET_assert (0 == GNUNET_memcmp (in, &out));