diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/taler-merchant-httpd_check-payment.c | 49 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_pay.c | 157 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_proposal.c | 3 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_refund.c | 8 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_track-transaction.c | 54 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 154 | ||||
-rw-r--r-- | src/backenddb/test_merchantdb.c | 70 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 66 |
8 files changed, 133 insertions, 428 deletions
diff --git a/src/backend/taler-merchant-httpd_check-payment.c b/src/backend/taler-merchant-httpd_check-payment.c index 247f7982..8366186c 100644 --- a/src/backend/taler-merchant-httpd_check-payment.c +++ b/src/backend/taler-merchant-httpd_check-payment.c @@ -94,6 +94,7 @@ MH_handler_check_payment (struct TMH_RequestHandler *rh, json_t *contract_terms; struct GNUNET_HashCode h_contract_terms; struct TALER_Amount refund_amount; + char *last_session_id; order_id = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, @@ -186,10 +187,9 @@ MH_handler_check_payment (struct TMH_RequestHandler *rh, GNUNET_assert (NULL != order_id); - - qs = db->find_contract_terms (db->cls, &contract_terms, + &last_session_id, order_id, &mi->pubkey); if (0 > qs) @@ -230,6 +230,9 @@ MH_handler_check_payment (struct TMH_RequestHandler *rh, goto do_pay; } + GNUNET_assert (NULL != contract_terms); + GNUNET_assert (NULL != last_session_id); + if (GNUNET_OK != TALER_JSON_hash (contract_terms, &h_contract_terms)) @@ -244,20 +247,14 @@ MH_handler_check_payment (struct TMH_RequestHandler *rh, sizeof (struct GNUNET_HashCode)); - /* Check if transaction is already known */ + /* Check if paid */ { - struct GNUNET_HashCode h_xwire; - struct GNUNET_TIME_Absolute xtimestamp; - struct GNUNET_TIME_Absolute xrefund; - struct TALER_Amount xtotal_amount; + json_t *xcontract_terms = NULL; - qs = db->find_transaction (db->cls, - &h_contract_terms, - &mi->pubkey, - &h_xwire, - &xtimestamp, - &xrefund, - &xtotal_amount); + qs = db->find_paid_contract_terms_from_hash (db->cls, + &xcontract_terms, + &h_contract_terms, + &mi->pubkey); if (0 > qs) { /* Always report on hard error as well to enable diagnostics */ @@ -273,10 +270,22 @@ MH_handler_check_payment (struct TMH_RequestHandler *rh, goto do_pay; } GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); - - TALER_amount_get_zero (xtotal_amount.currency, &refund_amount); + GNUNET_assert (NULL != xcontract_terms); + json_decref (xcontract_terms); } + { + struct TALER_Amount amount; + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount ("amount", &amount), + GNUNET_JSON_spec_end () + }; + if (GNUNET_OK != GNUNET_JSON_parse (contract_terms, spec, NULL, NULL)) + return TMH_RESPONSE_reply_internal_error (connection, + TALER_EC_CHECK_PAYMENT_DB_FETCH_CONTRACT_TERMS_ERROR, + "Merchant database error (contract terms corrupted)"); + TALER_amount_get_zero (amount.currency, &refund_amount); + } for (unsigned int i=0;i<MAX_RETRIES;i++) { @@ -301,15 +310,16 @@ MH_handler_check_payment (struct TMH_RequestHandler *rh, GNUNET_free_non_null (h_contract_terms_str); { - int refunded = 0 != refund_amount.value || 0 != refund_amount.fraction; + int refunded = (0 != refund_amount.value) || (0 != refund_amount.fraction); int res; res = TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, - "{s:o s:b, s:b, s:o}", + "{s:o s:b, s:b, s:o, s:s}", "contract_terms", contract_terms, "paid", 1, "refunded", refunded, - "refund_amount", TALER_JSON_from_amount (&refund_amount)); + "refund_amount", TALER_JSON_from_amount (&refund_amount), + "last_session_id", last_session_id); return res; } @@ -331,6 +341,7 @@ do_pay: 0); GNUNET_free_non_null (h_contract_terms_str); GNUNET_free_non_null (final_contract_url); + json_decref (contract_terms); GNUNET_free (url); return ret; } diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c index 442c8364..b112edf5 100644 --- a/src/backend/taler-merchant-httpd_pay.c +++ b/src/backend/taler-merchant-httpd_pay.c @@ -1292,6 +1292,7 @@ parse_pay (struct MHD_Connection *connection, const char *mode; struct TALER_MerchantPublicKeyP merchant_pub; int res; + char *last_session_id; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("mode", &mode), @@ -1323,6 +1324,7 @@ parse_pay (struct MHD_Connection *connection, GNUNET_assert (NULL == pc->contract_terms); qs = db->find_contract_terms (db->cls, &pc->contract_terms, + &last_session_id, order_id, &merchant_pub); if (0 > qs) @@ -1351,6 +1353,8 @@ parse_pay (struct MHD_Connection *connection, return GNUNET_NO; } + GNUNET_free (last_session_id); + if (GNUNET_OK != TALER_JSON_hash (pc->contract_terms, &pc->h_contract_terms)) @@ -1858,7 +1862,8 @@ begin_transaction (struct PayContext *pc) /* Payment succeeded, commit! */ qs = db->mark_proposal_paid (db->cls, &pc->h_contract_terms, - &pc->mi->pubkey); + &pc->mi->pubkey, + pc->session_id); if (0 <= qs) qs = db->commit (db->cls); if (0 > qs) @@ -1885,153 +1890,9 @@ begin_transaction (struct PayContext *pc) } - /* Check if transaction is already known, if not store it. */ - { - struct GNUNET_HashCode h_xwire; - struct GNUNET_TIME_Absolute xtimestamp; - struct GNUNET_TIME_Absolute xrefund; - struct TALER_Amount xtotal_amount; - - qs = db->find_transaction (db->cls, - &pc->h_contract_terms, - &pc->mi->pubkey, - &h_xwire, - &xtimestamp, - &xrefund, - &xtotal_amount); - if (0 > qs) - { - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - { - db->rollback (db->cls); - begin_transaction (pc); - return; - } - /* Always report on hard error as well to enable diagnostics */ - GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); - db->rollback (db->cls); - resume_pay_with_response (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:I, s:s}", - "code", (json_int_t) TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR, - "hint", "Merchant database error")); - return; - } - - if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) && - ( (xtimestamp.abs_value_us != pc->timestamp.abs_value_us) || - (xrefund.abs_value_us != pc->refund_deadline.abs_value_us) || - (0 != memcmp (&h_xwire, - &pc->h_wire, - sizeof (struct GNUNET_HashCode))) || - (0 != TALER_amount_cmp (&xtotal_amount, - &pc->amount) ) ) ) - { - GNUNET_break (0); - db->rollback (db->cls); - resume_pay_with_response (pc, - MHD_HTTP_BAD_REQUEST, - TMH_RESPONSE_make_json_pack ("{s:I, s:s}", - "code", (json_int_t) TALER_EC_PAY_DB_TRANSACTION_ID_CONFLICT, - "hint", "Transaction ID reused with different transaction details")); - return; - } - } - - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - { - struct GNUNET_TIME_Absolute now; - enum GNUNET_DB_QueryStatus qs_st; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Dealing with new transaction `%s'\n", - GNUNET_h2s (&pc->h_contract_terms)); - - now = GNUNET_TIME_absolute_get (); - if (now.abs_value_us > pc->pay_deadline.abs_value_us) - { - /* Time expired, we don't accept this payment now! */ - const char *pd_str; - - pd_str = GNUNET_STRINGS_absolute_time_to_string (pc->pay_deadline); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Attempt to pay coins for expired contract. Deadline: `%s'\n", - pd_str); - db->rollback (db->cls); - resume_pay_with_response (pc, - MHD_HTTP_BAD_REQUEST, - TMH_RESPONSE_make_json_pack ("{s:I, s:s}", - "code", (json_int_t) TALER_EC_PAY_OFFER_EXPIRED, - "hint", "The time to pay for this contract has expired.")); - return; - } - - qs_st = db->store_transaction (db->cls, - &pc->h_contract_terms, - &pc->mi->pubkey, - &pc->h_wire, - pc->timestamp, - pc->refund_deadline, - &pc->amount); - /* Only retry if SOFT error occurred. Exit in case of OK or HARD failure */ - if (GNUNET_DB_STATUS_SOFT_ERROR == qs_st) - { - db->rollback (db->cls); - begin_transaction (pc); - return; - } - /* Exit in case of HARD failure */ - if (GNUNET_DB_STATUS_HARD_ERROR == qs_st) - { - GNUNET_break (0); - db->rollback (db->cls); - resume_pay_with_response (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:I, s:s}", - "code", (json_int_t) TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR, - "hint", "Merchant database error: hard error while storing transaction")); - } - - /** - * Break if we couldn't modify one, and only one line; this - * includes hard errors. - */ - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs_st) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected query status %d while storing /pay transaction!\n", - (int) qs_st); - db->rollback (db->cls); - resume_pay_with_response (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:I, s:s}", - "code", (json_int_t) TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR, - "hint", "Merchant database error: failed to store transaction")); - return; - } - - qs = db->commit (db->cls); - if (0 > qs) - { - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - { - db->rollback (db->cls); - begin_transaction (pc); - return; - } - resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_PAY_DB_STORE_PAYMENTS_ERROR, - "Merchant database error: could not commit"); - return; - } - } /* end of if (GNUNET_NO == qs) */ - else - { - /* transaction record already existed, we made no DB changes, - so we can just rollback */ - db->rollback (db->cls); - } + /* we made no DB changes, + so we can just rollback */ + db->rollback (db->cls); /* Ok, we need to first go to the network. Do that interaction in *tiny* transactions. */ diff --git a/src/backend/taler-merchant-httpd_proposal.c b/src/backend/taler-merchant-httpd_proposal.c index 4026625b..64bd5e99 100644 --- a/src/backend/taler-merchant-httpd_proposal.c +++ b/src/backend/taler-merchant-httpd_proposal.c @@ -567,6 +567,7 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh, enum GNUNET_DB_QueryStatus qs; json_t *contract_terms; struct MerchantInstance *mi; + char *last_session_id; instance = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, @@ -599,6 +600,7 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh, qs = db->find_contract_terms (db->cls, &contract_terms, + &last_session_id, order_id, &mi->pubkey); if (0 > qs) @@ -669,6 +671,7 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh, } GNUNET_assert (NULL != contract_terms); + GNUNET_free_non_null (last_session_id); const char *stored_nonce = json_string_value (json_object_get (contract_terms, "nonce")); diff --git a/src/backend/taler-merchant-httpd_refund.c b/src/backend/taler-merchant-httpd_refund.c index a9f54279..8a6060c3 100644 --- a/src/backend/taler-merchant-httpd_refund.c +++ b/src/backend/taler-merchant-httpd_refund.c @@ -117,6 +117,7 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh, const char *order_id; const char *reason; const char *merchant; + char *last_session_id; struct MerchantInstance *mi; struct GNUNET_HashCode h_contract_terms; struct TALER_MerchantRefundConfirmationPS confirmation; @@ -183,6 +184,7 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh, /* Convert order id to h_contract_terms */ qs = db->find_contract_terms (db->cls, &contract_terms, + &last_session_id, order_id, &mi->pubkey); if (0 > qs) @@ -206,6 +208,8 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh, "Order id not found in database"); } + GNUNET_free (last_session_id); + if (GNUNET_OK != TALER_JSON_hash (contract_terms, &h_contract_terms)) @@ -418,6 +422,7 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh, json_t *contract_terms; struct MerchantInstance *mi; enum GNUNET_DB_QueryStatus qs; + char *last_session_id; instance = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, @@ -459,6 +464,7 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh, contract_terms = NULL; qs = db->find_contract_terms (db->cls, &contract_terms, + &last_session_id, order_id, &mi->pubkey); if (0 > qs) @@ -483,6 +489,8 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh, "Order id not found in database"); } + GNUNET_free (last_session_id); + if (GNUNET_OK != TALER_JSON_hash (contract_terms, &h_contract_terms)) diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c index e59e89ae..99bd33b4 100644 --- a/src/backend/taler-merchant-httpd_track-transaction.c +++ b/src/backend/taler-merchant-httpd_track-transaction.c @@ -1022,6 +1022,7 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, enum GNUNET_DB_QueryStatus qs; struct GNUNET_HashCode h_instance; struct json_t *contract_terms; + char *last_session_id; if (NULL == *connection_cls) { @@ -1096,6 +1097,7 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, qs = db->find_contract_terms (db->cls, &contract_terms, + &last_session_id, order_id, &tctx->mi->pubkey); if (0 > qs) @@ -1109,6 +1111,9 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, return TMH_RESPONSE_reply_not_found (connection, TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND, "Given order_id doesn't map to any proposal"); + + GNUNET_free (last_session_id); + if (GNUNET_OK != TALER_JSON_hash (contract_terms, &tctx->h_contract_terms)) @@ -1118,33 +1123,34 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh, TALER_EC_INTERNAL_LOGIC_ERROR, "Failed to hash contract terms"); } - json_decref (contract_terms); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Trying to track h_contract_terms '%s'\n", - GNUNET_h2s (&tctx->h_contract_terms)); - qs = db->find_transaction (db->cls, - &tctx->h_contract_terms, - &tctx->mi->pubkey, - &tctx->h_wire, - &tctx->timestamp, - &tctx->refund_deadline, - &tctx->total_amount); - if (0 > qs) { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs); - return TMH_RESPONSE_reply_internal_error (connection, - TALER_EC_TRACK_TRANSACTION_DB_FETCH_TRANSACTION_ERROR, - "Database error finding transaction"); - } - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "h_contract_terms not found\n"); - return TMH_RESPONSE_reply_not_found (connection, - TALER_EC_TRACK_TRANSACTION_TRANSACTION_UNKNOWN, - "h_contract_terms is unknown"); + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_absolute_time ("refund_deadline", + &tctx->refund_deadline), + GNUNET_JSON_spec_absolute_time ("timestamp", + &tctx->timestamp), + TALER_JSON_spec_amount ("amount", + &tctx->total_amount), + GNUNET_JSON_spec_fixed_auto ("H_wire", + &tctx->h_wire), + GNUNET_JSON_spec_end() + }; + + if (GNUNET_YES != GNUNET_JSON_parse (contract_terms, + spec, + NULL, NULL)) + { + GNUNET_break (0); + GNUNET_JSON_parse_free (spec); + json_decref (contract_terms); + return TMH_RESPONSE_reply_internal_error (connection, + TALER_EC_INTERNAL_LOGIC_ERROR, + "Failed to parse contract terms from DB"); + } + json_decref (contract_terms); } + tctx->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; qs = db->find_payments (db->cls, &tctx->h_contract_terms, diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index a160ae0e..881f682d 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -115,22 +115,10 @@ postgres_initialize (void *cls) ",timestamp INT8 NOT NULL" ",row_id BIGSERIAL UNIQUE" ",paid boolean DEFAULT FALSE NOT NULL" + ",last_session_id VARCHAR DEFAULT '' NOT NULL" ",PRIMARY KEY (order_id, merchant_pub)" ",UNIQUE (h_contract_terms, merchant_pub)" ");"), - /* Contracts that were paid */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_transactions (" - " h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)" - ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)" - ",h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)" - ",timestamp INT8 NOT NULL" - ",refund_deadline INT8 NOT NULL" - ",total_amount_val INT8 NOT NULL" - ",total_amount_frac INT4 NOT NULL" - ",total_amount_curr VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL" - ",PRIMARY KEY (h_contract_terms, merchant_pub)" - ",FOREIGN KEY (h_contract_terms, merchant_pub) REFERENCES merchant_contract_terms (h_contract_terms, merchant_pub)" - ");"), /* Table with the proofs for each coin we deposited at the exchange */ GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_deposits (" " h_contract_terms BYTEA NOT NULL" @@ -152,7 +140,7 @@ postgres_initialize (void *cls) ",signkey_pub BYTEA NOT NULL CHECK (LENGTH(signkey_pub)=32)" ",exchange_proof BYTEA NOT NULL" ",PRIMARY KEY (h_contract_terms, coin_pub)" - ",FOREIGN KEY (h_contract_terms, merchant_pub) REFERENCES merchant_transactions (h_contract_terms, merchant_pub)" + ",FOREIGN KEY (h_contract_terms, merchant_pub) REFERENCES merchant_contract_terms (h_contract_terms, merchant_pub)" ");"), GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_proofs (" " exchange_url VARCHAR NOT NULL" @@ -248,19 +236,6 @@ postgres_initialize (void *cls) GNUNET_PQ_EXECUTE_STATEMENT_END }; struct GNUNET_PQ_PreparedStatement ps[] = { - GNUNET_PQ_make_prepare ("insert_transaction", - "INSERT INTO merchant_transactions" - "(h_contract_terms" - ",merchant_pub" - ",h_wire" - ",timestamp" - ",refund_deadline" - ",total_amount_val" - ",total_amount_frac" - ",total_amount_curr" - ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8)", - 8), GNUNET_PQ_make_prepare ("insert_deposit", "INSERT INTO merchant_deposits" "(h_contract_terms" @@ -335,7 +310,8 @@ postgres_initialize (void *cls) 4), GNUNET_PQ_make_prepare ("mark_proposal_paid", "UPDATE merchant_contract_terms SET" - " paid=TRUE WHERE h_contract_terms=$1" + " paid=TRUE, last_session_id=$3" + " WHERE h_contract_terms=$1" " AND merchant_pub=$2", 2), GNUNET_PQ_make_prepare ("insert_wire_fee", @@ -411,6 +387,7 @@ postgres_initialize (void *cls) GNUNET_PQ_make_prepare ("find_contract_terms", "SELECT" " contract_terms" + ",last_session_id" " FROM merchant_contract_terms" " WHERE" " order_id=$1" @@ -480,18 +457,6 @@ postgres_initialize (void *cls) " ORDER BY row_id DESC, timestamp DESC" " LIMIT $4", 4), - GNUNET_PQ_make_prepare ("find_transaction", - "SELECT" - " h_wire" - ",timestamp" - ",refund_deadline" - ",total_amount_val" - ",total_amount_frac" - ",total_amount_curr" - " FROM merchant_transactions" - " WHERE h_contract_terms=$1" - " AND merchant_pub=$2", - 2), GNUNET_PQ_make_prepare ("find_deposits", "SELECT" " coin_pub" @@ -884,12 +849,14 @@ postgres_find_paid_contract_terms_from_hash (void *cls, * * @param cls closure * @param[out] contract_terms where to store the retrieved contract terms + * @param[out] last_session_id where to store the result * @param order id order id used to perform the lookup * @return transaction status */ static enum GNUNET_DB_QueryStatus postgres_find_contract_terms (void *cls, json_t **contract_terms, + char **last_session_id, const char *order_id, const struct TALER_MerchantPublicKeyP *merchant_pub) { @@ -903,6 +870,8 @@ postgres_find_contract_terms (void *cls, struct GNUNET_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_json ("contract_terms", contract_terms), + GNUNET_PQ_result_spec_string ("last_session_id", + last_session_id), GNUNET_PQ_result_spec_end }; @@ -1057,17 +1026,21 @@ postgres_insert_order (void *cls, * @param cls closure * @param h_contract_terms hash of the contract that is now paid * @param merchant_pub merchant's public key + * @param last_session_id session id used for the payment, NULL + * if payment was not session-bound * @return transaction status */ enum GNUNET_DB_QueryStatus postgres_mark_proposal_paid (void *cls, const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub) + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *last_session_id) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (h_contract_terms), GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_string ((last_session_id == NULL) ? "" : last_session_id), GNUNET_PQ_query_param_end }; @@ -1082,51 +1055,6 @@ postgres_mark_proposal_paid (void *cls, /** - * Insert transaction data into the database. - * - * @param cls closure - * @param h_contract_terms hashcode of the proposal data associated with the - * transaction being stored - * @param merchant_pub merchant's public key - * @param exchange_url URL of the exchange - * @param h_wire hash of our wire details - * @param timestamp time of the confirmation - * @param refund refund deadline - * @param total_amount total amount we receive for the contract after fees - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_store_transaction (void *cls, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund, - const struct TALER_Amount *total_amount) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_wire), - GNUNET_PQ_query_param_absolute_time (×tamp), - GNUNET_PQ_query_param_absolute_time (&refund), - TALER_PQ_query_param_amount (total_amount), - GNUNET_PQ_query_param_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Storing transaction with h_contract_terms '%s', merchant_pub '%s'.\n", - GNUNET_h2s (h_contract_terms), - TALER_B2S (merchant_pub)); - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_transaction", - params); -} - - -/** * Insert payment confirmation from the exchange into the database. * * @param cls closure @@ -1608,58 +1536,6 @@ postgres_find_contract_terms_by_date (void *cls, /** - * Find information about a transaction. - * - * @param cls our plugin handle - * @param h_contract_terms value used to perform the lookup - * @param merchant_pub merchant's public key - * @param[out] h_wire set to hash of wire details - * @param[out] timestamp set to timestamp - * @param[out] refund_deadline set to refund deadline - * @param[out] total_amount set to total amount - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_find_transaction (void *cls, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute *timestamp, - struct GNUNET_TIME_Absolute *refund_deadline, - struct TALER_Amount *total_amount) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("h_wire", - h_wire), - GNUNET_PQ_result_spec_absolute_time ("timestamp", - timestamp), - GNUNET_PQ_result_spec_absolute_time ("refund_deadline", - refund_deadline), - TALER_PQ_result_spec_amount ("total_amount", - total_amount), - GNUNET_PQ_result_spec_end - }; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Finding transaction for h_contract_terms '%s', merchant_pub: '%s'.\n", - GNUNET_h2s (h_contract_terms), - TALER_B2S (merchant_pub)); - - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "find_transaction", - params, - rs); -} - - -/** * Closure for #find_payments_cb(). */ struct FindPaymentsContext @@ -3548,12 +3424,10 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->cls = pg; plugin->drop_tables = &postgres_drop_tables; plugin->initialize = &postgres_initialize; - plugin->store_transaction = &postgres_store_transaction; plugin->store_deposit = &postgres_store_deposit; plugin->store_coin_to_transfer = &postgres_store_coin_to_transfer; plugin->store_transfer_to_proof = &postgres_store_transfer_to_proof; plugin->store_wire_fee_by_exchange = &postgres_store_wire_fee_by_exchange; - plugin->find_transaction = &postgres_find_transaction; plugin->find_payments_by_hash_and_coin = &postgres_find_payments_by_hash_and_coin; plugin->find_payments = &postgres_find_payments; plugin->find_transfers_by_hash = &postgres_find_transfers_by_hash; diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c index cbf51b31..33a05ddb 100644 --- a/src/backenddb/test_merchantdb.c +++ b/src/backenddb/test_merchantdb.c @@ -846,14 +846,40 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->mark_proposal_paid (plugin->cls, &h_contract_terms, - &merchant_pub)); + &merchant_pub, + "my-session-123")); + { + char *last_session_id; + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->find_contract_terms (plugin->cls, + &out, + &last_session_id, + order_id, + &merchant_pub)); + FAILIF (0 != strcmp (last_session_id, "my-session-123")); + GNUNET_free (last_session_id); + } + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->find_contract_terms (plugin->cls, - &out, - order_id, - &merchant_pub)); + plugin->mark_proposal_paid (plugin->cls, + &h_contract_terms, + &merchant_pub, + NULL)); + + + { + char *last_session_id; + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + plugin->find_contract_terms (plugin->cls, + &out, + &last_session_id, + order_id, + &merchant_pub)); + FAILIF (0 != strcmp (last_session_id, "")); + GNUNET_free (last_session_id); + } FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->find_contract_terms_history (plugin->cls, @@ -900,7 +926,8 @@ run (void *cls) FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->mark_proposal_paid (plugin->cls, &h_contract_terms_future, - &merchant_pub)); + &merchant_pub, + "hello")); FAILIF (2 != plugin->find_contract_terms_by_date_and_range (plugin->cls, fake_now, @@ -920,14 +947,6 @@ run (void *cls) NULL)); FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->store_transaction (plugin->cls, - &h_contract_terms, - &merchant_pub, - &h_wire, - timestamp, - refund_deadline, - &amount_with_fee)); - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->store_deposit (plugin->cls, &h_contract_terms, &merchant_pub, @@ -951,29 +970,6 @@ run (void *cls) GNUNET_TIME_UNIT_ZERO_ABS, &signkey_pub, transfer_proof)); - { - struct GNUNET_HashCode ah_wire; - struct GNUNET_TIME_Absolute atimestamp; - struct GNUNET_TIME_Absolute arefund_deadline; - struct TALER_Amount atotal_amount; - - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - plugin->find_transaction (plugin->cls, - &h_contract_terms, - &merchant_pub, - &ah_wire, - &atimestamp, - &arefund_deadline, - &atotal_amount)); - FAILIF (0 != memcmp (&ah_wire, - &h_wire, - sizeof (struct GNUNET_HashCode))); - FAILIF (atimestamp.abs_value_us != timestamp.abs_value_us); - FAILIF (arefund_deadline.abs_value_us != refund_deadline.abs_value_us); - FAILIF (0 != TALER_amount_cmp (&atotal_amount, - &amount_with_fee)); - } - FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != plugin->find_payments (plugin->cls, diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index 1005e6c5..6f497b00 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -233,18 +233,22 @@ struct TALER_MERCHANTDB_Plugin * @param cls closure * @param h_contract_terms hash of the contract that is now paid * @param merchant_pub merchant's public key + * @param last_session_id session id used for the payment, NULL + * if payment was not session-bound * @return transaction status */ enum GNUNET_DB_QueryStatus (*mark_proposal_paid) (void *cls, const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub); + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *last_session_id); /** * Retrieve proposal data given its order ID. * * @param cls closure * @param[out] contract_terms where to store the result + * @param[out] last_session_id where to store the result * @param order_id order_id used to lookup. * @param merchant_pub instance's public key. * @return transaction status @@ -252,6 +256,7 @@ struct TALER_MERCHANTDB_Plugin enum GNUNET_DB_QueryStatus (*find_contract_terms) (void *cls, json_t **contract_terms, + char **last_session_id, const char *order_id, const struct TALER_MerchantPublicKeyP *merchant_pub); @@ -373,28 +378,6 @@ struct TALER_MERCHANTDB_Plugin /** - * Insert transaction data into the database. - * - * @param cls closure - * @param h_contract_terms proposal data's hashcode - * @param merchant_pub merchant's public key - * @param h_wire hash of our wire details - * @param timestamp time of the confirmation - * @param refund refund deadline - * @param total_amount total amount we receive for the contract after fees - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*store_transaction) (void *cls, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund, - const struct TALER_Amount *total_amount); - - - /** * Insert payment confirmation from the exchange into the database. * * @param cls closure @@ -487,43 +470,6 @@ struct TALER_MERCHANTDB_Plugin const struct TALER_MasterSignatureP *exchange_sig); - /** - * Find information about a transaction. - * - * @param cls our plugin handle - * @param date limit to transactions' age - * @param cb function to call with transaction data - * @param cb_cls closure for @a cb - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*find_transactions_by_date) (void *cls, - struct GNUNET_TIME_Absolute date, - TALER_MERCHANTDB_TransactionCallback cb, - void *cb_cls); - - - /** - * Find information about a transaction. - * - * @param cls our plugin handle - * @param h_contract_terms proposal data's hashcode - * @param merchant_pub merchant's public key. - * @param[out] h_wire set to hash of wire details - * @param[out] timestamp set to timestamp - * @param[out] refund_deadline set to refund deadline - * @param[out] total_amount set to total amount - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*find_transaction) (void *cls, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute *timestamp, - struct GNUNET_TIME_Absolute *refund_deadline, - struct TALER_Amount *total_amount); - /** * Lookup information about coin payments by proposal data's hashcode. |