diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/include/taler_merchant_service.h | 364 | ||||
-rw-r--r-- | src/lib/merchant_api_merchant_get_order.c | 220 | ||||
-rw-r--r-- | src/lib/merchant_api_wallet_get_order.c | 95 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_get_reserve.c | 3 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_merchant_get_order.c | 87 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_merchant_get_tip.c | 3 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_pay_order.c | 3 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_wallet_get_order.c | 95 |
9 files changed, 423 insertions, 448 deletions
diff --git a/configure.ac b/configure.ac index 2e78d496..79130ef5 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,6 @@ AS_IF([test "x$doc_only" != xyes],[ # Checks for programs. AC_PROG_CC -AC_PROG_CC_C99 CFLAGS="-Wall -Wno-address-of-packed-member $CFLAGS" diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 815a885b..20a0ee8e 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -1595,35 +1595,78 @@ struct TALER_MERCHANT_OrderWalletGetHandle; /** + * Response to a GET /orders/$ID request. + */ +struct TALER_MERCHANT_OrderWalletGetResponse +{ + /** + * Full HTTP response details. + */ + struct TALER_MERCHANT_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Response details if the response code is #MHD_HTTP_OK. + */ + struct + { + + /** + * True if there is at least on refund on this payment. + */ + bool refunded; + + /** + * True if there are refunds waiting to be + * obtained. + */ + bool refund_pending; + + /** + * Amount that was refunded, only set if + * @e refunded is #GNUNET_YES. + */ + struct TALER_Amount refund_amount; + + } success; + + /** + * Response if a payment is required from the client. + */ + struct + { + + /** + * The URI that instructs the wallet to process + * the payment. + */ + const char *taler_pay_uri; + + /** + * Equivalent order that this customer paid already, or NULL for none. + */ + const char *already_paid_order_id; + + } payment_required; + + } details; +}; + + +/** * Callback to process a GET /orders/$ID response * * @param cls closure * @param hr HTTP response details - * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not - * settled, #GNUNET_SYSERR on error - * (note that refunded payments are returned as paid!) - * @param refunded #GNUNET_YES if there is at least on refund on this payment, - * #GNUNET_NO if refunded, #GNUNET_SYSERR or error - * @param refund_pending #GNUNET_YES if there are refunds waiting to be - * obtained, #GNUNET_NO if all refunds have been obtained, #GNUNET_SYSERR - * on error. - * @param refund_amount amount that was refunded, NULL if there - * was no refund - * @param taler_pay_uri the URI that instructs the wallets to process - * the payment - * @param already_paid_order_id equivalent order that this customer - * paid already, or NULL for none */ typedef void (*TALER_MERCHANT_OrderWalletGetCallback) ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - enum GNUNET_GenericReturnValue paid, - enum GNUNET_GenericReturnValue refunded, - enum GNUNET_GenericReturnValue refund_pending, - struct TALER_Amount *refund_amount, - const char *taler_pay_uri, - const char *already_paid_order_id); + const struct TALER_MERCHANT_OrderWalletGetResponse *owgs); /** @@ -1798,151 +1841,170 @@ enum TALER_MERCHANT_OrderStatusCode */ struct TALER_MERCHANT_OrderStatusResponse { - /** - * Status of the order. + * HTTP response details. */ - enum TALER_MERCHANT_OrderStatusCode status; + struct TALER_MERCHANT_HttpResponse hr; /** - * Details depending on the payment status given in @e status. + * Details provided depending on the HTTP status code. */ union { - - /** - * Details provided if @e status is #TALER_MERCHANT_OSC_PAID. - */ - struct - { - /** - * Amount that was refunded. - */ - struct TALER_Amount refund_amount; - - /** - * Amount that was deposited into our bank account, - * excluding fees. - */ - struct TALER_Amount deposit_total; - - /** - * The full contract terms of the order. - */ - const json_t *contract_terms; - - /** - * Array of wire transfers made for this payment to the - * merchant by the exchange. Of length @e wts_len. - */ - struct TALER_MERCHANT_WireTransfer *wts; - - /** - * Length of the @e wts array. - */ - unsigned int wts_len; - - /** - * Array of wire reports about problems tracking wire transfers. - * Of length @e wrs_len. - */ - struct TALER_MERCHANT_WireReport *wrs; - - /** - * Length of the @e wrs array. - */ - unsigned int wrs_len; - - /** - * Details returned by the merchant backend about refunds. - * Of length @e refunds_len. - */ - struct TALER_MERCHANT_RefundOrderDetail *refunds; - - /** - * Length of the @e refunds array. - */ - unsigned int refunds_len; - - /** - * Error code encountered trying to contact the exchange - * about the wire tracking, 0 for none. - */ - enum TALER_ErrorCode exchange_ec; - - /** - * HTTP status code encountered trying to contact the exchange - * about the wire tracking, 0 for no error. - */ - unsigned int exchange_hc; - - /** - * true if there is at least on refund on this payment, - * false if there are no refunds. - */ - bool refunded; - - /** - * true if refunds were approved that have not yet been obtained - * by the wallet. - */ - bool refund_pending; - - /** - * true if the exchange paid the merchant for this order, - * false if not. - */ - bool wired; - - } paid; - /** - * Details provided if @e status is #TALER_MERCHANT_OSC_CLAIMED. + * Details provided if the HTTP status is #MHD_OK. */ struct { /** - * The full contract terms of the claimed order (including client nonce from claiming). + * Status of the order. */ - const json_t *contract_terms; - - } claimed; - - /** - * Details provided if @e status is #TALER_MERCHANT_OSC_UNPAID. - */ - struct - { + enum TALER_MERCHANT_OrderStatusCode status; /** - * URI that should be shown to the wallet to trigger a payment. + * Details depending on the payment status given in @e status. */ - const char *taler_pay_uri; + union + { + + /** + * Details provided if @e status is #TALER_MERCHANT_OSC_PAID. + */ + struct + { + /** + * Amount that was refunded. + */ + struct TALER_Amount refund_amount; + + /** + * Amount that was deposited into our bank account, + * excluding fees. + */ + struct TALER_Amount deposit_total; + + /** + * The full contract terms of the order. + */ + const json_t *contract_terms; + + /** + * Array of wire transfers made for this payment to the + * merchant by the exchange. Of length @e wts_len. + */ + struct TALER_MERCHANT_WireTransfer *wts; + + /** + * Length of the @e wts array. + */ + unsigned int wts_len; + + /** + * Array of wire reports about problems tracking wire transfers. + * Of length @e wrs_len. + */ + struct TALER_MERCHANT_WireReport *wrs; + + /** + * Length of the @e wrs array. + */ + unsigned int wrs_len; + + /** + * Details returned by the merchant backend about refunds. + * Of length @e refunds_len. + */ + struct TALER_MERCHANT_RefundOrderDetail *refunds; + + /** + * Length of the @e refunds array. + */ + unsigned int refunds_len; + + /** + * Error code encountered trying to contact the exchange + * about the wire tracking, 0 for none. + */ + enum TALER_ErrorCode exchange_ec; + + /** + * HTTP status code encountered trying to contact the exchange + * about the wire tracking, 0 for no error. + */ + unsigned int exchange_hc; + + /** + * true if there is at least on refund on this payment, + * false if there are no refunds. + */ + bool refunded; + + /** + * true if refunds were approved that have not yet been obtained + * by the wallet. + */ + bool refund_pending; + + /** + * true if the exchange paid the merchant for this order, + * false if not. + */ + bool wired; + + } paid; + + /** + * 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 + { + + /** + * URI that should be shown to the wallet to trigger a payment. + */ + const char *taler_pay_uri; + + /** + * Alternative order ID which was paid for already in the same session. + * Only given if the same product was purchased before in the same session. + * Otherwise NULL. + */ + const char *already_paid_order_id; + + /** + * Order summary. + */ + const char *summary; + + /** + * Time when the order was created. + */ + struct GNUNET_TIME_Timestamp creation_time; + + /** + * Total amount the order is about (amount to be paid by customer). + */ + struct TALER_Amount contract_amount; + + } unpaid; + + } details; - /** - * Alternative order ID which was paid for already in the same session. - * Only given if the same product was purchased before in the same session. - * Otherwise NULL. - */ - const char *already_paid_order_id; - - /** - * Order summary. - */ - const char *summary; - - /** - * Time when the order was created. - */ - struct GNUNET_TIME_Timestamp creation_time; - - /** - * Total amount the order is about (amount to be paid by customer). - */ - struct TALER_Amount contract_amount; - - } unpaid; + } success; } details; }; @@ -1958,7 +2020,6 @@ struct TALER_MERCHANT_OrderStatusResponse typedef void (*TALER_MERCHANT_OrderMerchantGetCallback) ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, const struct TALER_MERCHANT_OrderStatusResponse *osr); @@ -3865,10 +3926,13 @@ struct TALER_MERCHANT_ExchangeKycFailureDetail */ struct TALER_MERCHANT_KycResponse { + /** + * HTTP response details. + */ struct TALER_MERCHANT_HttpResponse hr; /** - * Response details. + * Response details depending on the HTTP status. */ union { diff --git a/src/lib/merchant_api_merchant_get_order.c b/src/lib/merchant_api_merchant_get_order.c index 167e46be..f3181a3c 100644 --- a/src/lib/merchant_api_merchant_get_order.c +++ b/src/lib/merchant_api_merchant_get_order.c @@ -72,47 +72,48 @@ struct TALER_MERCHANT_OrderMerchantGetHandle * the response and call the callback. * * @param omgh handle for the request - * @param[in,out] hr HTTP response we got + * @param[in,out] osr HTTP response we got */ static void handle_unpaid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, - struct TALER_MERCHANT_HttpResponse *hr) + struct TALER_MERCHANT_OrderStatusResponse *osr) { - struct TALER_MERCHANT_OrderStatusResponse osr = { - .status = TALER_MERCHANT_OSC_UNPAID - }; struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount_any ("total_amount", - &osr.details.unpaid.contract_amount), + TALER_JSON_spec_amount_any ( + "total_amount", + &osr->details.success.details.unpaid.contract_amount), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("already_paid_order_id", - &osr.details.unpaid.already_paid_order_id), + GNUNET_JSON_spec_string ( + "already_paid_order_id", + &osr->details.success.details.unpaid.already_paid_order_id), NULL), - GNUNET_JSON_spec_string ("taler_pay_uri", - &osr.details.unpaid.taler_pay_uri), - GNUNET_JSON_spec_string ("summary", - &osr.details.unpaid.summary), - GNUNET_JSON_spec_timestamp ("creation_time", - &osr.details.unpaid.creation_time), + GNUNET_JSON_spec_string ( + "taler_pay_uri", + &osr->details.success.details.unpaid.taler_pay_uri), + GNUNET_JSON_spec_string ( + "summary", + &osr->details.success.details.unpaid.summary), + GNUNET_JSON_spec_timestamp ( + "creation_time", + &osr->details.success.details.unpaid.creation_time), GNUNET_JSON_spec_end () }; if (GNUNET_OK != - GNUNET_JSON_parse (hr->reply, + GNUNET_JSON_parse (osr->hr.reply, spec, NULL, NULL)) { GNUNET_break_op (0); - hr->http_status = 0; - hr->ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr->hr.http_status = 0; + osr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - hr, - NULL); + osr); return; } + osr->details.success.status = TALER_MERCHANT_OSC_UNPAID; omgh->cb (omgh->cb_cls, - hr, - &osr); + osr); } @@ -122,37 +123,34 @@ handle_unpaid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, * paid. Parse the response and call the callback. * * @param omgh handle for the request - * @param[in,out] hr HTTP response we got + * @param[in,out] osr HTTP response we got */ static void handle_claimed (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, - struct TALER_MERCHANT_HttpResponse *hr) + struct TALER_MERCHANT_OrderStatusResponse *osr) { - 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), + (json_t **) &osr->details.success.details.claimed. + contract_terms), GNUNET_JSON_spec_end () }; if (GNUNET_OK != - GNUNET_JSON_parse (hr->reply, + GNUNET_JSON_parse (osr->hr.reply, spec, NULL, NULL)) { GNUNET_break_op (0); - hr->http_status = 0; - hr->ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr->hr.http_status = 0; + osr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - hr, - NULL); + osr); return; } + osr->details.success.status = TALER_MERCHANT_OSC_CLAIMED; omgh->cb (omgh->cb_cls, - hr, - &osr); + osr); GNUNET_JSON_parse_free (spec); } @@ -163,37 +161,35 @@ handle_claimed (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, * the response and call the callback. * * @param omgh handle for the request - * @param[in,out] hr HTTP response we got + * @param[in,out] osr HTTP response we got */ static void handle_paid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, - struct TALER_MERCHANT_HttpResponse *hr) + struct TALER_MERCHANT_OrderStatusResponse *osr) { uint32_t ec32; uint32_t hc32; json_t *wire_details; json_t *wire_reports; json_t *refund_details; - struct TALER_MERCHANT_OrderStatusResponse osr = { - .status = TALER_MERCHANT_OSC_PAID - }; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_bool ("refunded", - &osr.details.paid.refunded), + &osr->details.success.details.paid.refunded), GNUNET_JSON_spec_bool ("refund_pending", - &osr.details.paid.refund_pending), + &osr->details.success.details.paid.refund_pending), GNUNET_JSON_spec_bool ("wired", - &osr.details.paid.wired), + &osr->details.success.details.paid.wired), TALER_JSON_spec_amount_any ("deposit_total", - &osr.details.paid.deposit_total), + &osr->details.success.details.paid.deposit_total), GNUNET_JSON_spec_uint32 ("exchange_code", &ec32), GNUNET_JSON_spec_uint32 ("exchange_http_status", &hc32), TALER_JSON_spec_amount_any ("refund_amount", - &osr.details.paid.refund_amount), - GNUNET_JSON_spec_json ("contract_terms", - (json_t **) &osr.details.paid.contract_terms), + &osr->details.success.details.paid.refund_amount), + GNUNET_JSON_spec_json ( + "contract_terms", + (json_t **) &osr->details.success.details.paid.contract_terms), GNUNET_JSON_spec_json ("wire_details", &wire_details), GNUNET_JSON_spec_json ("wire_reports", @@ -204,34 +200,33 @@ handle_paid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, }; if (GNUNET_OK != - GNUNET_JSON_parse (hr->reply, + GNUNET_JSON_parse (osr->hr.reply, spec, NULL, NULL)) { GNUNET_break_op (0); - hr->http_status = 0; - hr->ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr->hr.http_status = 0; + osr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - hr, - NULL); + osr); return; } if (! (json_is_array (wire_details) && json_is_array (wire_reports) && json_is_array (refund_details) && - json_is_object (osr.details.paid.contract_terms)) ) + json_is_object (osr->details.success.details.paid.contract_terms)) ) { GNUNET_break_op (0); - hr->http_status = 0; - hr->ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr->hr.http_status = 0; + osr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - hr, - NULL); + osr); GNUNET_JSON_parse_free (spec); return; } - osr.details.paid.exchange_ec = (enum TALER_ErrorCode) ec32; - osr.details.paid.exchange_hc = (unsigned int) hc32; + osr->details.success.status = TALER_MERCHANT_OSC_PAID; + osr->details.success.details.paid.exchange_ec = (enum TALER_ErrorCode) ec32; + osr->details.success.details.paid.exchange_hc = (unsigned int) hc32; { unsigned int wts_len = json_array_size (wire_details); unsigned int wrs_len = json_array_size (wire_reports); @@ -265,11 +260,10 @@ handle_paid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, NULL, NULL)) { GNUNET_break_op (0); - hr->http_status = 0; - hr->ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr->hr.http_status = 0; + osr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - hr, - NULL); + osr); GNUNET_JSON_parse_free (spec); return; } @@ -302,11 +296,10 @@ handle_paid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, NULL, NULL)) { GNUNET_break_op (0); - hr->http_status = 0; - hr->ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr->hr.http_status = 0; + osr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - hr, - NULL); + osr); GNUNET_JSON_parse_free (spec); return; } @@ -336,25 +329,23 @@ handle_paid (struct TALER_MERCHANT_OrderMerchantGetHandle *omgh, NULL, NULL)) { GNUNET_break_op (0); - hr->http_status = 0; - hr->ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr->hr.http_status = 0; + osr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - hr, - NULL); + osr); GNUNET_JSON_parse_free (spec); return; } } - osr.details.paid.wts = wts; - osr.details.paid.wts_len = wts_len; - osr.details.paid.wrs = wrs; - osr.details.paid.wrs_len = wrs_len; - osr.details.paid.refunds = ref; - osr.details.paid.refunds_len = ref_len; + osr->details.success.details.paid.wts = wts; + osr->details.success.details.paid.wts_len = wts_len; + osr->details.success.details.paid.wrs = wrs; + osr->details.success.details.paid.wrs_len = wrs_len; + osr->details.success.details.paid.refunds = ref; + osr->details.success.details.paid.refunds_len = ref_len; omgh->cb (omgh->cb_cls, - hr, - &osr); + osr); } GNUNET_JSON_parse_free (spec); } @@ -376,9 +367,9 @@ handle_merchant_order_get_finished (void *cls, struct TALER_MERCHANT_OrderMerchantGetHandle *omgh = cls; const json_t *json = response; const char *order_status; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_OrderStatusResponse osr = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json }; omgh->job = NULL; @@ -388,78 +379,79 @@ handle_merchant_order_get_finished (void *cls, /* see below */ break; case MHD_HTTP_UNAUTHORIZED: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, merchant says we need to authenticate. */ - break; + osr.hr.ec = TALER_JSON_get_error_code (json); + osr.hr.hint = TALER_JSON_get_error_hint (json); + omgh->cb (omgh->cb_cls, + &osr); + TALER_MERCHANT_merchant_order_get_cancel (omgh); + return; case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + osr.hr.ec = TALER_JSON_get_error_code (json); + osr.hr.hint = TALER_JSON_get_error_hint (json); omgh->cb (omgh->cb_cls, - &hr, - NULL); + &osr); TALER_MERCHANT_merchant_order_get_cancel (omgh); return; case MHD_HTTP_GATEWAY_TIMEOUT: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + osr.hr.ec = TALER_JSON_get_error_code (json); + osr.hr.hint = TALER_JSON_get_error_hint (json); omgh->cb (omgh->cb_cls, - &hr, - NULL); + &osr); TALER_MERCHANT_merchant_order_get_cancel (omgh); return; default: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + osr.hr.ec = TALER_JSON_get_error_code (json); + osr.hr.hint = TALER_JSON_get_error_hint (json); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Polling payment failed with HTTP status code %u/%d\n", (unsigned int) response_code, - (int) hr.ec); + (int) osr.hr.ec); GNUNET_break_op (0); omgh->cb (omgh->cb_cls, - &hr, - NULL); + &osr); TALER_MERCHANT_merchant_order_get_cancel (omgh); return; } - order_status = json_string_value (json_object_get (json, "order_status")); + order_status = json_string_value (json_object_get (json, + "order_status")); if (NULL == order_status) { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr.hr.http_status = 0; + osr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - &hr, - NULL); + &osr); TALER_MERCHANT_merchant_order_get_cancel (omgh); return; } - if (0 == strcmp ("paid", order_status)) + if (0 == strcmp ("paid", + order_status)) { handle_paid (omgh, - &hr); + &osr); } - else if (0 == strcmp ("claimed", order_status)) + else if (0 == strcmp ("claimed", + order_status)) { handle_claimed (omgh, - &hr); + &osr); } - else if (0 == strcmp ("unpaid", order_status)) + else if (0 == strcmp ("unpaid", + order_status)) { handle_unpaid (omgh, - &hr); + &osr); } else { GNUNET_break_op (0); - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + osr.hr.http_status = 0; + osr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; omgh->cb (omgh->cb_cls, - &hr, - NULL); + &osr); } TALER_MERCHANT_merchant_order_get_cancel (omgh); } diff --git a/src/lib/merchant_api_wallet_get_order.c b/src/lib/merchant_api_wallet_get_order.c index 4037ea57..9c24204a 100644 --- a/src/lib/merchant_api_wallet_get_order.c +++ b/src/lib/merchant_api_wallet_get_order.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2018, 2020 Taler Systems SA + Copyright (C) 2018, 2020, 2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -79,19 +79,13 @@ cb_failure (struct TALER_MERCHANT_OrderWalletGetHandle *owgh, enum TALER_ErrorCode ec, const json_t *reply) { - struct TALER_MERCHANT_HttpResponse hr = { - .ec = ec, - .reply = reply + struct TALER_MERCHANT_OrderWalletGetResponse owgr = { + .hr.ec = ec, + .hr.reply = reply }; owgh->cb (owgh->cb_cls, - &hr, - GNUNET_SYSERR, - GNUNET_SYSERR, - GNUNET_SYSERR, - NULL, - NULL, - NULL); + &owgr); } @@ -115,22 +109,19 @@ handle_wallet_get_order_finished (void *cls, { case MHD_HTTP_OK: { - struct TALER_Amount refund_amount; - bool refunded; - bool refund_pending; + struct TALER_MERCHANT_OrderWalletGetResponse owgr = { + .hr.reply = json, + .hr.http_status = MHD_HTTP_OK + }; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_bool ("refunded", - &refunded), + &owgr.details.success.refunded), GNUNET_JSON_spec_bool ("refund_pending", - &refund_pending), + &owgr.details.success.refund_pending), TALER_JSON_spec_amount_any ("refund_amount", - &refund_amount), + &owgr.details.success.refund_amount), GNUNET_JSON_spec_end () }; - struct TALER_MERCHANT_HttpResponse hr = { - .reply = json, - .http_status = MHD_HTTP_OK - }; if (GNUNET_OK != GNUNET_JSON_parse (json, @@ -144,70 +135,54 @@ handle_wallet_get_order_finished (void *cls, TALER_MERCHANT_wallet_order_get_cancel (owgh); return; } - owgh->cb (owgh->cb_cls, - &hr, - GNUNET_YES, - refunded ? GNUNET_YES : GNUNET_NO, - refund_pending ? GNUNET_YES : GNUNET_NO, - refunded ? &refund_amount : NULL, - NULL, /* paid! */ - NULL);/* paid! */ + &owgr); GNUNET_JSON_parse_free (spec); break; } case MHD_HTTP_PAYMENT_REQUIRED: { + struct TALER_MERCHANT_OrderWalletGetResponse owgr = { + .hr.reply = json, + .hr.http_status = MHD_HTTP_PAYMENT_REQUIRED + }; + /* Status is: unpaid */ - const char *taler_pay_uri = json_string_value (json_object_get (json, - "taler_pay_uri")); - const char *already_paid = json_string_value (json_object_get (json, - "already_paid_order_id")); - if (NULL == taler_pay_uri) + owgr.details.payment_required.taler_pay_uri + = json_string_value (json_object_get (json, + "taler_pay_uri")); + owgr.details.payment_required.already_paid_order_id + = json_string_value (json_object_get (json, + "already_paid_order_id")); + if (NULL == owgr.details.payment_required.taler_pay_uri) { GNUNET_break_op (0); cb_failure (owgh, TALER_EC_GENERIC_REPLY_MALFORMED, json); + break; } - else - { - struct TALER_MERCHANT_HttpResponse hr = { - .reply = json, - .http_status = MHD_HTTP_OK - }; - - owgh->cb (owgh->cb_cls, - &hr, - GNUNET_NO, - GNUNET_NO, - GNUNET_NO, - NULL, - taler_pay_uri, - already_paid); - } + owgh->cb (owgh->cb_cls, + &owgr); break; } default: { - struct TALER_MERCHANT_HttpResponse hr; + struct TALER_MERCHANT_OrderWalletGetResponse owgr = { + .hr.reply = json, + .hr.http_status = response_code + }; TALER_MERCHANT_parse_error_details_ (response, response_code, - &hr); + &owgr.hr); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Checking order status failed with HTTP status code %u/%d\n", (unsigned int) response_code, - (int) hr.ec); + (int) owgr.hr.ec); GNUNET_break_op (0); owgh->cb (owgh->cb_cls, - &hr, - GNUNET_SYSERR, - GNUNET_SYSERR, - GNUNET_SYSERR, - NULL, - NULL, - NULL); + &owgr); break; } } diff --git a/src/testing/testing_api_cmd_get_reserve.c b/src/testing/testing_api_cmd_get_reserve.c index 03b6a071..ef7f67e0 100644 --- a/src/testing/testing_api_cmd_get_reserve.c +++ b/src/testing/testing_api_cmd_get_reserve.c @@ -83,7 +83,6 @@ get_reserve_cb (void *cls, unsigned int tips_length, const struct TALER_MERCHANT_TipDetails tips[]) { - /* FIXME, deeper checks should be implemented here. */ struct GetReserveState *grs = cls; const struct TALER_TESTING_Command *reserve_cmd; @@ -105,8 +104,6 @@ get_reserve_cb (void *cls, switch (hr->http_status) { case MHD_HTTP_OK: - // FIXME: use grs->reserve_reference here to - // check if the data returned matches that from the POST / PATCH { const struct TALER_Amount *initial_amount; if (GNUNET_OK != diff --git a/src/testing/testing_api_cmd_merchant_get_order.c b/src/testing/testing_api_cmd_merchant_get_order.c index 85ba174f..8001ac43 100644 --- a/src/testing/testing_api_cmd_merchant_get_order.c +++ b/src/testing/testing_api_cmd_merchant_get_order.c @@ -130,45 +130,40 @@ apply_forget (void *cls, * Callback to process a GET /orders/$ID request * * @param cls closure - * @param hr HTTP response details - * @param osr order status response details (on success) + * @param osr order status response details */ static void merchant_get_order_cb ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, const struct TALER_MERCHANT_OrderStatusResponse *osr) { - /* FIXME, deeper checks should be implemented here. */ struct MerchantGetOrderState *gos = cls; gos->ogh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "GET /private/orders/$ID completed with status %u\n", - hr->http_status); - if (gos->http_status != hr->http_status) + osr->hr.http_status); + if (gos->http_status != osr->hr.http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u (%d) to command %s\n", - hr->http_status, - (int) hr->ec, + osr->hr.http_status, + (int) osr->hr.ec, TALER_TESTING_interpreter_get_current_label (gos->is)); TALER_TESTING_interpreter_fail (gos->is); return; } - switch (hr->http_status) + switch (osr->hr.http_status) { case MHD_HTTP_OK: - // FIXME: use gts->tip_reference here to - // check if the data returned matches that from the POST / PATCH - if (gos->osc != osr->status) + if (gos->osc != osr->details.success.status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order paid does not match\n"); TALER_TESTING_interpreter_fail (gos->is); return; } - switch (osr->status) + switch (osr->details.success.status) { case TALER_MERCHANT_OSC_PAID: { @@ -241,7 +236,7 @@ merchant_get_order_cb ( } if (1 != json_equal (ct, - osr->details.paid.contract_terms)) + osr->details.success.details.paid.contract_terms)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order contract terms do not match\n"); @@ -251,14 +246,14 @@ merchant_get_order_cb ( json_decref (ct); } - if (gos->wired != osr->details.paid.wired) + if (gos->wired != osr->details.success.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) + if (gos->transfers_length != osr->details.success.details.paid.wts_len) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Number of transfers found does not match\n"); @@ -285,7 +280,8 @@ merchant_get_order_cb ( return; } if (0 != GNUNET_memcmp (wtid, - &osr->details.paid.wts[i].wtid)) + &osr->details.success.details.paid.wts[i]. + wtid)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire transfer id does not match\n"); @@ -306,7 +302,8 @@ merchant_get_order_cb ( return; } if (0 != strcmp (*exchange_url, - osr->details.paid.wts[i].exchange_url)) + osr->details.success.details.paid.wts[i]. + exchange_url)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire transfer exchange url does not match\n"); @@ -340,12 +337,13 @@ merchant_get_order_cb ( 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))) + if ((GNUNET_OK != + TALER_amount_cmp_currency ( + &transfer_total, + &osr->details.success.details.paid.wts[i].total_amount)) || + (0 != TALER_amount_cmp ( + &transfer_total, + &osr->details.success.details.paid.wts[i].total_amount))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wire transfer total does not match\n"); @@ -354,14 +352,15 @@ merchant_get_order_cb ( } } } - if (gos->refunded != osr->details.paid.refunded) + if (gos->refunded != osr->details.success.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) + if (gos->refunds_length != + osr->details.success.details.paid.refunds_len) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Number of refunds found does not match\n"); @@ -369,10 +368,11 @@ merchant_get_order_cb ( return; } if (0 < gos->refunds_length) - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero ( - osr->details.paid.refund_amount.currency, - &refunded_total)); + GNUNET_assert ( + GNUNET_OK == + TALER_amount_set_zero ( + osr->details.success.details.paid.refund_amount.currency, + &refunded_total)); for (unsigned int i = 0; i < gos->refunds_length; ++i) { const struct TALER_TESTING_Command *refund_cmd; @@ -383,7 +383,7 @@ merchant_get_order_cb ( { const struct TALER_Amount *expected_amount; struct TALER_Amount *amount_found = - &osr->details.paid.refunds[i].refund_amount; + &osr->details.success.details.paid.refunds[i].refund_amount; if (GNUNET_OK != TALER_TESTING_get_trait_amount (refund_cmd, @@ -421,8 +421,9 @@ merchant_get_order_cb ( TALER_TESTING_interpreter_fail (gos->is); return; } - if (0 != strcmp (*expected_reason, - osr->details.paid.refunds[i].reason)) + if (0 != strcmp ( + *expected_reason, + osr->details.success.details.paid.refunds[i].reason)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Refund reason does not match\n"); @@ -432,7 +433,7 @@ merchant_get_order_cb ( } } - if (gos->wired != osr->details.paid.wired) + if (gos->wired != osr->details.success.details.paid.wired) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order wired does not match\n"); @@ -446,19 +447,19 @@ merchant_get_order_cb ( break; case TALER_MERCHANT_OSC_UNPAID: { - /* 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)) + TALER_MERCHANT_parse_pay_uri ( + osr->details.success.details.unpaid.taler_pay_uri, + &pud)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Taler pay uri `%s' is malformed\n", - osr->details.unpaid.taler_pay_uri); + osr->details.success.details.unpaid.taler_pay_uri); TALER_TESTING_interpreter_fail (gos->is); return; } @@ -511,7 +512,7 @@ merchant_get_order_cb ( { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order pay uri `%s' does not match, wanted %s/%s\n", - osr->details.unpaid.taler_pay_uri, + osr->details.success.details.unpaid.taler_pay_uri, host, *order_id); TALER_TESTING_interpreter_fail (gos->is); @@ -541,8 +542,8 @@ merchant_get_order_cb ( return; } TALER_MERCHANT_parse_pay_uri_free (&pud); + break; } - break; } break; default: @@ -860,17 +861,15 @@ conclude_task (void *cls) * Callback to process a GET /private/orders/$ID request * * @param cls closure - * @param hr HTTP response details - * @param osr order status response details (on success) + * @param osr order status response details */ static void merchant_poll_order_cb ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, const struct TALER_MERCHANT_OrderStatusResponse *osr) { - /* FIXME, deeper checks should be implemented here. */ struct MerchantPollOrderStartState *pos = cls; + const struct TALER_MERCHANT_HttpResponse *hr = &osr->hr; pos->ogh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/testing/testing_api_cmd_merchant_get_tip.c b/src/testing/testing_api_cmd_merchant_get_tip.c index a4841da1..1ea5229d 100644 --- a/src/testing/testing_api_cmd_merchant_get_tip.c +++ b/src/testing/testing_api_cmd_merchant_get_tip.c @@ -99,7 +99,6 @@ merchant_get_tip_cb (void *cls, unsigned int pickups_length, const struct TALER_MERCHANT_PickupDetail pickups[]) { - /* FIXME, deeper checks should be implemented here. */ struct MerchantTipGetState *gts = cls; const struct TALER_TESTING_Command *authorize_cmd; struct TALER_Amount expected_total_picked_up; @@ -124,8 +123,6 @@ merchant_get_tip_cb (void *cls, switch (hr->http_status) { case MHD_HTTP_OK: - // FIXME: use gts->tip_reference here to - // check if the data returned matches that from the POST / PATCH { const struct TALER_Amount *initial_amount; diff --git a/src/testing/testing_api_cmd_pay_order.c b/src/testing/testing_api_cmd_pay_order.c index 61a43b9e..cd589965 100644 --- a/src/testing/testing_api_cmd_pay_order.c +++ b/src/testing/testing_api_cmd_pay_order.c @@ -306,8 +306,7 @@ pay_run (void *cls, &total_amount), TALER_JSON_spec_amount_any ("max_fee", &max_fee), - /* FIXME oec - * add minimum age */ + /* FIXME oec: parse minimum age, use data later? */ GNUNET_JSON_spec_end () }; diff --git a/src/testing/testing_api_cmd_wallet_get_order.c b/src/testing/testing_api_cmd_wallet_get_order.c index f9e89d63..771dc6f8 100644 --- a/src/testing/testing_api_cmd_wallet_get_order.c +++ b/src/testing/testing_api_cmd_wallet_get_order.c @@ -79,37 +79,15 @@ struct WalletGetOrderState * Callback to process a GET /orders/$ID request * * @param cls closure - * @param hr HTTP response details - * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not - * settled, #GNUNET_SYSERR on error - * (note that refunded payments are returned as paid!) - * @param refunded #GNUNET_YES if there is at least on refund on this payment, - * #GNUNET_NO if refunded, #GNUNET_SYSERR or error - * @param refund_pending #GNUNET_YES if there are refunds waiting to be - * obtained, #GNUNET_NO if all refunds have been obtained, #GNUNET_SYSERR - * on error. - * @param refund_amount amount that was refunded, NULL if there - * was no refund - * @param taler_pay_uri the URI that instructs the wallets to process - * the payment - * @param already_paid_order_id equivalent order that this customer - * paid already, or NULL for none + * @param owgr response details */ static void wallet_get_order_cb ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - enum GNUNET_GenericReturnValue paid, - enum GNUNET_GenericReturnValue refunded, - enum GNUNET_GenericReturnValue refund_pending, - struct TALER_Amount *refund_amount, - const char *taler_pay_uri, - const char *already_paid_order_id) + const struct TALER_MERCHANT_OrderWalletGetResponse *owgr) { struct WalletGetOrderState *gos = cls; - bool paid_b = (paid == GNUNET_YES); - bool refunded_b = (refunded == GNUNET_YES); - bool refund_pending_b = (refund_pending == GNUNET_YES); + const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr; gos->ogh = NULL; if (gos->http_status != hr->http_status) @@ -125,44 +103,36 @@ wallet_get_order_cb ( switch (hr->http_status) { case MHD_HTTP_OK: - // FIXME: use gos->order_reference here to - // check if the data returned matches that from the POST / PATCH - if (gos->paid != paid_b) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Order paid does not match\n"); - TALER_TESTING_interpreter_fail (gos->is); - return; - } - if (gos->refunded != refunded_b) + if (gos->refunded != owgr->details.success.refunded) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order refunded does not match\n"); TALER_TESTING_interpreter_fail (gos->is); return; } - if (gos->refund_pending != refund_pending_b) + if (gos->refund_pending != owgr->details.success.refund_pending) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order refund pending does not match\n"); TALER_TESTING_interpreter_fail (gos->is); return; } - if (! paid_b) + break; + case MHD_HTTP_PAYMENT_REQUIRED: { - /* 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 (taler_pay_uri, - &pud)) + TALER_MERCHANT_parse_pay_uri ( + owgr->details.payment_required.taler_pay_uri, + &pud)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Taler pay uri `%s' is malformed\n", - taler_pay_uri); + owgr->details.payment_required.taler_pay_uri); TALER_TESTING_interpreter_fail (gos->is); return; } @@ -216,7 +186,7 @@ wallet_get_order_cb ( { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Order pay uri `%s' does not match `%s'\n", - taler_pay_uri, + owgr->details.payment_required.taler_pay_uri, pud.order_id); TALER_TESTING_interpreter_fail (gos->is); TALER_MERCHANT_parse_pay_uri_free (&pud); @@ -565,34 +535,15 @@ conclude_task (void *cls) * Process response from a GET /orders/$ID request * * @param cls a `struct WalletPollOrderStartState *` - * @param hr HTTP response details - * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not - * settled, #GNUNET_SYSERR on error - * (note that refunded payments are returned as paid!) - * @param refunded #GNUNET_YES if there is at least on refund on this payment, - * #GNUNET_NO if refunded, #GNUNET_SYSERR or error - * @param refund_pending #GNUNET_YES if there are refunds waiting to be - * obtained, #GNUNET_NO if all refunds have been obtained, #GNUNET_SYSERR - * on error. - * @param refund_amount amount that was refunded, NULL if there - * was no refund - * @param taler_pay_uri the URI that instructs the wallets to process - * the payment - * @param already_paid_order_id equivalent order that this customer - * paid already, or NULL for none + * @param owgr response details */ static void wallet_poll_order_cb ( void *cls, - const struct TALER_MERCHANT_HttpResponse *hr, - enum GNUNET_GenericReturnValue paid, - enum GNUNET_GenericReturnValue refunded, - enum GNUNET_GenericReturnValue refund_pending, - struct TALER_Amount *refund_amount, - const char *taler_pay_uri, - const char *already_paid_order_id) + const struct TALER_MERCHANT_OrderWalletGetResponse *owgr) { struct WalletPollOrderStartState *pos = cls; + const struct TALER_MERCHANT_HttpResponse *hr = &owgr->hr; pos->ogh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -602,13 +553,15 @@ wallet_poll_order_cb ( switch (hr->http_status) { case MHD_HTTP_OK: - pos->paid = (GNUNET_YES == paid); - pos->refunded = (GNUNET_YES == refunded); - pos->refund_pending = (GNUNET_YES == refund_pending); - if (NULL != refund_amount) - pos->refund_available = *refund_amount; - if (NULL != already_paid_order_id) - pos->already_paid_order_id = GNUNET_strdup (already_paid_order_id); + pos->paid = true; + pos->refunded = owgr->details.success.refunded; + pos->refund_pending = owgr->details.success.refund_pending; + if (owgr->details.success.refunded) + pos->refund_available = owgr->details.success.refund_amount; + break; + case MHD_HTTP_PAYMENT_REQUIRED: + pos->already_paid_order_id = GNUNET_strdup ( + owgr->details.payment_required.already_paid_order_id); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |