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 (8975B)


      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             exit 0
     63             ;;
     64         r)
     65             # Nothing needed from context
     66             exit 0
     67             ;;
     68         v)
     69             echo "$0 v0.0.3"
     70             exit 0
     71             ;;
     72         V)
     73             VERBOSE=1
     74             ;;
     75         ?)
     76         exit_fail "Unrecognized command line option"
     77         ;;
     78     esac
     79 done
     80 
     81 if [ 1 = "$VERBOSE" ]
     82 then
     83     echo "Running $0" 1>&2
     84 fi
     85 
     86 # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlProgramInput
     87 # for the full JSON with possible inputs.
     88 
     89 # First, extract inputs we need
     90 INPUTS=$(jq '{"current_rules":.current_rules,"attributes":.attributes}')
     91 
     92 
     93 # Check form ID, must be 'vqf-902.11'
     94 FORM_ID=$(echo "$INPUTS" | jq -r '.attributes.FORM_ID')
     95 
     96 # The 'form' here should be the VQF 902.11 customer form
     97 if [ "$FORM_ID" != "vqf_902_1_customer" ]
     98 then
     99     echo "Unexpected form ID $FORM_ID" 1>&2
    100     echo "$INPUTS" | exec taler-exchange-helper-measure-freeze
    101     exit 1
    102 fi
    103 
    104 # Get entity type
    105 LEGAL_ENTITY=$(echo "$INPUTS" | jq -r '.attributes.CUSTOMER_TYPE_VQF // null')
    106 # Get current rules.
    107 CURRENT_RULES=$(echo "$INPUTS" | jq '.current_rules // null')
    108 # Get context values.
    109 EXPIRATION_TIME=$(echo "$INPUTS" | jq '.context.expiration_time // .current_rules.expiration_time // null')
    110 
    111 # What is the next form to show?
    112 FORM="error"
    113 INVESTIGATE="false"
    114 
    115 case "$LEGAL_ENTITY"
    116 in
    117     "NATURAL_PERSON")
    118         FORM="none"
    119         # Check all mandatory attributes are present.
    120         echo "$INPUTS" \
    121             | jq '.attributes' \
    122             | jq -r 'def get($k):
    123              if has($k)
    124                then .[$k]
    125                else error("attribute \($k) missing")
    126            end;
    127            {"FULL_NAME":get("FULL_NAME"),
    128             "DOMICILE_ADDRESS":get("DOMICILE_ADDRESS"),
    129             "DATE_OF_BIRTH":get("DATE_OF_BIRTH"),
    130             "NATIONALITY":get("NATIONALITY"),
    131             "PERSONAL_IDENTIFICATION_DOCUMENT_COPY":get("PERSONAL_IDENTIFICATION_DOCUMENT_COPY"),
    132             "CUSTOMER_IS_SOLE_PROPRIETOR":get("CUSTOMER_IS_SOLE_PROPRIETOR")
    133            }' \
    134                  > /dev/null \
    135                  || exec taler-exchange-helper-measure-freeze
    136         ;;
    137     "OPERATIONAL")
    138         FORM="form-vqf-902.11"
    139         # Check all mandatory attributes are present.
    140         echo "$INPUTS" \
    141             | jq '.attributes' \
    142             | jq -r 'def get($k):
    143              if has($k)
    144                then .[$k]
    145                else error("attribute \($k) missing")
    146            end;
    147            {"COMPANY_NAME":get("COMPANY_NAME"),
    148             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    149             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    150             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    151            }' \
    152                  > /dev/null \
    153                  || exec taler-exchange-helper-measure-freeze
    154         ;;
    155     "FOUNDATION")
    156         # FIXME: #9825: Not yet supported!
    157         # FORM="vqf-902.12"
    158         FORM=error
    159         INVESTIGATE="true"
    160         # Check all mandatory attributes are present.
    161         echo "$INPUTS" \
    162             | jq '.attributes' \
    163             | jq -r 'def get($k):
    164              if has($k)
    165                then .[$k]
    166                else error("attribute \($k) missing")
    167            end;
    168            {"COMPANY_NAME":get("COMPANY_NAME"),
    169             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    170             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    171             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    172            }' \
    173                  > /dev/null \
    174                  || exec taler-exchange-helper-measure-freeze
    175         ;;
    176     "TRUST")
    177         # FIXME: #9027: Not yet supported!
    178         # FORM="vqf-902.13"
    179         FORM=error
    180         INVESTIGATE="true"
    181         # Check all mandatory attributes are present.
    182         echo "$INPUTS" \
    183             | jq '.attributes' \
    184             | jq -r 'def get($k):
    185              if has($k)
    186                then .[$k]
    187                else error("attribute \($k) missing")
    188            end;
    189            {"COMPANY_NAME":get("COMPANY_NAME"),
    190             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    191             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    192             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    193            }' \
    194                  > /dev/null \
    195                  || exec taler-exchange-helper-measure-freeze
    196         ;;
    197     "LIFE_INSURANCE")
    198         # FIXME: #9826: Not yet supported!
    199         # FORM="vqf-902.15"
    200         FORM=error
    201         INVESTIGATE="true"
    202         # Check all mandatory attributes are present.
    203         echo "$INPUTS" \
    204             | jq '.attributes' \
    205             | jq -r 'def get($k):
    206              if has($k)
    207                then .[$k]
    208                else error("attribute missing")
    209            end;
    210            {"COMPANY_NAME":get("COMPANY_NAME"),
    211             "REGISTERED_OFFICE_ADDRESS":get("REGISTERED_OFFICE_ADDRESS"),
    212             "LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY":get("LEGAL_ENTITY_IDENTIFICATION_DOCUMENT_COPY"),
    213             "ESTABLISHER_LIST":get("ESTABLISHER_LIST")
    214            }' \
    215                  > /dev/null \
    216                  || exec taler-exchange-helper-measure-freeze
    217         ;;
    218     "OTHER")
    219         FORM="form-vqf-902.9"
    220         INVESTIGATE="true"
    221         ;;
    222 esac
    223 
    224 NEW_MEASURES="null"
    225 # Check high-level case
    226 case "$FORM"
    227 in
    228     "error")
    229         # This should not happen, immediately trigger investigation and show error to the user.
    230         echo "ERROR: Unexpected legal entity '${LEGAL_ENTITY}'" 1>&2
    231         NEW_RULES=$(echo "$CURRENT_RULES" | jq '(.rules[] |= if (.measures[0]=="kyx") then .measures=["inform-internal-error"] else . end)')
    232         INVESTIGATE="true"
    233         ;;
    234     "none")
    235         # Immediately trigger address validation.
    236         echo "$INPUTS" | taler-exchange-helper-measure-tops-address-check
    237         exit $?
    238         ;;
    239     *)
    240         # Proceed to FORM.
    241         echo "Selected VQF form ${FORM}." 1>&2
    242         # Force user to fill in $FORM
    243         NEW_RULES=$(echo "$CURRENT_RULES" | jq --arg form "$FORM" '(.rules[] |= if (.measures[0]=="kyx") then .measures=[$form] else . end)')
    244         NEW_MEASURES="\"$FORM\""
    245         ;;
    246 esac
    247 
    248 # When the information expires, simply ask the user to do the
    249 # same form again.
    250 SUCCESSOR_MEASURE='"kyx"'
    251 
    252 # Finally, output the new rules.
    253 # See https://docs.taler.net/taler-kyc-manual.html#tsref-type-AmlOutcome
    254 # for the required output format.
    255 
    256 jq -n \
    257     --argjson inv "$INVESTIGATE" \
    258     --argjson et "$EXPIRATION_TIME" \
    259     --argjson sm "$SUCCESSOR_MEASURE" \
    260     --argjson nm "$NEW_MEASURES" \
    261     --argjson nr "$NEW_RULES" \
    262 '
    263 {
    264   "to_investigate": $inv,
    265   "new_measures": $nm,
    266   "new_rules": (
    267     $nr + {
    268       "expiration_time": $et,
    269       "successor_measure": $sm,
    270       "custom_measures": ({} + $nr.custom_measures)
    271     }
    272   )
    273 } | del(..|nulls)
    274 '
    275 
    276 exit 0