Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2018, 2020 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify
6 : it under the terms of the GNU General Public License as
7 : published by the Free Software Foundation; either version 3, or
8 : (at your option) any later version.
9 :
10 : TALER is distributed in the hope that it will be useful, but
11 : WITHOUT ANY WARRANTY; without even the implied warranty of
12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : GNU General Public License for more details.
14 :
15 : You should have received a copy of the GNU General Public
16 : License along with TALER; see the file COPYING. If not, see
17 : <http://www.gnu.org/licenses/>
18 : */
19 :
20 : /**
21 : * @file testing_api_cmd_claim_order.c
22 : * @brief command to claim an order
23 : * @author Marcello Stanisci
24 : */
25 : #include "platform.h"
26 : #include <taler/taler_exchange_service.h>
27 : #include <taler/taler_testing_lib.h>
28 : #include "taler_merchant_service.h"
29 : #include "taler_merchant_testing_lib.h"
30 :
31 : /**
32 : * State for a "order claim" CMD. Not used by
33 : * the initial claim operation.
34 : */
35 : struct OrderClaimState
36 : {
37 : /**
38 : * The interpreter state.
39 : */
40 : struct TALER_TESTING_Interpreter *is;
41 :
42 : /**
43 : * URL of the merchant backend.
44 : */
45 : const char *merchant_url;
46 :
47 : /**
48 : * Contract terms we downloaded. Only set if we got #MHD_HTTP_OK.
49 : */
50 : json_t *contract_terms;
51 :
52 : /**
53 : * Hash over the contract terms. Only set if we got #MHD_HTTP_OK.
54 : */
55 : struct TALER_PrivateContractHashP contract_terms_hash;
56 :
57 : /**
58 : * Signature of the merchant. Only set if we got #MHD_HTTP_OK.
59 : */
60 : struct TALER_MerchantSignatureP merchant_sig;
61 :
62 : /**
63 : * Public key of the merchant. Only set if we got #MHD_HTTP_OK.
64 : */
65 : struct TALER_MerchantPublicKeyP merchant_pub;
66 :
67 : /**
68 : * Expected status code.
69 : */
70 : unsigned int http_status;
71 :
72 : /**
73 : * /order/claim operation handle.
74 : */
75 : struct TALER_MERCHANT_OrderClaimHandle *och;
76 :
77 : /**
78 : * Reference to a order operation. Will offer the
79 : * nonce for the operation.
80 : */
81 : const char *order_reference;
82 :
83 : /**
84 : * Order id to claim upon. If null, the @a order_reference
85 : * will offer this value.
86 : */
87 : const char *order_id;
88 : };
89 :
90 :
91 : /**
92 : * Free the state of a "order claim" CMD, and possibly
93 : * cancel it if it did not complete.
94 : *
95 : * @param cls closure.
96 : * @param cmd command being freed.
97 : */
98 : static void
99 0 : order_claim_cleanup (void *cls,
100 : const struct TALER_TESTING_Command *cmd)
101 : {
102 0 : struct OrderClaimState *pls = cls;
103 :
104 0 : if (NULL != pls->och)
105 : {
106 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
107 : "Command '%s' did not complete\n",
108 : cmd->label);
109 0 : TALER_MERCHANT_order_claim_cancel (pls->och);
110 0 : pls->och = NULL;
111 : }
112 0 : if (NULL != pls->contract_terms)
113 : {
114 0 : json_decref (pls->contract_terms);
115 0 : pls->contract_terms = NULL;
116 : }
117 0 : GNUNET_free (pls);
118 0 : }
119 :
120 :
121 : /**
122 : * Callback for "order claim" operation, to check the
123 : * response code is as expected.
124 : *
125 : * @param cls closure
126 : * @param hr HTTP response we got
127 : * @param contract_terms the contract terms; they are the
128 : * backend-filled up order minus cryptographic
129 : * information.
130 : * @param sig merchant signature over the contract terms.
131 : * @param hash hash code of the contract terms.
132 : */
133 : static void
134 0 : order_claim_cb (void *cls,
135 : const struct TALER_MERCHANT_HttpResponse *hr,
136 : const json_t *contract_terms,
137 : const struct TALER_MerchantSignatureP *sig,
138 : const struct TALER_PrivateContractHashP *hash)
139 : {
140 0 : struct OrderClaimState *pls = cls;
141 :
142 0 : pls->och = NULL;
143 0 : if (pls->http_status != hr->http_status)
144 0 : TALER_TESTING_FAIL (pls->is);
145 0 : if (MHD_HTTP_OK == hr->http_status)
146 : {
147 0 : pls->contract_terms = json_object_get (hr->reply,
148 : "contract_terms");
149 0 : if (NULL == pls->contract_terms)
150 0 : TALER_TESTING_FAIL (pls->is);
151 0 : json_incref (pls->contract_terms);
152 0 : pls->contract_terms_hash = *hash;
153 0 : pls->merchant_sig = *sig;
154 : {
155 : const char *error_name;
156 : unsigned int error_line;
157 : struct GNUNET_JSON_Specification spec[] = {
158 0 : GNUNET_JSON_spec_fixed_auto ("merchant_pub",
159 : &pls->merchant_pub),
160 0 : GNUNET_JSON_spec_end ()
161 : };
162 :
163 0 : if (GNUNET_OK !=
164 0 : GNUNET_JSON_parse (contract_terms,
165 : spec,
166 : &error_name,
167 : &error_line))
168 0 : TALER_TESTING_FAIL (pls->is);
169 : }
170 : }
171 0 : TALER_TESTING_interpreter_next (pls->is);
172 : }
173 :
174 :
175 : /**
176 : * Run the "order claim" CMD.
177 : *
178 : * @param cls closure.
179 : * @param cmd command currently being run.
180 : * @param is interpreter state.
181 : */
182 : static void
183 0 : order_claim_run (void *cls,
184 : const struct TALER_TESTING_Command *cmd,
185 : struct TALER_TESTING_Interpreter *is)
186 : {
187 0 : struct OrderClaimState *pls = cls;
188 : const char **order_id;
189 : const struct GNUNET_CRYPTO_EddsaPublicKey *nonce;
190 : /* Only used if we do NOT use the nonce/token from traits. */
191 : struct GNUNET_CRYPTO_EddsaPublicKey dummy_nonce;
192 : const struct TALER_ClaimTokenP *claim_token;
193 :
194 0 : pls->is = is;
195 0 : if (NULL != pls->order_id)
196 : {
197 0 : order_id = &pls->order_id;
198 0 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
199 : &dummy_nonce,
200 : sizeof (dummy_nonce));
201 0 : nonce = &dummy_nonce;
202 0 : claim_token = NULL;
203 : }
204 : else
205 : {
206 : const struct TALER_TESTING_Command *order_cmd;
207 :
208 : order_cmd
209 0 : = TALER_TESTING_interpreter_lookup_command (is,
210 : pls->order_reference);
211 0 : if (NULL == order_cmd)
212 0 : TALER_TESTING_FAIL (is);
213 0 : if (GNUNET_OK !=
214 0 : TALER_TESTING_get_trait_claim_nonce (order_cmd,
215 : &nonce))
216 : {
217 0 : GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
218 : &dummy_nonce,
219 : sizeof (dummy_nonce));
220 0 : nonce = &dummy_nonce;
221 : }
222 0 : if (GNUNET_OK !=
223 0 : TALER_TESTING_get_trait_claim_token (order_cmd,
224 : &claim_token))
225 0 : claim_token = NULL;
226 0 : if (GNUNET_OK !=
227 0 : TALER_TESTING_get_trait_order_id (order_cmd,
228 : &order_id))
229 0 : TALER_TESTING_FAIL (is);
230 : }
231 0 : pls->och = TALER_MERCHANT_order_claim (is->ctx,
232 : pls->merchant_url,
233 : *order_id,
234 : nonce,
235 : claim_token,
236 : &order_claim_cb,
237 : pls);
238 0 : if (NULL == pls->och)
239 0 : TALER_TESTING_FAIL (is);
240 : }
241 :
242 :
243 : /**
244 : * Offer internal data to other commands.
245 : *
246 : * @param cls closure
247 : * @param[out] ret result (could be anything)
248 : * @param trait name of the trait
249 : * @param index index number of the object to extract.
250 : * @return #GNUNET_OK on success
251 : */
252 : static enum GNUNET_GenericReturnValue
253 0 : order_claim_traits (void *cls,
254 : const void **ret,
255 : const char *trait,
256 : unsigned int index)
257 : {
258 0 : struct OrderClaimState *pls = cls;
259 : struct TALER_TESTING_Trait traits[] = {
260 0 : TALER_TESTING_make_trait_contract_terms (pls->contract_terms),
261 0 : TALER_TESTING_make_trait_h_contract_terms (&pls->contract_terms_hash),
262 0 : TALER_TESTING_make_trait_merchant_sig (&pls->merchant_sig),
263 0 : TALER_TESTING_make_trait_merchant_pub (&pls->merchant_pub),
264 0 : TALER_TESTING_trait_end ()
265 : };
266 :
267 0 : return TALER_TESTING_get_trait (traits,
268 : ret,
269 : trait,
270 : index);
271 : }
272 :
273 :
274 : struct TALER_TESTING_Command
275 0 : TALER_TESTING_cmd_merchant_claim_order (
276 : const char *label,
277 : const char *merchant_url,
278 : unsigned int http_status,
279 : const char *order_reference,
280 : const char *order_id)
281 : {
282 : struct OrderClaimState *pls;
283 :
284 0 : pls = GNUNET_new (struct OrderClaimState);
285 0 : pls->http_status = http_status;
286 0 : pls->order_reference = order_reference;
287 0 : pls->merchant_url = merchant_url;
288 0 : pls->order_id = order_id;
289 : {
290 0 : struct TALER_TESTING_Command cmd = {
291 : .cls = pls,
292 : .label = label,
293 : .run = &order_claim_run,
294 : .cleanup = &order_claim_cleanup,
295 : .traits = &order_claim_traits
296 : };
297 :
298 0 : return cmd;
299 : }
300 : }
|