Module: Bakong::Khqr::Controllers::DecodeNonKHQR
- Defined in:
- lib/bakong/khqr/controllers/decode_non_khqr.rb
Overview
Generic EMVCo TLV decoder for QR strings that may or may not be KHQR. Walks up to three levels of nested TLV for the same composite-tag ranges the upstream JS package handles (26–51, 80–99, 62, 64).
Class Method Summary collapse
- .call(qr) ⇒ Object
- .composite_tag?(tag) ⇒ Boolean
- .extract_tlv(string) ⇒ Object
- .valid?(tag, length, value) ⇒ Boolean
Class Method Details
.call(qr) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/bakong/khqr/controllers/decode_non_khqr.rb', line 12 def call(qr) first_level = {} final_data = {} remainder = qr loop do parsed = extract_tlv(remainder) break unless valid?(parsed[:tag], parsed[:length], parsed[:value]) first_level[parsed[:tag]] = parsed[:value] remainder = parsed[:remain] break if remainder.nil? || remainder.empty? end first_level.each do |tag, value| final_data[tag] = value next unless composite_tag?(tag) next if value.length < 6 second_level = {} remaining_value = value loop do third_level = {} parsed = extract_tlv(remaining_value) break unless valid?(parsed[:tag], parsed[:length], parsed[:value]) sub_tag = parsed[:tag] sub_value = parsed[:value] remaining_value = parsed[:remain] if tag == "62" && (50..99).cover?(sub_tag.to_i) inner = sub_value loop do inner_parsed = extract_tlv(inner) break unless valid?(inner_parsed[:tag], inner_parsed[:length], inner_parsed[:value]) third_level[inner_parsed[:tag]] = inner_parsed[:value] inner = inner_parsed[:remain] break if inner.nil? || inner.empty? end end second_level[sub_tag] = third_level.empty? ? sub_value : third_level break if remaining_value.nil? || remaining_value.empty? end final_data[tag] = second_level unless second_level.empty? end final_data end |
.composite_tag?(tag) ⇒ Boolean
73 74 75 76 |
# File 'lib/bakong/khqr/controllers/decode_non_khqr.rb', line 73 def composite_tag?(tag) int = tag.to_i (26..51).cover?(int) || (80..99).cover?(int) || tag == "64" || tag == "62" end |
.extract_tlv(string) ⇒ Object
65 66 67 68 69 70 71 |
# File 'lib/bakong/khqr/controllers/decode_non_khqr.rb', line 65 def extract_tlv(string) tag = string[0, 2].to_s length = string[2, 2].to_i value = string[4, length].to_s remain = string[(4 + length)..] || "" { tag: tag, length: length, value: value, remain: remain } end |
.valid?(tag, length, value) ⇒ Boolean
78 79 80 |
# File 'lib/bakong/khqr/controllers/decode_non_khqr.rb', line 78 def valid?(tag, length, value) tag.match?(/\A\d+\z/) && length == value.length end |