merchant_api_post_order_claim.c (6805B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2023 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Lesser General Public License as 7 published by the Free Software Foundation; either version 2.1, 8 or (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 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with TALER; see the file COPYING.LGPL. If not, 17 see <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file merchant_api_post_order_claim.c 21 * @brief Implementation of POST /orders/$ID/claim 22 * @author Christian Grothoff 23 * @author Marcello Stanisci 24 */ 25 #include "platform.h" 26 #include <curl/curl.h> 27 #include <jansson.h> 28 #include <microhttpd.h> /* just for HTTP status codes */ 29 #include <gnunet/gnunet_util_lib.h> 30 #include <gnunet/gnunet_curl_lib.h> 31 #include "taler_merchant_service.h" 32 #include "merchant_api_curl_defaults.h" 33 #include <taler/taler_json_lib.h> 34 #include <taler/taler_signatures.h> 35 #include <taler/taler_curl_lib.h> 36 37 38 /** 39 * Structure representing a POST /orders/$ID/claim operation. 40 */ 41 struct TALER_MERCHANT_OrderClaimHandle 42 { 43 /** 44 * Full URL, includes "/orders/$ID/claim". 45 */ 46 char *url; 47 48 /** 49 * Handle for the request. 50 */ 51 struct GNUNET_CURL_Job *job; 52 53 /** 54 * Function to call with the result. 55 */ 56 TALER_MERCHANT_OrderClaimCallback cb; 57 58 /** 59 * Closure for @a cb. 60 */ 61 void *cb_cls; 62 63 /** 64 * Reference to the execution context. 65 */ 66 struct GNUNET_CURL_Context *ctx; 67 68 /** 69 * Minor context that holds body and headers. 70 */ 71 struct TALER_CURL_PostContext post_ctx; 72 }; 73 74 75 /** 76 * Function called when we're done processing the 77 * POST /orders/$ID/claim request. 78 * 79 * @param cls the `struct TALER_MERCHANT_OrderClaimHandle` 80 * @param response_code HTTP response code, 0 on error 81 * @param response response body, should be NULL 82 */ 83 static void 84 handle_post_order_claim_finished (void *cls, 85 long response_code, 86 const void *response) 87 { 88 struct TALER_MERCHANT_OrderClaimHandle *och = cls; 89 const json_t *json = response; 90 struct TALER_MERCHANT_OrderClaimResponse ocr = { 91 .hr.http_status = (unsigned int) response_code, 92 .hr.reply = json 93 }; 94 struct GNUNET_JSON_Specification spec[] = { 95 GNUNET_JSON_spec_object_const ( 96 "contract_terms", 97 &ocr.details.ok.contract_terms), 98 GNUNET_JSON_spec_fixed_auto ( 99 "sig", 100 &ocr.details.ok.sig), 101 GNUNET_JSON_spec_end () 102 }; 103 104 och->job = NULL; 105 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 106 "Order claimed with status %u\n", 107 (unsigned int) response_code); 108 109 if (MHD_HTTP_OK != response_code) 110 { 111 ocr.hr.ec = TALER_JSON_get_error_code (json); 112 ocr.hr.hint = TALER_JSON_get_error_hint (json); 113 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 114 "Proposal lookup failed with HTTP status code %u/%d\n", 115 (unsigned int) response_code, 116 (int) ocr.hr.ec); 117 och->cb (och->cb_cls, 118 &ocr); 119 TALER_MERCHANT_order_claim_cancel (och); 120 return; 121 } 122 123 if (GNUNET_OK != 124 GNUNET_JSON_parse (json, 125 spec, 126 NULL, NULL)) 127 { 128 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 129 "Claiming order failed: could not parse JSON response\n"); 130 GNUNET_break_op (0); 131 ocr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 132 ocr.hr.http_status = 0; 133 och->cb (och->cb_cls, 134 &ocr); 135 TALER_MERCHANT_order_claim_cancel (och); 136 return; 137 } 138 139 if (GNUNET_OK != 140 TALER_JSON_contract_hash (ocr.details.ok.contract_terms, 141 &ocr.details.ok.h_contract_terms)) 142 { 143 GNUNET_break (0); 144 ocr.hr.ec = TALER_EC_MERCHANT_POST_ORDERS_ID_CLAIM_CLIENT_INTERNAL_FAILURE; 145 ocr.hr.http_status = 0; 146 GNUNET_JSON_parse_free (spec); 147 och->cb (och->cb_cls, 148 &ocr); 149 TALER_MERCHANT_order_claim_cancel (och); 150 return; 151 } 152 och->cb (och->cb_cls, 153 &ocr); 154 GNUNET_JSON_parse_free (spec); 155 TALER_MERCHANT_order_claim_cancel (och); 156 } 157 158 159 struct TALER_MERCHANT_OrderClaimHandle * 160 TALER_MERCHANT_order_claim (struct GNUNET_CURL_Context *ctx, 161 const char *backend_url, 162 const char *order_id, 163 const struct GNUNET_CRYPTO_EddsaPublicKey *nonce, 164 const struct TALER_ClaimTokenP *claim_token, 165 TALER_MERCHANT_OrderClaimCallback cb, 166 void *cb_cls) 167 { 168 struct TALER_MERCHANT_OrderClaimHandle *och; 169 json_t *req_obj; 170 171 if (NULL == order_id) 172 { 173 GNUNET_break (0); 174 return NULL; 175 } 176 req_obj = GNUNET_JSON_PACK ( 177 GNUNET_JSON_pack_data_auto ("nonce", 178 nonce), 179 GNUNET_JSON_pack_allow_null ( 180 GNUNET_JSON_pack_data_auto ("token", 181 claim_token))); 182 och = GNUNET_new (struct TALER_MERCHANT_OrderClaimHandle); 183 och->ctx = ctx; 184 och->cb = cb; 185 och->cb_cls = cb_cls; 186 { 187 char *path; 188 189 GNUNET_asprintf (&path, 190 "orders/%s/claim", 191 order_id); 192 och->url = TALER_url_join (backend_url, 193 path, 194 NULL); 195 GNUNET_free (path); 196 } 197 if (NULL == och->url) 198 { 199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 200 "Could not construct request URL.\n"); 201 json_decref (req_obj); 202 GNUNET_free (och); 203 return NULL; 204 } 205 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 206 "Claiming order at %s\n", 207 och->url); 208 { 209 CURL *eh; 210 211 eh = TALER_MERCHANT_curl_easy_get_ (och->url); 212 GNUNET_assert (GNUNET_OK == 213 TALER_curl_easy_post (&och->post_ctx, 214 eh, 215 req_obj)); 216 json_decref (req_obj); 217 och->job = GNUNET_CURL_job_add2 (ctx, 218 eh, 219 och->post_ctx.headers, 220 &handle_post_order_claim_finished, 221 och); 222 GNUNET_assert (NULL != och->job); 223 } 224 return och; 225 } 226 227 228 void 229 TALER_MERCHANT_order_claim_cancel (struct TALER_MERCHANT_OrderClaimHandle *och) 230 { 231 if (NULL != och->job) 232 { 233 GNUNET_CURL_job_cancel (och->job); 234 och->job = NULL; 235 } 236 TALER_curl_easy_post_finished (&och->post_ctx); 237 GNUNET_free (och->url); 238 GNUNET_free (och); 239 } 240 241 242 /* end of merchant_api_post_order_claim.c */