aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/taler-merchant-httpd_contract.c229
-rw-r--r--src/backend/taler-merchant-httpd_contract.h26
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c21
3 files changed, 269 insertions, 7 deletions
diff --git a/src/backend/taler-merchant-httpd_contract.c b/src/backend/taler-merchant-httpd_contract.c
index 38c82e70..60f45776 100644
--- a/src/backend/taler-merchant-httpd_contract.c
+++ b/src/backend/taler-merchant-httpd_contract.c
@@ -23,7 +23,7 @@
#include "taler-merchant-httpd_contract.h"
enum TALER_MerchantContractInputType
-TMH_string_to_contract_input_type (const char *str)
+TMH_contract_input_type_from_string (const char *str)
{
/* For now, only 'token' is the only supported option. */
if (0 == strcmp("token", str))
@@ -35,7 +35,7 @@ TMH_string_to_contract_input_type (const char *str)
}
enum TALER_MerchantContractOutputType
-TMH_string_to_contract_output_type (const char *str)
+TMH_contract_output_type_from_string (const char *str)
{
/* For now, only 'token' is the only supported option. */
if (0 == strcmp("token", str))
@@ -45,3 +45,228 @@ TMH_string_to_contract_output_type (const char *str)
return TALER_MCOT_INVALID;
}
+
+const char *
+TMH_string_from_contract_input_type (enum TALER_MerchantContractInputType t)
+{
+ switch (t) {
+ case TALER_MCIT_TOKEN:
+ return "token";
+ case TALER_MCIT_COIN:
+ return "coin";
+ default:
+ return "invalid";
+ }
+}
+
+const char *
+TMH_string_from_contract_output_type (enum TALER_MerchantContractOutputType t)
+{
+ switch (t) {
+ case TALER_MCOT_TOKEN:
+ return "token";
+ case TALER_MCOT_COIN:
+ return "coin";
+ case TALER_MCOT_TAX_RECEIPT:
+ return "tax_receipt";
+ default:
+ return "invalid";
+ }
+}
+
+/**
+ * Parse given JSON object to choices array.
+ *
+ * @param cls closure, pointer to array length
+ * @param root the json array representing the choices
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_choice (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct TALER_MerchantContractChoice **choices = spec->ptr;
+ unsigned int *choices_len = cls;
+ if (!json_is_array (root))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ GNUNET_array_grow (*choices,
+ *choices_len,
+ json_array_size (root));
+
+ for (unsigned int i = 0; i<*choices_len; i++)
+ {
+ const json_t *jinputs;
+ const json_t *joutputs;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_array_const ("inputs",
+ &jinputs),
+ GNUNET_JSON_spec_array_const ("outputs",
+ &joutputs),
+ GNUNET_JSON_spec_end ()
+ };
+ const char *error_name;
+ unsigned int error_line;
+ struct TALER_MerchantContractChoice *choice = &(*choices)[i];
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json_array_get (root, i),
+ spec,
+ &error_name,
+ &error_line))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to parse %s at %u: %s\n",
+ spec[error_line].field,
+ error_line,
+ error_name);
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ {
+ const json_t *jinput;
+ size_t idx;
+ json_array_foreach ((json_t *) jinputs, idx, jinput)
+ {
+ struct TALER_MerchantContractInput input = {.details.token.count = 1};
+ const char *kind;
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("kind",
+ &kind),
+ GNUNET_JSON_spec_string ("token_family_slug",
+ &input.details.token.token_family_slug),
+ GNUNET_JSON_spec_timestamp ("valid_after",
+ &input.details.token.valid_after),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("count",
+ &input.details.token.count),
+ NULL),
+ GNUNET_JSON_spec_end()
+ };
+ const char *ierror_name;
+ unsigned int ierror_line;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (jinput,
+ ispec,
+ &ierror_name,
+ &ierror_line))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to parse %s at %u: %s\n",
+ spec[ierror_line].field,
+ ierror_line,
+ ierror_name);
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ input.type = TMH_contract_input_type_from_string (kind);
+
+ if (TALER_MCIT_INVALID == input.type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Field 'kind' invalid in input #%u\n",
+ (unsigned int) idx);
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ if (0 == input.details.token.count)
+ {
+ /* Ignore inputs with 'number' field set to 0 */
+ continue;
+ }
+
+ GNUNET_array_append (choice->inputs,
+ choice->inputs_len,
+ input);
+ }
+ }
+
+ {
+ const json_t *joutput;
+ size_t idx;
+ json_array_foreach ((json_t *) joutputs, idx, joutput)
+ {
+ struct TALER_MerchantContractOutput output = {.details.token.count = 1};
+ const char *kind;
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("kind",
+ &kind),
+ GNUNET_JSON_spec_string ("token_family_slug",
+ &output.details.token.token_family_slug),
+ GNUNET_JSON_spec_timestamp ("valid_after",
+ &output.details.token.valid_after),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("count",
+ &output.details.token.count),
+ NULL),
+ GNUNET_JSON_spec_end()
+ };
+ const char *ierror_name;
+ unsigned int ierror_line;
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (joutput,
+ ispec,
+ &ierror_name,
+ &ierror_line))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to parse %s at %u: %s\n",
+ spec[ierror_line].field,
+ ierror_line,
+ ierror_name);
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ output.type = TMH_contract_output_type_from_string (kind);
+
+ if (TALER_MCOT_INVALID == output.type)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Field 'kind' invalid in output #%u\n",
+ (unsigned int) idx);
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ if (0 == output.details.token.count)
+ {
+ /* Ignore outputs with 'number' field set to 0 */
+ continue;
+ }
+
+ GNUNET_array_append (choice->outputs,
+ choice->outputs_len,
+ output);
+ }
+ }
+ }
+
+ return GNUNET_OK;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_choices (const char *name,
+ struct TALER_MerchantContractChoice **choices,
+ unsigned int *choices_len)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .cls = (void *) choices_len,
+ .parser = &parse_choice,
+ .field = name,
+ .ptr = choices,
+ };
+
+ return ret;
+} \ No newline at end of file
diff --git a/src/backend/taler-merchant-httpd_contract.h b/src/backend/taler-merchant-httpd_contract.h
index b231d732..ee77b4c1 100644
--- a/src/backend/taler-merchant-httpd_contract.h
+++ b/src/backend/taler-merchant-httpd_contract.h
@@ -551,10 +551,16 @@ struct TALER_MerchantContract
};
enum TALER_MerchantContractInputType
-TMH_string_to_contract_input_type (const char *str);
+TMH_contract_input_type_from_string (const char *str);
enum TALER_MerchantContractOutputType
-TMH_string_to_contract_output_type (const char *str);
+TMH_contract_output_type_from_string (const char *str);
+
+const char *
+TMH_string_from_contract_input_type (enum TALER_MerchantContractInputType t);
+
+const char *
+TMH_string_from_contract_output_type (enum TALER_MerchantContractOutputType t);
/**
* Serialize @a contract to a JSON object, ready to be stored in the database.
@@ -584,4 +590,18 @@ enum GNUNET_GenericReturnValue
TMH_serialize_contract_v1 (const struct TALER_MerchantContract *contract,
const struct TMH_MerchantInstance *instance,
json_t *exchanges,
- json_t **out); \ No newline at end of file
+ json_t **out);
+
+/**
+ * Provide specification to parse given JSON array to an array
+ * of contract choices.
+ *
+ * @param name name of the choices field in the JSON
+ * @param[out] choices pointer to the first element of the array
+ * @param[out] choices_len pointer to the length of the array
+ * @return spec for parsing a choices array
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_choices (const char *name,
+ struct TALER_MerchantContractChoice **choices,
+ unsigned int *choices_len);
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 2bdf891f..5532f1ab 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -26,12 +26,14 @@
*/
#include "platform.h"
#include <gnunet/gnunet_json_lib.h>
+#include <jansson.h>
#include <stdint.h>
#include <taler/taler_dbevents.h>
#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
#include <taler/taler_exchange_service.h>
#include "taler-merchant-httpd_exchanges.h"
+#include "taler-merchant-httpd_contract.h"
#include "taler-merchant-httpd_helper.h"
#include "taler-merchant-httpd_post-orders-ID-pay.h"
#include "taler-merchant-httpd_private-get-orders.h"
@@ -317,6 +319,11 @@ struct PayContext
struct TokenUseConfirmation *tokens;
/**
+ * Array with @e choices_cnt choices from the contract terms.
+ */
+ struct TALER_MerchantContractChoice *choices;
+
+ /**
* MHD connection to return to
*/
struct MHD_Connection *connection;
@@ -475,6 +482,11 @@ struct PayContext
size_t tokens_cnt;
/**
+ * Length of the @e choices array.
+ */
+ unsigned int choices_len;
+
+ /**
* Number of exchanges involved in the payment. Length
* of the @e eg array.
*/
@@ -2342,6 +2354,11 @@ phase_check_contract (struct PayContext *pc)
&pc->pay_deadline),
GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
&pc->wire_transfer_deadline),
+ GNUNET_JSON_spec_mark_optional (
+ TALER_JSON_spec_choices ("choices",
+ &pc->choices,
+ &pc->choices_len),
+ NULL),
GNUNET_JSON_spec_fixed_auto ("h_wire",
&pc->h_wire),
GNUNET_JSON_spec_mark_optional (
@@ -2667,8 +2684,8 @@ phase_parse_pay (struct PayContext *pc)
&tuc->sig),
GNUNET_JSON_spec_fixed_auto ("token_pub",
&tuc->pub),
- // TALER_JSON_spec_denom_sig ("ub_sig",
- // &tuc->unblinded_sig),
+ TALER_JSON_spec_token_issue_sig ("ub_sig",
+ &tuc->unblinded_sig),
GNUNET_JSON_spec_fixed_auto ("h_issue",
&tuc->h_issue),
GNUNET_JSON_spec_end ()