taler-mdb

GNU Taler Extensions and Integrations
Log | Files | Refs | Submodules | README | LICENSE

commit a1173e118edb4a6d386b152e9c3176107d403521
parent f53522a3bb661e64228dbaed6b660d819990a721
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  5 Dec 2019 17:02:51 +0100

basic refund integration (currently 404s)

Diffstat:
MREADME | 45+++++++++------------------------------------
Msrc/main.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 114 insertions(+), 39 deletions(-)

diff --git a/README b/README @@ -1,8 +1,9 @@ -# Project : GNUTaler snack machine +# Project: GNU Taler snack machine #### Author(s) * BOSS Marco * HOFER Dominik + * GROTHOFF Christian #### Prerequisite * GNU gcc tool-chain @@ -10,18 +11,19 @@ * libnfc * libcurl * pthread - * Gnu make + * GNU make + * GNUnet + * GNU Taler (exchange + merchant) #### Tested on * Ubuntu LTS (18.04) #### Description - This is a app to run a snack machine as taler merchant with nfc payment interface. + This is a app to run a snack machine as Taler merchant with NFC payment interface. #### Tasks - * fix bug when order pending -> press cancel -> abort from gunent scheduler - Nov 12 18:47:04-224202 util-scheduler-4656 ERROR `select' failed at scheduler.c:2336 with error: Bad file descriptor - Nov 12 18:47:04-224321 taler-mdb-4656 ERROR Assertion failed at scheduler.c:2370. Aborting. + Improve documentation + Integration testing #### Remarks * When using an ACR122 device there may be problems with libnfc, see libnfc for further information @@ -35,35 +37,7 @@ =================== TODO: - -- Use common prefix for all exported symbols in your - codebase, i.e. 'SNACK_'; you can then continue with - a file-specific prefix, i.e. 'SNACK_nfc_'. But you - MUST NOT use only 'nfc_', as that is "reserved" - for functions from libnfc! -- Consider to use GNUNET_log() for logging, - (#include <gnunet/gnunet_util_lib.h>, -lgnunetutil) -- - or define your own wrapper, but never printf, and - avoid using 'fprintf' directly (logging abstraction!) -- Consider using GNUNET_CONFIGURATION_* to obtain - configuration data (CURRENCY, Taler backend!) -- - or write your own configuration parser, but avoid - hard-coding parameters users would want to change! -- Consider using GNUNET_GETOPT_* to parse command-line - arguments -- - or use getopt() and implement --help yourself... -- Strongly consider using GNUNET_strdup(), GNUNET_malloc() - and other 'fundamental' functions of libgnunetutil, - instead of re-inventing that wheel... -- Consider using event loop (GNUNET_SCHEDULER_()) - instead of pthreads with cancellation -- stick to c89 style for local variables, i.e. do - not introduce variables in the middle of the scope -- stick to c89 style comments /* foo */, not // +- generate upper-case URLs once wallet supports TALER:// - document your functions Doxygen-style, in particular you must document every function, every argument, every struct, every member of every struct -- Use '&foo' if you want to use 'foo' as an argument - (higher order function) instead of calling 'foo()'. - -- makes no difference in C, but more readable -- -\ No newline at end of file diff --git a/src/main.c b/src/main.c @@ -25,7 +25,6 @@ along with * TODO: * - comment code (Boss) * - replace remaining MDB magic constants with #defines (Hofer) -* - implement refunds on failure to vend (TBD) */ #include "config.h" #include <stdio.h> @@ -260,6 +259,11 @@ struct PaymentActivity struct GNUNET_SCHEDULER_Task *delay_task; /** + * What is the price the user is paying? + */ + struct TALER_Amount amount; + + /** * Member to see if the wallet already received a uri * GNUNET_YES, GNUNET_NO * If yes, tunneling can be offered to the wallet @@ -354,6 +358,39 @@ struct Display /** + * DLL of pending refund operations. + */ +struct Refund +{ + /** + * DLL next pointer. + */ + struct Refund *next; + + /** + * DLL prev pointer. + */ + struct Refund *prev; + + /** + * Handle to the ongoing operation. + */ + struct TALER_MERCHANT_RefundIncreaseOperation *rio; + +}; + + +/** + * DLL head of refunds. + */ +static struct Refund *refund_head; + +/** + * DLL tail of refunds. + */ +static struct Refund *refund_tail; + +/** * NFC context used by the NFC reader */ static nfc_context *context; @@ -524,7 +561,7 @@ show_qrcode (const char *uri) upper = GNUNET_strdup (uri); /* NOTE: this line fails, Taler wallet likes URIs only lower-case! => Wallet bug! */ - // GNUNET_STRINGS_utf8_toupper (uri, upper); + /* GNUNET_STRINGS_utf8_toupper (uri, upper); */ /* first try encoding as uppercase-only alpha-numerical QR code (much smaller encoding); if that fails, also try using binary encoding (in case nick contains @@ -672,9 +709,21 @@ mdb_shutdown () static void shutdown_task (void *cls) { + struct Refund *r; + (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutdown initiated\n"); + while (NULL != (r = refund_head)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Pending refund operation aborted due to shutdown\n"); + GNUNET_CONTAINER_DLL_remove (refund_head, + refund_tail, + r); + TALER_MERCHANT_refund_increase_cancel (r->rio); + GNUNET_free (r); + } if (NULL != context) { nfc_exit (context); @@ -1163,6 +1212,7 @@ launch_payment (const struct Product *product) return NULL; } pa = GNUNET_new (struct PaymentActivity); + pa->amount = product->price; pa->po = TALER_MERCHANT_order_put (ctx, backendBaseUrl, orderReq, @@ -1198,17 +1248,69 @@ vend_success () /** + * Callback to process a POST /refund request + * + * @param cls closure + * @param http_status HTTP status code for this request + * @param ec taler-specific error code + * @param obj the response body + */ +static void +refund_complete_cb (void *cls, + unsigned int http_status, + enum TALER_ErrorCode ec, + const json_t *obj) +{ + struct Refund *r = cls; + + r->rio = NULL; + if (MHD_HTTP_OK != http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to grant consumer refund: %u/%d\n", + http_status, + ec); + } + GNUNET_CONTAINER_DLL_remove (refund_head, + refund_tail, + r); + GNUNET_free (r); +} + + +/** * Vending failed, provide refund. */ static void vend_failure () { + struct Refund *r; + GNUNET_break (NULL != payment_activity); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received MDB vend failure, refunding customer (FIXME: not implemented)\n"); mdb.cmd = &endSession; mdb.session_running = GNUNET_NO; - /* FIXME: refund logic here! */ + r = GNUNET_new (struct Refund); + r->rio = TALER_MERCHANT_refund_increase (ctx, + backendBaseUrl, + payment_activity->order_id, + &payment_activity->amount, + "failed to dispense product", + &refund_complete_cb, + r); + if (NULL == r->rio) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to launch refund interaction with the merchant backend!\n"); + GNUNET_free (r); + } + else + { + GNUNET_CONTAINER_DLL_insert (refund_head, + refund_tail, + r); + } if (NULL != payment_activity) { cleanup_payment (payment_activity);