class Epics::Client

Attributes

bic[W]
host_id[RW]
iban[W]
keys[RW]
keys_content[RW]
name[W]
partner_id[RW]
passphrase[RW]
url[RW]
user_id[RW]

Public Class Methods

new(keys_content, passphrase, url, host_id, user_id, partner_id) click to toggle source
# File lib/epics/client.rb, line 9
def initialize(keys_content, passphrase, url, host_id, user_id, partner_id)
  self.keys_content = keys_content.respond_to?(:read) ? keys_content.read : keys_content if keys_content
  self.passphrase = passphrase
  self.keys = extract_keys if keys_content
  self.url  = url
  self.host_id    = host_id
  self.user_id    = user_id
  self.partner_id = partner_id
end
setup(passphrase, url, host_id, user_id, partner_id, keysize = 2048) click to toggle source
# File lib/epics/client.rb, line 62
def self.setup(passphrase, url, host_id, user_id, partner_id, keysize = 2048)
  client = new(nil, passphrase, url, host_id, user_id, partner_id)
  client.keys = %w(A006 X002 E002).each_with_object({}) do |type, memo|
    memo[type] = Epics::Key.new( OpenSSL::PKey::RSA.generate(keysize) )
  end

  client
end

Public Instance Methods

AZV(document) click to toggle source
# File lib/epics/client.rb, line 120
def AZV(document)
  upload(Epics::AZV, document)
end
C2S(document) click to toggle source
# File lib/epics/client.rb, line 132
def C2S(document)
  upload(Epics::C2S, document)
end
C52(from, to) click to toggle source
# File lib/epics/client.rb, line 184
def C52(from, to)
  download_and_unzip(Epics::C52, from, to)
end
C53(from, to) click to toggle source
# File lib/epics/client.rb, line 188
def C53(from, to)
  download_and_unzip(Epics::C53, from, to)
end
C54(from, to) click to toggle source
# File lib/epics/client.rb, line 192
def C54(from, to)
  download_and_unzip(Epics::C54, from, to)
end
CCS(document) click to toggle source
# File lib/epics/client.rb, line 160
def CCS(document)
  upload(Epics::CCS, document)
end
CCT(document) click to toggle source
# File lib/epics/client.rb, line 156
def CCT(document)
  upload(Epics::CCT, document)
end
CD1(document) click to toggle source
# File lib/epics/client.rb, line 124
def CD1(document)
  upload(Epics::CD1, document)
end
CDB(document) click to toggle source
# File lib/epics/client.rb, line 128
def CDB(document)
  upload(Epics::CDB, document)
end
CDD(document) click to toggle source
# File lib/epics/client.rb, line 136
def CDD(document)
  upload(Epics::CDD, document)
end
CDS(document) click to toggle source
# File lib/epics/client.rb, line 148
def CDS(document)
  upload(Epics::CDS, document)
end
CDZ(from = nil, to = nil) click to toggle source
# File lib/epics/client.rb, line 176
def CDZ(from = nil, to = nil)
  download_and_unzip(Epics::CDZ, from, to)
end
CRZ(from = nil, to = nil) click to toggle source
# File lib/epics/client.rb, line 180
def CRZ(from = nil, to = nil)
  download_and_unzip(Epics::CRZ, from, to)
end
HAA() click to toggle source
# File lib/epics/client.rb, line 208
def HAA
  Nokogiri::XML(download(Epics::HAA)).at_xpath("//xmlns:OrderTypes", xmlns: "urn:org:ebics:H004").content.split(/\s/)
end
HAC(from = nil, to = nil) click to toggle source
# File lib/epics/client.rb, line 233
def HAC(from = nil, to = nil)
  download(Epics::HAC, from, to)
end
HIA() click to toggle source
# File lib/epics/client.rb, line 93
def HIA
  post(url, Epics::HIA.new(self).to_xml).body.ok?
end
HKD() click to toggle source
# File lib/epics/client.rb, line 225
def HKD
  download(Epics::HKD)
end
HPB() click to toggle source
# File lib/epics/client.rb, line 101
def HPB
  Nokogiri::XML(download(Epics::HPB)).xpath("//xmlns:PubKeyValue", xmlns: "urn:org:ebics:H004").each do |node|
    type = node.parent.last_element_child.content

    modulus  = Base64.decode64(node.at_xpath(".//*[local-name() = 'Modulus']").content)
    exponent = Base64.decode64(node.at_xpath(".//*[local-name() = 'Exponent']").content)

    sequence = []
    sequence << OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(modulus, 2))
    sequence << OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(exponent, 2))

    bank = OpenSSL::PKey::RSA.new(OpenSSL::ASN1::Sequence(sequence).to_der)

    self.keys["#{host_id.upcase}.#{type}"] = Epics::Key.new(bank)
  end

  [bank_x, bank_e]
end
HPD() click to toggle source
# File lib/epics/client.rb, line 221
def HPD
  download(Epics::HPD)
end
HTD() click to toggle source
# File lib/epics/client.rb, line 212
def HTD
  Nokogiri::XML(download(Epics::HTD)).tap do |htd|
    @iban        ||= htd.at_xpath("//xmlns:AccountNumber[@international='true']", xmlns: "urn:org:ebics:H004").text rescue nil
    @bic         ||= htd.at_xpath("//xmlns:BankCode[@international='true']", xmlns: "urn:org:ebics:H004").text rescue nil
    @name        ||= htd.at_xpath("//xmlns:Name", xmlns: "urn:org:ebics:H004").text rescue nil
    @order_types ||= htd.search("//xmlns:OrderTypes", xmlns: "urn:org:ebics:H004").map{|o| o.content.split(/\s/) }.delete_if{|o| o == ""}.flatten
  end.to_xml
end
INI() click to toggle source
# File lib/epics/client.rb, line 97
def INI
  post(url, Epics::INI.new(self).to_xml).body.ok?
end
PTK(from, to) click to toggle source
# File lib/epics/client.rb, line 229
def PTK(from, to)
  download(Epics::PTK, from, to)
end
STA(from = nil, to = nil) click to toggle source
# File lib/epics/client.rb, line 168
def STA(from = nil, to = nil)
  download(Epics::STA, from, to)
end
VMK(from = nil, to = nil) click to toggle source
# File lib/epics/client.rb, line 172
def VMK(from = nil, to = nil)
  download(Epics::VMK, from, to)
end
XCT(document) click to toggle source
# File lib/epics/client.rb, line 164
def XCT(document)
  upload(Epics::XCT, document)
end
XDS(document) click to toggle source
# File lib/epics/client.rb, line 152
def XDS(document)
  upload(Epics::XDS, document)
end
XE2(document) click to toggle source
# File lib/epics/client.rb, line 140
def XE2(document)
  upload(Epics::XE2, document)
end
XE3(document) click to toggle source
# File lib/epics/client.rb, line 144
def XE3(document)
  upload(Epics::XE3, document)
end
Z52(from, to) click to toggle source
# File lib/epics/client.rb, line 196
def Z52(from, to)
  download_and_unzip(Epics::Z52, from, to)
end
Z53(from, to) click to toggle source
# File lib/epics/client.rb, line 200
def Z53(from, to)
  download_and_unzip(Epics::Z53, from, to)
end
Z54(from, to) click to toggle source
# File lib/epics/client.rb, line 204
def Z54(from, to)
  download_and_unzip(Epics::Z54, from, to)
end
a() click to toggle source
# File lib/epics/client.rb, line 30
def a
  keys["A006"]
end
bank_e() click to toggle source
# File lib/epics/client.rb, line 38
def bank_e
  keys["#{host_id.upcase}.E002"]
end
bank_x() click to toggle source
# File lib/epics/client.rb, line 42
def bank_x
  keys["#{host_id.upcase}.X002"]
end
bic() click to toggle source
# File lib/epics/client.rb, line 54
def bic
  @bic ||= (self.HTD; @bic)
end
credit(document) click to toggle source
# File lib/epics/client.rb, line 81
def credit(document)
  self.CCT(document)
end
debit(document, type = :CDD) click to toggle source
# File lib/epics/client.rb, line 85
def debit(document, type = :CDD)
  self.public_send(type, document)
end
e() click to toggle source
# File lib/epics/client.rb, line 26
def e
  keys["E002"]
end
iban() click to toggle source
# File lib/epics/client.rb, line 50
def iban
  @iban ||= (self.HTD; @iban)
end
ini_letter(bankname) click to toggle source
# File lib/epics/client.rb, line 71
def ini_letter(bankname)
  raw = File.read(File.join(File.dirname(__FILE__), '../letter/', 'ini.erb'))
  ERB.new(raw).result(binding)
end
inspect() click to toggle source
# File lib/epics/client.rb, line 19
def inspect
  "#<#{self.class}:#{self.object_id}
   @keys=#{self.keys.keys},
   @user_id=\"#{self.user_id}\",
   @partner_id=\"#{self.partner_id}\""
end
name() click to toggle source
# File lib/epics/client.rb, line 46
def name
  @name ||= (self.HTD; @name)
end
order_types() click to toggle source
# File lib/epics/client.rb, line 58
def order_types
  @order_types ||= (self.HTD; @order_types)
end
save_ini_letter(bankname, path) click to toggle source
# File lib/epics/client.rb, line 76
def save_ini_letter(bankname, path)
  File.write(path, ini_letter(bankname))
  path
end
save_keys(path) click to toggle source
# File lib/epics/client.rb, line 237
def save_keys(path)
  File.write(path, dump_keys)
end
statements(from, to, type = :STA) click to toggle source
# File lib/epics/client.rb, line 89
def statements(from, to, type = :STA)
  self.public_send(type, from, to)
end
x() click to toggle source
# File lib/epics/client.rb, line 34
def x
  keys["X002"]
end

Private Instance Methods

connection() click to toggle source
# File lib/epics/client.rb, line 275
def connection
  @connection ||= Faraday.new(headers: { 'Content-Type' => 'text/xml', user_agent: "EPICS v#{Epics::VERSION}"}, ssl: { verify: verify_ssl? }) do |faraday|
    faraday.use Epics::XMLSIG, { client: self }
    faraday.use Epics::ParseEbics, { client: self}
    # faraday.use MyAdapter
    # faraday.response :logger                  # log requests to STDOUT
  end
end
decrypt(data) click to toggle source
# File lib/epics/client.rb, line 307
def decrypt(data)
  data = Base64.strict_decode64(data)
  salt = data[0..7]
  data = data[8..-1]

  cipher = setup_cipher(:decrypt, self.passphrase, salt)
  cipher.update(data) + cipher.final
end
download(order_type, *args) click to toggle source
# File lib/epics/client.rb, line 255
def download(order_type, *args)
  document = order_type.new(self, *args)
  res = post(url, document.to_xml).body
  document.transaction_id = res.transaction_id

  if res.segmented? && res.last_segment?
    post(url, document.to_receipt_xml).body
  end

  res.order_data
end
download_and_unzip(order_type, *args) click to toggle source
# File lib/epics/client.rb, line 267
def download_and_unzip(order_type, *args)
  [].tap do |entries|
    Zip::File.open_buffer(StringIO.new(download(order_type, *args))).each do |zipfile|
      entries << zipfile.get_input_stream.read
    end
  end
end
dump_keys() click to toggle source
# File lib/epics/client.rb, line 290
def dump_keys
  JSON.dump(keys.each_with_object({}) {|(k,v),m| m[k]= encrypt(v.key.to_pem)})
end
encrypt(data) click to toggle source
# File lib/epics/client.rb, line 300
def encrypt(data)
  salt = OpenSSL::Random.random_bytes(8)

  cipher = setup_cipher(:encrypt, self.passphrase, salt)
  Base64.strict_encode64([salt, cipher.update(data) + cipher.final].join)
end
extract_keys() click to toggle source
# File lib/epics/client.rb, line 284
def extract_keys
  JSON.load(self.keys_content).each_with_object({}) do |(type, key), memo|
    memo[type] = Epics::Key.new(decrypt(key)) if key
  end
end
new_cipher() click to toggle source
# File lib/epics/client.rb, line 294
def new_cipher
  # Re-using the cipher between keys has weird behaviours with openssl3
  # Using a fresh key instead of memoizing it on the client simplifies things
  OpenSSL::Cipher.new('aes-256-cbc')
end
setup_cipher(method, passphrase, salt) click to toggle source
# File lib/epics/client.rb, line 316
def setup_cipher(method, passphrase, salt)
  cipher = new_cipher
  cipher.send(method)
  cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(passphrase, salt, 1, cipher.key_len)
  cipher
end
upload(order_type, document) click to toggle source
# File lib/epics/client.rb, line 243
def upload(order_type, document)
  order = order_type.new(self, document)
  res = post(url, order.to_xml).body
  order.transaction_id = res.transaction_id

  order_id = res.order_id

  res = post(url, order.to_transfer_xml).body

  return res.transaction_id, [res.order_id, order_id].detect { |id| id.to_s.chars.any? }
end
verify_ssl?() click to toggle source
# File lib/epics/client.rb, line 323
def verify_ssl?
  ENV['EPICS_VERIFY_SSL'] != 'false'
end