gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-merchant] branch master updated: Change '/pay' API a


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch master updated: Change '/pay' API according to #4891
Date: Sun, 12 Feb 2017 02:55:47 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new 053798e  Change '/pay' API according to #4891
053798e is described below

commit 053798e564dcaf640e26208078293268362b9dcc
Author: Florian Dold <address@hidden>
AuthorDate: Sun Feb 12 02:55:12 2017 +0100

    Change '/pay' API according to #4891
---
 src/backend/taler-merchant-httpd_pay.c      | 523 +++++++++++++++-------------
 src/backend/taler-merchant-httpd_proposal.c |   2 +
 src/include/taler_merchant_service.h        |  12 +-
 src/lib/merchant_api_pay.c                  | 158 ++-------
 src/lib/test_merchant_api.c                 |   1 +
 5 files changed, 316 insertions(+), 380 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_pay.c 
b/src/backend/taler-merchant-httpd_pay.c
index 052d2aa..89039ed 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -38,11 +38,6 @@
  */
 #define PAY_TIMEOUT (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
30))
 
-/**
- * The instance which is working this request
- */
-struct MerchantInstance *mi;
-
 
 /**
  * Information we keep for an individual call to the /pay handler.
@@ -247,6 +242,12 @@ struct PayContext
    */
   struct MerchantInstance *mi;
 
+  /**
+   * Proposal data for the proposal that is being
+   * payed for in this context.
+   */
+  json_t *proposal_data;
+
 };
 
 
@@ -428,12 +429,13 @@ deposit_cb (void *cls,
   mr.purpose.size = htonl (sizeof (mr));
   mr.h_proposal_data = pc->h_proposal_data;
 
-  GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
+  GNUNET_CRYPTO_eddsa_sign (&pc->mi->privkey.eddsa_priv,
                             &mr.purpose,
                            &sig);
   resume_pay_with_response (pc,
                             MHD_HTTP_OK,
-                            TMH_RESPONSE_make_json_pack ("{s:s, s:o}",
+                            TMH_RESPONSE_make_json_pack ("{s:o, s:s, s:o}",
+                                                         "proposal_data", 
pc->proposal_data,
                                                          "sig",
                                                         json_string_value 
(GNUNET_JSON_from_data_auto (&sig)),
                                                          "h_proposal_data",
@@ -496,6 +498,11 @@ pay_context_cleanup (struct TM_HandlerContext *hc)
     GNUNET_free (pc->chosen_exchange);
     pc->chosen_exchange = NULL;
   }
+  if (NULL != pc->proposal_data)
+  {
+    json_decref (pc->proposal_data);
+    pc->proposal_data = NULL;
+  }
   GNUNET_free (pc);
 }
 
@@ -884,277 +891,241 @@ transaction_double_check (void *cls,
   return;
 }
 
+
+
 /**
- * Accomplish this payment.
+ * Try to parse the pay request into the given pay context.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure
- *       (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a
- *       upload_data
- * @return MHD result code
+ * Schedules an error response in the connection on failure.
+ *
+ * @return #GNUNET_YES on success
  */
-int
-MH_handler_pay (struct TMH_RequestHandler *rh,
-               struct MHD_Connection *connection,
-               void **connection_cls,
-               const char *upload_data,
-               size_t *upload_data_size)
+static int
+parse_pay (struct MHD_Connection *connection, json_t *root, struct PayContext 
*pc)
 {
-  struct PayContext *pc;
+  json_t *coins;
+  json_t *coin;
+  json_t *merchant;
+  unsigned int coins_index;
+  const char *chosen_exchange;
+  const char *order_id;
+  struct GNUNET_HashCode h_oid;
+  struct TALER_MerchantPublicKeyP merchant_pub;
   int res;
-  json_t *root;
-  struct GNUNET_TIME_Absolute now;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "In handler for /pay.\n");
-  if (NULL == *connection_cls)
-  {
-    pc = GNUNET_new (struct PayContext);
-    pc->hc.cc = &pay_context_cleanup;
-    pc->connection = connection;
-    *connection_cls = pc;
-  }
-  else
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_json ("coins", &coins),
+    GNUNET_JSON_spec_string ("exchange", &chosen_exchange),
+    GNUNET_JSON_spec_string ("order_id", &order_id),
+    GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
+    GNUNET_JSON_spec_end()
+  };
+
+  res = TMH_PARSE_json_data (connection,
+                             root,
+                             spec);
+  if (GNUNET_YES != res)
   {
-    /* not the first call, recover state */
-    pc = *connection_cls;
+    GNUNET_break (0);
+    return res;
   }
-  if (0 != pc->response_code)
+
+  GNUNET_CRYPTO_hash (order_id,
+                      strlen (order_id),
+                      &h_oid);
+
+  res = db->find_proposal_data (db->cls,
+                                &pc->proposal_data,
+                                &h_oid,
+                                &merchant_pub);
+
+
+  if (GNUNET_OK != res)
   {
-    /* We are *done* processing the request, just queue the response (!) */
-    if (UINT_MAX == pc->response_code)
+
+    if (MHD_YES != TMH_RESPONSE_reply_not_found (connection,
+                                                 
TALER_EC_PAY_DB_STORE_PAY_ERROR,
+                                                 "Proposal not found"))
     {
       GNUNET_break (0);
-      return MHD_NO; /* hard error */
+      return GNUNET_SYSERR;
     }
-    res = MHD_queue_response (connection,
-                             pc->response_code,
-                             pc->response);
-    if (NULL != pc->response)
+    return GNUNET_NO;
+  }
+
+
+  if (GNUNET_OK != TALER_JSON_hash (pc->proposal_data, &pc->h_proposal_data))
+  {
+    if (MHD_YES != TMH_RESPONSE_reply_internal_error (connection,
+                                                      TALER_EC_NONE,
+                                                      "Can not hash proposal"))
     {
-      MHD_destroy_response (pc->response);
-      pc->response = NULL;
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
     }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Queueing response (%u) for /pay (%s).\n",
-               (unsigned int) pc->response_code,
-               res ? "OK" : "FAILED");
-    return res;
+    return GNUNET_NO;
   }
-  if (NULL != pc->chosen_exchange)
+
+
+  merchant = json_object_get (pc->proposal_data, "merchant");
+  if (NULL == merchant)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Shouldn't be here. Old MHD version?\n");
-    return MHD_YES;
+    // invalid contract:
+    GNUNET_break (0);
+    if (MHD_YES != TMH_RESPONSE_reply_internal_error (connection,
+                                                      TALER_EC_NONE,
+                                                      "No merchant field in 
contract"))
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_NO;
   }
-  res = TMH_PARSE_post_json (connection,
-                            &pc->json_parse_context,
-                            upload_data,
-                            upload_data_size,
-                            &root);
-  if (GNUNET_SYSERR == res)
+  pc->mi = get_instance (merchant);
+
+  if (NULL == pc->mi)
   {
-    GNUNET_break (0);
-    return TMH_RESPONSE_reply_invalid_json (connection);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Not able to find the specified instance\n");
+    if (MHD_NO == TMH_RESPONSE_reply_not_found (connection,
+                                                TALER_EC_PAY_INSTANCE_UNKNOWN,
+                                                "Unknown instance given"))
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_NO;
   }
-  if ((GNUNET_NO == res) || (NULL == root))
-    return MHD_YES; /* the POST's body has to be further fetched */
 
-  mi = get_instance (root);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "/pay: picked instance %s with key %s\n",
+              pc->mi->id,
+              GNUNET_STRINGS_data_to_string_alloc (&pc->mi->pubkey, sizeof 
(pc->mi->pubkey)));
+
+  pc->chosen_exchange = GNUNET_strdup (chosen_exchange);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Parsed JSON for /pay.\n");
+
+
 
-  /* Got the JSON upload, parse it */
   {
-    json_t *coins;
-    json_t *coin;
-    unsigned int coins_index;
-    struct TALER_MerchantSignatureP merchant_sig;
-    struct TALER_ProposalDataPS pdps;
-    const char *chosen_exchange;
-    struct GNUNET_JSON_Specification spec[] = {
-      TALER_JSON_spec_amount ("amount", &pc->amount),
-      GNUNET_JSON_spec_json ("coins", &coins),
-      GNUNET_JSON_spec_fixed_auto ("h_proposal_data", &pc->h_proposal_data),
-      TALER_JSON_spec_amount ("max_fee", &pc->max_fee),
-      GNUNET_JSON_spec_fixed_auto ("merchant_sig", &merchant_sig),
-      GNUNET_JSON_spec_string ("exchange", &chosen_exchange),
-      GNUNET_JSON_spec_absolute_time ("refund_deadline", &pc->refund_deadline),
-      GNUNET_JSON_spec_absolute_time ("pay_deadline", &pc->pay_deadline),
-      GNUNET_JSON_spec_absolute_time ("timestamp", &pc->timestamp),
+    struct GNUNET_JSON_Specification espec[] = {
+      GNUNET_JSON_spec_absolute_time ("refund_deadline",
+                                      &pc->refund_deadline),
+      GNUNET_JSON_spec_absolute_time ("pay_deadline",
+                                      &pc->pay_deadline),
+      GNUNET_JSON_spec_absolute_time ("timestamp",
+                                      &pc->timestamp),
+      TALER_JSON_spec_amount ("max_fee",
+                              &pc->max_fee),
+      TALER_JSON_spec_amount ("amount",
+                              &pc->amount),
       GNUNET_JSON_spec_end()
     };
 
     res = TMH_PARSE_json_data (connection,
-                              root,
-                              spec);
+                               pc->proposal_data,
+                               espec);
     if (GNUNET_YES != res)
     {
-      json_decref (root);
+      GNUNET_JSON_parse_free (spec);
       GNUNET_break (0);
       return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
     }
-    pc->mi = get_instance (root);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-               "/pay: picked instance %s\n",
-               pc->mi->id);
-
-    if (NULL == pc->mi)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "Not able to find the specified instance\n");
-      json_decref (root);
-      return TMH_RESPONSE_reply_not_found (connection,
-                                          TALER_EC_PAY_INSTANCE_UNKNOWN,
-                                          "Unknown instance given");
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "The instance for this deposit is '%s', whose bank details are 
'%s'\n",
-               pc->mi->id,
-               json_dumps (pc->mi->j_wire,
-                           JSON_COMPACT));
-    pc->chosen_exchange = GNUNET_strdup (chosen_exchange);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               "Parsed JSON for /pay.\n");
-    pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
-    pdps.purpose.size = htonl (sizeof (pdps));
-    pdps.hash = pc->h_proposal_data;
 
-    struct GNUNET_HashCode dummy;
+    pc->wire_transfer_deadline = GNUNET_TIME_absolute_add (pc->timestamp, 
wire_transfer_delay);
 
-    GNUNET_CRYPTO_hash (&merchant_sig.eddsa_sig,
-                        sizeof (merchant_sig.eddsa_sig),
-                        &dummy);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Verifying signature '%s'\n",
-                GNUNET_h2s (&dummy));
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "of hashed data '%s'\n",
-                GNUNET_h2s (&pc->h_proposal_data));
-
-    GNUNET_CRYPTO_hash (&pc->mi->privkey.eddsa_priv,
-                        sizeof (pc->mi->privkey.eddsa_priv),
-                        &dummy);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "with private key '%s'\n",
-                GNUNET_h2s (&dummy));
-
-    if (GNUNET_OK !=
-       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_CONTRACT,
-                                   &pdps.purpose,
-                                   &merchant_sig.eddsa_sig,
-                                   &pc->mi->pubkey.eddsa_pub))
+    if (pc->wire_transfer_deadline.abs_value_us < 
pc->refund_deadline.abs_value_us)
     {
       GNUNET_break (0);
       GNUNET_JSON_parse_free (spec);
-      json_decref (root);
       return TMH_RESPONSE_reply_external_error (connection,
-                                               
TALER_EC_PAY_MERCHANT_SIGNATURE_INVALID,
-                                               "invalid merchant signature 
supplied");
+                                                
TALER_EC_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE,
+                                                "refund deadline after wire 
transfer deadline");
     }
+  }
 
-    /* 'wire_transfer_deadline' is optional, if it is not present,
-       generate it here; it will be timestamp plus the
-       wire_transfer_delay supplied in config file */
-    if (NULL == json_object_get (root,
-                                "wire_transfer_deadline"))
-    {
-      pc->wire_transfer_deadline
-       = GNUNET_TIME_absolute_add (pc->timestamp,
-                                   wire_transfer_delay);
-      if (pc->wire_transfer_deadline.abs_value_us < 
pc->refund_deadline.abs_value_us)
-      {
-       /* Refund value very large, delay wire transfer accordingly */
-       pc->wire_transfer_deadline = pc->refund_deadline;
-      }
-    }
-    else
-    {
-      struct GNUNET_JSON_Specification espec[] = {
-       GNUNET_JSON_spec_absolute_time ("wire_transfer_deadline",
-                                       &pc->wire_transfer_deadline),
-       GNUNET_JSON_spec_end()
-      };
-
-      res = TMH_PARSE_json_data (connection,
-                                root,
-                                espec);
-      if (GNUNET_YES != res)
-      {
-       GNUNET_JSON_parse_free (spec);
-       json_decref (root);
-       GNUNET_break (0);
-       return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-      }
-      if (pc->wire_transfer_deadline.abs_value_us < 
pc->refund_deadline.abs_value_us)
-      {
-       GNUNET_break (0);
-       GNUNET_JSON_parse_free (spec);
-       json_decref (root);
-       return TMH_RESPONSE_reply_external_error (connection,
-                                                 
TALER_EC_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE,
-                                                 "refund deadline after wire 
transfer deadline");
-      }
-    }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "parsed timestamps\n");
+
+
+  pc->coins_cnt = json_array_size (coins);
+  if (0 == pc->coins_cnt)
+  {
+    GNUNET_JSON_parse_free (spec);
+    return TMH_RESPONSE_reply_arg_invalid (connection,
+                                           TALER_EC_PAY_COINS_ARRAY_EMPTY,
+                                           "coins");
+  }
+  /* note: 1 coin = 1 deposit confirmation expected */
+  pc->dc = GNUNET_new_array (pc->coins_cnt,
+                             struct DepositConfirmation);
 
+  /* This loop populates the array 'dc' in 'pc' */
+  json_array_foreach (coins, coins_index, coin)
+  {
+    struct DepositConfirmation *dc = &pc->dc[coins_index];
+    struct GNUNET_JSON_Specification spec[] = {
+      TALER_JSON_spec_denomination_public_key ("denom_pub", &dc->denom),
+      TALER_JSON_spec_amount ("f" /* FIXME */, &dc->amount_with_fee),
+      GNUNET_JSON_spec_fixed_auto ("coin_pub", &dc->coin_pub),
+      TALER_JSON_spec_denomination_signature ("ub_sig", &dc->ub_sig),
+      GNUNET_JSON_spec_fixed_auto ("coin_sig", &dc->coin_sig),
+      GNUNET_JSON_spec_end()
+    };
 
-    pc->coins_cnt = json_array_size (coins);
-    if (0 == pc->coins_cnt)
+    res = TMH_PARSE_json_data (connection,
+                               coin,
+                               spec);
+    if (GNUNET_YES != res)
     {
       GNUNET_JSON_parse_free (spec);
       json_decref (root);
-      return TMH_RESPONSE_reply_arg_invalid (connection,
-                                            TALER_EC_PAY_COINS_ARRAY_EMPTY,
-                                            "coins");
+      GNUNET_break (0);
+      return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
     }
-    /* note: 1 coin = 1 deposit confirmation expected */
-    pc->dc = GNUNET_new_array (pc->coins_cnt,
-                              struct DepositConfirmation);
 
-    /* This loop populates the array 'dc' in 'pc' */
-    json_array_foreach (coins, coins_index, coin)
     {
-      struct DepositConfirmation *dc = &pc->dc[coins_index];
-      struct GNUNET_JSON_Specification spec[] = {
-       TALER_JSON_spec_denomination_public_key ("denom_pub", &dc->denom),
-       TALER_JSON_spec_amount ("f" /* FIXME */, &dc->amount_with_fee),
-       GNUNET_JSON_spec_fixed_auto ("coin_pub", &dc->coin_pub),
-       TALER_JSON_spec_denomination_signature ("ub_sig", &dc->ub_sig),
-       GNUNET_JSON_spec_fixed_auto ("coin_sig", &dc->coin_sig),
-       GNUNET_JSON_spec_end()
-      };
-
-      res = TMH_PARSE_json_data (connection,
-                                coin,
-                                spec);
-      if (GNUNET_YES != res)
-      {
-       GNUNET_JSON_parse_free (spec);
-       json_decref (root);
-       GNUNET_break (0);
-       return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
-      }
+      char *s;
+
+      s = TALER_amount_to_string (&dc->amount_with_fee);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Coin #%i has f %s\n",
+                  coins_index,
+                  s);
+      GNUNET_free (s);
+   }
+
+    dc->index = coins_index;
+    dc->pc = pc;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "parsed coins\n");
 
-      {
-       char *s;
-
-       s = TALER_amount_to_string (&dc->amount_with_fee);
-       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                   "Coin #%i has f %s\n",
-                   coins_index,
-                   s);
-       GNUNET_free (s);
-     }
-
-      dc->index = coins_index;
-      dc->pc = pc;
-    }
-    GNUNET_JSON_parse_free (spec);
-  } /* end of parsing of JSON upload */
   pc->pending = pc->coins_cnt;
 
+  GNUNET_JSON_parse_free (spec);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Process a payment for a proposal.
+ */
+static int
+handler_pay_json (struct MHD_Connection *connection,
+                  json_t *root,
+                  struct PayContext *pc)
+{
+  int ret;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "about to parse '/pay' body\n");
+
+  ret = parse_pay (connection, root, pc);
+  if (GNUNET_OK != ret)
+    return ret;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "parsed '/pay' body\n");
+
   /* Check if this payment attempt has already succeeded */
   if (GNUNET_SYSERR ==
       db->find_payments (db->cls,
@@ -1164,7 +1135,6 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
                         pc))
   {
     GNUNET_break (0);
-    json_decref (root);
     return TMH_RESPONSE_reply_internal_error (connection,
                                              
TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR,
                                              "Merchant database error");
@@ -1183,7 +1153,6 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
                              MHD_HTTP_OK,
                              resp);
     MHD_destroy_response (resp);
-    json_decref (root);
     return ret;
   }
   /* Check if transaction is already known, if not store it. */
@@ -1195,7 +1164,6 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
                             pc))
   {
     GNUNET_break (0);
-    json_decref (root);
     return TMH_RESPONSE_reply_internal_error (connection,
                                              
TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR,
                                                "Merchant database error");
@@ -1203,16 +1171,17 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
   if (GNUNET_SYSERR == pc->transaction_exits)
   {
     GNUNET_break (0);
-    json_decref (root);
     return TMH_RESPONSE_reply_external_error (connection,
                                               
TALER_EC_PAY_DB_TRANSACTION_ID_CONFLICT,
                                              "Transaction ID reused with 
different transaction details");
   }
   if (GNUNET_NO == pc->transaction_exits)
   {
+    struct GNUNET_TIME_Absolute now;
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Dealing with new transaction '%s'\n",
                 GNUNET_h2s (&pc->h_proposal_data));
+
     now = GNUNET_TIME_absolute_get ();
     if (now.abs_value_us > pc->pay_deadline.abs_value_us)
     {
@@ -1243,7 +1212,6 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
                                &pc->amount))
     {
       GNUNET_break (0);
-      json_decref (root);
       return TMH_RESPONSE_reply_internal_error (connection,
                                                
TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR,
                                                "Merchant database error");
@@ -1272,7 +1240,94 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
   pc->timeout_task = GNUNET_SCHEDULER_add_delayed (PAY_TIMEOUT,
                                                    &handle_pay_timeout,
                                                    pc);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Process a payment for a proposal.
+ * Takes data from the given MHD connection.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure
+ *       (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a
+ *       upload_data
+ * @return MHD result code
+ */
+int
+MH_handler_pay (struct TMH_RequestHandler *rh,
+               struct MHD_Connection *connection,
+               void **connection_cls,
+               const char *upload_data,
+               size_t *upload_data_size)
+{
+  struct PayContext *pc;
+  int res;
+  json_t *root;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "In handler for /pay.\n");
+  if (NULL == *connection_cls)
+  {
+    pc = GNUNET_new (struct PayContext);
+    pc->hc.cc = &pay_context_cleanup;
+    pc->connection = connection;
+    *connection_cls = pc;
+  }
+  else
+  {
+    /* not the first call, recover state */
+    pc = *connection_cls;
+  }
+  if (0 != pc->response_code)
+  {
+    /* We are *done* processing the request, just queue the response (!) */
+    if (UINT_MAX == pc->response_code)
+    {
+      GNUNET_break (0);
+      return MHD_NO; /* hard error */
+    }
+    res = MHD_queue_response (connection,
+                             pc->response_code,
+                             pc->response);
+    if (NULL != pc->response)
+    {
+      MHD_destroy_response (pc->response);
+      pc->response = NULL;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Queueing response (%u) for /pay (%s).\n",
+               (unsigned int) pc->response_code,
+               res ? "OK" : "FAILED");
+    return res;
+  }
+  if (NULL != pc->chosen_exchange)
+  {
+    // FIXME: explain in comment why this could happen!
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Shouldn't be here. Old MHD version?\n");
+    return MHD_YES;
+  }
+  res = TMH_PARSE_post_json (connection,
+                            &pc->json_parse_context,
+                            upload_data,
+                            upload_data_size,
+                            &root);
+  if (GNUNET_SYSERR == res)
+  {
+    GNUNET_break (0);
+    return TMH_RESPONSE_reply_invalid_json (connection);
+  }
+  if ((GNUNET_NO == res) || (NULL == root))
+    return MHD_YES; /* the POST's body has to be further fetched */
+
+  res = handler_pay_json (connection, root, pc);
   json_decref (root);
+  if (GNUNET_SYSERR == res)
+    return MHD_NO;
   return MHD_YES;
 }
 
diff --git a/src/backend/taler-merchant-httpd_proposal.c 
b/src/backend/taler-merchant-httpd_proposal.c
index 0ee23c8..3b5660d 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -289,6 +289,8 @@ MH_handler_proposal_put (struct TMH_RequestHandler *rh,
   GNUNET_CRYPTO_hash (order_id,
                       strlen (order_id),
                       &h_oid);
+
+
   if (GNUNET_OK !=
       db->insert_proposal_data (db->cls,
                                 &h_oid,
diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index 6c549c8..99bab17 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -248,6 +248,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
                            struct GNUNET_TIME_Absolute pay_deadline,
                            const struct GNUNET_HashCode *h_wire,
                           const char *exchange_uri,
+                           const char *order_id,
                            unsigned int num_coins,
                            const struct TALER_MERCHANT_PayCoin *coins,
                            TALER_MERCHANT_PayCallback pay_cb,
@@ -327,15 +328,8 @@ struct TALER_MERCHANT_PaidCoin
 struct TALER_MERCHANT_Pay *
 TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
                             const char *merchant_uri,
-                            const char *instance,
-                             const struct GNUNET_HashCode *h_contract,
-                            const struct TALER_Amount *amount,
-                            const struct TALER_Amount *max_fee,
-                             const struct TALER_MerchantSignatureP 
*merchant_sig,
-                             struct GNUNET_TIME_Absolute refund_deadline,
-                             struct GNUNET_TIME_Absolute pay_deadline,
-                             struct GNUNET_TIME_Absolute timestamp,
-                             struct GNUNET_TIME_Absolute 
wire_transfer_deadline,
+                             const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                            const char *order_id,
                             const char *exchange_uri,
                              unsigned int num_coins,
                              const struct TALER_MERCHANT_PaidCoin *coins,
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c
index 76c247a..6910bde 100644
--- a/src/lib/merchant_api_pay.c
+++ b/src/lib/merchant_api_pay.c
@@ -288,6 +288,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
                            struct GNUNET_TIME_Absolute pay_deadline,
                            const struct GNUNET_HashCode *h_wire,
                           const char *exchange_uri,
+                           const char *order_id,
                            unsigned int num_coins,
                            const struct TALER_MERCHANT_PayCoin *coins,
                            TALER_MERCHANT_PayCallback pay_cb,
@@ -301,6 +302,14 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
   (void) GNUNET_TIME_round_abs (&pay_deadline);
   (void) GNUNET_TIME_round_abs (&refund_deadline);
 
+  if (GNUNET_YES !=
+      TALER_amount_cmp_currency (amount,
+                                 max_fee))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
   dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
   dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
   dr.h_proposal_data = *h_proposal_data;
@@ -331,6 +340,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
     }
     TALER_amount_hton (&dr.deposit_fee,
                       &fee);
+
     GNUNET_CRYPTO_eddsa_sign (&coin->coin_priv.eddsa_priv,
                              &dr.purpose,
                              &p->coin_sig.eddsa_signature);
@@ -343,15 +353,8 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
   }
   return TALER_MERCHANT_pay_frontend (ctx,
                                      merchant_uri,
-                                      instance,
-                                     h_proposal_data,
-                                      amount,
-                                     max_fee,
-                                     merchant_sig,
-                                     refund_deadline,
-                                     pay_deadline,
-                                     timestamp,
-                                     GNUNET_TIME_UNIT_ZERO_ABS,
+                                      merchant_pub,
+                                      order_id,
                                      exchange_uri,
                                      num_coins,
                                      pc,
@@ -368,19 +371,9 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
  *
  * @param ctx the execution loop context
  * @param merchant_uri base URI of the merchant's backend
- * @param instance which merchant instance will receive this payment
- * @param h_contract hash of the contact of the merchant with the customer
- * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
- * @param transaction_id transaction id for the transaction between merchant 
and customer
- * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the merchant (can be zero if refunds are not allowed)
- * @param deadline to pay for this contract
- * @param wire_transfer_deadline date by which the merchant would like the 
exchange to execute the wire transfer (can be zero if there is no specific date 
desired by the frontend). If non-zero, must be larger than @a refund_deadline.
  * @param exchange_uri URI of the exchange that the coins belong to
  * @param num_coins number of coins used to pay
  * @param coins array of coins we use to pay
- * @param coin_sig the signature made with purpose 
#TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s 
private key.
- * @param max_fee maximum fee covered by the merchant (according to the 
contract)
- * @param amount total value of the contract to be paid to the merchant
  * @param pay_cb the callback to call when a reply for this request is 
available
  * @param pay_cb_cls closure for @a pay_cb
  * @return a handle for this request
@@ -388,15 +381,8 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
 struct TALER_MERCHANT_Pay *
 TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
                             const char *merchant_uri,
-                            const char *instance,
-                             const struct GNUNET_HashCode *h_proposal_data,
-                            const struct TALER_Amount *amount,
-                            const struct TALER_Amount *max_fee,
-                             const struct TALER_MerchantSignatureP 
*merchant_sig,
-                             struct GNUNET_TIME_Absolute refund_deadline,
-                             struct GNUNET_TIME_Absolute pay_deadline,
-                             struct GNUNET_TIME_Absolute timestamp,
-                             struct GNUNET_TIME_Absolute 
wire_transfer_deadline,
+                             const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                             const char *order_id,
                             const char *exchange_uri,
                              unsigned int num_coins,
                              const struct TALER_MERCHANT_PaidCoin *coins,
@@ -411,23 +397,6 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context 
*ctx,
   struct TALER_Amount total_amount;
   unsigned int i;
 
-  (void) GNUNET_TIME_round_abs (&timestamp);
-  (void) GNUNET_TIME_round_abs (&refund_deadline);
-  (void) GNUNET_TIME_round_abs (&wire_transfer_deadline);
-
-  if (GNUNET_YES !=
-      TALER_amount_cmp_currency (amount,
-                                 max_fee))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  if ( (0 != wire_transfer_deadline.abs_value_us) &&
-       (wire_transfer_deadline.abs_value_us < refund_deadline.abs_value_us) )
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
   if (0 == num_coins)
   {
     GNUNET_break (0);
@@ -489,101 +458,16 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context 
*ctx,
                                           j_coin));
   }
 
-  { /* Sanity check that total_amount and total_fee
-       match amount/max_fee requirements */
-    struct TALER_Amount fee_left;
-
-    if (GNUNET_OK ==
-       TALER_amount_subtract (&fee_left,
-                              &total_fee,
-                              max_fee))
-    {
-      /* Wallet must cover part of the fee! */
-      struct TALER_Amount new_amount;
-
-      if (GNUNET_OK !=
-         TALER_amount_add (&new_amount,
-                           &fee_left,
-                           amount))
-      {
-       /* integer overflow */
-       GNUNET_break (0);
-       json_decref (j_coins);
-       return NULL;
-      }
-      if (GNUNET_YES !=
-          TALER_amount_cmp_currency (&new_amount,
-                                     &total_amount))
-      {
-        GNUNET_break (0);
-       json_decref (j_coins);
-        return NULL;
-      }
-      if (1 ==
-         TALER_amount_cmp (&new_amount,
-                           &total_amount))
-      {
-       /* new_amount > total_amount: all of the coins (total_amount)
-          do not add up to at least the new_amount owed to the
-          merchant, this request is bogus, abort */
-       GNUNET_break (0);
-       json_decref (j_coins);
-       return NULL;
-      }
-    }
-    else
-    {
-      /* Full fee covered by merchant, but our total
-        must at least cover the total contract amount */
-      if (GNUNET_YES !=
-          TALER_amount_cmp_currency (amount,
-                                     &total_amount))
-      {
-        GNUNET_break (0);
-       json_decref (j_coins);
-        return NULL;
-      }
-      if (1 ==
-         TALER_amount_cmp (amount,
-                           &total_amount))
-       {
-         /* amount > total_amount: all of the coins (total_amount) do
-          not add up to at least the amount owed to the merchant,
-          this request is bogus, abort */
-       GNUNET_break (0);
-       json_decref (j_coins);
-       return NULL;
-      }
-    }
-  } /* end of sanity check */
-
-  pay_obj = json_pack ("{s:o," /* h_proposal_data */
-                       " s:o," /* timestamp */
-                       " s:o, s:o," /* refund_deadline, pay_deadline */
+  pay_obj = json_pack ("{"
                        " s:s," /* exchange */
-                       " s:o, s:o," /* coins, max_fee */
-                       " s:o, s:o}",/* amount, signature */
-                       "h_proposal_data", GNUNET_JSON_from_data_auto 
(h_proposal_data),
-                       "timestamp", GNUNET_JSON_from_time_abs (timestamp),
-                       "refund_deadline", GNUNET_JSON_from_time_abs 
(refund_deadline),
-                       "pay_deadline", GNUNET_JSON_from_time_abs 
(pay_deadline),
+                       " s:o," /* coins */
+                       " s:s," /* order_id */
+                       " s:o," /* merchant_pub */
+                       "}",
                       "exchange", exchange_uri,
                       "coins", j_coins,
-                       "max_fee", TALER_JSON_from_amount (max_fee),
-                       "amount", TALER_JSON_from_amount (amount),
-                       "merchant_sig", GNUNET_JSON_from_data_auto 
(merchant_sig));
-  if (NULL != instance)
-    json_object_set_new (pay_obj,
-                         "instance",
-                         json_string (instance));
-
-  if (0 != wire_transfer_deadline.abs_value_us)
-  {
-    /* Frontend did have an execution date in mind, add it */
-    json_object_set_new (pay_obj,
-                        "wire_transfer_deadline",
-                        GNUNET_JSON_from_time_abs (wire_transfer_deadline));
-  }
+                       "order_id", order_id,
+                       "merchant_pub", GNUNET_JSON_from_data_auto 
(merchant_pub));
 
   ph = GNUNET_new (struct TALER_MERCHANT_Pay);
   ph->ctx = ctx;
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index 0588b5e..679e41a 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -1857,6 +1857,7 @@ interpreter_run (void *cls)
                                     pay_deadline,
                                     &h_wire,
                                     EXCHANGE_URI,
+                                     order_id,
                                     1 /* num_coins */,
                                     &pc /* coins */,
                                     &pay_cb,

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]