exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 752d53e8a053bfc6656f9ab036215afe8d1efaed
parent 97cec69dfeda6d94e29897a1f329120fa0b2498c
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 16 Dec 2025 19:52:04 +0100

work on tops-aml-pdf test

Diffstat:
Mcontrib/typst/Makefile.am | 2++
Acontrib/typst/generic_note.typ | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acontrib/typst/generic_upload.typ | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcontrib/typst/vqf_902_1_customer.typ | 2+-
Mcontrib/typst/vqf_902_1_officer.typ | 2+-
Mcontrib/typst/vqf_902_4.typ | 13+++++++------
Mcontrib/typst/vqf_902_5.typ | 4+---
Msrc/exchange/taler-exchange-httpd_aml-attributes-get.c | 2+-
Msrc/mhd/mhd_typst.c | 23+++++++++++++++++++++--
9 files changed, 201 insertions(+), 14 deletions(-)

diff --git a/contrib/typst/Makefile.am b/contrib/typst/Makefile.am @@ -6,6 +6,8 @@ dist_formdata_DATA = \ accept-tos.typ \ challenger_postal.typ \ challenger_sms.typ \ + generic_note.typ \ + generic_upload.typ \ taler-logo.svg \ pointing_finger.svg \ vqf_902_1_customer.typ \ diff --git a/contrib/typst/generic_note.typ b/contrib/typst/generic_note.typ @@ -0,0 +1,78 @@ +// Generic note form. + +#let form(data) = { + set page( + paper: "a4", + margin: (left: 2cm, right: 2cm, top: 2cm, bottom: 2.5cm), + footer: context [ + #grid( + columns: (1fr, 1fr), + align: (left, right), + text(size: 8pt)[ + ], + text(size: 8pt)[ + Page #here().page() of #counter(page).final().first() + ] + ) + ] + ) + + set text(font: "Liberation Sans", size: 10pt) + set par(justify: false, leading: 0.65em) + + // Helper function to get value or empty string + let get(key, default: "") = { + data.at(key, default: default) + } + + // Helper function for checkbox + let checkbox(checked) = { + box( + width: 3mm, + height: 3mm, + stroke: 0.5pt + black, + inset: 0.3mm, + if checked == true or checked == "true" { + place(center + horizon, text(size: 8pt, sym.checkmark)) + } + ) + } + + // Header + align(center, text(size: 11pt, weight: "bold")[CONFIDENTIAL]) + + v(0.5em) + + grid( + columns: (50%, 50%), + gutter: 1em, + image("taler-logo.svg", width: 80%), + align(right)[ + #table( + columns: (1fr, 1fr), + stroke: 0.5pt + black, + inset: 5pt, + align: (left, left), + [AMLA File No.], + [#get("FILE_NUMBER")] + ) + ] + ) + + v(1em) + + // Section 1: Note + text(size: 11pt, weight: "bold")[Note:] + + v(0.5em) + + get("NOTE_TEXT") + + v(0.5em) +} + +// Example usage: +#form(( + "GENERIC_NOTE": "This is a great customer.", + "FILE_NUMBER": 42, +)) +\ No newline at end of file diff --git a/contrib/typst/generic_upload.typ b/contrib/typst/generic_upload.typ @@ -0,0 +1,87 @@ +// Generic note form. + +#let form(data) = { + set page( + paper: "a4", + margin: (left: 2cm, right: 2cm, top: 2cm, bottom: 2.5cm), + footer: context [ + #grid( + columns: (1fr, 1fr), + align: (left, right), + text(size: 8pt)[ + ], + text(size: 8pt)[ + Page #here().page() of #counter(page).final().first() + ] + ) + ] + ) + + set text(font: "Liberation Sans", size: 10pt) + set par(justify: false, leading: 0.65em) + + // Helper function to get value or empty string + let get(key, default: "") = { + data.at(key, default: default) + } + + // Helper function for checkbox + let checkbox(checked) = { + box( + width: 3mm, + height: 3mm, + stroke: 0.5pt + black, + inset: 0.3mm, + if checked == true or checked == "true" { + place(center + horizon, text(size: 8pt, sym.checkmark)) + } + ) + } + + // Header + align(center, text(size: 11pt, weight: "bold")[CONFIDENTIAL]) + + v(0.5em) + + grid( + columns: (50%, 50%), + gutter: 1em, + image("taler-logo.svg", width: 80%), + align(right)[ + #table( + columns: (1fr, 1fr), + stroke: 0.5pt + black, + inset: 5pt, + align: (left, left), + [AMLA File No.], + [#get("FILE_NUMBER")] + ) + ] + ) + + v(1em) + + // Section 1: File upload with note + text(size: 11pt, weight: "bold")[File upload with note:] + + v(0.5em) + + block(breakable: false)[ + #v(0.5em) + #table( + columns: (35%, 65%), + stroke: 0.5pt + black, + inset: 5pt, + [Note:], [#get("NOTE_TEXT")], + [Filename:], [#get("FILE").at("FILENAME")], + ) + #v(0.5em) + ] +} + +// Example usage: +#form(( + "NOTE_TEXT": "This is a great customer.", + "FILE" : ( "FILENAME":"test.txt", "CONTENTS":"..."), + "FILE_NUMBER": 42, +)) +\ No newline at end of file diff --git a/contrib/typst/vqf_902_1_customer.typ b/contrib/typst/vqf_902_1_customer.typ @@ -10,7 +10,7 @@ columns: (1fr, 1fr), align: (left, right), text(size: 8pt)[ - VQF doc. Nr. 902.1#linebreak() + VQF doc. Nr. 902.1-customer#linebreak() Version of 1 September 2021 ], text(size: 8pt)[ diff --git a/contrib/typst/vqf_902_1_officer.typ b/contrib/typst/vqf_902_1_officer.typ @@ -10,7 +10,7 @@ columns: (1fr, 1fr), align: (left, right), text(size: 8pt)[ - VQF doc. Nr. 902.1#linebreak() + VQF doc. Nr. 902.1-officer#linebreak() Version of 1 September 2021 ], text(size: 8pt)[ diff --git a/contrib/typst/vqf_902_4.typ b/contrib/typst/vqf_902_4.typ @@ -131,7 +131,7 @@ let pep_domestic = get("PEP_DOMESTIC") let pep_intl = get("PEP_INTERNATIONAL_ORGANIZATION") let any_pep = pep_foreign or pep_domestic or pep_intl - let any_risk = get("ANY_RISK_CRITERION") + let pep_high_risk = get("PEP_HIGH_RISK") block(breakable: false)[ #table( @@ -174,8 +174,8 @@ #grid( columns: (auto, 1fr), gutter: 0.5em, - checkbox(not any_risk), [No], - checkbox(any_risk), [#grid( + checkbox(not pep_high_risk), [No], + checkbox(pep_high_risk), [#grid( columns: (auto, auto, auto), gutter: 0.5em, [Yes], @@ -653,15 +653,16 @@ text(size: 9pt, style: "italic")[⚠ *This form has to be updated immediately if "FILING_DATE": "10.11.2025", "PEP_FOREIGN": false, "PEP_DOMESTIC": false, - "PEP_ACCEPTANCE_DATE": "", + "PEP_HIGH_RISK": false, + "PEP_ACCEPTANCE_DATE": "2024-02-13", "ANY_RISK_CRITERION": false, "PEP_INTERNATIONAL_ORGANIZATION": false, "HIGH_RISK_COUNTRY": false, - "COUNTRY_RISK_ACCEPTANCE_DATE": "", + "COUNTRY_RISK_ACCEPTANCE_DATE": "2024-2-13", "COUNTRY_RISK_NATIONALITY_LEVEL": "LOW", "INDUSTRY_RISK_LEVEL": "TRANSPARENT", "CONTACT_RISK_LEVEL": "LOW", "RISK_CLASSIFICATION_LEVEL": "NO_HIGH_RISK", "TRANSACTION_RISK_RULE": "more than 50k/month", - "HIGH_RISK_ACCEPTANCE_DATE": "", + "HIGH_RISK_ACCEPTANCE_DATE": "2024-3-20", )) \ No newline at end of file diff --git a/contrib/typst/vqf_902_5.typ b/contrib/typst/vqf_902_5.typ @@ -147,7 +147,6 @@ v(0.5em) - let have_assets = get("BIZREL_HAVE_ASSETS") let origin_cat = get("BIZREL_ORIGIN_CATEGORY") block(breakable: false)[ @@ -156,7 +155,7 @@ stroke: 0.5pt + black, inset: 5pt, [Nature, amount and currency of the involved assets], - [#if have_assets {get("BIZREL_ORIGIN_NATURE")} else {""}], + [#get("BIZREL_ORIGIN_NATURE")], [Category], [#grid( columns: (auto, 1fr), @@ -242,7 +241,6 @@ "FILING_DATE": "10.11.2025", "BIZREL_PROFESSION": "Software Engineer", "BIZREL_INCOME": "Annual income CHF 150,000", - "BIZREL_HAVE_ASSETS": true, "BIZREL_ORIGIN_NATURE": "CHF 50,000 in cash", "BIZREL_ORIGIN_CATEGORY": "SAVINGS", "BIZREL_PURPOSE": "Payment services", diff --git a/src/exchange/taler-exchange-httpd_aml-attributes-get.c b/src/exchange/taler-exchange-httpd_aml-attributes-get.c @@ -775,7 +775,7 @@ TEH_handler_aml_attributes_get ( rctx); MHD_suspend_connection (rc->connection); rctx->tc = TALER_MHD_typst (TEH_cfg, - true, + false, "exchange", rctx->details.pdf.off, rctx->details.pdf.docs, diff --git a/src/mhd/mhd_typst.c b/src/mhd/mhd_typst.c @@ -387,6 +387,21 @@ complete_response (void *cls) /** + * Cancel typst. Wrapper task to do so asynchronously. + * + * @param[in] cls a `struct TALER_MHD_TypstContext` + */ +static void +cancel_async (void *cls) +{ + struct TALER_MHD_TypstContext *tc = cls; + + tc->t = NULL; + TALER_MHD_typst_cancel (tc); +} + + +/** * Called when a typst helper exited. * * @param cls our `struct TypstStage *` @@ -432,7 +447,9 @@ typst_done_cb (void *cls, typst_context_fail (tc, TALER_EC_EXCHANGE_GENERIC_TYPST_TEMPLATE_FAILURE, err); - TALER_MHD_typst_cancel (tc); + GNUNET_assert (NULL == tc->t); + tc->t = GNUNET_SCHEDULER_add_now (&cancel_async, + tc); return; } break; @@ -450,7 +467,9 @@ typst_done_cb (void *cls, typst_context_fail (tc, TALER_EC_EXCHANGE_GENERIC_TYPST_CRASH, err); - TALER_MHD_typst_cancel (tc); + GNUNET_assert (NULL == tc->t); + tc->t = GNUNET_SCHEDULER_add_now (&cancel_async, + tc); return; } break;