Class: Complicode::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/complicode/generator.rb

Constant Summary collapse

BASE64 =
%w[
  0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V
  W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z + /
].freeze

Instance Method Summary collapse

Instance Method Details

#append_partial_keys(seeds, partial_keys) ⇒ Object



69
70
71
# File 'lib/complicode/generator.rb', line 69

def append_partial_keys(seeds, partial_keys)
  seeds.map.with_index { |seed, index| seed + partial_keys[index].value }
end

#append_verification_digits(seed, count) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/complicode/generator.rb', line 40

def append_verification_digits(seed, count)
  case seed
  when Array
    seed.map { |seed| append_verification_digits(seed, count) }
  else
    count.times do
      seed = seed.to_s + Verhoeff.checksum_digit_of(seed).to_s
    end

    seed
  end
end

#call(authorization_code:, key:, invoice:) ⇒ String

Parameters:

Returns:

  • (String)


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
# File 'lib/complicode/generator.rb', line 14

def call(authorization_code:, key:, invoice:)
  key.freeze

  seeds = [
    invoice.number.to_s,
    invoice.nit.to_s,
    invoice.issue_date.strftime("%Y%m%d"),
    invoice.amount.round.to_s,
  ]

  seeds = append_verification_digits(seeds, 2)
  digits = generate_verification_digits(seeds)
  partial_keys = generate_partial_keys(key.dup, digits)

  seeds.unshift(authorization_code)
  seeds = append_partial_keys(seeds, partial_keys)

  encryption_key = key + digits
  encrypted_data = encrypt(seeds.join, encryption_key)

  ascii_sums = generate_ascii_sums(encrypted_data, partial_keys.count)
  base64_data = generate_base64_data(ascii_sums, partial_keys)

  format(encrypt(base64_data, encryption_key))
end

#encrypt(data, encryption_key) ⇒ String

Parameters:

  • data (String)
  • encryption_key (String)

Returns:

  • (String)


97
98
99
# File 'lib/complicode/generator.rb', line 97

def encrypt(data, encryption_key)
  RC4.new(encryption_key).encrypt(data).unpack1("H*").upcase
end

#format(code) ⇒ String

Parameters:

  • code (String)

Returns:

  • (String)


103
104
105
# File 'lib/complicode/generator.rb', line 103

def format(code)
  code.scan(/.{2}/).join("-")
end

#generate_ascii_sums(data, partials_count) ⇒ Struct

Parameters:

  • encrypted_data (String)
  • partials_count (Integer)

Returns:

  • (Struct)


76
77
78
79
80
81
82
83
# File 'lib/complicode/generator.rb', line 76

def generate_ascii_sums(data, partials_count)
  Struct.new(:total, :partials).new(0, Array.new(partials_count, 0)).tap do |sums|
    data.each_byte.with_index do |byte, index|
      sums.total += byte
      sums.partials[index % partials_count] += byte
    end
  end
end

#generate_base64_data(ascii_sums, partial_keys) ⇒ String

Parameters:

  • ascii_sums (Struct)
  • partial_keys (Array<String>)

Returns:

  • (String)


88
89
90
91
92
# File 'lib/complicode/generator.rb', line 88

def generate_base64_data(ascii_sums, partial_keys)
  ascii_sums.partials.each_with_index.inject(0) { |sum, (partial_sum, index)|
    sum + ascii_sums.total * partial_sum / partial_keys[index].size
  }.b(10).to_s(BASE64)
end

#generate_partial_keys(key, digits) ⇒ Array<Complicode::PartialKey>

Parameters:

  • key (String)
  • digits (String)

Returns:



64
65
66
67
# File 'lib/complicode/generator.rb', line 64

def generate_partial_keys(key, digits)
  partial_key_sizes = digits.split("").map { |digit| digit.to_i + 1 }
  partial_key_sizes.map { |index| PartialKey.new(value: key.slice!(0...index)) }
end

#generate_verification_digits(seeds) ⇒ String

Parameters:

  • invoice (Array<String>)

Returns:

  • (String)


55
56
57
58
59
# File 'lib/complicode/generator.rb', line 55

def generate_verification_digits(seeds)
  sum = seeds.map(&:to_i).sum
  sum = append_verification_digits(sum, 5)
  sum.to_s[-5..-1]
end