exchange

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

taler-exchange-helper-measure-tops-kyx-check (9089B)


      1 #!/bin/bash
      2 #
      3 #  This file is part of TALER
      4 #  Copyright (C) 2024 Taler Systems SA
      5 #
      6 #  TALER is free software; you can redistribute it and/or modify it under the
      7 #  terms of the GNU General Public License as published by the Free Software
      8 #  Foundation; either version 3, or (at your option) any later version.
      9 #
     10 #  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     11 #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     12 #  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     13 #
     14 #  You should have received a copy of the GNU General Public License along with
     15 #  TALER; see the file COPYING.  If not, If not, see <http://www.gnu.org/license>
     16 #
     17 
     18 # Hard error reporting on.
     19 set -eu
     20 
     21 
     22 # Exit, with error message (hard failure)
     23 function exit_fail() {
     24     echo " FAIL: " "$@" >&2
     25     EXIT_STATUS=1
     26     exit "$EXIT_STATUS"
     27 }
     28 
     29 CONF="$HOME/.config/taler-exchange.conf"
     30 VERBOSE=0
     31 
     32 while getopts 'ac:hirvV' OPTION;
     33 do
     34     case "$OPTION" in
     35         a)
     36             # Legal entity type is required.
     37             echo "CUSTOMER_TYPE"
     38             echo "CUSTOMER_TYPE_VQF"
     39             exit 0
     40             ;;
     41         c)
     42             # shellcheck disable=SC2034
     43             CONF="$OPTARG"
     44             ;;
     45         h)
     46             echo "This is a KYC measure program that determines the next VQF form to ask for (if any) based on the type of legal entity the customer claimed to be on the primary form."
     47             echo 'Supported options:'
     48             echo '  -a           -- show required attributes'
     49             # shellcheck disable=SC2016
     50             echo '  -c $CONF     -- set configuration'
     51             echo '  -h           -- print this help'
     52             echo '  -i           -- show required inputs'
     53             echo '  -r           -- show required context'
     54             echo '  -v           -- show version'
     55             echo '  -V           -- be verbose'
     56             exit 0
     57             ;;
     58         i)
     59             # Need context and current_rules.
     60             echo "attributes"
     61             echo "current_rules"
     62             echo "default_rules"
     63             exit 0
     64             ;;
     65         r)
     66             # Nothing needed from context
     67             exit 0
     68             ;;
     69         v)
     70             echo "$0 v0.0.3"
     71             exit 0
     72             ;;
     73         V)
     74             VERBOSE=1
     75             ;;
     76         ?)
     77         exit_fail "Unrecognized command line option"
     78         ;;
     79     esac
     80 done
     81 
     82 if [ 1 = "$VERBOSE" ]
     83 then
     84     echo "Running $0" 1>&2
     85 fi
     86 
     87 # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlProgramInput
     88 # for the full JSON with possible inputs.
     89 
     90 # First, extract inputs we need
     91 INPUTS=$(jq '{"current_rules":(.current_rules // .default_rules // error("neither current_rules nor default_rules provided")),"attributes":.attributes}')
     92 
     93 
     94 # Check form ID, must be 'vqf-902.11'
     95 FORM_ID=$(echo "$INPUTS" | jq -r '.attributes.FORM_ID')
     96 
     97 # The 'form' here should be the VQF 902.11 customer form
     98 if [ "$FORM_ID" != "vqf_902_1_customer" ]
     99 then
    100     echo "Unexpected form ID $FORM_ID" 1>&2
    101     echo "$INPUTS" | exec taler-exchange-helper-measure-freeze
    102     exit 1
    103 fi
    104 
    105 # Get entity type
    106 LEGAL_ENTITY=$(echo "$INPUTS" | jq -r '.attributes.CUSTOMER_TYPE_VQF // null')
    107 # Get current rules.
    108 CURRENT_RULES=$(echo "$INPUTS" | jq '.current_rules // null')
    109 # Get context values.
    110 EXPIRATION_TIME=$(echo "$INPUTS" | jq '.context.expiration_time // .current_rules.expiration_time // null')
    111 
    112 # What is the next form to show?
    113 FORM="error"
    114 INVESTIGATE="false"
    115 
    116 case "$LEGAL_ENTITY"
    117 in
    118     "NATURAL_PERSON")
    119         FORM="none"
    120         # Check all mandatory attributes are present.
    121         echo "$INPUTS" \
    122             | jq '.attributes' \
    123             | jq -r 'def get($k):
    124              if has($k)
    125                then .[$k]
    126                else error("attribute \($k) missing")
    127            end;
    128            {"FULL_NAME":get("FULL_NAME"),
    129             "DOMICILE_ADDRESS":get("DOMICILE_ADDRESS"),
    130             "DATE_OF_BIRTH":get("DATE_OF_BIRTH"),
    131             "NATIONALITY":get("NATIONALITY"),
    132             "PERSONAL_IDENTIFICATION_DOCUMENT_COPY":get("PERSONAL_IDENTIFICATION_DOCUMENT_COPY"),
    133             "CUSTOMER_IS_SOLE_PROPRIETOR":get("CUSTOMER_IS_SOLE_PROPRIETOR")
    134            }' \
    135                  > /dev/null \
    136                  || exec taler-exchange-helper-measure-freeze
    137         ;;
    138     "OPERATIONAL")
    139         FORM="form-vqf-902.11"
    140         # Check all mandatory attributes are present.
    141         echo "$INPUTS" \
    142             | jq '.attributes' \
    143             | jq -r 'def get($k):
    144              if has($k)
    145                then .[$k]
    146                else error("attribute \($k) missing")
    147            end;
    148            {"COMPANY_NAME":get("COMPANY_NAME"),
    149             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    150             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    151             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    152            }' \
    153                  > /dev/null \
    154                  || exec taler-exchange-helper-measure-freeze
    155         ;;
    156     "FOUNDATION")
    157         # FIXME: #9825: Not yet supported!
    158         # FORM="vqf-902.12"
    159         FORM=error
    160         INVESTIGATE="true"
    161         # Check all mandatory attributes are present.
    162         echo "$INPUTS" \
    163             | jq '.attributes' \
    164             | jq -r 'def get($k):
    165              if has($k)
    166                then .[$k]
    167                else error("attribute \($k) missing")
    168            end;
    169            {"COMPANY_NAME":get("COMPANY_NAME"),
    170             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    171             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    172             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    173            }' \
    174                  > /dev/null \
    175                  || exec taler-exchange-helper-measure-freeze
    176         ;;
    177     "TRUST")
    178         # FIXME: #9027: Not yet supported!
    179         # FORM="vqf-902.13"
    180         FORM=error
    181         INVESTIGATE="true"
    182         # Check all mandatory attributes are present.
    183         echo "$INPUTS" \
    184             | jq '.attributes' \
    185             | jq -r 'def get($k):
    186              if has($k)
    187                then .[$k]
    188                else error("attribute \($k) missing")
    189            end;
    190            {"COMPANY_NAME":get("COMPANY_NAME"),
    191             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    192             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    193             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    194            }' \
    195                  > /dev/null \
    196                  || exec taler-exchange-helper-measure-freeze
    197         ;;
    198     "LIFE_INSURANCE")
    199         # FIXME: #9826: Not yet supported!
    200         # FORM="vqf-902.15"
    201         FORM=error
    202         INVESTIGATE="true"
    203         # Check all mandatory attributes are present.
    204         echo "$INPUTS" \
    205             | jq '.attributes' \
    206             | jq -r 'def get($k):
    207              if has($k)
    208                then .[$k]
    209                else error("attribute missing")
    210            end;
    211            {"COMPANY_NAME":get("COMPANY_NAME"),
    212             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    213             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    214             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    215            }' \
    216                  > /dev/null \
    217                  || exec taler-exchange-helper-measure-freeze
    218         ;;
    219     "OTHER")
    220         FORM="form-vqf-902.9"
    221         INVESTIGATE="true"
    222         ;;
    223 esac
    224 
    225 NEW_MEASURES="null"
    226 # Check high-level case
    227 case "$FORM"
    228 in
    229     "error")
    230         # This should not happen, immediately trigger investigation and show error to the user.
    231         echo "ERROR: Unexpected legal entity '${LEGAL_ENTITY}'" 1>&2
    232         NEW_RULES=$(echo "$CURRENT_RULES" | jq '(.rules[] |= if (.measures[0]=="kyx") then .measures=["inform-internal-error"] else . end)')
    233         INVESTIGATE="true"
    234         ;;
    235     "none")
    236         # Immediately trigger address validation.
    237         echo "$INPUTS" | taler-exchange-helper-measure-tops-address-check
    238         exit $?
    239         ;;
    240     *)
    241         # Proceed to FORM.
    242         echo "Selected VQF form ${FORM}." 1>&2
    243         # Force user to fill in $FORM
    244         NEW_RULES=$(echo "$CURRENT_RULES" | jq --arg form "$FORM" '(.rules[] |= if (.measures[0]=="kyx") then .measures=[$form] else . end)')
    245         NEW_MEASURES="\"$FORM\""
    246         ;;
    247 esac
    248 
    249 # When the information expires, simply ask the user to do the
    250 # same form again.
    251 SUCCESSOR_MEASURE='"kyx"'
    252 
    253 # Finally, output the new rules.
    254 # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome
    255 # for the required output format.
    256 
    257 jq -n \
    258     --argjson inv "$INVESTIGATE" \
    259     --argjson et "$EXPIRATION_TIME" \
    260     --argjson sm "$SUCCESSOR_MEASURE" \
    261     --argjson nm "$NEW_MEASURES" \
    262     --argjson nr "$NEW_RULES" \
    263 '
    264 {
    265   "to_investigate": $inv,
    266   "new_measures": $nm,
    267   "new_rules": (
    268     $nr + {
    269       "expiration_time": $et,
    270       "successor_measure": $sm,
    271       "custom_measures": ({} + $nr.custom_measures)
    272     }
    273   )
    274 } | del(..|nulls)
    275 '
    276 
    277 exit 0