[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant] branch master updated: implement #7052
From: |
gnunet |
Subject: |
[taler-merchant] branch master updated: implement #7052 |
Date: |
Sat, 20 Nov 2021 21:22:04 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository merchant.
The following commit(s) were added to refs/heads/master by this push:
new 8edd5641 implement #7052
8edd5641 is described below
commit 8edd5641430d7e352cf9d14edd3e57b6f75642a3
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat Nov 20 21:22:01 2021 +0100
implement #7052
---
src/backend/taler-merchant-httpd.c | 13 +-
src/backend/taler-merchant-httpd.h | 9 +
.../taler-merchant-httpd_post-orders-ID-pay.c | 316 ++++++++++++++++++++-
3 files changed, 328 insertions(+), 10 deletions(-)
diff --git a/src/backend/taler-merchant-httpd.c
b/src/backend/taler-merchant-httpd.c
index 9f460df1..73d3327f 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -199,13 +199,8 @@ TMH_compute_auth (const char *token,
}
-/**
- * Decrement reference counter of @a mi, and free if it hits zero.
- *
- * @param[in,out] mi merchant instance to update and possibly free
- */
-static void
-instance_decref (struct TMH_MerchantInstance *mi)
+void
+TMH_instance_decref (struct TMH_MerchantInstance *mi)
{
struct TMH_WireMethod *wm;
@@ -252,7 +247,7 @@ TMH_instance_free_cb (void *cls,
GNUNET_CONTAINER_multihashmap_remove (TMH_by_id_map,
&mi->h_instance,
mi));
- instance_decref (mi);
+ TMH_instance_decref (mi);
return GNUNET_YES;
}
@@ -360,7 +355,7 @@ handle_mhd_completion_callback (void *cls,
if (NULL != hc->request_body)
json_decref (hc->request_body);
if (NULL != hc->instance)
- instance_decref (hc->instance);
+ TMH_instance_decref (hc->instance);
GNUNET_free (hc);
*con_cls = NULL;
}
diff --git a/src/backend/taler-merchant-httpd.h
b/src/backend/taler-merchant-httpd.h
index 7fbc8bb5..f81b15aa 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -639,6 +639,15 @@ enum GNUNET_GenericReturnValue
TMH_add_instance (struct TMH_MerchantInstance *mi);
+/**
+ * Decrement reference counter of @a mi, and free if it hits zero.
+ *
+ * @param[in,out] mi merchant instance to update and possibly free
+ */
+void
+TMH_instance_decref (struct TMH_MerchantInstance *mi);
+
+
/**
* Lookup a merchant instance by its instance ID.
*
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index fcdb9821..3baf7293 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -46,6 +46,13 @@
*/
#define MAX_COIN_ALLOWED_COINS 1024
+/**
+ * How often do we ask the exchange again about our
+ * KYC status? Very rarely, as if the user actively
+ * changes it, we should usually notice anyway.
+ */
+#define KYC_RETRY_FREQUENCY GNUNET_TIME_UNIT_WEEKS
+
/**
* Information we keep for an individual call to the pay handler.
*/
@@ -359,6 +366,69 @@ struct PayContext
};
+/**
+ * Active KYC operation with an exchange.
+ */
+struct KycContext
+{
+ /**
+ * Kept in a DLL.
+ */
+ struct KycContext *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct KycContext *prev;
+
+ /**
+ * Looking for the exchange.
+ */
+ struct TMH_EXCHANGES_FindOperation *fo;
+
+ /**
+ * Exchange this is about.
+ */
+ char *exchange_url;
+
+ /**
+ * Merchant instance this is for.
+ */
+ struct TMH_MerchantInstance *mi;
+
+ /**
+ * Wire method we are checking the status of.
+ */
+ struct TMH_WireMethod *wm;
+
+ /**
+ * Handle for the GET /deposits operation.
+ */
+ struct TALER_EXCHANGE_DepositGetHandle *dg;
+
+ /**
+ * Contract we are looking up.
+ */
+ struct TALER_PrivateContractHash h_contract_terms;
+
+ /**
+ * Coin we are looking up.
+ */
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+
+ /**
+ * Initial DB timestamp.
+ */
+ struct GNUNET_TIME_Absolute kyc_timestamp;
+
+ /**
+ * Initial KYC status.
+ */
+ bool kyc_ok;
+
+};
+
+
/**
* Head of active pay context DLL.
*/
@@ -369,6 +439,44 @@ static struct PayContext *pc_head;
*/
static struct PayContext *pc_tail;
+/**
+ * Head of active KYC context DLL.
+ */
+static struct KycContext *kc_head;
+
+/**
+ * Tail of active KYC context DLL.
+ */
+static struct KycContext *kc_tail;
+
+
+/**
+ * Free resources used by @a kc.
+ *
+ * @param[in] kc object to free
+ */
+static void
+destroy_kc (struct KycContext *kc)
+{
+ if (NULL != kc->fo)
+ {
+ TMH_EXCHANGES_find_exchange_cancel (kc->fo);
+ kc->fo = NULL;
+ }
+ if (NULL != kc->dg)
+ {
+ TALER_EXCHANGE_deposits_get_cancel (kc->dg);
+ kc->dg = NULL;
+ }
+ TMH_instance_decref (kc->mi);
+ kc->mi = NULL;
+ GNUNET_free (kc->exchange_url);
+ GNUNET_CONTAINER_DLL_remove (kc_head,
+ kc_tail,
+ kc);
+ GNUNET_free (kc);
+}
+
/**
* Compute the timeout for a /pay request based on the number of coins
@@ -419,6 +527,15 @@ abort_active_deposits (struct PayContext *pc)
void
TMH_force_pc_resume ()
{
+ struct KycContext *kc;
+
+ while (NULL != (kc = kc_head))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Aborting KYC check at %s\n",
+ kc->exchange_url);
+ destroy_kc (kc);
+ }
for (struct PayContext *pc = pc_head;
NULL != pc;
pc = pc->next)
@@ -555,6 +672,200 @@ static void
execute_pay_transaction (struct PayContext *pc);
+/**
+ * Function called with detailed wire transfer data.
+ *
+ * @param cls a `struct KycContext *`
+ * @param hr HTTP response data
+ * @param dd details about the deposit (NULL on errors)
+ */
+static void
+deposit_get_callback (
+ void *cls,
+ const struct TALER_EXCHANGE_GetDepositResponse *dr)
+{
+ struct KycContext *kc = cls;
+ enum GNUNET_DB_QueryStatus qs;
+
+ kc->dg = NULL;
+ switch (dr->hr.http_status)
+ {
+ case MHD_HTTP_OK:
+ qs = TMH_db->account_kyc_set_status (
+ TMH_db->cls,
+ kc->mi->settings.id,
+ &kc->wm->h_wire,
+ kc->exchange_url,
+ dr->details.success.payment_target_uuid,
+ NULL, /* no signature */
+ NULL, /* no signature */
+ GNUNET_TIME_absolute_get (),
+ true);
+ GNUNET_break (qs > 0);
+ break;
+ case MHD_HTTP_ACCEPTED:
+ qs = TMH_db->account_kyc_set_status (
+ TMH_db->cls,
+ kc->mi->settings.id,
+ &kc->wm->h_wire,
+ kc->exchange_url,
+ dr->details.accepted.payment_target_uuid,
+ NULL, /* no signature */
+ NULL, /* no signature */
+ GNUNET_TIME_absolute_get (),
+ dr->details.accepted.kyc_ok);
+ GNUNET_break (qs > 0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "KYC check failed at %s with unexpected status %u\n",
+ kc->exchange_url,
+ dr->hr.http_status);
+ }
+ destroy_kc (kc);
+}
+
+
+/**
+ * Function called with the result of our exchange lookup.
+ *
+ * @param cls the `struct KycContext`
+ * @param hr HTTP response details
+ * @param exchange_handle NULL if exchange was not found to be acceptable
+ * @param payto_uri payto://-URI of the exchange
+ * @param wire_fee current applicable fee for dealing with @a exchange_handle,
+ * NULL if not available
+ * @param exchange_trusted true if this exchange is
+ * trusted by config
+ */
+static void
+process_kyc_with_exchange (void *cls,
+ const struct TALER_EXCHANGE_HttpResponse *hr,
+ struct TALER_EXCHANGE_Handle *exchange_handle,
+ const char *payto_uri,
+ const struct TALER_Amount *wire_fee,
+ bool exchange_trusted)
+{
+ struct KycContext *kc = cls;
+
+ kc->fo = NULL;
+ if (NULL == exchange_handle)
+ {
+ destroy_kc (kc);
+ return;
+ }
+ kc->dg = TALER_EXCHANGE_deposits_get (exchange_handle,
+ &kc->mi->merchant_priv,
+ &kc->wm->h_wire,
+ &kc->h_contract_terms,
+ &kc->coin_pub,
+ &deposit_get_callback,
+ kc);
+ if (NULL == kc->dg)
+ {
+ GNUNET_break (0);
+ destroy_kc (kc);
+ }
+}
+
+
+/**
+ * Function called from ``account_kyc_get_status``
+ * with KYC status information for this merchant.
+ *
+ * @param cls a `struct KycContext *`
+ * @param h_wire hash of the wire account
+ * @param exchange_kyc_serial serial number for the KYC process at the
exchange, 0 if unknown
+ * @param payto_uri payto:// URI of the merchant's bank account
+ * @param exchange_url base URL of the exchange for which this is a status
+ * @param last_check when did we last get an update on our KYC status from the
exchange
+ * @param kyc_ok true if we satisfied the KYC requirements
+ */
+static void
+kyc_cb (
+ void *cls,
+ const struct TALER_MerchantWireHash *h_wire,
+ uint64_t exchange_kyc_serial,
+ const char *payto_uri,
+ const char *exchange_url,
+ struct GNUNET_TIME_Absolute last_check,
+ bool kyc_ok)
+{
+ struct KycContext *kc = cls;
+
+ kc->kyc_timestamp = last_check;
+ kc->kyc_ok = kyc_ok;
+}
+
+
+/**
+ * Check for our KYC status at @a exchange_url for the
+ * payment of @a pc. First checks if we already have a
+ * positive result from the exchange, and if not checks
+ * with the exchange.
+ *
+ * @param pc payment context to use as starting point
+ * @param dc deposit confirmation we are triggering on
+ */
+static void
+check_kyc (struct PayContext *pc,
+ const struct DepositConfirmation *dc)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct KycContext *kc;
+
+ kc = GNUNET_new (struct KycContext);
+ qs = TMH_db->account_kyc_get_status (TMH_db->cls,
+ pc->hc->instance->settings.id,
+ &pc->wm->h_wire,
+ dc->exchange_url,
+ &kyc_cb,
+ kc);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ GNUNET_free (kc);
+ return;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ if (kc->kyc_ok)
+ {
+ GNUNET_free (kc);
+ return; /* we are done */
+ }
+ if (GNUNET_TIME_absolute_get_duration (kc->kyc_timestamp).rel_value_us <
+ KYC_RETRY_FREQUENCY.rel_value_us)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Not re-checking KYC status at `%s', as we already recently
asked\n",
+ dc->exchange_url);
+ GNUNET_free (kc);
+ return;
+ }
+ }
+ kc->mi = pc->hc->instance;
+ kc->mi->rc++;
+ kc->wm = pc->wm;
+ kc->exchange_url = GNUNET_strdup (dc->exchange_url);
+ kc->h_contract_terms = pc->h_contract_terms;
+ kc->coin_pub = dc->coin_pub;
+ GNUNET_CONTAINER_DLL_insert (kc_head,
+ kc_tail,
+ kc);
+ kc->fo = TMH_EXCHANGES_find_exchange (dc->exchange_url,
+ NULL,
+ GNUNET_NO,
+ &process_kyc_with_exchange,
+ kc);
+ if (NULL == kc->fo)
+ {
+ GNUNET_break (0);
+ destroy_kc (kc);
+ }
+}
+
+
/**
* Callback to handle a deposit permission's response.
*
@@ -629,6 +940,8 @@ deposit_cb (void *cls,
if (0 != pc->pending_at_ce)
return; /* still more to do with current exchange */
+ check_kyc (pc,
+ dc);
find_next_exchange (pc);
return;
}
@@ -1337,8 +1650,9 @@ trigger_payment_notification (struct PayContext *pc)
/**
+ * Actually perform the payment transaction.
*
- *
+ * @param pc payment transaction to run
*/
static void
execute_pay_transaction (struct PayContext *pc)
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-merchant] branch master updated: implement #7052,
gnunet <=