commit ca4d9eed5190b6d79dd2f7eac03a21e0cf69c3c8
parent d8b70e33e6300a168fa35606c5de9723fcd979c4
Author: Marcello Stanisci <marcello.stanisci@inria.fr>
Date: Thu, 24 Sep 2015 12:11:18 +0200
adding "refund_deadline" mgmt (DB,testcase,httpd,library)
Diffstat:
7 files changed, 100 insertions(+), 61 deletions(-)
diff --git a/src/backend-lib/merchant_db.c b/src/backend-lib/merchant_db.c
@@ -97,6 +97,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
"timestamp INT8 NOT NULL,"
"expiry INT8 NOT NULL,"
"edate INT8 NOT NULL,"
+ "refund_deadline INT8 NOT NULL,"
"product INT8 NOT NULL);"
"CREATE %1$s TABLE IF NOT EXISTS checkouts ("
"coin_pub BYTEA PRIMARY KEY,"
@@ -122,10 +123,10 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
(conn,
"contract_create",
"INSERT INTO contracts"
- "(contract_id, hash, timestamp, expiry, edate, amount, amount_fraction, amount_currency,"
+ "(contract_id, hash, timestamp, expiry, edate, refund_deadline, amount, amount_fraction, amount_currency,"
"description, nounce, product) VALUES"
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
- 11, NULL)));
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
+ 12, NULL)));
EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
PQclear (res);
@@ -214,6 +215,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
* @param expiry the time when the contract will expire
* @param edate when the merchant wants to receive the wire transfer corresponding
* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param refund deadline until which the merchant can return the paid amount
* @param amount the taler amount corresponding to the contract
* @param hash of the stringified JSON corresponding to this contract
* @param c_id contract's id
@@ -228,6 +230,7 @@ MERCHANT_DB_contract_create (PGconn *conn,
const struct GNUNET_TIME_Absolute timestamp,
const struct GNUNET_TIME_Absolute expiry,
struct GNUNET_TIME_Absolute edate,
+ struct GNUNET_TIME_Absolute refund,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_contract,
uint64_t c_id,
@@ -250,6 +253,7 @@ MERCHANT_DB_contract_create (PGconn *conn,
TALER_PQ_query_param_absolute_time (×tamp),
TALER_PQ_query_param_absolute_time (&expiry),
TALER_PQ_query_param_absolute_time (&edate),
+ TALER_PQ_query_param_absolute_time (&refund),
TALER_PQ_query_param_amount (amount),
/* A *string* is being put in the following statement,
though the column is declared as *blob*. Will this be
diff --git a/src/backend-lib/merchant_db.h b/src/backend-lib/merchant_db.h
@@ -66,6 +66,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp);
* @param expiry the time when the contract will expire
* @param edate when the merchant wants to receive the wire transfer corresponding
* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param refund deadline until which the merchant can return the paid amount
* @param amount the taler amount corresponding to the contract
* @param hash of the stringified JSON corresponding to this contract
* @param c_id contract's id
@@ -80,6 +81,7 @@ MERCHANT_DB_contract_create (PGconn *conn,
const struct GNUNET_TIME_Absolute timestamp,
const struct GNUNET_TIME_Absolute expiry,
struct GNUNET_TIME_Absolute edate,
+ struct GNUNET_TIME_Absolute refund,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_contract,
uint64_t c_id,
diff --git a/src/backend-lib/taler-merchant-httpd_contract.c b/src/backend-lib/taler-merchant-httpd_contract.c
@@ -98,6 +98,7 @@ MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire,
* @param expiry the time when the contract will expire
* @param edate when the merchant wants to receive the wire transfer corresponding
* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param refund deadline until which the merchant can return the paid amount
* @param nounce the nounce used to hash the wire details
* @param contract_str where to store
* @return pointer to the (stringified) contract; NULL upon errors
@@ -114,6 +115,7 @@ MERCHANT_handle_contract (const json_t *j_contract,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute expiry,
struct GNUNET_TIME_Absolute edate,
+ struct GNUNET_TIME_Absolute refund,
uint64_t nounce)
{
json_t *j_amount;
@@ -127,17 +129,25 @@ MERCHANT_handle_contract (const json_t *j_contract,
/* Extracting values useful for DB work. Only gettable from the JSON
since they are generated by the frontend */
- if (-1 == json_unpack (j_contract, "{s:o, s:I, s:{s:{s:I}}}",
+ if (-1 == json_unpack (j_contract, "{s:o, s:I, s:{s:I}}",
"amount", &j_amount,
"trans_id", &j_trans_id,
- "details", "items",
- "product_id", &j_product_id))
+ "details", "product_id",
+ &j_product_id))
{
printf ("no unpacking\n");
return NULL;
}
- /* DB will store the amount */
+ /* DB will store the amount -- WARNING: this call produces a
+ 'protocol violation' in json.c */
+
+ #if 0
+ char *str = json_dumps (j_amount, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
+ printf ("extracted amount : %s\n", str);
+ #endif
+
+
TALER_json_to_amount (j_amount, &amount);
contract_str = json_dumps (j_contract, JSON_COMPACT | JSON_PRESERVE_ORDER);
GNUNET_CRYPTO_hash (contract_str, strlen (contract_str) + 1,
@@ -150,6 +160,7 @@ MERCHANT_handle_contract (const json_t *j_contract,
timestamp,
expiry,
edate,
+ refund,
&amount,
&contract->h_contract_details,
(uint64_t) j_trans_id, // safe?
diff --git a/src/backend-lib/taler_merchant_contract_lib.h b/src/backend-lib/taler_merchant_contract_lib.h
@@ -84,6 +84,7 @@ MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire,
* @param expiry the time when the contract will expire
* @param edate when the merchant wants to receive the wire transfer corresponding
* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param refund deadline until which the merchant can return the paid amount
* @param nounce the nounce used to hash the wire details
* @param contract_str where to store
* @return pointer to the (stringified) contract; NULL upon errors
@@ -100,4 +101,5 @@ MERCHANT_handle_contract (const json_t *j_contract,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute expiry,
struct GNUNET_TIME_Absolute edate,
+ struct GNUNET_TIME_Absolute refund,
uint64_t nounce);
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
@@ -342,35 +342,26 @@ url_handler (void *cls,
struct MHD_Response *resp;
json_t *root;
json_t *j_sig_enc;
+ json_t *j_h_contract;
+ json_t *j_tmp;
json_t *eddsa_pub_enc;
json_t *response;
json_t *j_mints;
json_t *j_mint;
json_t *j_wire;
int cnt; /* loop counter */
- char *str; /* to debug JSONs */
char *deposit_body;
- json_t *root_tmp;
json_t *j_contract_add;
- json_t *j_details_tmp;
- json_t *j_max_fee_tmp;
- json_int_t j_int_trans_id_tmp;
- json_t *j_trans_id_tmp;
- int64_t trans_id_tmp;
- char *ub_sig;
- char *coin_pub;
- char *denom_key;
- char *contract_sig;
- char *h_contract;
struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Absolute expiry;
struct GNUNET_TIME_Absolute edate;
+ struct GNUNET_TIME_Absolute refund;
struct GNUNET_HashCode h_json_wire;
- struct TALER_Amount amount_tmp;
json_t *j_h_json_wire;
struct curl_slist *slist;
char *contract_str;
struct GNUNET_HashCode h_contract_str;
+ uint64_t nounce;
CURL *curl;
CURLcode curl_res;
@@ -428,19 +419,45 @@ url_handler (void *cls,
TODO: Check if there is a row in 'contracts' table corresponding
to this contract ('s hash). If so, the corresponding 'nounce' and
'edate' have to be retrieved */
-
- j_wire =
-
+ /* Get this dep. perm.'s H_contract */
+
+ if (NULL == (j_h_contract = json_object_get (root, "H_contract")))
+ {
+ printf ("H_contract field missing\n");
+ status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ goto end;
+ }
+ TALER_json_to_data (j_h_contract, &h_contract_str, sizeof (struct GNUNET_HashCode));
+ if (GNUNET_SYSERR ==
+ MERCHANT_DB_get_contract_values (db_conn,
+ &h_contract_str,
+ &nounce,
+ &edate))
+ {
+ printf ("not existing contract\n");
+ status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ goto end;
+ }
+ /* Reproducing the wire object */
+ j_wire = MERCHANT_get_wire_json (wire,
+ nounce,
+ edate);
/* Encoding merchant's key */
GNUNET_CRYPTO_eddsa_key_get_public (privkey, &pub);
eddsa_pub_enc = TALER_json_from_data ((void *) &pub, sizeof (pub));
- /* Crafting the wire JSON */
if (NULL == (j_tmp = json_pack ("{s:o, s:I}",
"merchant_pub", eddsa_pub_enc,
"wire", j_wire)))
+ if (-1 == json_object_update (root, j_tmp))
+ {
+ printf ("depperm not augmented\n");
+ status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ goto end;
+ }
+
/* POST to mint's "/deposit" */
curl = curl_easy_init ();
@@ -457,7 +474,7 @@ url_handler (void *cls,
/* NOTE: hopefully, this string won't need any URL-encoding, since as for the
Jansson specs, any space and-or newline are not in place using JSON_COMPACT
flag */
- deposit_body = json_dumps (j_depperm, JSON_COMPACT | JSON_PRESERVE_ORDER);
+ deposit_body = json_dumps (root, JSON_COMPACT | JSON_PRESERVE_ORDER);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, deposit_body);
curl_res = curl_easy_perform (curl);
@@ -520,31 +537,25 @@ url_handler (void *cls,
GNUNET_CRYPTO_eddsa_public_key_to_string (&mint_infos[cnt].pubkey));
json_array_append_new (j_mints, j_mint);
- #define DEBUGG
- #ifdef DEBUG
+ #if 0
printf ("mint(s): url %s, key %s\n", mint_infos[cnt].hostname,
GNUNET_CRYPTO_eddsa_public_key_to_string (&mint_infos[cnt].pubkey));
- str = json_dumps (j_mint, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
+ char *str = json_dumps (j_mint, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
printf ("%s\n", str);
#endif
}
- if (-1 == (json_object_update (root, j_mints)))
- {
- printf ("no mints specified in contract\n");
- goto end;
-
-
- }
-
-
/* timestamp */
now = GNUNET_TIME_absolute_get ();
/* expiry */
expiry = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS);
- /* edate */
+ /* edate, note: this value must be generated now (and not when the
+ wallet sends back a deposit permission because the hashed 'wire' object,
+ which carries this values in it, has to be included in the signed bundle
+ by the wallet) */
edate = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS);
+ refund = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS);
/* getting the SEPA-aware JSON */
/* nounce for hashing the wire object */
@@ -559,33 +570,41 @@ url_handler (void *cls,
if (GNUNET_SYSERR == TALER_hash_json (j_wire, &h_json_wire))
goto end;
j_h_json_wire = TALER_json_from_data (&h_json_wire, sizeof (struct GNUNET_HashCode));
- /* get key JSON entry */
+ /* JSONify public key */
eddsa_pub_enc = TALER_json_from_data ((void *) &pub, sizeof (pub));
- if (NULL == (j_contract_add = json_pack ("{s:o, s:o, s:o}",
+ if (NULL == (j_contract_add = json_pack ("{s:o, s:o, s:o, s:o, s:o}",
"merchant_pub", eddsa_pub_enc,
"H_wire", j_h_json_wire,
- "timestamp", TALER_json_from_abs (now))))
+ "timestamp", TALER_json_from_abs (now),
+ "refund", TALER_json_from_abs (refund),
+ "mints", j_mints)))
{
printf ("BAD contract enhancement\n");
goto end;
}
/* melt to what received from the wallet */
- if (-1 == json_object_update (j_contract_add, root))
+ if (-1 == json_object_update (root, j_contract_add))
{
printf ("depperm response not built\n");
goto end;
}
- if (GNUNET_SYSERR == MERCHANT_handle_contract (root,
- db_conn,
- &contract,
- now,
- expiry,
- edate,
- nounce,
- contract_str))
+ #if 0
+ char *str = json_dumps (root, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
+ printf ("augmented root : %s\n", str);
+ #endif
+
+
+ if (NULL == (contract_str = MERCHANT_handle_contract (root,
+ db_conn,
+ &contract,
+ now,
+ expiry,
+ edate,
+ refund,
+ nounce)))
{
status = MHD_HTTP_INTERNAL_SERVER_ERROR;
goto end;
@@ -600,7 +619,10 @@ url_handler (void *cls,
*
* {"contract" : {the contract in "plain" JSON},
* "sig" : base32 encoding of the signed 'struct ContractNBO',
- * "eddsa_pub" : base32 encoding of merchant's public key}
+ * "eddsa_pub" : base32 encoding of merchant's public key,
+ * "h_contract" : the wallet will use this in the signature (to
+ * avoid neverending bugs due to how JavaScript stringifies the
+ * JSON respect to how libjansson does. To be soon removed.)}
*
*/
@@ -613,7 +635,7 @@ url_handler (void *cls,
"sig", j_sig_enc,
"eddsa_pub", eddsa_pub_enc,
"h_contract",
- TALER_json_from_data (h_contract_str, sizeof (struct GNUNET_HashCode)));
+ TALER_json_from_data ((void *) &h_contract_str, sizeof (struct GNUNET_HashCode)));
GNUNET_free (contract_str);
@@ -769,7 +791,6 @@ run (void *cls, char *const *args, const char *cfgfile,
/* WARNING: a 'poll_mhd ()' call is here in the original merchant. Is that
mandatory ? */
- GNUNET_CRYPTO_hash (wire, sizeof (*wire), &h_wire);
result = GNUNET_OK;
EXITIF_exit:
diff --git a/src/frontend/generate_taler_contract.php b/src/frontend/generate_taler_contract.php
@@ -25,7 +25,7 @@
to the wallet
*/
-$cli_debug = !TRUE;
+$cli_debug = TRUE;
// 1) recover the session information
session_start();
@@ -47,12 +47,10 @@ if (!$cli_debug)
else
{
$receiver = "Test Receiver";
- $amount = "5";
+ $amount = 5;
}
-
-
/* Fill in variables for simple JSON contract */
// fake product id
// --- FIXME: base on receiver for more realism!
@@ -136,7 +134,7 @@ http_response_code ($status_code);
// Now generate our body
if ($status_code != 200)
{
- echo "Error while generating the contract, response code: " . $status_code;
+ echo "Error while generating the contract, response code: " . $status_code . "\n";
}
else
{
diff --git a/src/tests/merchant-contract-test.c b/src/tests/merchant-contract-test.c
@@ -203,11 +203,10 @@ run (void *cls, char *const *args, const char *cfgfile,
j_teatax = json_pack ("{s:o}",
"teatax", j_tax_amount);
- if (NULL == (j_item = json_pack ("{s:s, s:I, s:o, s:I, s:[o]}",
+ if (NULL == (j_item = json_pack ("{s:s, s:I, s:o, s:[o]}",
"description", desc,
"quantity", json_integer_value (j_quantity),
"itemprice", j_item_price,
- "product_id", json_integer_value (j_pid),
"taxes", j_teatax)))
{
printf ("error in packing [j_item: %p]\n", j_item);
@@ -252,7 +251,8 @@ run (void *cls, char *const *args, const char *cfgfile,
- j_details = json_pack ("{s:o, s:o, s:o, s:o, s:o}",
+ j_details = json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o}",
+ "product_id", json_integer_value (j_pid),
"items", j_item,
"delivery date", j_deldate,
"delivery location", j_delloc,
@@ -287,6 +287,7 @@ run (void *cls, char *const *args, const char *cfgfile,
now,
now,
now,
+ now,
nounce)))
printf ("errors in contract handling\n");