aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--configure.ac35
-rw-r--r--src/backend/Makefile.am21
-rw-r--r--src/backend/taler-merchant-httpd_get-orders-ID.c237
4 files changed, 257 insertions, 38 deletions
diff --git a/README b/README
index 9977eefe..69f3a3f2 100644
--- a/README
+++ b/README
@@ -27,7 +27,7 @@ libgcrypt: LGPL, owned by Free Software Foundation
postgresql: PostgreSQL License, AGPL- and LGPL-Compatible, owned by The PostgreSQL
Global Development Group
libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V.
-PHP: PHP License, AGPL- and LGPL-Compatible, owned by The PHP Group
+libqrencode: LGPL v2.1+, Copyright Kentaro Fukuchi
5. DIRECTORY STRUCTURE
diff --git a/configure.ac b/configure.ac
index 0f5a5fb8..399f7592 100644
--- a/configure.ac
+++ b/configure.ac
@@ -132,6 +132,41 @@ PKG_CHECK_MODULES([JANSSON], [jansson >= 2.3],
*** You need libjansson to build this program.
***]])])
+
+# test for libqrencode
+qrencode=0
+QR_LIBS="-lqrencode"
+AC_MSG_CHECKING(for libqrencode)
+AC_ARG_WITH(qrencode,
+ [ --with-qrencode=PFX Base of libqrencode installation],
+ [AC_MSG_RESULT([$with_qrencode])
+ AS_CASE([$with_qrencode],
+ [no],[],
+ [yes],[
+ AC_CHECK_HEADERS(qrencode.h,qrencode=1)
+ ],
+ [
+ CPPFLAGS="-I$with_qrencode/include $CPPFLAGS"
+ QR_CFLAGS="-I$with_qrencode/include"
+ QR_LIBS="-L$with_qrencode/lib -lqrencode"
+ AC_CHECK_HEADERS(qrencode.h,qrencode=1)
+ ])
+ ],
+ [AC_MSG_RESULT([--with-qrencode not specified])
+ AC_CHECK_HEADERS(qrencode.h,qrencode=1)])
+
+AS_IF([test "$qrencode" != 1],
+[AC_MSG_ERROR([[
+***
+*** You need libqrencode to build this program.
+*** ]])])
+
+
+AC_SUBST(QR_CFLAGS)
+AC_SUBST(QR_LIBS)
+
+
+
# check for libgnurl
# libgnurl
LIBGNURL_CHECK_CONFIG(,7.34.0,gnurl=1,gnurl=0)
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 87bd5efe..a95026fb 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -91,24 +91,6 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_post-tips-ID-pickup.h \
taler-merchant-httpd_reserves.c \
taler-merchant-httpd_reserves.h
-
-DEAD = \
- taler-merchant-httpd_check-payment.c taler-merchant-httpd_check-payment.h \
- taler-merchant-httpd_history.c taler-merchant-httpd_history.h \
- taler-merchant-httpd_order.c taler-merchant-httpd_order.h \
- taler-merchant-httpd_pay.c taler-merchant-httpd_pay.h \
- taler-merchant-httpd_poll-payment.c taler-merchant-httpd_poll-payment.h \
- taler-merchant-httpd_proposal.c taler-merchant-httpd_proposal.h \
- taler-merchant-httpd_refund.c taler-merchant-httpd_refund.h \
- taler-merchant-httpd_refund_increase.c taler-merchant-httpd_refund_increase.h \
- taler-merchant-httpd_refund_lookup.c taler-merchant-httpd_refund_lookup.h \
- taler-merchant-httpd_tip-authorize.c taler-merchant-httpd_tip-authorize.h \
- taler-merchant-httpd_tip-pickup.c taler-merchant-httpd_tip-pickup.h \
- taler-merchant-httpd_tip-pickup_get.c \
- taler-merchant-httpd_tip-query.c taler-merchant-httpd_tip-query.h \
- taler-merchant-httpd_tip-reserve-helper.c taler-merchant-httpd_tip-reserve-helper.h \
- taler-merchant-httpd_track-transaction.c taler-merchant-httpd_track-transaction.h \
- taler-merchant-httpd_track-transfer.c taler-merchant-httpd_track-transfer.h
taler_merchant_httpd_LDADD = \
$(top_builddir)/src/backenddb/libtalermerchantdb.la \
-ltalerexchange \
@@ -122,4 +104,7 @@ taler_merchant_httpd_LDADD = \
-lgnunetcurl \
-lgnunetjson \
-lgnunetutil \
+ @QR_LIBS@
$(XLIB)
+taler_merchant_httpd_CFLAGS = \
+ @QR_CFLAGS@
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c
index 21582699..7310483d 100644
--- a/src/backend/taler-merchant-httpd_get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_get-orders-ID.c
@@ -21,6 +21,7 @@
*/
#include "platform.h"
#include <jansson.h>
+#include <qrencode.h>
#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
#include <taler/taler_exchange_service.h>
@@ -220,6 +221,12 @@ struct GetOrderData
*/
bool refunded;
+ /**
+ * Set to true if the client requested HTML, otherwise
+ * we generate JSON.
+ */
+ bool generate_html;
+
};
@@ -235,6 +242,77 @@ static struct GetOrderData *god_tail;
/**
+ * Create the QR code image for a URI.
+ *
+ * @param uri input string to encode
+ * @return NULL on error, encoded URI otherwise
+ */
+static char *
+create_qrcode (const char *uri)
+{
+ QRinput *qri;
+ QRcode *qrc;
+ struct GNUNET_Buffer buf = { 0 };
+
+ qri = QRinput_new2 (0,
+ QR_ECLEVEL_M);
+ if (NULL == qri)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRinput_new2");
+ return NULL;
+ }
+ /* first try encoding as uppercase-only alpha-numerical
+ QR code (much smaller encoding); if that fails, also
+ try using binary encoding */
+ if ( (0 !=
+ QRinput_append (qri,
+ QR_MODE_AN,
+ strlen (uri),
+ (unsigned char *) uri)) &&
+ (0 !=
+ QRinput_append (qri,
+ QR_MODE_8,
+ strlen (uri),
+ (unsigned char *) uri)) )
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRinput_append");
+ QRinput_free (qri);
+ return NULL;
+ }
+ qrc = QRcode_encodeInput (qri);
+ if (NULL == qrc)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRcode_encodeInput");
+ QRinput_free (qri);
+ return NULL;
+ }
+ QRinput_free (qri);
+ /* FIXME-Dold: generate <img> with inline SVG instead of <pre> here! */
+ GNUNET_buffer_write_str (&buf,
+ "<pre>\n\n\n\n ");
+ for (unsigned int y = 0; y<qrc->width; y++)
+ {
+ for (unsigned int x = 0; x<qrc->width; x++)
+ {
+ unsigned int off = x + y * qrc->width;
+ GNUNET_buffer_write_fstr (&buf,
+ "%s",
+ (0 != (qrc->data[off] & 1)) ? "██" : " ");
+ }
+ GNUNET_buffer_write_str (&buf,
+ "\n ");
+ }
+ GNUNET_buffer_write_str (&buf,
+ "\n\n\n\n</pre>");
+ QRcode_free (qrc);
+ return GNUNET_buffer_reap_str (&buf);
+}
+
+
+/**
* Force resuming all suspended order lookups, needed during shutdown.
*/
void
@@ -375,13 +453,54 @@ send_pay_request (struct GetOrderData *god,
god->order_id,
god->session_id,
god->hc->instance->settings.id);
- ret = TALER_MHD_reply_json_pack (god->sc.con,
- MHD_HTTP_OK,
- "{s:s, s:s, s:s?}",
- "taler_pay_uri", taler_pay_uri,
- "order_status", "unpaid",
- "already_paid_order_id",
- already_paid_order_id);
+ if (god->generate_html)
+ {
+ struct MHD_Response *reply;
+ char *qr;
+ char *body;
+
+ qr = create_qrcode (taler_pay_uri);
+ if (NULL == qr)
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ GNUNET_asprintf (&body,
+ "<html><body>%s</body></html>",
+ qr);
+ GNUNET_free (qr);
+ reply = MHD_create_response_from_buffer (strlen (body),
+ body,
+ MHD_RESPMEM_MUST_COPY);
+ GNUNET_free (body);
+ if (NULL == reply)
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ GNUNET_break (MHD_NO !=
+ MHD_add_response_header (reply,
+ "Taler",
+ taler_pay_uri));
+ GNUNET_break (MHD_NO !=
+ MHD_add_response_header (reply,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
+ "text/html"));
+ ret = MHD_queue_response (god->sc.con,
+ MHD_HTTP_OK,
+ reply);
+ MHD_destroy_response (reply);
+ }
+ else
+ {
+ ret = TALER_MHD_reply_json_pack (god->sc.con,
+ MHD_HTTP_OK,
+ "{s:s, s:s, s:s?}",
+ "taler_pay_uri", taler_pay_uri,
+ "order_status", "unpaid",
+ "already_paid_order_id",
+ already_paid_order_id);
+ }
GNUNET_free (taler_pay_uri);
return ret;
}
@@ -683,6 +802,44 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
}
}
+ { /* check for 'Accept' header */
+ const char *accept;
+
+ accept = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND,
+ MHD_HTTP_HEADER_ACCEPT);
+ if (NULL != accept)
+ {
+ char *a = GNUNET_strdup (accept);
+ char *saveptr;
+
+ for (char *t = strtok_r (a, ",", &saveptr);
+ NULL != t;
+ t = strtok_r (NULL, ",", &saveptr))
+ {
+ char *end;
+
+ /* skip leading whitespace */
+ while (isspace ((unsigned char) t[0]))
+ t++;
+ /* trim of ';q=' parameter and everything after space */
+ end = strchr (t, ';');
+ if (NULL != end)
+ *end = '\0';
+ end = strchr (t, ' ');
+ if (NULL != end)
+ *end = '\0';
+ if (0 == strcasecmp ("text/html",
+ t))
+ {
+ god->generate_html = true;
+ break;
+ }
+ }
+ GNUNET_free (a);
+ }
+ } /* end check for 'Accept' header */
+
{
const char *long_poll_timeout_s;
@@ -1058,18 +1215,60 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
refund));
}
- return TALER_MHD_reply_json_pack (
- connection,
- MHD_HTTP_OK,
- "{s:s, s:b, s:o, s:o, s:o}",
- "order_status", "paid",
- "refunded", god->refunded,
- "refund_amount",
- TALER_JSON_from_amount (&god->refund_amount),
- "refunds",
- ra,
- "merchant_pub",
- GNUNET_JSON_from_data_auto (&hc->instance->merchant_pub));
+ if (god->generate_html)
+ {
+ int ret;
+ struct MHD_Response *reply;
+ char *body;
+
+#if 0
+ char *qr;
+
+ qr = create_qrcode (taler_refund_uri);
+ if (NULL == qr)
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+#endif
+ GNUNET_asprintf (&body,
+ "<html><body>Paid. Refund: %s</body></html>",
+ TALER_amount2s (&god->refund_amount));
+ // GNUNET_free (qr);
+ reply = MHD_create_response_from_buffer (strlen (body),
+ body,
+ MHD_RESPMEM_MUST_COPY);
+ GNUNET_free (body);
+ if (NULL == reply)
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ GNUNET_break (MHD_NO !=
+ MHD_add_response_header (reply,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
+ "text/html"));
+ ret = MHD_queue_response (god->sc.con,
+ MHD_HTTP_OK,
+ reply);
+ MHD_destroy_response (reply);
+ return ret;
+ }
+ else
+ {
+ return TALER_MHD_reply_json_pack (
+ connection,
+ MHD_HTTP_OK,
+ "{s:s, s:b, s:o, s:o, s:o}",
+ "order_status", "paid",
+ "refunded", god->refunded,
+ "refund_amount",
+ TALER_JSON_from_amount (&god->refund_amount),
+ "refunds",
+ ra,
+ "merchant_pub",
+ GNUNET_JSON_from_data_auto (&hc->instance->merchant_pub));
+ }
}
}