contract_serialize.c (5945B)
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 json_from_contract_v0 ( 39 const struct TALER_MERCHANT_ProtoContract *input) 40 { 41 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 json_from_contract_v1 ( 62 const struct TALER_MERCHANT_ProtoContract *input) 63 { 64 json_t *choices; 65 json_t *families; 66 67 choices = json_array (); 68 GNUNET_assert (0 != choices); 69 for (unsigned i = 0; i < input->details.v1.choices_len; i++) 70 GNUNET_assert (0 == json_array_append_new ( 71 choices, 72 TALER_MERCHANT_json_from_contract_choice ( 73 &input->details.v1.choices[i]))); 74 75 families = json_object (); 76 GNUNET_assert (0 != families); 77 for (unsigned i = 0; i < input->details.v1.token_authorities_len; i++) 78 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 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 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 bj = TALER_MERCHANT_base_terms_serialize (pc->base); 107 switch (pc->base->version) 108 { 109 case TALER_MERCHANT_CONTRACT_VERSION_0: 110 details = json_from_contract_v0 (pc); 111 goto success; 112 case TALER_MERCHANT_CONTRACT_VERSION_1: 113 details = json_from_contract_v1 (pc); 114 goto success; 115 } 116 117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 118 "unknown contract type version %d", 119 pc->base->version); 120 GNUNET_assert (0); 121 return NULL; 122 123 success: 124 products = json_array (); 125 GNUNET_assert (NULL != products); 126 for (size_t i = 0; i<pc->products_len; i++) 127 { 128 GNUNET_assert ( 129 0 == 130 json_array_append_new (products, 131 TALER_MERCHANT_product_sold_serialize ( 132 &pc->products[i]))); 133 } 134 135 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 TALER_MERCHANT_contract_serialize ( 171 const struct TALER_MERCHANT_Contract *input) 172 { 173 json_t *pj; 174 175 pj = TALER_MERCHANT_proto_contract_serialize (input->pc); 176 if (NULL == pj) 177 { 178 GNUNET_break (0); 179 return NULL; 180 } 181 return GNUNET_JSON_PACK ( 182 GNUNET_JSON_pack_string ("nonce", 183 input->nonce), 184 GNUNET_JSON_pack_object_steal (NULL, 185 pj)); 186 }