from otree.api import * import string import numpy as np import random c = cu doc = 'Payment processing' class Constants(BaseConstants): name_in_url = 'payment' players_per_group = None num_rounds=1 LETTERS_DICT={} #generates dictionary to translate letters (from ascii values) into numerical values according to IBAN verification algorithm (A=10, ...) for i,d in enumerate(string.digits + string.ascii_uppercase): LETTERS_DICT[ord(d)] = str(i) choice_set=[] for i in string.digits: choice_set.append(ord(i)) for i in range(ord('A'), ord('Z')+1): choice_set.append(i) def generate_random_id(): '''Generates a random (non-secure) identifier out of uppercase latters and numbers''' random_string = '' for i in range(10): random_char = random.choice(Constants.choice_set) # Keep appending random characters using chr(x) random_string += (chr(random_char)) return random_string class Subsession(BaseSubsession): pass def creating_session(subsession): for players in subsession.get_players(): players.payout_id = generate_random_id() class Group(BaseGroup): pass class Player(BasePlayer): payout_id = models.StringField(initial='') #for reference in case participant needs to contact experimenters iban_number = models.StringField(label='IBAN (account number)') iban_name = models.StringField(label='Name of account holder') class Payment(Page): #payment details page form_model = 'player' form_fields=['iban_number', 'iban_name'] @staticmethod def error_message(player, values): if check_iban(values['iban_number']) !=1: return 'IBAN invalid - please check your account number' @staticmethod def before_next_page(player, timeout_happened): player.iban_number = ''.join(player.iban_number.split()) player.iban_number = player.iban_number.upper() class Thanks(Page): #final summary page form_model = 'player' def iban_letter_replacement(iban_string): '''Replaces letters in a string with numerical values defined in LETTERS_DICT''' iban_numeric = iban_string.translate(Constants.LETTERS_DICT) return iban_numeric def iban_valid(iban_string): '''IBAN mod 97 verification check, returns TRUE if IBAN valid according to this check''' inverted_iban = iban_string[4:] + iban_string[:4] inverted_numeric = int(iban_letter_replacement(inverted_iban)) return (inverted_numeric % 97) ==1 def iban_char_verify(iban_string): '''Generates IBAN verification characters and compares them with the given ones, returns TRUE if identical''' iban_nc = iban_string[4:] + iban_string[:2] + '00' iban_nc_inv_num = int(iban_letter_replacement(iban_nc)) return '{:02}'.format(98 - iban_nc_inv_num % 97)==iban_string[2:4] def check_iban(iban_string): '''Verfies IBAN validity with mod97 check as well as the verification characters''' iban_string = iban_string.upper() iban_string = ''.join(iban_string.split()) #removes all type of whitespaces try: return iban_char_verify(iban_string) and iban_valid(iban_string) except: return False page_sequence = [Payment, Thanks]