merchant

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

commit e24064063f5d7dc36ab14e1f911708e6d981a10e
parent fc51e020796e4faa5435520adb5e3ca67ee6105f
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri,  2 Oct 2020 20:20:08 +0200

implement #6616 claim status in /private/orders/ID handler

Diffstat:
Msrc/backend/taler-merchant-httpd_private-get-orders-ID.c | 15++++++++++++++-
Msrc/include/taler_merchant_service.h | 45++++++++++++++++++++++++++++++++++++++++-----
Msrc/include/taler_merchant_testing_lib.h | 8++++----
Msrc/lib/merchant_api_merchant_get_order.c | 50++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/testing/test_merchant_api.c | 18+++++++++---------
Msrc/testing/testing_api_cmd_merchant_get_order.c | 599++++++++++++++++++++++++++++++++++++++++---------------------------------------
6 files changed, 419 insertions(+), 316 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_private-get-orders-ID.c b/src/backend/taler-merchant-httpd_private-get-orders-ID.c @@ -1044,7 +1044,20 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, gorc->session_id, gorc->fulfillment_url); } - + if ( (! paid) && + (! order_only) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Order %s claimed but not paid yet\n", + hc->infix); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:O, s:s}", + "contract_terms", + gorc->contract_terms, + "order_status", + "claimed"); + } if (paid && (! wired) && gorc->transfer_status_requested) diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -1632,24 +1632,46 @@ struct TALER_MERCHANT_RefundOrderDetail /** + * Status of an order. + */ +enum TALER_MERCHANT_OrderStatusCode +{ + /** + * The order was paid. + */ + TALER_MERCHANT_OSC_PAID = 1, + + /** + * The order was claimed but not yet paid. + */ + TALER_MERCHANT_OSC_CLAIMED = 2, + + /** + * The order was never paid or claimed. + */ + TALER_MERCHANT_OSC_UNPAID = 3 +}; + + +/** * Details about the status of an order. */ struct TALER_MERCHANT_OrderStatusResponse { /** - * true if the payment is settled, false if not settled. + * Status of the order. */ - bool paid; + enum TALER_MERCHANT_OrderStatusCode status; /** - * Details depending on the payment status given in @e paid. + * Details depending on the payment status given in @e status. */ union { /** - * Details provided if @e paid is #GNUNET_YES. + * Details provided if @e status is #TALER_MERCHANT_OSC_PAID. */ struct { @@ -1729,7 +1751,20 @@ struct TALER_MERCHANT_OrderStatusResponse } paid; /** - * Details provided if @e paid is #GNUNET_NO. + * Details provided if @e status is #TALER_MERCHANT_OSC_CLAIMED. + */ + struct + { + + /** + * The full contract terms of the claimed order (including client nonce from claiming). + */ + const json_t *contract_terms; + + } claimed; + + /** + * Details provided if @e status is #TALER_MERCHANT_OSC_UNPAID. */ struct { diff --git a/src/include/taler_merchant_testing_lib.h b/src/include/taler_merchant_testing_lib.h @@ -641,7 +641,7 @@ TALER_TESTING_cmd_wallet_poll_order_conclude ( * @param merchant_url base URL of the merchant which will * serve the request. * @param order_reference reference to a command that created an order. - * @param paid whether the order has been paid for or not. + * @param osc expected order status * @param refunded whether the order has been refunded. * @param http_status expected HTTP response code for the request. * @param ... NULL-terminated list of labels (const char *) of @@ -653,7 +653,7 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_get_order (const char *label, const char *merchant_url, const char *order_reference, - bool paid, + enum TALER_MERCHANT_OrderStatusCode osc, bool refunded, unsigned int http_status, ...); @@ -666,7 +666,7 @@ TALER_TESTING_cmd_merchant_get_order (const char *label, * @param merchant_url base URL of the merchant which will * serve the request. * @param order_reference reference to a command that created an order. - * @param paid whether the order has been paid for or not. + * @param osc expected order status * @param wired whether the order has been wired or not. * @param transfers NULL-terminated list of labels (const char *) of * wire transfers (commands) we expect to be aggregated in the order @@ -686,7 +686,7 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_get_order2 (const char *label, const char *merchant_url, const char *order_reference, - bool paid, + enum TALER_MERCHANT_OrderStatusCode osc, bool wired, const char **transfers, bool refunded, diff --git a/src/lib/merchant_api_merchant_get_order.c b/src/lib/merchant_api_merchant_get_order.c @@ -95,7 +95,7 @@ handle_unpaid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, } { struct TALER_MERCHANT_OrderStatusResponse osr = { - .paid = false, + .status = TALER_MERCHANT_OSC_UNPAID, .details.unpaid.taler_pay_uri = taler_pay_uri, .details.unpaid.already_paid_order_id = already_paid_order_id }; @@ -109,6 +109,47 @@ handle_unpaid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, /** * Function called when we're done processing the GET /private/orders/$ORDER + * request and we got an HTTP status of OK and the order was claimed but not + * paid. Parse the response and call the callback. + * + * @param omgh handle for the request + * @param[in,out] hr HTTP response we got + */ +static void +handle_claimed (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, + struct TALER_MERCHANT_HttpResponse *hr) +{ + struct TALER_MERCHANT_OrderStatusResponse osr = { + .status = TALER_MERCHANT_OSC_CLAIMED + }; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("contract_terms", + (json_t **) &osr.details.claimed.contract_terms), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (hr->reply, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + hr->http_status = 0; + hr->ec = TALER_EC_MERCHANT_ORDER_GET_REPLY_MALFORMED; + omgh->cb (omgh->cb_cls, + hr, + NULL); + return; + } + omgh->cb (omgh->cb_cls, + hr, + &osr); + GNUNET_JSON_parse_free (spec); +} + + +/** + * Function called when we're done processing the GET /private/orders/$ORDER * request and we got an HTTP status of OK and the order was paid. Parse * the response and call the callback. * @@ -125,7 +166,7 @@ handle_paid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, json_t *wire_reports; json_t *refund_details; struct TALER_MERCHANT_OrderStatusResponse osr = { - .paid = true + .status = TALER_MERCHANT_OSC_PAID }; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_bool ("refunded", @@ -377,6 +418,11 @@ handle_merchant_order_get_finished (void *cls, handle_paid (omgh, &hr); } + else if (0 == strcmp ("claimed", order_status)) + { + handle_claimed (omgh, + &hr); + } else if (0 == strcmp ("unpaid", order_status)) { handle_unpaid (omgh, diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c @@ -213,7 +213,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order ("get-order-4", merchant_url, "create-proposal-4", - false, + TALER_MERCHANT_OSC_UNPAID, false, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_delete_order ("delete-order-4", @@ -334,7 +334,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order ("get-order-merchant-1", merchant_url, "create-proposal-1", - false, + TALER_MERCHANT_OSC_CLAIMED, false, MHD_HTTP_OK), TALER_TESTING_cmd_poll_order_start ("poll-order-merchant-1-start", @@ -367,7 +367,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order ("get-order-merchant-1-2", merchant_url, "create-proposal-1", - true, + TALER_MERCHANT_OSC_PAID, false, MHD_HTTP_OK), TALER_TESTING_cmd_merchant_get_orders ("get-orders-1-paid", @@ -407,7 +407,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order2 ("get-order-merchant-1-2", merchant_url, "create-proposal-1", - true, + TALER_MERCHANT_OSC_PAID, true, order_1_transfers, false, @@ -424,7 +424,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order2 ("get-order-merchant-1-forget-1", merchant_url, "create-proposal-1", - true, + TALER_MERCHANT_OSC_PAID, true, order_1_transfers, false, @@ -455,7 +455,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order2 ("get-order-merchant-1-forget-2", merchant_url, "create-proposal-1", - true, + TALER_MERCHANT_OSC_PAID, true, order_1_transfers, false, @@ -472,7 +472,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order2 ("get-order-merchant-1-forget-3", merchant_url, "create-proposal-1", - true, + TALER_MERCHANT_OSC_PAID, true, order_1_transfers, false, @@ -715,7 +715,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order ("get-order-merchant-1r", merchant_url, "create-proposal-1r", - true, + TALER_MERCHANT_OSC_PAID, true, MHD_HTTP_OK, "refund-increase-1r", @@ -724,7 +724,7 @@ run (void *cls, TALER_TESTING_cmd_merchant_get_order2 ("get-order-merchant-1r-2", merchant_url, "create-proposal-1r", - true, + TALER_MERCHANT_OSC_PAID, false, NULL, true, diff --git a/src/testing/testing_api_cmd_merchant_get_order.c b/src/testing/testing_api_cmd_merchant_get_order.c @@ -59,9 +59,9 @@ struct MerchantGetOrderState const char *order_reference; /** - * Whether the order was paid or not. + * Expected order status. */ - bool paid; + enum TALER_MERCHANT_OrderStatusCode osc; /** * Whether the order was refunded or not. @@ -162,355 +162,364 @@ merchant_get_order_cb ( case MHD_HTTP_OK: // FIXME: use gts->tip_reference here to // check if the data returned matches that from the POST / PATCH - if (gos->paid != osr->paid) + if (gos->osc != osr->status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order paid does not match\n"); TALER_TESTING_interpreter_fail (gos->is); return; } - if (gos->paid) + switch (osr->status) { - const struct TALER_TESTING_Command *order_cmd; - struct TALER_Amount refunded_total; - - order_cmd = TALER_TESTING_interpreter_lookup_command ( - gos->is, - gos->order_reference); - + case TALER_MERCHANT_OSC_PAID: { - const json_t *expected_contract_terms; - json_t *ct; - - if (GNUNET_OK != - TALER_TESTING_get_trait_contract_terms (order_cmd, - 0, - &expected_contract_terms)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not fetch order contract terms\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } + const struct TALER_TESTING_Command *order_cmd; + struct TALER_Amount refunded_total; - ct = json_deep_copy (expected_contract_terms); + order_cmd = TALER_TESTING_interpreter_lookup_command ( + gos->is, + gos->order_reference); - /* Apply all forgets, then compare */ - for (unsigned int i = 0; i < gos->forgets_length; ++i) { - const struct TALER_TESTING_Command *forget_cmd; - const unsigned int *paths_length; - - forget_cmd = TALER_TESTING_interpreter_lookup_command ( - gos->is, - gos->forgets[i]); + const json_t *expected_contract_terms; + json_t *ct; if (GNUNET_OK != - TALER_TESTING_get_trait_uint32 (forget_cmd, - 0, - &paths_length)) + TALER_TESTING_get_trait_contract_terms (order_cmd, + 0, + &expected_contract_terms)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Couldn't fetch forget paths length\n"); + "Could not fetch order contract terms\n"); TALER_TESTING_interpreter_fail (gos->is); return; } - for (unsigned int j = 0; j < *paths_length; ++j) + ct = json_deep_copy (expected_contract_terms); + + /* Apply all forgets, then compare */ + for (unsigned int i = 0; i < gos->forgets_length; ++i) { - const char *path; - int res = GNUNET_OK; + const struct TALER_TESTING_Command *forget_cmd; + const unsigned int *paths_length; + + forget_cmd = TALER_TESTING_interpreter_lookup_command ( + gos->is, + gos->forgets[i]); if (GNUNET_OK != - TALER_TESTING_get_trait_string (forget_cmd, - j, - &path)) + TALER_TESTING_get_trait_uint32 (forget_cmd, + 0, + &paths_length)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Couldn't fetch forget path\n"); + "Couldn't fetch forget paths length\n"); TALER_TESTING_interpreter_fail (gos->is); return; } - GNUNET_assert (GNUNET_OK == - TALER_JSON_expand_path (ct, - path, - &apply_forget, - &res)); - GNUNET_assert (GNUNET_OK == res); + for (unsigned int j = 0; j < *paths_length; ++j) + { + const char *path; + int res = GNUNET_OK; + + if (GNUNET_OK != + TALER_TESTING_get_trait_string (forget_cmd, + j, + &path)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Couldn't fetch forget path\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + + GNUNET_assert (GNUNET_OK == + TALER_JSON_expand_path (ct, + path, + &apply_forget, + &res)); + GNUNET_assert (GNUNET_OK == res); + } } - } - if (1 != json_equal (ct, - osr->details.paid.contract_terms)) + if (1 != json_equal (ct, + osr->details.paid.contract_terms)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Order contract terms do not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + + json_decref (ct); + } + if (gos->wired != osr->details.paid.wired) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Order contract terms do not match\n"); + "Order wired does not match\n"); TALER_TESTING_interpreter_fail (gos->is); return; } - - json_decref (ct); - } - if (gos->wired != osr->details.paid.wired) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Order wired does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - if (gos->transfers_length != osr->details.paid.wts_len) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Number of transfers found does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - for (unsigned int i = 0; i < gos->transfers_length; ++i) - { - const struct TALER_TESTING_Command *transfer_cmd; - - transfer_cmd = TALER_TESTING_interpreter_lookup_command ( - gos->is, - gos->transfers[i]); + if (gos->transfers_length != osr->details.paid.wts_len) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Number of transfers found does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + for (unsigned int i = 0; i < gos->transfers_length; ++i) { - const struct TALER_WireTransferIdentifierRawP *wtid; + const struct TALER_TESTING_Command *transfer_cmd; - if (GNUNET_OK != - TALER_TESTING_get_trait_wtid (transfer_cmd, - 0, - &wtid)) + transfer_cmd = TALER_TESTING_interpreter_lookup_command ( + gos->is, + gos->transfers[i]); { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not fetch wire transfer id\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; + const struct TALER_WireTransferIdentifierRawP *wtid; + + if (GNUNET_OK != + TALER_TESTING_get_trait_wtid (transfer_cmd, + 0, + &wtid)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not fetch wire transfer id\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + if (0 != GNUNET_memcmp (wtid, + &osr->details.paid.wts[i].wtid)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire transfer id does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } } - if (0 != GNUNET_memcmp (wtid, - &osr->details.paid.wts[i].wtid)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Wire transfer id does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - } - { - const char *exchange_url; + const char *exchange_url; - if (GNUNET_OK != - TALER_TESTING_get_trait_string (transfer_cmd, - 1, - &exchange_url)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not fetch wire transfer exchange url\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; + if (GNUNET_OK != + TALER_TESTING_get_trait_string (transfer_cmd, + 1, + &exchange_url)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not fetch wire transfer exchange url\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + if (0 != strcmp (exchange_url, + osr->details.paid.wts[i].exchange_url)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire transfer exchange url does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } } - if (0 != strcmp (exchange_url, - osr->details.paid.wts[i].exchange_url)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Wire transfer exchange url does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; + struct TALER_Amount transfer_total; + const struct TALER_Amount *transfer_amount; + const struct TALER_Amount *transfer_fee; + + if ((GNUNET_OK != + TALER_TESTING_get_trait_amount_obj (transfer_cmd, + 0, + &transfer_amount)) || + (GNUNET_OK != + TALER_TESTING_get_trait_amount_obj (transfer_cmd, + 1, + &transfer_fee))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not fetch wire transfer amount/fee\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + if (0 > TALER_amount_add (&transfer_total, + transfer_amount, + transfer_fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not total wire transfer\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + if ((GNUNET_OK != TALER_amount_cmp_currency (&transfer_total, + &osr->details.paid.wts[ + i] + .total_amount)) || + (0 != TALER_amount_cmp (&transfer_total, + &osr->details.paid.wts[i].total_amount))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire transfer total does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } } } + if (gos->refunded != osr->details.paid.refunded) { - struct TALER_Amount transfer_total; - const struct TALER_Amount *transfer_amount; - const struct TALER_Amount *transfer_fee; - - if ((GNUNET_OK != - TALER_TESTING_get_trait_amount_obj (transfer_cmd, - 0, - &transfer_amount)) || - (GNUNET_OK != - TALER_TESTING_get_trait_amount_obj (transfer_cmd, - 1, - &transfer_fee))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not fetch wire transfer amount/fee\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - if (0 > TALER_amount_add (&transfer_total, - transfer_amount, - transfer_fee)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not total wire transfer\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - if ((GNUNET_OK != TALER_amount_cmp_currency (&transfer_total, - &osr->details.paid.wts[i] - .total_amount)) || - (0 != TALER_amount_cmp (&transfer_total, - &osr->details.paid.wts[i].total_amount))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Wire transfer total does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Order refunded does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; } - } - if (gos->refunded != osr->details.paid.refunded) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Order refunded does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - if (gos->refunds_length != osr->details.paid.refunds_len) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Number of refunds found does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - if (0 < gos->refunds_length) - GNUNET_assert (GNUNET_OK == - TALER_amount_get_zero (osr->details.paid.refund_amount.currency, - &refunded_total)); - for (unsigned int i = 0; i < gos->refunds_length; ++i) - { - const struct TALER_TESTING_Command *refund_cmd; - - refund_cmd = TALER_TESTING_interpreter_lookup_command ( - gos->is, - gos->refunds[i]); + if (gos->refunds_length != osr->details.paid.refunds_len) { - const char *expected_amount_str; - struct TALER_Amount expected_amount; - struct TALER_Amount *amount_found = - &osr->details.paid.refunds[i].refund_amount; - - if (GNUNET_OK != - TALER_TESTING_get_trait_string (refund_cmd, - 0, - &expected_amount_str)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not fetch refund amount\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (expected_amount_str, - &expected_amount)); - GNUNET_assert (0 <= TALER_amount_add (&refunded_total, - &refunded_total, - amount_found)); - if ((GNUNET_OK != - TALER_amount_cmp_currency (&expected_amount, - &refunded_total)) || - (0 != TALER_amount_cmp (&expected_amount, - &refunded_total))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Refund amounts do not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Number of refunds found does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; } + if (0 < gos->refunds_length) + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero ( + osr->details.paid.refund_amount.currency, + &refunded_total)); + for (unsigned int i = 0; i < gos->refunds_length; ++i) { - const char *expected_reason; + const struct TALER_TESTING_Command *refund_cmd; - if (GNUNET_OK != - TALER_TESTING_get_trait_string (refund_cmd, - 1, - &expected_reason)) + refund_cmd = TALER_TESTING_interpreter_lookup_command ( + gos->is, + gos->refunds[i]); { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not fetch reason\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; + const char *expected_amount_str; + struct TALER_Amount expected_amount; + struct TALER_Amount *amount_found = + &osr->details.paid.refunds[i].refund_amount; + + if (GNUNET_OK != + TALER_TESTING_get_trait_string (refund_cmd, + 0, + &expected_amount_str)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not fetch refund amount\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (expected_amount_str, + &expected_amount)); + GNUNET_assert (0 <= TALER_amount_add (&refunded_total, + &refunded_total, + amount_found)); + if ((GNUNET_OK != + TALER_amount_cmp_currency (&expected_amount, + &refunded_total)) || + (0 != TALER_amount_cmp (&expected_amount, + &refunded_total))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Refund amounts do not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } } - if (0 != strcmp (expected_reason, - osr->details.paid.refunds[i].reason)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Refund reason does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; + const char *expected_reason; + + if (GNUNET_OK != + TALER_TESTING_get_trait_string (refund_cmd, + 1, + &expected_reason)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not fetch reason\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + if (0 != strcmp (expected_reason, + osr->details.paid.refunds[i].reason)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Refund reason does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } } } - } - if (gos->wired != osr->details.paid.wired) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Order wired does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; + if (gos->wired != osr->details.paid.wired) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Order wired does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } } - } - else - { - /* FIXME: Check all of the members of `pud` */ - struct TALER_MERCHANT_PayUriData pud; - const struct TALER_TESTING_Command *order_cmd; - const char *order_id; - const struct TALER_ClaimTokenP *claim_token; - - if (GNUNET_OK != - TALER_MERCHANT_parse_pay_uri (osr->details.unpaid.taler_pay_uri, - &pud)) + break; + case TALER_MERCHANT_OSC_CLAIMED: + /* FIXME: Check contract terms... */ + break; + case TALER_MERCHANT_OSC_UNPAID: { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Taler pay uri is malformed\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } + /* FIXME: Check all of the members of `pud` */ + struct TALER_MERCHANT_PayUriData pud; + const struct TALER_TESTING_Command *order_cmd; + const char *order_id; + const struct TALER_ClaimTokenP *claim_token; - order_cmd = TALER_TESTING_interpreter_lookup_command ( - gos->is, - gos->order_reference); - - if (GNUNET_OK != - TALER_TESTING_get_trait_order_id (order_cmd, - 0, - &order_id)) - TALER_TESTING_FAIL (gos->is); - - if (GNUNET_OK != - TALER_TESTING_get_trait_claim_token (order_cmd, - 0, - &claim_token)) - TALER_TESTING_FAIL (gos->is); - - if ((0 != strcmp ("localhost:8080", - pud.merchant_host)) || - (NULL != pud.merchant_prefix_path) || - (0 != strcmp (order_id, - pud.order_id)) || - (NULL != pud.ssid)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Order pay uri does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - TALER_MERCHANT_parse_pay_uri_free (&pud); - return; - } - /* The claim token is not given in the pay uri if the order - has been claimed already. */ - if ((NULL != pud.claim_token) && - ((NULL == claim_token) || - (0 != GNUNET_memcmp (claim_token, - pud.claim_token)))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Order pay uri does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - TALER_MERCHANT_parse_pay_uri_free (&pud); - return; + if (GNUNET_OK != + TALER_MERCHANT_parse_pay_uri (osr->details.unpaid.taler_pay_uri, + &pud)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Taler pay uri is malformed\n"); + TALER_TESTING_interpreter_fail (gos->is); + return; + } + + order_cmd = TALER_TESTING_interpreter_lookup_command ( + gos->is, + gos->order_reference); + + if (GNUNET_OK != + TALER_TESTING_get_trait_order_id (order_cmd, + 0, + &order_id)) + TALER_TESTING_FAIL (gos->is); + + if (GNUNET_OK != + TALER_TESTING_get_trait_claim_token (order_cmd, + 0, + &claim_token)) + TALER_TESTING_FAIL (gos->is); + + if ((0 != strcmp ("localhost:8080", + pud.merchant_host)) || + (NULL != pud.merchant_prefix_path) || + (0 != strcmp (order_id, + pud.order_id)) || + (NULL != pud.ssid)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Order pay uri does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + TALER_MERCHANT_parse_pay_uri_free (&pud); + return; + } + /* The claim token is not given in the pay uri if the order + has been claimed already. */ + if ((NULL != pud.claim_token) && + ((NULL == claim_token) || + (0 != GNUNET_memcmp (claim_token, + pud.claim_token)))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Order pay uri does not match\n"); + TALER_TESTING_interpreter_fail (gos->is); + TALER_MERCHANT_parse_pay_uri_free (&pud); + return; + } } + break; } - break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unhandled HTTP status.\n"); @@ -602,7 +611,7 @@ merchant_get_order_cleanup (void *cls, * @param merchant_url base URL of the merchant which will * serve the request. * @param order_reference reference to a command that created an order. - * @param paid whether the order has been paid for or not. + * @param osc expected order status code * @param refunded whether the order has been refunded. * @param http_status expected HTTP response code for the request. * @param ... NULL-terminated list of labels (const char *) of @@ -614,7 +623,7 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_get_order (const char *label, const char *merchant_url, const char *order_reference, - bool paid, + enum TALER_MERCHANT_OrderStatusCode osc, bool refunded, unsigned int http_status, ...) @@ -624,7 +633,7 @@ TALER_TESTING_cmd_merchant_get_order (const char *label, gos = GNUNET_new (struct MerchantGetOrderState); gos->merchant_url = merchant_url; gos->order_reference = order_reference; - gos->paid = paid; + gos->osc = osc; gos->refunded = refunded; gos->http_status = http_status; if (refunded) @@ -661,7 +670,7 @@ TALER_TESTING_cmd_merchant_get_order (const char *label, * @param merchant_url base URL of the merchant which will * serve the request. * @param order_reference reference to a command that created an order. - * @param paid whether the order has been paid for or not. + * @param osc expected order status * @param wired whether the order has been wired or not. * @param transfers NULL-terminated list of labels (const char *) of * wire transfers (commands) we expect to be aggregated in the order @@ -681,7 +690,7 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_merchant_get_order2 (const char *label, const char *merchant_url, const char *order_reference, - bool paid, + enum TALER_MERCHANT_OrderStatusCode osc, bool wired, const char **transfers, bool refunded, @@ -694,7 +703,7 @@ TALER_TESTING_cmd_merchant_get_order2 (const char *label, gos = GNUNET_new (struct MerchantGetOrderState); gos->merchant_url = merchant_url; gos->order_reference = order_reference; - gos->paid = paid; + gos->osc = osc; gos->wired = wired; gos->refunded = refunded; gos->http_status = http_status;