#!/usr/bin/env python3 # hacked from https://github.com/mindmedia/paynow.py and # https://www.emvco.com/wp-content/uploads/documents/EMVCo-Merchant-Presented-QR-Specification-v1.1.pdf import sys import binascii Fields = { "00" : "Format_ID", "01" : "Proxy_type", "26" : "Merchant_Account_Info", "2600" : "Domain", "2601" : "PayNow_ID_type", "2602" : "PayNow_ID", "2603" : "Is_editable", "2604" : "Expiration", "52" : "Merchant_category", "53" : "Transaction_currency", "54" : "Transaction_amount", "55" : "Transaction_convenience_fee_is_presented", "56" : "Transaction_convenience_fee_fixed", "57" : "Transaction_convenience_fee_pct", "58" : "Country_code", "59" : "Merchant_name", "60" : "Merchant_city", "61" : "Merchant_postal_code", "62" : "Bill_Info", "6201" : "Bill_number", "6202" : "Bill_phone_number", "6203" : "Bill_store_label", "6204" : "Bill_loyalty_number", "6204" : "Bill_reference_number", "6206" : "Bill_customer_label", "6206" : "Bill_terminal_label", "6208" : "Bill_transaction_purpose", "6210" : "Bill_merchant_tax_id", "6211" : "Bill_merchant_channel", "63" : "CRC" } def Transaction_currency_fn(num): ''' Lookup the currency code -- https://www.iban.com/currency-codes ''' return { "036" : "AUD", "096" : "BND", "124" : "CAD", "156" : "CNY", "344" : "HKD", "356" : "INR", "360" : "IDR", "392" : "JPY", "410" : "KRW", "446" : "MOP", "458" : "MYR", "554" : "NZD", "608" : "PHP", "682" : "SAR", "702" : "SGD", "704" : "VND", "764" : "THB", "784" : "AED", "826" : "GBP", "840" : "USD", "901" : "TWD", "978" : "EUR", }[num] def has_subfield(field_id): ''' do any Field IDs have `field_id` as a prefix? ''' return 1 < len( [ k for k in Fields.keys() if k.startswith( field_id ) ]) def get_field(Fs, i): ''' get the next field, its value, and offset increment ''' f = Fs[ i : i+2 ] l = int( Fs[ i+2 : i+4 ]) return f, Fs[ i+4 : i+4+l ], i+4+l def scan(fields, reply={}, i=0, prefix=''): ''' parse the fields into `reply` ''' while i < len(fields): f,v,i = get_field(fields, i) f = prefix + f reply[f] = v if has_subfield(f): scan( v, reply, prefix=f ) return reply qr = ' '.join(sys.argv[1:]) assert qr[ -4: ] == '{:04X}'.format( binascii.crc_hqx(qr[ 0:-4 ].encode('utf-8'), 0xFFFF)) for fid,fval in scan(qr).items(): if has_subfield(fid): continue for fn in [ v for k,v in globals().items() if k == Fields[fid] + '_fn' ]: fval = fn(fval) print(fid, Fields[fid], fval)