exchange

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

commit dd7148285da1f6a9efe1ee55307acf1a02007ba9
parent 53d3b742e90dbd275b2d08e96613d12ac4280b77
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 22 Dec 2024 16:00:55 +0100

work on AML programs

Diffstat:
Msrc/kyclogic/Makefile.am | 2++
Msrc/kyclogic/taler-exchange-helper-measure-enable-deposits | 8++++----
Asrc/kyclogic/taler-exchange-helper-measure-inform-investigate | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kyclogic/taler-exchange-helper-measure-preserve-set-expiration | 4++--
Asrc/kyclogic/taler-exchange-helper-measure-tops-address-check | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/kyclogic/taler-exchange-helper-measure-tops-kyx-check | 17++++++++---------
Msrc/kyclogic/taler-exchange-helper-measure-tops-postal-check | 8++++----
Msrc/kyclogic/taler-exchange-helper-measure-tops-sms-check | 8++++----
Msrc/kyclogic/taler-exchange-helper-measure-update-from-context | 8++++----
9 files changed, 288 insertions(+), 27 deletions(-)

diff --git a/src/kyclogic/Makefile.am b/src/kyclogic/Makefile.am @@ -19,9 +19,11 @@ bin_SCRIPTS = \ taler-exchange-helper-measure-defaults-but-investigate \ taler-exchange-helper-measure-enable-deposits \ taler-exchange-helper-measure-freeze \ + taler-exchange-helper-measure-inform-investigate \ taler-exchange-helper-measure-none \ taler-exchange-helper-measure-preserve-but-investigate \ taler-exchange-helper-measure-preserve-set-expiration \ + taler-exchange-helper-measure-tops-address-check \ taler-exchange-helper-measure-tops-kyx-check \ taler-exchange-helper-measure-tops-postal-check \ taler-exchange-helper-measure-tops-sms-check \ diff --git a/src/kyclogic/taler-exchange-helper-measure-enable-deposits b/src/kyclogic/taler-exchange-helper-measure-enable-deposits @@ -120,10 +120,10 @@ fi # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome # for the required output format. jq \ - --jsonarg et "$EXPIRATION_TIME" \ - --jsonarg sm "$SUCCESSOR_MEASURE" \ - --jsonarg cm "$CUSTOM_MEASURES" \ - --jsonarg nr "$NEW_RULES" \ + --argjson et "$EXPIRATION_TIME" \ + --argjson sm "$SUCCESSOR_MEASURE" \ + --argjson cm "$CUSTOM_MEASURES" \ + --argjson nr "$NEW_RULES" \ '{"new_rules":$nr+{"expiration_time":$et,"successor_measure":$sm,"custom_measures":($nr.custom_measures+$cm)}}|del(..|nulls)' exit 0 diff --git a/src/kyclogic/taler-exchange-helper-measure-inform-investigate b/src/kyclogic/taler-exchange-helper-measure-inform-investigate @@ -0,0 +1,100 @@ +#!/bin/bash +# +# This file is part of TALER +# Copyright (C) 2024 Taler Systems SA +# +# TALER is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3, 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/license> +# + +# Hard error reporting on. +set -eu + + + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: " "$@" >&2 + EXIT_STATUS=1 + exit "$EXIT_STATUS" +} + +CONF="$HOME/.config/taler-exchange.conf" +VERBOSE=0 + +while getopts 'ac:hirvV' OPTION; +do + case "$OPTION" in + a) + # No attributes are required. + exit 0 + ;; + c) + # shellcheck disable=SC2034 + CONF="$OPTARG" + ;; + h) + echo "This is a KYC measure program that flags and account for manual investigation and informs the user about it." + echo 'Supported options:' + echo ' -a -- show required attributes' + # shellcheck disable=SC2016 + echo ' -c $CONF -- set configuration' + echo ' -h -- print this help' + echo ' -i -- show required inputs' + echo ' -r -- show required context' + echo ' -v -- show version' + echo ' -V -- be verbose' + exit 0 + ;; + i) + # Need current rules. + echo "current_rules" + exit 0 + ;; + r) + # No context is required. + exit 0 + ;; + v) + echo "$0 v0.0.0" + exit 0 + ;; + V) + VERBOSE=1 + ;; + ?) + exit_fail "Unrecognized command line option" + ;; + esac +done + +if [ 1 = "$VERBOSE" ] +then + echo "Running $0" 1>&2 +fi + +# See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlProgramInput +# for the full JSON with possible inputs. + +# First, extract inputs we need +CURRENT_RULES=$(jq '.current_rules') + +# FIXME: not generic, figure out how to do this nicely regardless of +# what rule we are at. +NEW_RULES=$(echo "$CURRENT_RULES" | jq '(.rules[] | select (.rule_name==\"kyc-rule-deposit-limit-zero\").measures=["form-info-investigation"])') + + +# Finally, output the new rules. +# See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome +# for the required output format. + +echo "$NEW_RULES" \ + | jq '.+{"to_investigate": true}' diff --git a/src/kyclogic/taler-exchange-helper-measure-preserve-set-expiration b/src/kyclogic/taler-exchange-helper-measure-preserve-set-expiration @@ -100,8 +100,8 @@ SUCCESSOR_MEASURE=$(echo "$INPUTS" | jq '.context.successor_measure // null') echo "$INPUTS" \ | jq \ - --jsonarg et "$EXPIRATION_TIME" \ - --jsonarg sm "$SUCCESSOR_MEASURE" \ + --argjson et "$EXPIRATION_TIME" \ + --argjson sm "$SUCCESSOR_MEASURE" \ '.current_rules+{"new_rules":(.new_rules+{"expiration_time":$et,"successor_measure":$sm})}|del(..|nulls)' exit 0 diff --git a/src/kyclogic/taler-exchange-helper-measure-tops-address-check b/src/kyclogic/taler-exchange-helper-measure-tops-address-check @@ -0,0 +1,160 @@ +#!/bin/bash +# +# This file is part of TALER +# Copyright (C) 2024 Taler Systems SA +# +# TALER is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3, 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/license> +# + +# Hard error reporting on. +set -eu + + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: " "$@" >&2 + EXIT_STATUS=1 + exit "$EXIT_STATUS" +} + +CONF="$HOME/.config/taler-exchange.conf" +VERBOSE=0 + +while getopts 'ac:hirvV' OPTION; +do + case "$OPTION" in + a) + # Address data is required. + echo "ADDRESS_STREET_NAME" + echo "ADDRESS_ZIPCODE" + echo "ADDRESS_COUNTRY_CC" + exit 0 + ;; + c) + # shellcheck disable=SC2034 + CONF="$OPTARG" + ;; + h) + echo "This is a KYC measure program that sets up a measure to validate the address of the customer via Challenger." + echo 'Supported options:' + echo ' -a -- show required attributes' + # shellcheck disable=SC2016 + echo ' -c $CONF -- set configuration' + echo ' -h -- print this help' + echo ' -i -- show required inputs' + echo ' -r -- show required context' + echo ' -v -- show version' + echo ' -V -- be verbose' + exit 0 + ;; + i) + # Need context and current_rules. + echo "attributes" + echo "current_rules" + exit 0 + ;; + r) + # Nothing needed from context + exit 0 + ;; + v) + echo "$0 v0.0.0" + exit 0 + ;; + V) + VERBOSE=1 + ;; + ?) + exit_fail "Unrecognized command line option" + ;; + esac +done + +if [ 1 = "$VERBOSE" ] +then + echo "Running $0" 1>&2 +fi + +# See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlProgramInput +# for the full JSON with possible inputs. + +# First, extract inputs we need +INPUTS=$(jq '{"current_rules":.current_rules,"attributes":.attributes}') + +# Get address data +ADDRESS_NAME=$(echo "$INPUTS" | jq '.attributes.PERSON_FULL_NAME // .attributes.BUSINESS_DISPLAY_NAME // null') +# FIXME: +# Set 'name' to either of the two above, whichever one is non-null! + +ADDRESS_STREET_NAME=$(echo "$INPUTS" | jq '.attributes.ADDRESS_STREET_NAME // .attributes.ADDRESS_BUILDING_NAME // null') +ADDRESS_STREET_NUMBER=$(echo "$INPUTS" | jq '.attributes.ADDRESS_STREET_NUMBER // .attributes.ADDRESS_BUILDING_NUMBER // null') +ADDRESS_LINES=$(echo "$INPUTS" | jq '.attributes.ADDRESS_LINES // null') +ADDRESS_ZIPCODE=$(echo "$INPUTS" | jq '.attributes.ADDRESS_ZIPCODE // null') +ADDRESS_TOWN=$(echo "$INPUTS" | jq '.attributes.ADDRESS_TOWN_DISTRICT // .attributes.ADDRESS_TOWN_LOCATION // null') +ADDRESS_COUNTRY_SUBDIVISION=$(echo "$INPUTS" | jq '.attributes.ADDRESS_COUNTRY_SUBDIVISION // null') +ADDRESS_COUNTRY_CC=$(echo "$INPUTS" | jq '.attributes.ADDRESS_COUNTRY_CC // null') + +case "$ADDRESS_COUNTRY_CC" +in + ch) + COUNTRY="Switzerland" + ;; + de) + COUNTRY="Germany" + ;; + fr) + COUNTRY="France" + ;; + it) + COUNTRY="Italy" + ;; + *) + echo "ERROR: Country code '${ADDDRESS_COUNTRY_CC}' not recognized" 1>&2 + COUNTRY="${ADDRESS_COUNTRY_CC}" + ;; +esac + +# Convert address data to Challenger format as best we can. +ADDRESS=$(jq \ + --argjson full_name "$ADDRESS_NAME $ADDRESS_LINES" \ + --argjson street "$ADDRESS_STREET_NAME $ADDRESS_STREET_NUMBER" \ + --argjson city "$ADDRESS_TOWN" \ + --argjson postcode "$ADDRESS_ZIPCODE" \ + --argjson country "$COUNTRY" \ + '{"full_name":$full_name,"street":$street,"city":$city,"postcode":$postcode,"country":$country}') + +# Get current rules. +CURRENT_RULES=$(echo "$INPUTS" | jq '.current_rules // null') +# Get context values. +EXPIRATION_TIME=$(echo "$INPUTS" | jq '.context.expiration_time // .current_rules.expiration_time // null') +# Preserve successor measure. +SUCCESSOR_MEASURE=$(echo "$INPUTS" | jq '.current_rules.successor_measure // null') + +# Define custom measure for address validation +CUSTOM_MEASURES=$(jq \ + --argjson address "$ADDRESS" \ + '{"custom-address-investigation":{"context":{"initial_address":$address},"check_name":"postal-registration","prog_name":"inform-investigate","operation_type":"DEPOSIT"}}') + +# Then trigger Challenger address check via oauth2, kyc-check-postal-registration +NEW_RULES=$(echo "$CURRENT_RULES" | jq '(.rules[] | select (.rule_name=="kyc-rule-deposit-limit-zero").measures=["custom-address-investigation"])' | jq --argjson cm "$CUSTOM_MEASURES" '.custom_measures=$cm') + +# Finally, output the new rules. +# See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome +# for the required output format. +jq \ + --argjson et "$EXPIRATION_TIME" \ + --argjson sm "$SUCCESSOR_MEASURE" \ + --argjson cm "$CUSTOM_MEASURES" \ + --argjson nr "$NEW_RULES" \ + '{"new_rules":$nr+{"expiration_time":$et,"successor_measure":$sm,"custom_measures":($nr.custom_measures+$cm)}}|del(..|nulls)' + +exit 0 diff --git a/src/kyclogic/taler-exchange-helper-measure-tops-kyx-check b/src/kyclogic/taler-exchange-helper-measure-tops-kyx-check @@ -129,10 +129,9 @@ in INVESTIGATE="true" ;; "none") - # Immediately trigger investigation. - # FIXME: or rather: address validation! - NEW_RULES=$(echo "$CURRENT_RULES" | jq '(.rules[] | select (.rule_name==\"kyc-rule-deposit-limit-zero\").measures=["form-info-investigation"])') - INVESTIGATE="true" + # Immediately trigger address validation. + echo "$INPUTS" | taler-exchange-helper-measure-tops-address-check + exit $? ;; *) # Proceed to FORM. @@ -148,11 +147,11 @@ esac # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome # for the required output format. jq \ - --jsonarg inv "$INVESTIGATE" \ - --jsonarg et "$EXPIRATION_TIME" \ - --jsonarg sm "$SUCCESSOR_MEASURE" \ - --jsonarg cm "$CUSTOM_MEASURES" \ - --jsonarg nr "$NEW_RULES" \ + --argjson inv "$INVESTIGATE" \ + --argjson et "$EXPIRATION_TIME" \ + --argjson sm "$SUCCESSOR_MEASURE" \ + --argjson cm "$CUSTOM_MEASURES" \ + --argjson nr "$NEW_RULES" \ '{"to_investigate":$inv,"new_rules":$nr+{"expiration_time":$et,"successor_measure":$sm,"custom_measures":($nr.custom_measures+$cm)}}|del(..|nulls)' exit 0 diff --git a/src/kyclogic/taler-exchange-helper-measure-tops-postal-check b/src/kyclogic/taler-exchange-helper-measure-tops-postal-check @@ -124,10 +124,10 @@ fi # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome # for the required output format. jq \ - --jsonarg et "$EXPIRATION_TIME" \ - --jsonarg sm "$SUCCESSOR_MEASURE" \ - --jsonarg cm "$CUSTOM_MEASURES" \ - --jsonarg nr "$NEW_RULES" \ + --argjson et "$EXPIRATION_TIME" \ + --argjson sm "$SUCCESSOR_MEASURE" \ + --argjson cm "$CUSTOM_MEASURES" \ + --argjson nr "$NEW_RULES" \ '{"new_rules":$nr+{"expiration_time":$et,"successor_measure":$sm,"custom_measures":($nr.custom_measures+$cm)}}|del(..|nulls)' exit 0 diff --git a/src/kyclogic/taler-exchange-helper-measure-tops-sms-check b/src/kyclogic/taler-exchange-helper-measure-tops-sms-check @@ -121,10 +121,10 @@ fi # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome # for the required output format. jq \ - --jsonarg et "$EXPIRATION_TIME" \ - --jsonarg sm "$SUCCESSOR_MEASURE" \ - --jsonarg cm "$CUSTOM_MEASURES" \ - --jsonarg nr "$NEW_RULES" \ + --argjson et "$EXPIRATION_TIME" \ + --argjson sm "$SUCCESSOR_MEASURE" \ + --argjson cm "$CUSTOM_MEASURES" \ + --argjson nr "$NEW_RULES" \ '{"new_rules":$nr+{"expiration_time":$et,"successor_measure":$sm,"custom_measures":($nr.custom_measures+$cm)}}|del(..|nulls)' exit 0 diff --git a/src/kyclogic/taler-exchange-helper-measure-update-from-context b/src/kyclogic/taler-exchange-helper-measure-update-from-context @@ -104,10 +104,10 @@ NEW_RULES=$(echo "$INPUTS" | jq '.context.new_rules // null') echo "$INPUTS" \ | jq \ - --jsonarg et "$EXPIRATION_TIME" \ - --jsonarg sm "$SUCCESSOR_MEASURE" \ - --jsonarg cm "$CUSTOM_MEASURES" \ - --jsonarg nr "$NEW_RULES" \ + --argjson et "$EXPIRATION_TIME" \ + --argjson sm "$SUCCESSOR_MEASURE" \ + --argjson cm "$CUSTOM_MEASURES" \ + --argjson nr "$NEW_RULES" \ '.current_rules+{"new_rules":(.current_rules.new_rules+{"expiration_time":$et,"successor_measure":$sm,"rules":(.current_rules.new_rules.rules+$nr),"custom_measures":(.current_rules.custom_measures+$cm)})}|del(..|nulls)' exit 0