merchant_api_post-private-transfers.c (7205B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-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 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, 11 but 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 16 Public License along with TALER; see the file COPYING.LGPL. 17 If not, see <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file merchant_api_post-private-transfers-new.c 21 * @brief Implementation of the POST /private/transfers request 22 * @author Christian Grothoff 23 */ 24 #include "taler/platform.h" 25 #include <curl/curl.h> 26 #include <jansson.h> 27 #include <microhttpd.h> /* just for HTTP status codes */ 28 #include <gnunet/gnunet_util_lib.h> 29 #include <gnunet/gnunet_curl_lib.h> 30 #include <taler/taler-merchant/post-private-transfers.h> 31 #include "merchant_api_curl_defaults.h" 32 #include "merchant_api_common.h" 33 #include <taler/taler_json_lib.h> 34 #include <taler/taler_curl_lib.h> 35 36 37 /** 38 * Handle for a POST /private/transfers operation. 39 */ 40 struct TALER_MERCHANT_PostPrivateTransfersHandle 41 { 42 /** 43 * Base URL of the merchant backend. 44 */ 45 char *base_url; 46 47 /** 48 * The full URL for this request. 49 */ 50 char *url; 51 52 /** 53 * Handle for the request. 54 */ 55 struct GNUNET_CURL_Job *job; 56 57 /** 58 * Function to call with the result. 59 */ 60 TALER_MERCHANT_PostPrivateTransfersCallback cb; 61 62 /** 63 * Closure for @a cb. 64 */ 65 TALER_MERCHANT_POST_PRIVATE_TRANSFERS_RESULT_CLOSURE *cb_cls; 66 67 /** 68 * Reference to the execution context. 69 */ 70 struct GNUNET_CURL_Context *ctx; 71 72 /** 73 * Minor context that holds body and headers. 74 */ 75 struct TALER_CURL_PostContext post_ctx; 76 77 /** 78 * Amount credited in this transfer. 79 */ 80 struct TALER_Amount credit_amount; 81 82 /** 83 * Wire transfer identifier. 84 */ 85 struct TALER_WireTransferIdentifierRawP wtid; 86 87 /** 88 * Payto URI of the merchant account. 89 */ 90 struct TALER_FullPayto payto_uri; 91 92 /** 93 * Base URL of the exchange. 94 */ 95 char *exchange_url; 96 }; 97 98 99 /** 100 * Function called when we're done processing the 101 * HTTP POST /private/transfers request. 102 * 103 * @param cls the `struct TALER_MERCHANT_PostPrivateTransfersHandle` 104 * @param response_code HTTP response code, 0 on error 105 * @param response response body, NULL if not in JSON 106 */ 107 static void 108 handle_post_transfers_finished (void *cls, 109 long response_code, 110 const void *response) 111 { 112 struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth = cls; 113 const json_t *json = response; 114 struct TALER_MERCHANT_PostPrivateTransfersResponse ptr = { 115 .hr.http_status = (unsigned int) response_code, 116 .hr.reply = json 117 }; 118 119 ppth->job = NULL; 120 switch (response_code) 121 { 122 case 0: 123 ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 124 break; 125 case MHD_HTTP_NO_CONTENT: 126 break; 127 case MHD_HTTP_UNAUTHORIZED: 128 ptr.hr.ec = TALER_JSON_get_error_code (json); 129 ptr.hr.hint = TALER_JSON_get_error_hint (json); 130 break; 131 case MHD_HTTP_NOT_FOUND: 132 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 133 "Did not find any data\n"); 134 ptr.hr.ec = TALER_JSON_get_error_code (json); 135 ptr.hr.hint = TALER_JSON_get_error_hint (json); 136 break; 137 case MHD_HTTP_CONFLICT: 138 ptr.hr.ec = TALER_JSON_get_error_code (json); 139 ptr.hr.hint = TALER_JSON_get_error_hint (json); 140 break; 141 case MHD_HTTP_INTERNAL_SERVER_ERROR: 142 ptr.hr.ec = TALER_JSON_get_error_code (json); 143 ptr.hr.hint = TALER_JSON_get_error_hint (json); 144 break; 145 default: 146 GNUNET_break_op (0); 147 TALER_MERCHANT_parse_error_details_ (json, 148 response_code, 149 &ptr.hr); 150 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 151 "Unexpected response code %u/%d\n", 152 (unsigned int) ptr.hr.http_status, 153 (int) ptr.hr.ec); 154 break; 155 } 156 ppth->cb (ppth->cb_cls, 157 &ptr); 158 TALER_MERCHANT_post_private_transfers_cancel (ppth); 159 } 160 161 162 struct TALER_MERCHANT_PostPrivateTransfersHandle * 163 TALER_MERCHANT_post_private_transfers_create ( 164 struct GNUNET_CURL_Context *ctx, 165 const char *url, 166 const struct TALER_Amount *credit_amount, 167 const struct TALER_WireTransferIdentifierRawP *wtid, 168 struct TALER_FullPayto payto_uri, 169 const char *exchange_url) 170 { 171 struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth; 172 173 ppth = GNUNET_new (struct TALER_MERCHANT_PostPrivateTransfersHandle); 174 ppth->ctx = ctx; 175 ppth->base_url = GNUNET_strdup (url); 176 ppth->credit_amount = *credit_amount; 177 ppth->wtid = *wtid; 178 ppth->payto_uri.full_payto = GNUNET_strdup (payto_uri.full_payto); 179 ppth->exchange_url = GNUNET_strdup (exchange_url); 180 return ppth; 181 } 182 183 184 enum TALER_ErrorCode 185 TALER_MERCHANT_post_private_transfers_start ( 186 struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth, 187 TALER_MERCHANT_PostPrivateTransfersCallback cb, 188 TALER_MERCHANT_POST_PRIVATE_TRANSFERS_RESULT_CLOSURE *cb_cls) 189 { 190 json_t *req_obj; 191 CURL *eh; 192 193 ppth->cb = cb; 194 ppth->cb_cls = cb_cls; 195 ppth->url = TALER_url_join (ppth->base_url, 196 "private/transfers", 197 NULL); 198 if (NULL == ppth->url) 199 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 200 req_obj = GNUNET_JSON_PACK ( 201 TALER_JSON_pack_amount ("credit_amount", 202 &ppth->credit_amount), 203 GNUNET_JSON_pack_data_auto ("wtid", 204 &ppth->wtid), 205 TALER_JSON_pack_full_payto ("payto_uri", 206 ppth->payto_uri), 207 GNUNET_JSON_pack_string ("exchange_url", 208 ppth->exchange_url)); 209 eh = TALER_MERCHANT_curl_easy_get_ (ppth->url); 210 if ( (NULL == eh) || 211 (GNUNET_OK != 212 TALER_curl_easy_post (&ppth->post_ctx, 213 eh, 214 req_obj)) ) 215 { 216 GNUNET_break (0); 217 json_decref (req_obj); 218 if (NULL != eh) 219 curl_easy_cleanup (eh); 220 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 221 } 222 json_decref (req_obj); 223 ppth->job = GNUNET_CURL_job_add2 (ppth->ctx, 224 eh, 225 ppth->post_ctx.headers, 226 &handle_post_transfers_finished, 227 ppth); 228 if (NULL == ppth->job) 229 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 230 return TALER_EC_NONE; 231 } 232 233 234 void 235 TALER_MERCHANT_post_private_transfers_cancel ( 236 struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth) 237 { 238 if (NULL != ppth->job) 239 { 240 GNUNET_CURL_job_cancel (ppth->job); 241 ppth->job = NULL; 242 } 243 TALER_curl_easy_post_finished (&ppth->post_ctx); 244 GNUNET_free (ppth->payto_uri.full_payto); 245 GNUNET_free (ppth->exchange_url); 246 GNUNET_free (ppth->url); 247 GNUNET_free (ppth->base_url); 248 GNUNET_free (ppth); 249 } 250 251 252 /* end of merchant_api_post-private-transfers-new.c */