/* This file is part of TALER Copyright (C) 2014-2017, 2020 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with TALER; see the file COPYING.LGPL. If not, see */ /** * @file lib/merchant_api_tip_pickup.c * @brief Implementation of the /tip-pickup request of the merchant's HTTP API * @author Marcello Stanisci * @author Christian Grothoff */ #include "platform.h" #include #include #include /* just for HTTP status codes */ #include #include #include "taler_merchant_service.h" #include #include #include /** * Data we keep per planchet. */ struct PlanchetData { /** * Secrets of the planchet. */ struct TALER_PlanchetSecretsP ps; /** * Denomination key we are withdrawing. */ struct TALER_EXCHANGE_DenomPublicKey pk; /** * Hash of the public key of the coin we are signing. */ struct GNUNET_HashCode c_hash; }; /** * Handle for a /tip-pickup operation. */ struct TALER_MERCHANT_TipPickupHandle { /** * Function to call with the result. */ TALER_MERCHANT_TipPickupCallback cb; /** * Closure for @a cb. */ void *cb_cls; /** * Handle for the actual (internal) withdraw operation. */ struct TALER_MERCHANT_TipPickup2Handle *tpo2; /** * Number of planchets/coins used for this operation. */ unsigned int num_planchets; /** * Array of length @e num_planchets. */ struct PlanchetData *planchets; }; /** * Callback for a /tip-pickup request. Returns the result of the operation. * Note that the client MUST still do the unblinding of the @a blind_sigs. * * @param cls closure, a `struct TALER_MERCHANT_TipPickupHandle *` * @param hr HTTP response details * @param num_blind_sigs length of the @a reserve_sigs array, 0 on error * @param blind_sigs array of blind signatures over the planchets, NULL on error */ static void pickup_done_cb (void *cls, const struct TALER_MERCHANT_HttpResponse *hr, unsigned int num_blind_sigs, const struct TALER_MERCHANT_BlindSignature *blind_sigs) { struct TALER_MERCHANT_TipPickupHandle *tp = cls; tp->tpo2 = NULL; if (NULL == blind_sigs) { tp->cb (tp->cb_cls, hr, 0, NULL); TALER_MERCHANT_tip_pickup_cancel (tp); return; } { struct TALER_DenominationSignature sigs[num_blind_sigs]; int ok; ok = GNUNET_OK; memset (sigs, 0, sizeof (sigs)); for (unsigned int i = 0; iplanchets[i].pk.key, blind_sigs[i].blind_sig, &tp->planchets[i].ps, &tp->planchets[i].c_hash, &fc)) { ok = GNUNET_SYSERR; break; } sigs[i] = fc.sig; } if (GNUNET_OK == ok) { tp->cb (tp->cb_cls, hr, num_blind_sigs, sigs); } else { struct TALER_MERCHANT_HttpResponse hrx = { .reply = hr->reply, .http_status = 0, .ec = TALER_EC_TIP_PICKUP_UNBLIND_FAILURE }; tp->cb (tp->cb_cls, &hrx, 0, NULL); } for (unsigned int i = 0; iplanchets, tp->num_planchets, num_planchets); for (unsigned int i = 0; iplanchets[i].ps = pds[i].ps; if (GNUNET_OK != TALER_planchet_prepare (&pds[i].pk->key, &tp->planchets[i].ps, &tp->planchets[i].c_hash, &details[i])) { GNUNET_break (0); GNUNET_array_grow (tp->planchets, tp->num_planchets, 0); GNUNET_free (tp); return NULL; } } for (unsigned int i = 0; iplanchets[i].pk = *pds[i].pk; tp->planchets[i].pk.key.rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup (pds[i].pk->key.rsa_public_key); } tp->cb = pickup_cb; tp->cb_cls = pickup_cb_cls; tp->tpo2 = TALER_MERCHANT_tip_pickup2 (ctx, backend_url, tip_id, num_planchets, details, &pickup_done_cb, tp); if (NULL == tp->tpo2) { GNUNET_break (0); TALER_MERCHANT_tip_pickup_cancel (tp); return NULL; } return tp; } /** * Cancel a pending /tip-pickup request * * @param tp handle from the operation to cancel */ void TALER_MERCHANT_tip_pickup_cancel (struct TALER_MERCHANT_TipPickupHandle *tp) { for (unsigned int i = 0; inum_planchets; i++) GNUNET_CRYPTO_rsa_public_key_dup (tp->planchets[i].pk.key.rsa_public_key); GNUNET_array_grow (tp->planchets, tp->num_planchets, 0); if (NULL != tp->tpo2) { TALER_MERCHANT_tip_pickup2_cancel (tp->tpo2); tp->tpo2 = NULL; } GNUNET_free (tp); } /* end of merchant_api_tip_pickup.c */