Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2026 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 : * @file src/testing/testing_api_cmd_check_order_external.c
21 : * @brief command to check the external payments and refunds an order
22 : * reports through GET /private/orders/$ORDER_ID
23 : * @author Bohdan Potuzhnyi
24 : * @author Volodymyr Potuzhnyi
25 : */
26 : #include "platform.h"
27 : struct CheckOrderExternalState;
28 : #define TALER_MERCHANT_GET_PRIVATE_ORDER_RESULT_CLOSURE \
29 : struct CheckOrderExternalState
30 : #include <taler/taler_exchange_service.h>
31 : #include <taler/taler_testing_lib.h>
32 : #include "taler/taler_merchant_service.h"
33 : #include "taler/taler_merchant_testing_lib.h"
34 :
35 :
36 : /**
37 : * State of a "check order external" CMD.
38 : */
39 : struct CheckOrderExternalState
40 : {
41 :
42 : /**
43 : * Handle for the order status request.
44 : */
45 : struct TALER_MERCHANT_GetPrivateOrderHandle *ogh;
46 :
47 : /**
48 : * The interpreter state.
49 : */
50 : struct TALER_TESTING_Interpreter *is;
51 :
52 : /**
53 : * Base URL of the merchant serving the request.
54 : */
55 : const char *merchant_url;
56 :
57 : /**
58 : * ID of the order to check.
59 : */
60 : const char *order_id;
61 :
62 : /**
63 : * Number of entries expected in "amount_external" of the contract.
64 : */
65 : unsigned int expected_payments;
66 :
67 : /**
68 : * Number of entries expected in "refunds_external" of the status.
69 : */
70 : unsigned int expected_refunds;
71 :
72 : /**
73 : * Choice the order is expected to have been paid with, -1 if the
74 : * contract has no choices.
75 : */
76 : int expected_choice_index;
77 :
78 : };
79 :
80 :
81 : /**
82 : * Callback for the order status request.
83 : *
84 : * @param coes closure for this function
85 : * @param osr response being processed
86 : */
87 : static void
88 4 : check_order_external_cb (
89 : struct CheckOrderExternalState *coes,
90 : const struct TALER_MERCHANT_GetPrivateOrderResponse *osr)
91 : {
92 : size_t payments;
93 : size_t refunds;
94 :
95 4 : coes->ogh = NULL;
96 4 : if (MHD_HTTP_OK != osr->hr.http_status)
97 : {
98 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
99 : "Unexpected response code %u (%d) to command %s\n",
100 : osr->hr.http_status,
101 : (int) osr->hr.ec,
102 : TALER_TESTING_interpreter_get_current_label (coes->is));
103 0 : TALER_TESTING_interpreter_fail (coes->is);
104 0 : return;
105 : }
106 4 : if (TALER_MERCHANT_OSC_PAID != osr->details.ok.status)
107 : {
108 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
109 : "Order `%s' is not paid, cannot check external payments\n",
110 : coes->order_id);
111 0 : TALER_TESTING_interpreter_fail (coes->is);
112 0 : return;
113 : }
114 4 : payments = json_array_size (
115 4 : json_object_get (osr->details.ok.details.paid.contract_terms,
116 : "amount_external"));
117 4 : refunds = json_array_size (osr->details.ok.details.paid.refunds_external);
118 4 : if (coes->expected_choice_index !=
119 4 : osr->details.ok.details.paid.choice_index)
120 : {
121 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
122 : "Order `%s' was paid with choice %d, expected %d\n",
123 : coes->order_id,
124 : osr->details.ok.details.paid.choice_index,
125 : coes->expected_choice_index);
126 0 : TALER_TESTING_interpreter_fail (coes->is);
127 0 : return;
128 : }
129 4 : if ( (payments != (size_t) coes->expected_payments) ||
130 4 : (refunds != (size_t) coes->expected_refunds) )
131 : {
132 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
133 : "Order `%s' reports %u external payments and %u external refunds, expected %u and %u\n",
134 : coes->order_id,
135 : (unsigned int) payments,
136 : (unsigned int) refunds,
137 : coes->expected_payments,
138 : coes->expected_refunds);
139 0 : TALER_TESTING_interpreter_fail (coes->is);
140 0 : return;
141 : }
142 4 : TALER_TESTING_interpreter_next (coes->is);
143 : }
144 :
145 :
146 : /**
147 : * Run the "check order external" CMD.
148 : *
149 : * @param cls closure.
150 : * @param cmd command being run now.
151 : * @param is interpreter state.
152 : */
153 : static void
154 4 : check_order_external_run (void *cls,
155 : const struct TALER_TESTING_Command *cmd,
156 : struct TALER_TESTING_Interpreter *is)
157 : {
158 4 : struct CheckOrderExternalState *coes = cls;
159 :
160 4 : coes->is = is;
161 4 : coes->ogh = TALER_MERCHANT_get_private_order_create (
162 : TALER_TESTING_interpreter_get_context (is),
163 : coes->merchant_url,
164 : coes->order_id);
165 4 : GNUNET_assert (NULL != coes->ogh);
166 : {
167 : enum TALER_ErrorCode ec;
168 :
169 4 : ec = TALER_MERCHANT_get_private_order_start (coes->ogh,
170 : &check_order_external_cb,
171 : coes);
172 4 : GNUNET_assert (TALER_EC_NONE == ec);
173 : }
174 4 : }
175 :
176 :
177 : /**
178 : * Free the state of a "check order external" CMD.
179 : *
180 : * @param cls closure.
181 : * @param cmd command being run.
182 : */
183 : static void
184 4 : check_order_external_cleanup (void *cls,
185 : const struct TALER_TESTING_Command *cmd)
186 : {
187 4 : struct CheckOrderExternalState *coes = cls;
188 :
189 4 : if (NULL != coes->ogh)
190 : {
191 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
192 : "GET /private/orders/$ORDER_ID operation did not complete\n");
193 0 : TALER_MERCHANT_get_private_order_cancel (coes->ogh);
194 : }
195 4 : GNUNET_free (coes);
196 4 : }
197 :
198 :
199 : struct TALER_TESTING_Command
200 4 : TALER_TESTING_cmd_merchant_check_order_external (
201 : const char *label,
202 : const char *merchant_url,
203 : const char *order_id,
204 : unsigned int expected_payments,
205 : unsigned int expected_refunds,
206 : int expected_choice_index)
207 : {
208 : struct CheckOrderExternalState *coes;
209 :
210 4 : coes = GNUNET_new (struct CheckOrderExternalState);
211 4 : coes->merchant_url = merchant_url;
212 4 : coes->order_id = order_id;
213 4 : coes->expected_payments = expected_payments;
214 4 : coes->expected_refunds = expected_refunds;
215 4 : coes->expected_choice_index = expected_choice_index;
216 : {
217 4 : struct TALER_TESTING_Command cmd = {
218 : .cls = coes,
219 : .label = label,
220 : .run = &check_order_external_run,
221 : .cleanup = &check_order_external_cleanup
222 : };
223 :
224 4 : return cmd;
225 : }
226 : }
|