Line data Source code
1 : /*
2 : This file is part of GNU Taler
3 : Copyright (C) 2024, 2025 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file src/util/contract_serialize.c
18 : * @brief shared logic for contract terms serialization
19 : * @author Iván Ávalos
20 : * @author Christian Grothoff
21 : */
22 : #include "platform.h"
23 : #include <gnunet/gnunet_json_lib.h>
24 : #include <gnunet/gnunet_common.h>
25 : #include <taler/taler_json_lib.h>
26 : #include <jansson.h>
27 : #include "taler/taler_util.h"
28 : #include "taler/taler_merchant_util.h"
29 :
30 :
31 : /**
32 : * Get JSON object with contract terms v0-specific fields.
33 : *
34 : * @param[in] input contract terms v0
35 : * @return JSON object with @a input v0 fields; NULL on error
36 : */
37 : static json_t *
38 1 : json_from_contract_v0 (
39 : const struct TALER_MERCHANT_ProtoContract *input)
40 : {
41 1 : return GNUNET_JSON_PACK (
42 : TALER_JSON_pack_amount ("amount",
43 : &input->details.v0.brutto),
44 : GNUNET_JSON_pack_allow_null (
45 : TALER_JSON_pack_amount ("tip",
46 : input->details.v0.no_tip
47 : ? NULL
48 : : &input->details.v0.tip)),
49 : TALER_JSON_pack_amount ("max_fee",
50 : &input->details.v0.max_fee));
51 : }
52 :
53 :
54 : /**
55 : * Get JSON object with contract terms v1-specific fields.
56 : *
57 : * @param[in] input contract terms v1
58 : * @return JSON object with @a input v1 fields; NULL on error
59 : */
60 : static json_t *
61 1 : json_from_contract_v1 (
62 : const struct TALER_MERCHANT_ProtoContract *input)
63 : {
64 : json_t *choices;
65 : json_t *families;
66 :
67 1 : choices = json_array ();
68 1 : GNUNET_assert (0 != choices);
69 2 : for (unsigned i = 0; i < input->details.v1.choices_len; i++)
70 1 : GNUNET_assert (0 == json_array_append_new (
71 : choices,
72 : TALER_MERCHANT_json_from_contract_choice (
73 : &input->details.v1.choices[i])));
74 :
75 1 : families = json_object ();
76 1 : GNUNET_assert (0 != families);
77 3 : for (unsigned i = 0; i < input->details.v1.token_authorities_len; i++)
78 2 : GNUNET_assert (0 == json_object_set_new (
79 : families,
80 : input->details.v1.token_authorities[i].slug,
81 : TALER_MERCHANT_json_from_token_family (
82 : &input->details.v1.token_authorities[i])));
83 :
84 1 : return GNUNET_JSON_PACK (
85 : GNUNET_JSON_pack_array_steal ("choices",
86 : choices),
87 : GNUNET_JSON_pack_object_steal ("token_families",
88 : families));
89 : }
90 :
91 :
92 : /**
93 : * Serialize proto contract into JSON object.
94 : *
95 : * @param[in] pc proto contract to serialize
96 : * @return JSON representation of @a pc; NULL on error
97 : */
98 : json_t *
99 2 : TALER_MERCHANT_proto_contract_serialize (
100 : const struct TALER_MERCHANT_ProtoContract *pc)
101 : {
102 : json_t *bj;
103 : json_t *details;
104 : json_t *products;
105 :
106 2 : bj = TALER_MERCHANT_base_terms_serialize (pc->base);
107 2 : switch (pc->base->version)
108 : {
109 1 : case TALER_MERCHANT_CONTRACT_VERSION_0:
110 1 : details = json_from_contract_v0 (pc);
111 1 : goto success;
112 1 : case TALER_MERCHANT_CONTRACT_VERSION_1:
113 1 : details = json_from_contract_v1 (pc);
114 1 : goto success;
115 : }
116 :
117 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 : "unknown contract type version %d",
119 : pc->base->version);
120 0 : GNUNET_assert (0);
121 : return NULL;
122 :
123 2 : success:
124 2 : products = json_array ();
125 2 : GNUNET_assert (NULL != products);
126 2 : for (size_t i = 0; i<pc->products_len; i++)
127 : {
128 0 : GNUNET_assert (
129 : 0 ==
130 : json_array_append_new (products,
131 : TALER_MERCHANT_product_sold_serialize (
132 : &pc->products[i])));
133 : }
134 :
135 2 : return GNUNET_JSON_PACK (
136 : GNUNET_JSON_pack_string ("order_id",
137 : pc->order_id),
138 : GNUNET_JSON_pack_object_steal (NULL,
139 : bj),
140 : GNUNET_JSON_pack_timestamp ("timestamp",
141 : pc->timestamp),
142 : GNUNET_JSON_pack_timestamp ("refund_deadline",
143 : pc->refund_deadline),
144 : GNUNET_JSON_pack_timestamp ("pay_deadline",
145 : pc->pay_deadline),
146 : GNUNET_JSON_pack_timestamp ("wire_transfer_deadline",
147 : pc->wire_deadline),
148 : GNUNET_JSON_pack_data_auto ("merchant_pub",
149 : &pc->merchant_pub.eddsa_pub),
150 : GNUNET_JSON_pack_string ("merchant_base_url",
151 : pc->merchant_base_url),
152 : GNUNET_JSON_pack_object_steal (
153 : "merchant",
154 : TALER_MERCHANT_metadata_to_json (
155 : &pc->merchant)),
156 : GNUNET_JSON_pack_array_steal ("products",
157 : products),
158 : GNUNET_JSON_pack_data_auto ("h_wire",
159 : &pc->h_wire),
160 : GNUNET_JSON_pack_string ("wire_method",
161 : pc->wire_method),
162 : GNUNET_JSON_pack_array_incref ("exchanges",
163 : pc->exchanges),
164 : GNUNET_JSON_pack_object_steal (NULL,
165 : details));
166 : }
167 :
168 :
169 : json_t *
170 2 : TALER_MERCHANT_contract_serialize (
171 : const struct TALER_MERCHANT_Contract *input)
172 : {
173 : json_t *pj;
174 :
175 2 : pj = TALER_MERCHANT_proto_contract_serialize (input->pc);
176 2 : if (NULL == pj)
177 : {
178 0 : GNUNET_break (0);
179 0 : return NULL;
180 : }
181 2 : return GNUNET_JSON_PACK (
182 : GNUNET_JSON_pack_string ("nonce",
183 : input->nonce),
184 : GNUNET_JSON_pack_object_steal (NULL,
185 : pj));
186 : }
|