-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathclient.rb
More file actions
97 lines (74 loc) · 2.98 KB
/
client.rb
File metadata and controls
97 lines (74 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
require "lemonway/core_ext/hash"
require 'savon'
require "rexml/document"
module Lemonway
class Client
class Error < StandardError
attr_reader :code
def initialize(code: nil, message:)
super(message)
@code = code
end
end
attr_accessor :instance
def initialize api_opts={}, client_opts={}, &block
[api_opts, client_opts].each(&:symbolize_keys!)
@xml_mini_backend = client_opts.delete(:xml_mini_backend) || ActiveSupport::XmlMini_REXML
@entity_expansion_text_limit = client_opts.delete(:entity_expansion_text_limit) || 10**20
@instance = Savon.client client_opts.update(wsdl: api_opts.delete(:wsdl)), &block
@api_options = api_opts.camelize_keys.with_indifferent_access
end
def operations
@instance.operations
end
def method_missing method_name, *args, &block
if operations.include? method_name.to_sym
client_call method_name, *args, &block
else
super
end
end
private
def client_call method_name, message_opts = {}, client_opts = {}, &block
resp = @instance.call method_name, client_opts.update(message: build_message(message_opts)), &block
result = resp.body.fetch(:"#{method_name}_response").fetch(:"#{method_name}_result")
result = with_custom_parser_options { Hash.from_xml(result) } unless result.is_a? Hash
result = result.underscore_keys(true).with_indifferent_access
if result.key?(:e)
raise Error, code: result.fetch(:e).try(:fetch, :code), message: result.fetch(:e).try(:fetch, :msg)
elsif result.key?(:trans)
result[:trans].fetch(:hpay, result[:trans])
elsif result.key?(:wallet)
result[:wallet]
else
result
end
rescue KeyError => e
#todo improve this message
raise Error, message: "#{e.message}, expected `#{method_name}_response.#{method_name}_result` but got : #{resp.body.inspect}"
end
# work around for
# - Nokogiri::XML::SyntaxError: xmlns: URI Service_mb is not absolute
# - RuntimeError: entity expansion has grown too large
def with_custom_parser_options &block
original_backend = ActiveSupport::XmlMini.backend
original_text_limit = REXML::Document.entity_expansion_text_limit
ActiveSupport::XmlMini.backend = @xml_mini_backend
REXML::Document.entity_expansion_text_limit = @entity_expansion_text_limit
yield
ensure
ActiveSupport::XmlMini.backend = original_backend
REXML::Document.entity_expansion_text_limit = original_text_limit
end
def build_message opts = {}
opts = @api_options.merge(opts.symbolize_keys.camelize_keys)
[:amount, :amountTot, :amountCom].each do |key|
opts[key] = sprintf("%.2f",opts[key]) if opts.key?(key) and opts[key].is_a?(Numeric)
end
[:updateDate].each do |key|
opts[key] = opts[key].to_datetime.utc.to_i.to_s if opts.key?(key) and [Date, Time].any?{|k| opts[key].is_a?(k)}
end
opts
end
end
end