merchant

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

commit 24a2a3f887ce34d42dc20dc7952b8edeb4a21bd4
parent 2789caa9b8658e88eebf3333475f989e7cd2fd37
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed,  3 Jun 2020 20:39:11 +0200

new backenddb APIs for GET /private/orders/ID

Diffstat:
Msrc/backend/taler-merchant-httpd_get-orders-ID.c | 13+++++++++----
Msrc/backend/taler-merchant-httpd_post-orders-ID-claim.c | 13+++++++++----
Msrc/backend/taler-merchant-httpd_post-orders-ID-pay.c | 4+++-
Msrc/backend/taler-merchant-httpd_private-delete-orders-ID.c | 7++++++-
Msrc/backend/taler-merchant-httpd_private-get-orders-ID.c | 59+++++++++++++++++++++++++++++++++--------------------------
Msrc/backenddb/plugin_merchantdb_postgres.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/backenddb/test_merchantdb.c | 14+++++++-------
Msrc/include/taler_merchantdb_plugin.h | 23++++++++++++++++++++++-
8 files changed, 160 insertions(+), 46 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -743,10 +743,15 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, /* Convert order_id to h_contract_terms */ TMH_db->preflight (TMH_db->cls); - qs = TMH_db->lookup_contract_terms (TMH_db->cls, - hc->instance->settings.id, - order_id, - &god->contract_terms); + { + uint64_t order_serial; + + qs = TMH_db->lookup_contract_terms (TMH_db->cls, + hc->instance->settings.id, + order_id, + &god->contract_terms, + &order_serial); + } if (0 > qs) { /* single, read-only SQL statements should never cause diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-claim.c b/src/backend/taler-merchant-httpd_post-orders-ID-claim.c @@ -65,10 +65,15 @@ claim_order (const char *instance_id, GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; } - qs = TMH_db->lookup_contract_terms (TMH_db->cls, - order_id, - instance_id, - contract_terms); + { + uint64_t order_serial; + + qs = TMH_db->lookup_contract_terms (TMH_db->cls, + order_id, + instance_id, + contract_terms, + &order_serial); + } if (0 > qs) { TMH_db->rollback (TMH_db->cls); diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c @@ -1592,11 +1592,13 @@ parse_pay (struct MHD_Connection *connection, { enum GNUNET_DB_QueryStatus qs; json_t *contract_terms = NULL; + uint64_t order_serial; qs = TMH_db->lookup_contract_terms (TMH_db->cls, hc->instance->settings.id, pc->order_id, - &contract_terms); + &contract_terms, + &order_serial); if (0 > qs) { /* single, read-only SQL statements should never cause diff --git a/src/backend/taler-merchant-httpd_private-delete-orders-ID.c b/src/backend/taler-merchant-httpd_private-delete-orders-ID.c @@ -67,10 +67,15 @@ TMH_private_delete_orders_ID (const struct TMH_RequestHandler *rh, hc->infix, NULL); if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + uint64_t order_serial; + qs = TMH_db->lookup_contract_terms (TMH_db->cls, mi->settings.id, hc->infix, - NULL); + NULL, + &order_serial); + } if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, diff --git a/src/backend/taler-merchant-httpd_private-get-orders-ID.c b/src/backend/taler-merchant-httpd_private-get-orders-ID.c @@ -217,12 +217,12 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, GNUNET_STRINGS_absolute_time_to_string ( gorc->sc.long_poll_timeout)); - db->preflight (db->cls); - qs = db->lookup_contract_terms (db->cls, - hc->instance.settings->id, - hc->infix, - &gorc->contract_terms, - &gorc->order_serial); + TMH_db->preflight (TMH_db->cls); + qs = TMH_db->lookup_contract_terms (TMH_db->cls, + hc->instance.settings->id, + hc->infix, + &gorc->contract_terms, + &gorc->order_serial); if (0 > qs) { /* single, read-only SQL statements should never cause @@ -268,12 +268,12 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, bool paid; bool wired; - db->preflight (db->cls); - qs = db->lookup_payment_status (db->cls, - gorc->order_serial, - gorc->session_id, - &paid, - &wired); + TMH_db->preflight (TMH_db->cls); + qs = TMH_db->lookup_payment_status (TMH_db->cls, + gorc->order_serial, + gorc->session_id, + &paid, + &wired); if (0 >= qs) { /* single, read-only SQL statements should never cause @@ -288,12 +288,11 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, { char *already_paid_order_id; - qs = db->lookup_repayment_status (db->cls, - hc->instance->settings.id, - hc->infix, - gorc->session_id, - gorc->fulfillment_url, - &already_paid_order_id); + qs = TMH_db->lookup_order_by_fulfillment (TMH_db->cls, + hc->instance->settings.id, + gorc->fulfillment_url, + gorc->session_id, + &already_paid_order_id); if (0 > qs) { /* single, read-only SQL statements should never cause @@ -372,10 +371,16 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, /* Here we know the user DID pay, compute refunds... */ /* Accumulate refunds, if any. */ - qs = db->select_refunds_by_order (db->cls, - gorc->order_serial, - &process_refunds_cb, - gorc); + { + struct GNUNET_HashCode h_contract_terms; + + // FIXME: init h_contract_terms! + qs = TMH_db->lookup_refunds (TMH_db->cls, + hc->instance.settings->id, + &h_contract_terms, + &process_refunds_cb, + gorc); + } if (0 > qs) { GNUNET_break (0); @@ -390,10 +395,12 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, { json_t *wire_details = NULL; - qs = db->select_wire_details_by_order (db->cls, - gorc->order_serial, - &process_wire_details, - &wire_details); +#if FIXME + qs = TMH_db->select_wire_details_by_order (TMH_db->cls, + gorc->order_serial, + &process_wire_details, + &wire_details); +#endif if (0 > qs) { GNUNET_break (0); diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c @@ -1359,13 +1359,15 @@ postgres_insert_order_lock (void *cls, * @param instance_id instance's identifier * @param order_id order_id used to lookup. * @param[out] contract_terms where to store the result, NULL to only check for existence + * @param[out] order_serial set to the order's serial number * @return transaction status */ static enum GNUNET_DB_QueryStatus postgres_lookup_contract_terms (void *cls, const char *instance_id, const char *order_id, - json_t **contract_terms) + json_t **contract_terms, + uint64_t *order_serial) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -1376,6 +1378,8 @@ postgres_lookup_contract_terms (void *cls, struct GNUNET_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_json ("contract_terms", contract_terms), + GNUNET_PQ_result_spec_uint64 ("order_serial", + order_serial), GNUNET_PQ_result_spec_end }; @@ -2000,6 +2004,59 @@ postgres_lookup_order_status (void *cls, /** + * Retrieve payment and wire status for a given @a order_serial and session ID. + * + * @param cls closure + * @param order_serial identifies the order + * @param session_id session for which to check the payment status, NULL for any + * @param[out] paid set to the payment status of the contract + * @param[out] wired set to the wire transfer status of the exchange payment + * @return transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_lookup_payment_status (void *cls, + uint64_t order_serial, + const char *session_id, + bool *paid, + bool *wired) +{ + struct PostgresClosure *pg = cls; + uint8_t paid8; + uint8_t wired8; + enum GNUNET_DB_QueryStatus qs; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&order_serial), + GNUNET_PQ_query_param_string (session_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("paid", + &paid8), + GNUNET_PQ_result_spec_auto_from_type ("wired", + &wired8), + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_payment_status", + params, + rs); + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + *paid = (0 != paid8); + *wired = (0 != wired8); + } + else + { + *paid = false; /* just to be safe(r) */ + *wired = false; /* just to be safe(r) */ + } + return qs; +} + + +/** * Closure for #process_refund_cb(). */ struct FindRefundContext @@ -6162,7 +6219,9 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) 4), /* for postgres_lookup_contract_terms() */ GNUNET_PQ_make_prepare ("lookup_contract_terms", - "SELECT contract_terms" + "SELECT" + " contract_terms" + ",order_serial" " FROM merchant_contract_terms" " WHERE order_id=$2" " AND merchant_serial=" @@ -6390,6 +6449,15 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " WHERE merchant_id=$1)" " AND order_id=$2", 2), + /* for postgres_lookup_payment_status() */ + GNUNET_PQ_make_prepare ("lookup_payment_status", + "SELECT" + " wired" + ",paid" + " FROM merchant_contract_terms" + " WHERE order_serial=$1" + " AND session_id=$2", + 2), /* for process_refund_cb() used in postgres_increase_refund() */ GNUNET_PQ_make_prepare ("find_refunds_by_coin", "SELECT" @@ -7287,6 +7355,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->mark_contract_paid = &postgres_mark_contract_paid; plugin->refund_coin = &postgres_refund_coin; plugin->lookup_order_status = &postgres_lookup_order_status; + plugin->lookup_payment_status = &postgres_lookup_payment_status; plugin->increase_refund = &postgres_increase_refund; plugin->lookup_refunds_detailed = &postgres_lookup_refunds_detailed; plugin->insert_refund_proof = &postgres_insert_refund_proof; diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c @@ -1119,15 +1119,17 @@ test_lookup_contract_terms (const char *instance_id, const json_t *expected_contract) { json_t *contract = NULL; + uint64_t order_serial; + if (1 != plugin->lookup_contract_terms (plugin->cls, instance_id, order_id, - &contract)) + &contract, + &order_serial)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Lookup contract terms failed\n"); - if (NULL != contract) - json_decref (contract); + GNUNET_assert (NULL == contract); return 1; } if (1 != json_equal (expected_contract, @@ -1135,12 +1137,10 @@ test_lookup_contract_terms (const char *instance_id, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Lookup contract terms failed: mismatched data\n"); - if (NULL != contract) - json_decref (contract); + json_decref (contract); return 1; } - if (NULL != contract) - json_decref (contract); + json_decref (contract); return 0; } diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -1036,13 +1036,15 @@ struct TALER_MERCHANTDB_Plugin * @param instance_id instance's identifier * @param order_id order_id used to lookup. * @param[out] contract_terms where to store the result, NULL to only check for existence + * @param[out] order_serial set to the order's serial number * @return transaction status */ enum GNUNET_DB_QueryStatus (*lookup_contract_terms)(void *cls, const char *instance_id, const char *order_id, - json_t **contract_terms); + json_t **contract_terms, + uint64_t *order_serial); /** @@ -1240,6 +1242,25 @@ struct TALER_MERCHANTDB_Plugin /** + * Retrieve payment and wire status for a given @a order_serial and + * session ID. + * + * @param cls closure + * @param order_serial identifies the order + * @param session_id session for which to check the payment status, NULL for any + * @param[out] paid set to the payment status of the contract + * @param[out] wired set to the wire transfer status of the exchange payment + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_payment_status)(void *cls, + uint64_t order_serial, + const char *session_id, + bool *paid, + bool *wired); + + + /** * Function called when some backoffice staff decides to award or * increase the refund on an existing contract. This function * MUST be called from within a transaction scope setup by the