summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_post-orders-ID-paid.c
diff options
context:
space:
mode:
authorJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-07-24 03:15:16 -0400
committerJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-07-24 03:15:16 -0400
commit974b2b2c3077c929850c1598af1e1e124f530a7f (patch)
treeb7aca47e38a5cb0e097fdf4726620eaaa0e83f5d /src/backend/taler-merchant-httpd_post-orders-ID-paid.c
parentdc4125387b31155a9a5d9622bb22d5b55da2f2fd (diff)
downloadmerchant-974b2b2c3077c929850c1598af1e1e124f530a7f.tar.gz
merchant-974b2b2c3077c929850c1598af1e1e124f530a7f.tar.bz2
merchant-974b2b2c3077c929850c1598af1e1e124f530a7f.zip
implement & test POST /paid
Diffstat (limited to 'src/backend/taler-merchant-httpd_post-orders-ID-paid.c')
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-paid.c112
1 files changed, 94 insertions, 18 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-paid.c b/src/backend/taler-merchant-httpd_post-orders-ID-paid.c
index 6e6f64aa..623b2760 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-paid.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-paid.c
@@ -46,15 +46,18 @@ TMH_post_orders_ID_paid (const struct TMH_RequestHandler *rh,
.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK),
.purpose.size = htonl (sizeof (pr))
};
+ const char *order_id = hc->infix;
struct TALER_MerchantSignatureP merchant_sig;
const char *session_id;
+ json_t *contract_terms;
+ enum GNUNET_DB_QueryStatus qs;
{
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
- &pr.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("merchant_sig",
+ GNUNET_JSON_spec_fixed_auto ("sig",
&merchant_sig),
+ GNUNET_JSON_spec_fixed_auto ("h_contract",
+ &pr.h_contract_terms),
GNUNET_JSON_spec_string ("session_id",
&session_id),
GNUNET_JSON_spec_end ()
@@ -73,7 +76,7 @@ TMH_post_orders_ID_paid (const struct TMH_RequestHandler *rh,
}
}
-#if FIXME
+
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
&pr,
@@ -86,31 +89,104 @@ TMH_post_orders_ID_paid (const struct TMH_RequestHandler *rh,
MHD_HTTP_FORBIDDEN,
"{s:s, s:I}",
"hint", "deposit signature invalid",
- "code", (json_int_t) TALER_EC_PAID_SIGNATURE_INVALID);
+ "code", (json_int_t) TALER_EC_PAID_COIN_SIGNATURE_INVALID);
}
- // FIXME: check that h_contract_terms matches
- // this order-id (and that the order is known),
- // and if it does, update 'session_id' (if non-NULL)
- if (0)
+ TMH_db->preflight (TMH_db->cls);
+ {
+ uint64_t order_serial;
+ qs = TMH_db->lookup_contract_terms (TMH_db->cls,
+ hc->instance->settings.id,
+ order_id,
+ &contract_terms,
+ &order_serial);
+ }
+ if (0 > qs)
+ {
+ /* single, read-only SQL statements should never cause
+ serialization problems */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ /* Always report on hard error as well to enable diagnostics */
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_PAID_DB_ERROR,
+ "database error looking up contract");
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Unknown order id given: `%s'\n",
+ order_id);
return TALER_MHD_reply_json_pack (
connection,
MHD_HTTP_NOT_FOUND,
"{s:s, s:I}",
- "hint", "order unknwown",
+ "hint", "order unknown",
"code", (json_int_t) TALER_EC_PAID_ORDER_UNKNOWN);
}
- if (0)
+
{
- return TALER_MHD_reply_json_pack (
- connection,
- MHD_HTTP_CONFLICT,
- "{s:s, s:I}",
- "hint", "contract hash does not match this order",
- "code", (json_int_t) TALER_EC_PAID_CONTRACT_HASH_MISMATCH);
+ struct GNUNET_HashCode h_contract_terms;
+
+ if (GNUNET_OK !=
+ TALER_JSON_contract_hash (contract_terms,
+ &h_contract_terms))
+ {
+ GNUNET_break (0);
+ json_decref (contract_terms);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_INTERNAL_LOGIC_ERROR,
+ "Could not hash contract terms");
+ }
+ if (0 != GNUNET_memcmp (&pr.h_contract_terms,
+ &h_contract_terms))
+ {
+ json_decref (contract_terms);
+ return TALER_MHD_reply_json_pack (
+ connection,
+ MHD_HTTP_CONFLICT,
+ "{s:s, s:I}",
+ "hint", "contract hash does not match this order",
+ "code", (json_int_t) TALER_EC_PAID_CONTRACT_HASH_MISMATCH);
+ }
+ }
+ if (NULL != session_id)
+ {
+ if (GNUNET_OK !=
+ TMH_db->start (TMH_db->cls,
+ "post /paid"))
+ {
+ json_decref (contract_terms);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_PAID_DB_ERROR,
+ "failed to start database transaction");
+ }
+ qs = TMH_db->mark_contract_paid (TMH_db->cls,
+ hc->instance->settings.id,
+ &pr.h_contract_terms,
+ session_id);
+ /* Since the order was paid already, we get qs == 0. */
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ qs = TMH_db->commit (TMH_db->cls);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ TMH_db->rollback (TMH_db->cls);
+ json_decref (contract_terms);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_PAID_DB_ERROR,
+ "failed to update contract's session id");
+ }
}
-#endif
+ json_decref (contract_terms);
+
return TALER_MHD_reply_static (connection,
MHD_HTTP_NO_CONTENT,
NULL,