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: implement TALER_MER


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch master updated: implement TALER_MERCHANT_pay_abort() -- first version, lacks signature verification
Date: Thu, 28 Dec 2017 15:00:38 +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 a7b2d84  implement TALER_MERCHANT_pay_abort() -- first version, lacks 
signature verification
a7b2d84 is described below

commit a7b2d842a460c880ec9811312f129a4b87505615
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Dec 28 15:00:36 2017 +0100

    implement TALER_MERCHANT_pay_abort() -- first version, lacks signature 
verification
---
 src/backend/taler-merchant-httpd_pay.c |  28 +-
 src/include/taler_merchant_service.h   |  67 ++++
 src/lib/merchant_api_pay.c             | 690 ++++++++++++++++++++++++---------
 src/lib/merchant_api_refund.c          |   1 +
 4 files changed, 604 insertions(+), 182 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_pay.c 
b/src/backend/taler-merchant-httpd_pay.c
index 07e6887..da36d00 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -353,6 +353,11 @@ struct PayContext
    * part of #MH_force_pc_resume during shutdown.
    */
   int suspended;
+
+  /**
+   * Which operational mode is the /pay request made in?
+   */
+  enum { PC_MODE_PAY, PC_MODE_ABORT_REFUND } mode;
 };
 
 
@@ -1247,9 +1252,12 @@ parse_pay (struct MHD_Connection *connection,
   json_t *merchant;
   unsigned int coins_index;
   const char *order_id;
+  const char *mode;
   struct TALER_MerchantPublicKeyP merchant_pub;
   int res;
   struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("mode",
+                            &mode),                       
     GNUNET_JSON_spec_json ("coins",
                           &coins),
     GNUNET_JSON_spec_string ("order_id",
@@ -1332,6 +1340,11 @@ parse_pay (struct MHD_Connection *connection,
     }
     return GNUNET_NO;
   }
+  if (0 != strcasecmp ("abort-refund",
+                      mode))
+    pc->mode = PC_MODE_PAY;
+  else
+    pc->mode = PC_MODE_ABORT_REFUND;
   pc->mi = TMH_lookup_instance_json (merchant);
   if (NULL == pc->mi)
   {
@@ -1649,9 +1662,18 @@ begin_transaction (struct PayContext *pc)
     return;
   }
 
-  /* FIXME: check if wallet is going for a refund,
-     (on aborted operation), or for a payment! #5158 */
-
+  if (PC_MODE_ABORT_REFUND == pc->mode)
+  {
+    /* The wallet is going for a refund,
+       (on aborted operation)!
+       FIXME: implement #5158 */
+    resume_pay_with_error (pc,
+                          MHD_HTTP_INTERNAL_SERVER_ERROR,
+                          TALER_EC_NOT_IMPLEMENTED,
+                          "#5158 is still open");
+    return;
+  }
+  /* Default PC_MODE_PAY mode */
 
   /* Final termination case: all coins already known, just 
      generate ultimate outcome. */
diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index a3fca0f..ca90722 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -362,6 +362,73 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
 
 
 /**
+ * Callbacks of this type are used to serve the result of submitting a
+ * /pay request to a merchant.
+ *
+ * @param cls closure
+ * @param http_status HTTP response code, 200 or 300-level response codes
+ *                    can indicate success, depending on whether the 
interaction
+ *                    was with a merchant frontend or backend;
+ *                    0 if the merchant's reply is bogus (fails to follow the 
protocol)
+ * @param ec taler-specific error code
+ * @param num_refunds size of the @a merchant_sigs array, 0 on errors
+ * @param merchant_sigs merchant signatures refunding coins, NULL on errors
+ * @param obj the received JSON reply, with error details if the request failed
+ */
+typedef void
+(*TALER_MERCHANT_PayRefundCallback) (void *cls,
+                                    unsigned int http_status,
+                                    enum TALER_ErrorCode ec,
+                                    unsigned int num_refunds,
+                                    const struct TALER_MerchantSignatureP 
*merchant_sigs,
+                                    const json_t *obj);
+
+
+/**
+ * Run a payment abort operation, asking for refunds for coins
+ * that were previously spend on a /pay that failed to go through.
+ *
+ * @param ctx execution context
+ * @param merchant_url base URL of the merchant
+ * @param instance which merchant instance will receive this payment
+ * @param h_wire hash of the merchant’s account details
+ * @param h_contract hash of the contact of the merchant with the customer
+ * @param transaction_id transaction id for the transaction between merchant 
and customer
+ * @param amount total value of the contract to be paid to the merchant
+ * @param max_fee maximum fee covered by the merchant (according to the 
contract)
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param merchant_sig signature from the merchant over the original contract
+ * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
+ * @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 pay_deadline maximum time limit to pay for this contract
+ * @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 payref_cb the callback to call when a reply for this request is 
available
+ * @param payref_cb_cls closure for @a pay_cb
+ * @return a handle for this request
+ */
+struct TALER_MERCHANT_Pay *
+TALER_MERCHANT_pay_abort (struct GNUNET_CURL_Context *ctx,
+                         const char *merchant_url,
+                         const char *instance,
+                         const struct GNUNET_HashCode *h_contract,
+                         const struct TALER_Amount *amount,
+                         const struct TALER_Amount *max_fee,
+                         const struct TALER_MerchantPublicKeyP *merchant_pub,
+                         const struct TALER_MerchantSignatureP *merchant_sig,
+                         struct GNUNET_TIME_Absolute timestamp,
+                         struct GNUNET_TIME_Absolute refund_deadline,
+                         struct GNUNET_TIME_Absolute pay_deadline,
+                         const struct GNUNET_HashCode *h_wire,
+                         const char *order_id,
+                         unsigned int num_coins,
+                         const struct TALER_MERCHANT_PayCoin *coins,
+                         TALER_MERCHANT_PayRefundCallback payref_cb,
+                         void *payref_cb_cls);
+
+
+/**
  * Information we need from the frontend (ok, the frontend sends just JSON)
  * when forwarding a payment to the backend.
  */
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c
index bfb1ae8..276680e 100644
--- a/src/lib/merchant_api_pay.c
+++ b/src/lib/merchant_api_pay.c
@@ -54,16 +54,31 @@ struct TALER_MERCHANT_Pay
   struct GNUNET_CURL_Job *job;
 
   /**
-   * Function to call with the result.
+   * Function to call with the result in "pay" @e mode.
    */
-  TALER_MERCHANT_PayCallback cb;
+  TALER_MERCHANT_PayCallback pay_cb;
 
   /**
-   * Closure for @a cb.
+   * Closure for @a pay_cb.
    */
-  void *cb_cls;
+  void *pay_cb_cls;
 
   /**
+   * Function to call with the result in "abort-refund" @e mode.
+   */
+  TALER_MERCHANT_PayRefundCallback abort_cb;
+
+  /**
+   * Closure for @a abort_cb.
+   */
+  void *abort_cb_cls;
+
+  /**
+   * Operational mode, either "pay" or "abort-refund".
+   */
+  const char *mode;
+  
+  /**
    * Reference to the execution context.
    */
   struct GNUNET_CURL_Context *ctx;
@@ -82,6 +97,77 @@ struct TALER_MERCHANT_Pay
 
 
 /**
+ * Check that the response for a /pay refund is well-formed,
+ * and call the application callback with the result if it is
+ * OK. Otherwise returns #GNUNET_SYSERR.
+ *
+ * @param ph handle to operation that created the reply
+ * @param json the reply to parse
+ * @return #GNUNET_OK on success
+ */
+static int
+check_abort_refund (struct TALER_MERCHANT_Pay *ph,
+                   const json_t *json)
+{
+  json_t *refunds;
+  unsigned int num_refunds;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_json ("refunds", &refunds),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (json,
+                         spec,
+                         NULL, NULL))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  num_refunds = json_array_size (refunds);
+  if (num_refunds != ph->num_coins)
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return GNUNET_SYSERR;
+  }
+  {
+    struct TALER_MerchantSignatureP sigs[num_refunds];
+
+    for (unsigned int i=0;i<num_refunds;i++)
+    {
+      struct TALER_MerchantSignatureP *sig = &sigs[i];
+      json_t *deposit = json_array_get (refunds, i);
+      struct GNUNET_JSON_Specification spec_detail[] = {
+        GNUNET_JSON_spec_fixed_auto ("sig", sig),
+        GNUNET_JSON_spec_end()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (deposit,
+                             spec_detail,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+       GNUNET_JSON_parse_free (spec);
+        return GNUNET_SYSERR;
+      }
+    }
+    /* FIXME: check that signature is valid! */
+    ph->abort_cb (ph->abort_cb_cls,
+                 MHD_HTTP_OK,
+                 TALER_EC_NONE,
+                 num_refunds,
+                 sigs,
+                 json);
+    ph->abort_cb = NULL;
+  }
+  GNUNET_JSON_parse_free (spec);
+  return GNUNET_OK;
+}
+
+
+/**
  * We got a 403 response back from the exchange (or the merchant).
  * Now we need to check the provided cryptographic proof that the
  * coin was actually already spent!
@@ -196,199 +282,144 @@ handle_pay_finished (void *cls,
   struct TALER_MERCHANT_Pay *ph = cls;
 
   ph->job = NULL;
-  switch (response_code)
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             "/pay completed with response code %u\n",
+             (unsigned int) response_code);
+  if (0 == strcasecmp (ph->mode,
+                      "pay"))
   {
-  case 0:
-    break;
-  case MHD_HTTP_OK:
-    break;
-  case MHD_HTTP_BAD_REQUEST:
-    /* This should never happen, either us or the merchant is buggy
-       (or API version conflict); just pass JSON reply to the application */
-    break;
-  case MHD_HTTP_FORBIDDEN:
-    if (GNUNET_OK != check_forbidden (ph,
-                                      json))
+    switch (response_code)
     {
-      GNUNET_break_op (0);
+    case 0:
+      break;
+    case MHD_HTTP_OK:
+      break;
+    case MHD_HTTP_BAD_REQUEST:
+      /* This should never happen, either us or the merchant is buggy
+        (or API version conflict); just pass JSON reply to the application */
+      break;
+    case MHD_HTTP_FORBIDDEN:
+      if (GNUNET_OK != check_forbidden (ph,
+                                       json))
+      {
+       GNUNET_break_op (0);
+       response_code = 0;
+      }
+      break;
+    case MHD_HTTP_UNAUTHORIZED:
+      /* Nothing really to verify, merchant says one of the signatures is
+        invalid; as we checked them, this should never happen, we
+        should pass the JSON reply to the application */
+      break;
+    case MHD_HTTP_NOT_FOUND:
+      /* Nothing really to verify, this should never
+        happen, we should pass the JSON reply to the application */
+      break;
+    case MHD_HTTP_INTERNAL_SERVER_ERROR:
+      /* Server had an internal issue; we should retry, but this API
+        leaves this to the application */
+      break;
+    default:
+      /* unexpected response code */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 "Unexpected response code %u\n",
+                 (unsigned int) response_code);
+      GNUNET_break (0);
       response_code = 0;
-    }
-    break;
-  case MHD_HTTP_UNAUTHORIZED:
-    /* Nothing really to verify, merchant says one of the signatures is
-       invalid; as we checked them, this should never happen, we
-       should pass the JSON reply to the application */
-    break;
-  case MHD_HTTP_NOT_FOUND:
-    /* Nothing really to verify, this should never
-       happen, we should pass the JSON reply to the application */
-    break;
-  case MHD_HTTP_INTERNAL_SERVER_ERROR:
-    /* Server had an internal issue; we should retry, but this API
-       leaves this to the application */
-    break;
-  default:
-    /* unexpected response code */
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unexpected response code %u\n",
-                (unsigned int) response_code);
-    GNUNET_break (0);
-    response_code = 0;
-    break;
+      break;
+    }    
+    ph->pay_cb (ph->pay_cb_cls,
+               response_code,
+               TALER_JSON_get_error_code (json),
+               json);
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "/pay completed with response code %u\n",
-              (unsigned int) response_code);
-  ph->cb (ph->cb_cls,
-          response_code,
-         TALER_JSON_get_error_code (json),
-          json);
-  TALER_MERCHANT_pay_cancel (ph);
-}
-
-
-/**
- * Pay a merchant.  API for wallets that have the coin's private keys.
- * _NOTE_: this function does NOT calculate each coin amount in order
- * to match the contract total price.  This calculation is to be made
- * by the logic using this library.
- *
- * @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_terms hashcode of the proposal being paid
- * @param amount total value of the contract to be paid to the merchant
- * @param max_fee maximum fee covered by the merchant (according to the 
contract)
- * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
- * @param merchant_sig signature from the merchant over the original contract
- * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
- * @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 pay_deadline maximum time limit to pay for this contract
- * @param h_wire hash of the merchant’s account details
- * @param order_id order id of the proposal being paid
- * @param num_coins number of coins used to pay
- * @param coins array of coins we use to pay
- * @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
- */
-struct TALER_MERCHANT_Pay *
-TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
-                          const char *merchant_uri,
-                          const char *instance,
-                           const struct GNUNET_HashCode *h_contract_terms,
-                          const struct TALER_Amount *amount,
-                          const struct TALER_Amount *max_fee,
-                           const struct TALER_MerchantPublicKeyP *merchant_pub,
-                           const struct TALER_MerchantSignatureP *merchant_sig,
-                           struct GNUNET_TIME_Absolute timestamp,
-                           struct GNUNET_TIME_Absolute refund_deadline,
-                           struct GNUNET_TIME_Absolute pay_deadline,
-                           const struct GNUNET_HashCode *h_wire,
-                           const char *order_id,
-                           unsigned int num_coins,
-                           const struct TALER_MERCHANT_PayCoin *coins,
-                           TALER_MERCHANT_PayCallback pay_cb,
-                           void *pay_cb_cls)
-{
-  struct TALER_DepositRequestPS dr;
-  struct TALER_MERCHANT_PaidCoin pc[num_coins];
-
-  (void) GNUNET_TIME_round_abs (&timestamp);
-  (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_contract_terms = *h_contract_terms;
-  dr.h_wire = *h_wire;
-  dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
-  dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
-  dr.merchant = *merchant_pub;
-  for (unsigned int i=0;i<num_coins;i++)
+  else
   {
-    const struct TALER_MERCHANT_PayCoin *coin = &coins[i];
-    struct TALER_MERCHANT_PaidCoin *p = &pc[i];
-    struct TALER_Amount fee;
-
-    /* prepare 'dr' for this coin to generate coin signature */
-    GNUNET_CRYPTO_eddsa_key_get_public (&coin->coin_priv.eddsa_priv,
-                                       &dr.coin_pub.eddsa_pub);
-    TALER_amount_hton (&dr.amount_with_fee,
-                      &coin->amount_with_fee);
-    if (GNUNET_SYSERR ==
-       TALER_amount_subtract (&fee,
-                              &coin->amount_with_fee,
-                              &coin->amount_without_fee))
+    GNUNET_assert (0 == strcasecmp (ph->mode,
+                                   "abort-refund"));
+    
+    switch (response_code)
     {
-      /* Integer underflow, fee larger than total amount?
-        This should not happen (client violated API!) */
+    case 0:
+      break;
+    case MHD_HTTP_OK:
+      if (GNUNET_OK ==
+         check_abort_refund (ph,
+                             json))
+      {
+       TALER_MERCHANT_pay_cancel (ph);
+       return;
+      }
+      response_code = 0;
+      break;
+    case MHD_HTTP_BAD_REQUEST:
+      /* This should never happen, either us or the merchant is buggy
+        (or API version conflict); just pass JSON reply to the application */
+      break;
+    case MHD_HTTP_FORBIDDEN:
+      break;
+    case MHD_HTTP_UNAUTHORIZED:
+      /* Nothing really to verify, merchant says one of the signatures is
+        invalid; as we checked them, this should never happen, we
+        should pass the JSON reply to the application */
+      break;
+    case MHD_HTTP_NOT_FOUND:
+      /* Nothing really to verify, this should never
+        happen, we should pass the JSON reply to the application */
+      break;
+    case MHD_HTTP_INTERNAL_SERVER_ERROR:
+      /* Server had an internal issue; we should retry, but this API
+        leaves this to the application */
+      break;
+    default:
+      /* unexpected response code */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 "Unexpected response code %u\n",
+                 (unsigned int) response_code);
       GNUNET_break (0);
-      return NULL;
-    }
-    TALER_amount_hton (&dr.deposit_fee,
-                      &fee);
-    {
-      TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
-                       TALER_amount2s (&coin->amount_with_fee));
-      TALER_LOG_DEBUG ("... fee was %s\n",
-                       TALER_amount2s (&fee));
-    }
-
-    GNUNET_CRYPTO_eddsa_sign (&coin->coin_priv.eddsa_priv,
-                             &dr.purpose,
-                             &p->coin_sig.eddsa_signature);
-    p->denom_pub = coin->denom_pub;
-    p->denom_sig = coin->denom_sig;
-    p->denom_value = coin->denom_value;
-    p->coin_pub = dr.coin_pub;
-    p->amount_with_fee = coin->amount_with_fee;
-    p->amount_without_fee = coin->amount_without_fee;
-    p->exchange_url = coin->exchange_url;
+      response_code = 0;
+      break;
+    }    
+    ph->abort_cb (ph->abort_cb_cls,
+                 response_code,
+                 TALER_JSON_get_error_code (json),
+                 0,
+                 NULL,
+                 json);
   }
-  return TALER_MERCHANT_pay_frontend (ctx,
-                                     merchant_uri,
-                                      merchant_pub,
-                                      order_id,
-                                     num_coins,
-                                     pc,
-                                     pay_cb,
-                                     pay_cb_cls);
+    
+  TALER_MERCHANT_pay_cancel (ph);
 }
 
 
 /**
- * Pay a merchant.  API for frontends talking to backends. Here,
- * the frontend does not have the coin's private keys, but just
- * the public keys and signatures.  Note the subtle difference
- * in the type of @a coins compared to #TALER_MERCHANT_pay().
+ * Issue /pay request. Generic version for the various
+ * variants of the API.
  *
  * @param ctx the execution loop context
- * @param merchant_uri base URI of the merchant's backend
+ * @param merchant_url base URL of the merchant's backend
  * @param merchant_pub public key of the merchant
  * @param num_coins number of coins used to pay
  * @param coins array of coins we use to pay
+ * @param mode mode string to use ("pay" or "abort-refund").
  * @param pay_cb the callback to call when a reply for this request is 
available
  * @param pay_cb_cls closure for @a pay_cb
+ * @param abort_cb callback to call for the abort-refund variant
+ * @param abort_cb_cls closure for @a abort_cb
  * @return a handle for this request
  */
-struct TALER_MERCHANT_Pay *
-TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
-                            const char *merchant_uri,
-                             const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                             const char *order_id,
-                             unsigned int num_coins,
-                             const struct TALER_MERCHANT_PaidCoin *coins,
-                             TALER_MERCHANT_PayCallback pay_cb,
-                             void *pay_cb_cls)
+static struct TALER_MERCHANT_Pay *
+request_pay_generic (struct GNUNET_CURL_Context *ctx,
+                    const char *merchant_url,
+                    const struct TALER_MerchantPublicKeyP *merchant_pub,
+                    const char *order_id,
+                    unsigned int num_coins,
+                    const struct TALER_MERCHANT_PaidCoin *coins,
+                    const char *mode,
+                    TALER_MERCHANT_PayCallback pay_cb,
+                    void *pay_cb_cls,
+                    TALER_MERCHANT_PayRefundCallback abort_cb,
+                    void *abort_cb_cls)
 {
   struct TALER_MERCHANT_Pay *ph;
   json_t *pay_obj;
@@ -465,10 +496,12 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context 
*ctx,
   }
 
   pay_obj = json_pack ("{"
+                      " s:s," /* mode */
                        " s:o," /* coins */
                        " s:s," /* order_id */
                        " s:o," /* merchant_pub */
                        "}",
+                      "mode", mode,
                       "coins", j_coins,
                        "order_id", order_id,
                        "merchant_pub", GNUNET_JSON_from_data_auto 
(merchant_pub));
@@ -479,9 +512,12 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context 
*ctx,
   }
   ph = GNUNET_new (struct TALER_MERCHANT_Pay);
   ph->ctx = ctx;
-  ph->cb = pay_cb;
-  ph->cb_cls = pay_cb_cls;
-  ph->url = MAH_path_to_url_ (merchant_uri,
+  ph->mode = mode;
+  ph->abort_cb = abort_cb;
+  ph->abort_cb_cls = abort_cb_cls;
+  ph->pay_cb = pay_cb;
+  ph->pay_cb_cls = pay_cb_cls;
+  ph->url = MAH_path_to_url_ (merchant_url,
                              "/pay");
   ph->num_coins = num_coins;
   ph->coins = GNUNET_new_array (num_coins,
@@ -517,6 +553,302 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context 
*ctx,
 
 
 /**
+ * Pay a merchant.  API for wallets that have the coin's private keys.
+ * _NOTE_: this function does NOT calculate each coin amount in order
+ * to match the contract total price.  This calculation is to be made
+ * by the logic using this library.
+ *
+ * @param ctx the execution loop context
+ * @param merchant_url base URL of the merchant's backend
+ * @param instance which merchant instance will receive this payment
+ * @param h_contract_terms hashcode of the proposal being paid
+ * @param amount total value of the contract to be paid to the merchant
+ * @param max_fee maximum fee covered by the merchant (according to the 
contract)
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param merchant_sig signature from the merchant over the original contract
+ * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
+ * @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 pay_deadline maximum time limit to pay for this contract
+ * @param h_wire hash of the merchant’s account details
+ * @param order_id order id of the proposal being paid
+ * @param num_coins number of coins used to pay
+ * @param coins array of coins we use to pay
+ * @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
+ */
+static struct TALER_MERCHANT_Pay *
+prepare_pay_generic (struct GNUNET_CURL_Context *ctx,
+                    const char *merchant_url,
+                    const char *instance,
+                    const struct GNUNET_HashCode *h_contract_terms,
+                    const struct TALER_Amount *amount,
+                    const struct TALER_Amount *max_fee,
+                    const struct TALER_MerchantPublicKeyP *merchant_pub,
+                    const struct TALER_MerchantSignatureP *merchant_sig,
+                    struct GNUNET_TIME_Absolute timestamp,
+                    struct GNUNET_TIME_Absolute refund_deadline,
+                    struct GNUNET_TIME_Absolute pay_deadline,
+                    const struct GNUNET_HashCode *h_wire,
+                    const char *order_id,
+                    unsigned int num_coins,
+                    const struct TALER_MERCHANT_PayCoin *coins,
+                    const char *mode,
+                    TALER_MERCHANT_PayCallback pay_cb,
+                    void *pay_cb_cls,
+                    TALER_MERCHANT_PayRefundCallback abort_cb,
+                    void *abort_cb_cls)
+{
+  struct TALER_DepositRequestPS dr;
+  struct TALER_MERCHANT_PaidCoin pc[num_coins];
+
+  (void) GNUNET_TIME_round_abs (&timestamp);
+  (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_contract_terms = *h_contract_terms;
+  dr.h_wire = *h_wire;
+  dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
+  dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
+  dr.merchant = *merchant_pub;
+  for (unsigned int i=0;i<num_coins;i++)
+  {
+    const struct TALER_MERCHANT_PayCoin *coin = &coins[i];
+    struct TALER_MERCHANT_PaidCoin *p = &pc[i];
+    struct TALER_Amount fee;
+
+    /* prepare 'dr' for this coin to generate coin signature */
+    GNUNET_CRYPTO_eddsa_key_get_public (&coin->coin_priv.eddsa_priv,
+                                       &dr.coin_pub.eddsa_pub);
+    TALER_amount_hton (&dr.amount_with_fee,
+                      &coin->amount_with_fee);
+    if (GNUNET_SYSERR ==
+       TALER_amount_subtract (&fee,
+                              &coin->amount_with_fee,
+                              &coin->amount_without_fee))
+    {
+      /* Integer underflow, fee larger than total amount?
+        This should not happen (client violated API!) */
+      GNUNET_break (0);
+      return NULL;
+    }
+    TALER_amount_hton (&dr.deposit_fee,
+                      &fee);
+    {
+      TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
+                       TALER_amount2s (&coin->amount_with_fee));
+      TALER_LOG_DEBUG ("... fee was %s\n",
+                       TALER_amount2s (&fee));
+    }
+
+    GNUNET_CRYPTO_eddsa_sign (&coin->coin_priv.eddsa_priv,
+                             &dr.purpose,
+                             &p->coin_sig.eddsa_signature);
+    p->denom_pub = coin->denom_pub;
+    p->denom_sig = coin->denom_sig;
+    p->denom_value = coin->denom_value;
+    p->coin_pub = dr.coin_pub;
+    p->amount_with_fee = coin->amount_with_fee;
+    p->amount_without_fee = coin->amount_without_fee;
+    p->exchange_url = coin->exchange_url;
+  }
+  return request_pay_generic (ctx,
+                             merchant_url,
+                             merchant_pub,
+                             order_id,
+                             num_coins,
+                             pc,
+                             mode,
+                             pay_cb,
+                             pay_cb_cls,
+                             abort_cb,
+                             abort_cb_cls);
+}
+
+
+/**
+ * Pay a merchant.  API for wallets that have the coin's private keys.
+ * _NOTE_: this function does NOT calculate each coin amount in order
+ * to match the contract total price.  This calculation is to be made
+ * by the logic using this library.
+ *
+ * @param ctx the execution loop context
+ * @param merchant_url base URL of the merchant's backend
+ * @param instance which merchant instance will receive this payment
+ * @param h_contract_terms hashcode of the proposal being paid
+ * @param amount total value of the contract to be paid to the merchant
+ * @param max_fee maximum fee covered by the merchant (according to the 
contract)
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param merchant_sig signature from the merchant over the original contract
+ * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
+ * @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 pay_deadline maximum time limit to pay for this contract
+ * @param h_wire hash of the merchant’s account details
+ * @param order_id order id of the proposal being paid
+ * @param num_coins number of coins used to pay
+ * @param coins array of coins we use to pay
+ * @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
+ */
+struct TALER_MERCHANT_Pay *
+TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
+                          const char *merchant_url,
+                          const char *instance,
+                           const struct GNUNET_HashCode *h_contract_terms,
+                          const struct TALER_Amount *amount,
+                          const struct TALER_Amount *max_fee,
+                           const struct TALER_MerchantPublicKeyP *merchant_pub,
+                           const struct TALER_MerchantSignatureP *merchant_sig,
+                           struct GNUNET_TIME_Absolute timestamp,
+                           struct GNUNET_TIME_Absolute refund_deadline,
+                           struct GNUNET_TIME_Absolute pay_deadline,
+                           const struct GNUNET_HashCode *h_wire,
+                           const char *order_id,
+                           unsigned int num_coins,
+                           const struct TALER_MERCHANT_PayCoin *coins,
+                           TALER_MERCHANT_PayCallback pay_cb,
+                           void *pay_cb_cls)
+{
+  return prepare_pay_generic (ctx,
+                             merchant_url,
+                             instance,
+                             h_contract_terms,
+                             amount,
+                             max_fee,
+                             merchant_pub,
+                             merchant_sig,
+                             timestamp,
+                             refund_deadline,
+                             pay_deadline,
+                             h_wire,
+                             order_id,
+                             num_coins,
+                             coins,
+                             "pay",
+                             pay_cb,
+                             pay_cb_cls,
+                             NULL,
+                             NULL);
+}
+
+
+/**
+ * Run a payment abort operation, asking for refunds for coins
+ * that were previously spend on a /pay that failed to go through.
+ *
+ * @param ctx execution context
+ * @param merchant_url base URL of the merchant
+ * @param instance which merchant instance will receive this payment
+ * @param h_wire hash of the merchant’s account details
+ * @param h_contract hash of the contact of the merchant with the customer
+ * @param transaction_id transaction id for the transaction between merchant 
and customer
+ * @param amount total value of the contract to be paid to the merchant
+ * @param max_fee maximum fee covered by the merchant (according to the 
contract)
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param merchant_sig signature from the merchant over the original contract
+ * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
+ * @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 pay_deadline maximum time limit to pay for this contract
+ * @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 payref_cb the callback to call when a reply for this request is 
available
+ * @param payref_cb_cls closure for @a pay_cb
+ * @return a handle for this request
+ */
+struct TALER_MERCHANT_Pay *
+TALER_MERCHANT_pay_abort (struct GNUNET_CURL_Context *ctx,
+                         const char *merchant_url,
+                         const char *instance,
+                         const struct GNUNET_HashCode *h_contract,
+                         const struct TALER_Amount *amount,
+                         const struct TALER_Amount *max_fee,
+                         const struct TALER_MerchantPublicKeyP *merchant_pub,
+                         const struct TALER_MerchantSignatureP *merchant_sig,
+                         struct GNUNET_TIME_Absolute timestamp,
+                         struct GNUNET_TIME_Absolute refund_deadline,
+                         struct GNUNET_TIME_Absolute pay_deadline,
+                         const struct GNUNET_HashCode *h_wire,
+                         const char *order_id,
+                         unsigned int num_coins,
+                         const struct TALER_MERCHANT_PayCoin *coins,
+                         TALER_MERCHANT_PayRefundCallback payref_cb,
+                         void *payref_cb_cls)
+{
+  return prepare_pay_generic (ctx,
+                             merchant_url,
+                             instance,
+                             h_contract,
+                             amount,
+                             max_fee,
+                             merchant_pub,
+                             merchant_sig,
+                             timestamp,
+                             refund_deadline,
+                             pay_deadline,
+                             h_wire,
+                             order_id,
+                             num_coins,
+                             coins,
+                             "abort-refund",
+                             NULL,
+                             NULL,
+                             payref_cb,
+                             payref_cb_cls);
+}
+
+
+/**
+ * PAY a merchant.  API for frontends talking to backends. Here,
+ * the frontend does not have the coin's private keys, but just
+ * the public keys and signatures.  Note the subtle difference
+ * in the type of @a coins compared to #TALER_MERCHANT_pay().
+ *
+ * @param ctx the execution loop context
+ * @param merchant_url base URL of the merchant's backend
+ * @param merchant_pub public key of the merchant
+ * @param num_coins number of coins used to pay
+ * @param coins array of coins we use to pay
+ * @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
+ */
+struct TALER_MERCHANT_Pay *
+TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
+                            const char *merchant_url,
+                             const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                             const char *order_id,
+                             unsigned int num_coins,
+                             const struct TALER_MERCHANT_PaidCoin *coins,
+                             TALER_MERCHANT_PayCallback pay_cb,
+                             void *pay_cb_cls)
+{
+  return request_pay_generic (ctx,
+                             merchant_url,
+                             merchant_pub,
+                             order_id,
+                             num_coins,
+                             coins,
+                             "pay",
+                             pay_cb,
+                             pay_cb_cls,
+                             NULL,
+                             NULL);
+}
+
+
+/**
  * Cancel a pay permission request.  This function cannot be used
  * on a request handle if a response is already served for it.
  *
diff --git a/src/lib/merchant_api_refund.c b/src/lib/merchant_api_refund.c
index 8cea8b7..d9b6157 100644
--- a/src/lib/merchant_api_refund.c
+++ b/src/lib/merchant_api_refund.c
@@ -297,6 +297,7 @@ handle_refund_lookup_finished (void *cls,
   }
 }
 
+
 /**
  * Does a GET /refund.
  *

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



reply via email to

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