diff --git a/doc/Makefile.am b/doc/Makefile.am index 9481e41..94c0ef4 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -12,7 +12,6 @@ arch.jpg: arch.dot AM_MAKEINFOHTMLFLAGS = --no-split --css-ref=docstyle.css --css-ref=brown-paper.css man_MANS = \ - taler-merchant-tip-enable.1 \ taler-merchant-generate-payments.1 \ taler-merchant-httpd.1 diff --git a/doc/manual.texi b/doc/manual.texi index 3c7c3c0..b8e2c6c 100644 --- a/doc/manual.texi +++ b/doc/manual.texi @@ -1125,36 +1125,16 @@ Make your wire transfer and (optionally) check at ``https://exchange:443/reserve/status/reserve_pub=QPE24X...'' whether your transfer has arrived at the exchange. @c FIXME: we should create a nicer tool to do this check! -Once the funds have arrived, you can now enable tipping using: -@example -$ taler-merchant-tip-enable \ - --amount=AMOUNT \ - --backend=BACKEND_URI \ - --credit-uuid=CREDIT_UUID \ - --instance=INSTANCE \ - --expiration=EXPIRATION -@end example -For ``AMOUNT'', specify the amount you transferred in the usual Taler -format of ``CURRENCY:VALUE[.FRACTION]'', i.e. ``EUR:50''. The -``BACKEND_URI'' should be the URI where your Taler merchant backend is -running. For ``CREDIT_UUID'', you need to specify a unique number -that identifies your wire transfer. You may have gotten one from your -bank, or you can just make one up! The important thing is that you -must never use the same UUID twice, except to repeat a failed command. -For INSTANCE, specify the backend instance (i.e. ``default''). -Finally, for EXPIRATION, pick a date two weeks after the wire -transfer, unless you know that the exchange that is being used has a -different period for closing reserves. The format @code{YYYY-MM-DD} -is accepted. - -Note that an exchange will typically close a reserve after two weeks, +Once the funds have arrived, you can start to use the reserve +for tipping. + +Note that an exchange will typically close a reserve after four weeks, wiring all remaining funds back to the sender's account. Thus, you should plan to wire funds corresponding to a campaign of about two weeks to the exchange initially. If your campaign runs longer, you -should wire further funds to the reserve every week to prevent it from -expiring. You need to run the ``taler-merchant-tip-enable'' command -each time after you wire more funds to the reserve. +should wire further funds to the reserve every other week to prevent +it from expiring. @subsection Authorize a tip diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 648f2af..a83a185 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -23,7 +23,6 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_pay.c taler-merchant-httpd_pay.h \ taler-merchant-httpd_history.c taler-merchant-httpd_history.h \ taler-merchant-httpd_tip-authorize.c taler-merchant-httpd_tip-authorize.h \ - taler-merchant-httpd_tip-enable.c taler-merchant-httpd_tip-enable.h \ taler-merchant-httpd_tip-pickup.c taler-merchant-httpd_tip-pickup.h \ taler-merchant-httpd_tip-query.c taler-merchant-httpd_tip-query.h \ taler-merchant-httpd_track-transaction.c taler-merchant-httpd_track-transaction.h \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index 2bf927d..af32f27 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -245,12 +245,6 @@ url_handler (void *cls, { "/tip-pickup", NULL, "application/json", "Only POST is allowed", 0, &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED}, - { "/tip-enable", MHD_HTTP_METHOD_POST, "text/plain", - NULL, 0, - &MH_handler_tip_enable, MHD_HTTP_OK}, - { "/tip-enable", NULL, "application/json", - "Only POST is allowed", 0, - &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED}, { "/tip-query", MHD_HTTP_METHOD_GET, "text/plain", NULL, 0, &MH_handler_tip_query, MHD_HTTP_OK}, diff --git a/src/backend/taler-merchant-httpd_tip-authorize.c b/src/backend/taler-merchant-httpd_tip-authorize.c index c55b41b..aaa62c4 100644 --- a/src/backend/taler-merchant-httpd_tip-authorize.c +++ b/src/backend/taler-merchant-httpd_tip-authorize.c @@ -29,13 +29,8 @@ #include "taler-merchant-httpd_tip-authorize.h" -/** - * Information we keep for individual calls - * to requests that parse JSON, but keep no other state. - */ -struct TMH_JsonParseContext +struct TipAuthContext { - /** * This field MUST be first. * FIXME: Explain why! @@ -46,21 +41,218 @@ struct TMH_JsonParseContext * Placeholder for #TMH_PARSE_post_json() to keep its internal state. */ void *json_parse_context; + + /** + * HTTP connection we are handling. + */ + struct MHD_Connection *connection; + + /** + * Tip amount requested. + */ + struct TALER_Amount amount; + + /** + * Merchant instance to use. + */ + const char *instance; + + /** + * Justification to use. + */ + const char *justification; + + /** + * Pickup URL to use. + */ + const char *pickup_url; + + /** + * URL to navigate to after tip. + */ + const char *next_url; + + /** + * JSON request received. + */ + json_t *root; + + /** + * Handle to pending /reserve/status request. + */ + struct TALER_EXCHANGE_ReserveStatusHandle *rsh; + + /** + * Handle for operation to obtain exchange handle. + */ + struct TMH_EXCHANGES_FindOperation *fo; + + /** + * Private key used by this merchant for the tipping reserve. + */ + struct TALER_ReservePrivateKeyP reserve_priv; + + /** + * Flag set to #GNUNET_YES when we have tried /reserve/status of the + * tipping reserve already. + */ + int checked_status; + + /** + * Flag set to #GNUNET_YES when we have parsed the incoming JSON already. + */ + int parsed_json; }; /** - * Custom cleanup routine for a `struct TMH_JsonParseContext`. + * Custom cleanup routine for a `struct TipAuthContext`. * * @param hc the `struct TMH_JsonParseContext` to clean up. */ static void -json_parse_cleanup (struct TM_HandlerContext *hc) +cleanup_tac (struct TM_HandlerContext *hc) +{ + struct TipAuthContext *tac = (struct TipAuthContext *) hc; + + if (NULL != tac->root) + { + json_decref (tac->root); + tac->root = NULL; + } + if (NULL != tac->rsh) + { + TALER_EXCHANGE_reserve_status_cancel (tac->rsh); + tac->rsh = NULL; + } + if (NULL != tac->fo) + { + TMH_EXCHANGES_find_exchange_cancel (tac->fo); + tac->fo = NULL; + } + TMH_PARSE_post_cleanup_callback (tac->json_parse_context); + GNUNET_free (tac); +} + + +/** + * Function called with the result of the /reserve/status request + * for the tipping reserve. Update our database balance with the + * result. + * + * @param cls closure with a `struct TipAuthContext *' + * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request + * 0 if the exchange's reply is bogus (fails to follow the protocol) + * @param ec taler-specific error code, #TALER_EC_NONE on success + * @param[in] json original response in JSON format (useful only for diagnostics) + * @param balance current balance in the reserve, NULL on error + * @param history_length number of entries in the transaction history, 0 on error + * @param history detailed transaction history, NULL on error + */ +static void +handle_status (void *cls, + unsigned int http_status, + enum TALER_ErrorCode ec, + const json_t *json, + const struct TALER_Amount *balance, + unsigned int history_length, + const struct TALER_EXCHANGE_ReserveHistory *history) +{ + struct TipAuthContext *tac = cls; + struct GNUNET_TIME_Relative idle_reserve_expiration_time; + + if (MHD_HTTP_OK != http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to obtain tipping reserve status from exchange (%u/%d)\n"), + http_status, + ec); + MHD_resume_connection (tac->connection); + return; + } + + /* TODO: get this from the exchange! (See #5254.) */ + idle_reserve_expiration_time = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, + 4); + + /* Update DB based on status! */ + for (unsigned int i=0;ienable_tip_reserve (db->cls, + &tac->reserve_priv, + &uuid, + &history[i].amount, + expiration); + if (0 > qs) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Database error updating tipping reserve status: %d\n"), + qs); + } + } + case TALER_EXCHANGE_RTT_WITHDRAWAL: + /* expected */ + break; + case TALER_EXCHANGE_RTT_PAYBACK: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Encountered unsupported /payback operation on tipping reserve\n")); + break; + case TALER_EXCHANGE_RTT_CLOSE: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Exchange closed reserve (due to expiration), balance calulation is likely wrong. Please create a fresh reserve.\n")); + break; + } + } + /* Finally, resume processing */ + MHD_resume_connection (tac->connection); +} + + +/** + * Function called with the result of a #TMH_EXCHANGES_find_exchange() + * operation. + * + * @param cls closure with a `struct TipAuthContext *' + * @param eh handle to the exchange context + * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available + * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config + */ +static void +exchange_cont (void *cls, + struct TALER_EXCHANGE_Handle *eh, + const struct TALER_Amount *wire_fee, + int exchange_trusted) { - struct TMH_JsonParseContext *jpc = (struct TMH_JsonParseContext *) hc; + struct TipAuthContext *tac = cls; + struct TALER_ReservePublicKeyP reserve_pub; - TMH_PARSE_post_cleanup_callback (jpc->json_parse_context); - GNUNET_free (jpc); + tac->fo = NULL; + if (NULL == eh) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to contact exchange configured for tipping!\n")); + MHD_resume_connection (tac->connection); + return; + } + GNUNET_CRYPTO_eddsa_key_get_public (&tac->reserve_priv.eddsa_priv, + &reserve_pub.eddsa_pub); + tac->rsh = TALER_EXCHANGE_reserve_status (eh, + &reserve_pub, + &handle_status, + tac); } @@ -81,66 +273,63 @@ MH_handler_tip_authorize (struct TMH_RequestHandler *rh, const char *upload_data, size_t *upload_data_size) { - struct MerchantInstance *mi; + struct TipAuthContext *tac; int res; - struct TALER_Amount amount; - const char *instance; - const char *justification; - const char *pickup_url; - const char *next_url; - struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_amount ("amount", &amount), - GNUNET_JSON_spec_string ("instance", &instance), - GNUNET_JSON_spec_string ("justification", &justification), - GNUNET_JSON_spec_string ("pickup_url", &pickup_url), - GNUNET_JSON_spec_string ("next_url", &next_url), - GNUNET_JSON_spec_end() - }; - json_t *root; + struct MerchantInstance *mi; + enum TALER_ErrorCode ec; struct GNUNET_TIME_Absolute expiration; struct GNUNET_HashCode tip_id; - struct TMH_JsonParseContext *ctx; - enum TALER_ErrorCode ec; if (NULL == *connection_cls) { - ctx = GNUNET_new (struct TMH_JsonParseContext); - ctx->hc.cc = &json_parse_cleanup; - *connection_cls = ctx; + tac = GNUNET_new (struct TipAuthContext); + tac->hc.cc = &cleanup_tac; + *connection_cls = tac; } else { - ctx = *connection_cls; + tac = *connection_cls; } res = TMH_PARSE_post_json (connection, - &ctx->json_parse_context, + &tac->json_parse_context, upload_data, upload_data_size, - &root); + &tac->root); if (GNUNET_SYSERR == res) return MHD_NO; /* the POST's body has to be further fetched */ if ( (GNUNET_NO == res) || - (NULL == root) ) + (NULL == tac->root) ) return MHD_YES; - res = TMH_PARSE_json_data (connection, - root, - spec); - if (GNUNET_YES != res) + if (GNUNET_NO == tac->parsed_json) { - GNUNET_break_op (0); - json_decref (root); - return (GNUNET_NO == res) ? MHD_YES : MHD_NO; + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount ("amount", &tac->amount), + GNUNET_JSON_spec_string ("instance", &tac->instance), + GNUNET_JSON_spec_string ("justification", &tac->justification), + GNUNET_JSON_spec_string ("pickup_url", &tac->pickup_url), + GNUNET_JSON_spec_string ("next_url", &tac->next_url), + GNUNET_JSON_spec_end() + }; + + res = TMH_PARSE_json_data (connection, + tac->root, + spec); + if (GNUNET_YES != res) + { + GNUNET_break_op (0); + return (GNUNET_NO == res) ? MHD_YES : MHD_NO; + } + tac->parsed_json = GNUNET_YES; } - mi = TMH_lookup_instance (instance); + mi = TMH_lookup_instance (tac->instance); if (NULL == mi) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Instance `%s' not configured\n", - instance); - json_decref (root); + tac->instance); return TMH_RESPONSE_reply_not_found (connection, TALER_EC_TIP_AUTHORIZE_INSTANCE_UNKNOWN, "unknown instance"); @@ -149,19 +338,35 @@ MH_handler_tip_authorize (struct TMH_RequestHandler *rh, { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Instance `%s' not configured for tipping\n", - instance); - json_decref (root); + tac->instance); return TMH_RESPONSE_reply_not_found (connection, TALER_EC_TIP_AUTHORIZE_INSTANCE_DOES_NOT_TIP, "exchange for tipping not configured for the instance"); } + tac->reserve_priv = mi->tip_reserve; ec = db->authorize_tip (db->cls, - justification, - &amount, + tac->justification, + &tac->amount, &mi->tip_reserve, mi->tip_exchange, &expiration, &tip_id); + /* If we have insufficient funds according to OUR database, + check with exchange to see if the reserve has been topped up + in the meantime (or if tips were not withdrawn yet). */ + if ( (TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS == ec) && + (GNUNET_NO == tac->checked_status) ) + { + MHD_suspend_connection (connection); + tac->checked_status = GNUNET_YES; + tac->fo = TMH_EXCHANGES_find_exchange (mi->tip_exchange, + NULL, + &exchange_cont, + tac); + return MHD_YES; + } + + /* handle irrecoverable errors */ if (TALER_EC_NONE != ec) { unsigned int rc; @@ -184,43 +389,31 @@ MH_handler_tip_authorize (struct TMH_RequestHandler *rh, rc = MHD_HTTP_INTERNAL_SERVER_ERROR; break; } - json_decref (root); return TMH_RESPONSE_reply_rc (connection, - rc, - ec, - "Database error approving tip"); + rc, + ec, + "Database error approving tip"); } - if (0) + + /* generate success response */ { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Insufficient funds to authorize tip over `%s' at instance `%s'\n", - TALER_amount2s (&amount), - instance); - json_decref (root); - return TMH_RESPONSE_reply_rc (connection, - MHD_HTTP_PRECONDITION_FAILED, - TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS, - "Insufficient funds for tip"); + json_t *tip_token; + + tip_token = json_pack ("{s:o, s:o, s:o, s:s, s:s, s:s}", + "tip_id", GNUNET_JSON_from_data_auto (&tip_id), + "expiration", GNUNET_JSON_from_time_abs (expiration), + "amount", TALER_JSON_from_amount (&tac->amount), + "exchange_url", mi->tip_exchange, + "next_url", tac->next_url, + "pickup_url", tac->pickup_url); + return TMH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:s, s:o}", + "tip_id", GNUNET_JSON_from_data_auto (&tip_id), + "expiration", GNUNET_JSON_from_time_abs (expiration), + "exchange_url", mi->tip_exchange, + "tip_token", tip_token); } - json_t *tip_token = json_pack ("{s:o, s:o, s:o, s:s, s:s, s:s}", - "tip_id", GNUNET_JSON_from_data_auto (&tip_id), - "expiration", GNUNET_JSON_from_time_abs (expiration), - "amount", TALER_JSON_from_amount (&amount), - "exchange_url", mi->tip_exchange, - "next_url", next_url, - "pickup_url", pickup_url); - char *tip_token_str = json_dumps (tip_token, JSON_ENSURE_ASCII | JSON_COMPACT); - json_decref (tip_token); - json_decref (root); - int ret = TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o, s:o, s:s, s:s}", - "tip_id", GNUNET_JSON_from_data_auto (&tip_id), - "expiration", GNUNET_JSON_from_time_abs (expiration), - "exchange_url", mi->tip_exchange, - "tip_token", tip_token_str); - GNUNET_free (tip_token_str); - return ret; } /* end of taler-merchant-httpd_tip-authorize.c */ diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 51db135..81f1219 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -309,7 +309,7 @@ struct TALER_MERCHANT_PayCoin * Amount this coin is to contribute (without fee). */ struct TALER_Amount amount_without_fee; - + /** * Fee the exchange charges for refunds of this coin. */ @@ -317,7 +317,7 @@ struct TALER_MERCHANT_PayCoin /** * URL of the exchange that issued @e coin_priv. - */ + */ const char *exchange_url; }; @@ -373,12 +373,12 @@ struct TALER_MERCHANT_RefundEntry { /** * Merchant signature affirming the refund. - */ + */ struct TALER_MerchantSignatureP merchant_sig; /** * Public key of the refunded coin. - */ + */ struct TALER_CoinSpendPublicKeyP coin_pub; /** @@ -789,71 +789,6 @@ void TALER_MERCHANT_history_cancel (struct TALER_MERCHANT_HistoryOperation *ho); -/* ********************** /tip-enable ************************* */ - - -/** - * Handle for a /tip-enable operation. - */ -struct TALER_MERCHANT_TipEnableOperation; - - -/** - * Callback for a /tip-enable request. Returns the result of - * the operation. - * - * @param cls closure - * @param http_status HTTP status returned by the merchant backend - * @param ec taler-specific error code - */ -typedef void -(*TALER_MERCHANT_TipEnableCallback) (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec); - - -/** - * Issue a /tip-enable request to the backend. Informs the backend - * that a reserve is now available for tipping. Note that the - * respective @a reserve_priv must also be bound to one or more - * instances (together with the URL of the exchange) via the backend's - * configuration file before it can be used. Usually, the process - * is that one first configures an exchange and a @a reserve_priv for - * an instance, and then enables (or re-enables) the reserve by - * performing wire transfers and informs the backend about it using - * this API. - * - * @param ctx execution context - * @param backend_url base URL of the merchant backend - * @param amount amount that was credited to the reserve - * @param expiration when will the reserve expire - * @param reserve_priv private key of the reserve - * @param credit_uuid unique ID of the wire transfer - * @param enable_cb callback which will work the response gotten from the backend - * @param enable_cb_cls closure to pass to @a enable_cb - * @return handle for this operation, NULL upon errors - */ -struct TALER_MERCHANT_TipEnableOperation * -TALER_MERCHANT_tip_enable (struct GNUNET_CURL_Context *ctx, - const char *backend_url, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Absolute expiration, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct GNUNET_HashCode *credit_uuid, - TALER_MERCHANT_TipEnableCallback enable_cb, - void *enable_cb_cls); - - - -/** - * Cancel a pending /tip-enable request - * - * @param teo handle from the operation to cancel - */ -void -TALER_MERCHANT_tip_enable_cancel (struct TALER_MERCHANT_TipEnableOperation *teo); - - /* ********************** /tip-authorize ********************** */ /** diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 5f46122..4c6d5f8 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -18,7 +18,6 @@ libtalermerchant_la_SOURCES = \ merchant_api_proposal.c \ merchant_api_pay.c \ merchant_api_tip_authorize.c \ - merchant_api_tip_enable.c \ merchant_api_tip_pickup.c \ merchant_api_track_transaction.c \ merchant_api_track_transfer.c \ diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c index b09d78a..a51ac2e 100644 --- a/src/lib/test_merchant_api.c +++ b/src/lib/test_merchant_api.c @@ -175,14 +175,14 @@ enum OpCode /** * Resume pay operation with additional coins. - */ + */ OC_PAY_AGAIN, - + /** * Abort payment with coins, requesting refund. */ OC_PAY_ABORT, - + /** * Abort payment with coins, executing refund. */ @@ -233,11 +233,6 @@ enum OpCode */ OC_REFUND_LOOKUP, - /** - * Start a reserve for tipping. - */ - OC_TIP_ENABLE, - /** * Authorize a tip. */ @@ -551,12 +546,12 @@ struct Command */ const char *amount_without_fee; - /** + /** * Refund fee to use for each coin (only relevant if we * exercise /pay's abort functionality). */ const char *refund_fee; - + /** * Pay handle while operation is running. */ @@ -594,7 +589,7 @@ struct Command * Pay handle while operation is running. */ struct TALER_MERCHANT_Pay *ph; - + } pay_again; struct { @@ -609,7 +604,7 @@ struct Command */ struct TALER_MERCHANT_Pay *ph; - /** + /** * Set in #pay_refund_cb to number of refunds obtained. */ unsigned int num_refunds; @@ -621,12 +616,12 @@ struct Command /** * Set to the hash of the original contract. - */ - struct GNUNET_HashCode h_contract; + */ + struct GNUNET_HashCode h_contract; /** * Set to the merchant's public key. - */ + */ struct TALER_MerchantPublicKeyP merchant_pub; } pay_abort; @@ -635,7 +630,7 @@ struct Command /** * Reference to the pay_abort command to be refunded. - */ + */ const char *abort_ref; /** @@ -652,7 +647,7 @@ struct Command * Refund fee to expect. */ const char *refund_fee; - + /** * Handle to the refund operation. */ @@ -1870,7 +1865,7 @@ pay_again_cb (void *cls, } GNUNET_assert (NULL != (pref = find_command (is, - cmd->details.pay_again.pay_ref))); + cmd->details.pay_again.pay_ref))); if (MHD_HTTP_OK == http_status) { struct PaymentResponsePS mr; @@ -1882,7 +1877,7 @@ pay_again_cb (void *cls, &mr.h_contract_terms), GNUNET_JSON_spec_end () }; - + GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (obj, spec, @@ -2056,45 +2051,6 @@ track_transaction_cb (void *cls, } -/** - * Callback for a /tip-enable request. Returns the result of - * the operation. - * - * @param cls closure - * @param http_status HTTP status returned by the merchant backend - * @param ec taler-specific error code - */ -static void -tip_enable_cb (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec) -{ - struct InterpreterState *is = cls; - struct Command *cmd = &is->commands[is->ip]; - - cmd->details.tip_enable.teo = NULL; - if (cmd->expected_response_code != http_status) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u to command %s\n", - http_status, - cmd->label); - fail (is); - return; - } - if (cmd->details.tip_enable.expected_ec != ec) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected error code %u to command %s\n", - ec, - cmd->label); - fail (is); - return; - } - next_command (is); -} - - /** * Callback for a /tip-authorize request. Returns the result of * the operation. @@ -2553,13 +2509,6 @@ cleanup_state (struct InterpreterState *is) cmd->details.refund_lookup.rlo = NULL; } break; - case OC_TIP_ENABLE: - if (NULL != cmd->details.tip_enable.teo) - { - TALER_MERCHANT_tip_enable_cancel (cmd->details.tip_enable.teo); - cmd->details.tip_enable.teo = NULL; - } - break; case OC_TIP_AUTHORIZE: if (NULL != cmd->details.tip_authorize.tao) { @@ -2626,7 +2575,7 @@ cleanup_state (struct InterpreterState *is) * Parse the @a coins specification and grow the @a pc * array with the coins found, updating @a npc. * - * @param[in,out] pc pointer to array of coins found + * @param[in,out] pc pointer to array of coins found * @param[in,out] npc length of array at @a pc * @param[in] coins string specifying coins to add to @a pc, * clobbered in the process @@ -2641,8 +2590,8 @@ build_coins (struct TALER_MERCHANT_PayCoin **pc, struct InterpreterState *is, const struct Command *pref) { - char *token; - + char *token; + for (token = strtok (coins, ";"); NULL != token; token = strtok (NULL, ";")) @@ -2651,7 +2600,7 @@ build_coins (struct TALER_MERCHANT_PayCoin **pc, char *ctok; unsigned int ci; struct TALER_MERCHANT_PayCoin *icoin; - + /* Token syntax is "LABEL[/NUMBER]" */ ctok = strchr (token, '/'); ci = 0; @@ -2692,7 +2641,7 @@ build_coins (struct TALER_MERCHANT_PayCoin **pc, default: GNUNET_assert (0); } - + GNUNET_assert (GNUNET_OK == TALER_string_to_amount (pref->details.pay.amount_with_fee, &icoin->amount_with_fee)); @@ -2735,7 +2684,7 @@ pay_refund_cb (void *cls, { struct InterpreterState *is = cls; struct Command *cmd = &is->commands[is->ip]; - + cmd->details.pay_abort.ph = NULL; if (cmd->expected_response_code != http_status) { @@ -2784,7 +2733,7 @@ abort_refund_cb (void *cls, { struct InterpreterState *is = cls; struct Command *cmd = &is->commands[is->ip]; - + cmd->details.pay_abort_refund.rh = NULL; if (cmd->expected_response_code != http_status) { @@ -3289,7 +3238,7 @@ interpreter_run (void *cls) GNUNET_break (0); fail (is); } - break; + break; case OC_PAY_ABORT: { struct TALER_MERCHANT_PayCoin *pc; @@ -3420,7 +3369,7 @@ interpreter_run (void *cls) GNUNET_assert (ref->details.pay_abort.num_refunds > cmd->details.pay_abort_refund.num_coin); re = &ref->details.pay_abort.res[cmd->details.pay_abort_refund.num_coin]; - + GNUNET_assert (GNUNET_OK == TALER_string_to_amount (cmd->details.pay_abort_refund.refund_amount, @@ -3650,83 +3599,6 @@ interpreter_run (void *cls) } break; } - case OC_TIP_ENABLE: - { - const struct Command *uuid_ref; - struct TALER_ReservePrivateKeyP reserve_priv; - struct GNUNET_TIME_Absolute expiration; - - if (NULL != cmd->details.tip_enable.admin_add_incoming_ref) - { - ref = find_command (is, - cmd->details.tip_enable.admin_add_incoming_ref); - GNUNET_assert (NULL != ref); - GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc); - } - else - { - ref = NULL; - } - - /* Initialize 'credit_uuid' */ - if (NULL != cmd->details.tip_enable.uuid_ref) - { - uuid_ref = find_command (is, - cmd->details.tip_enable.uuid_ref); - GNUNET_assert (NULL != uuid_ref); - GNUNET_assert (OC_TIP_ENABLE == uuid_ref->oc); - cmd->details.tip_enable.credit_uuid - = uuid_ref->details.tip_enable.credit_uuid; - } - else - { - uuid_ref = NULL; - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &cmd->details.tip_enable.credit_uuid, - sizeof (cmd->details.tip_enable.credit_uuid)); - } - - /* Initialize 'amount' */ - if ( (NULL != ref) && - (NULL == cmd->details.tip_enable.amount) ) - { - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (ref->details.admin_add_incoming.amount, - &amount)); - } - else - { - GNUNET_assert (NULL != cmd->details.tip_enable.amount); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (cmd->details.tip_enable.amount, - &amount)); - } - if (NULL == ref) - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &reserve_priv, - sizeof (reserve_priv)); - /* Simply picked long enough for the test (we do not test expiration - behavior for now), should be short enough so that the reserve - expires before the test is run again, so that we avoid old - state messing up fresh runs. */ - expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); - - if (NULL == (cmd->details.tip_enable.teo - = TALER_MERCHANT_tip_enable - (ctx, - MERCHANT_URL, - &amount, - expiration, - (ref != NULL) ? &ref->details.admin_add_incoming.reserve_priv : &reserve_priv, - &cmd->details.tip_enable.credit_uuid, - &tip_enable_cb, - is))) - { - GNUNET_break (0); - fail (is); - } - break; - } case OC_TIP_AUTHORIZE: { GNUNET_assert (NULL != cmd->details.tip_authorize.amount); @@ -4318,17 +4190,6 @@ run (void *cls) .details.check_bank_transfer.account_debit = 62, .details.check_bank_transfer.account_credit = EXCHANGE_ACCOUNT_NO }, - { .oc = OC_TIP_ENABLE, - .label = "enable-tip-1", - .expected_response_code = MHD_HTTP_OK, - .details.tip_enable.admin_add_incoming_ref = "create-reserve-tip-1", - .details.tip_enable.amount = "EUR:5.01" }, - /* Test incrementing active reserve balance */ - { .oc = OC_TIP_ENABLE, - .label = "enable-tip-2", - .expected_response_code = MHD_HTTP_OK, - .details.tip_enable.admin_add_incoming_ref = "create-reserve-tip-1", - .details.tip_enable.amount = "EUR:5.01" }, /* Authorize two tips */ { .oc = OC_TIP_AUTHORIZE, .label = "authorize-tip-1", @@ -4519,7 +4380,7 @@ run (void *cls) .details.pay.refund_fee = "EUR:0.01", .details.pay_again.pay_ref = "pay-fail-partial-double-10", .details.pay_again.coin_ref = "withdraw-coin-10a;withdraw-coin-10b" }, - + /* Run transfers. */ { .oc = OC_RUN_AGGREGATOR, .label = "run-aggregator-10" }, @@ -4632,14 +4493,14 @@ run (void *cls) .details.pay_abort_refund.num_coin = 0, .details.pay_abort_refund.refund_amount = "EUR:5", .details.pay_abort_refund.refund_fee = "EUR:0.01" }, - + /* Run transfers. */ { .oc = OC_RUN_AGGREGATOR, .label = "run-aggregator-11" }, /* Check that there are no other unusual transfers */ { .oc = OC_CHECK_BANK_TRANSFERS_EMPTY, .label = "check_bank_empty-11" }, - + /* end of testcase */ { .oc = OC_END } }; diff --git a/src/merchant-tools/Makefile.am b/src/merchant-tools/Makefile.am index 7811d04..4e68837 100644 --- a/src/merchant-tools/Makefile.am +++ b/src/merchant-tools/Makefile.am @@ -3,8 +3,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include bin_PROGRAMS = \ taler-merchant-dbinit \ - taler-merchant-generate-payments \ - taler-merchant-tip-enable + taler-merchant-generate-payments taler_merchant_dbinit_SOURCES = \ taler-merchant-dbinit.c @@ -16,16 +15,6 @@ taler_merchant_dbinit_LDADD = \ -ltalerutil \ -ltalerpq -taler_merchant_tip_enable_SOURCES = \ - taler-merchant-tip-enable.c - -taler_merchant_tip_enable_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/lib/libtalermerchant.la \ - -lgnunetcurl \ - -lgnunetutil \ - -ltalerutil - taler_merchant_generate_payments_SOURCES = \ taler-merchant-generate-payments.c