killbill-orbital 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79c94a1e5cf3ddacf63444b693a0b576353b3c7b
4
- data.tar.gz: ccf210b4dd5e6e76047552eccfc00898ac27bc82
3
+ metadata.gz: cec1cf6adeb886d2e658647977c87cc258505954
4
+ data.tar.gz: a0f94ccdb83a09e44bafd3546f0c19aed32a256f
5
5
  SHA512:
6
- metadata.gz: 0bfef0b4ec28065a2b8dba0acd47a8c2e8491cb85b2920dcb602c4c2e3d3356ed64a7f9a964aebeb04277a97569f3950ad6c3904d5ae68fd13c5fea0592dc823
7
- data.tar.gz: 754d60b264e0d33e0dc58abcc4f76e8c316c3ce43bdcd602e709f1877a034983e12a78876e311e46b624e3f9c2468ce27ccbdab679d3a8b4abd9686d6f328650
6
+ metadata.gz: 36f2b52df194d8469e5c4957b2bded12f6d4d8a5dd7c67d3fe8d7ef03452163d8b4bd78a2bc6945381ce1211fa45f8f3bbe50366bee739a04d14b649dbef6448
7
+ data.tar.gz: 19170d1876ada2aa6d01ac59cf19682329bf1860518d4f4048625864856b32ec9a32318adb4dcf8b6fec8b5b2607309839f850c42fb33d867e147f6555eb2360
data/lib/orbital/api.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  module Killbill #:nodoc:
2
2
  module Orbital #:nodoc:
3
3
  class PaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PaymentPlugin
4
+ FIVE_MINUTES_AGO = (5 * 60)
5
+ ONE_HOUR_AGO = (1 * 3600)
4
6
 
5
7
  def initialize
6
8
  gateway_builder = Proc.new do |config|
@@ -30,7 +32,7 @@ module Killbill #:nodoc:
30
32
  options = {}
31
33
 
32
34
  properties = merge_properties(properties, options)
33
- super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
35
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, with_trace_num_and_order_id(properties))
34
36
  end
35
37
 
36
38
  def capture_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
@@ -43,7 +45,7 @@ module Killbill #:nodoc:
43
45
  options[:prior_auth_id] = last_auth_response.params_auth_code
44
46
  purchase_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, hash_to_properties(options), context)
45
47
  else
46
- super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
48
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, with_trace_num_and_order_id(properties))
47
49
  end
48
50
  end
49
51
 
@@ -52,7 +54,7 @@ module Killbill #:nodoc:
52
54
  options = {}
53
55
 
54
56
  properties = merge_properties(properties, options)
55
- super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
57
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, with_trace_num_and_order_id(properties))
56
58
  end
57
59
 
58
60
  def void_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
@@ -60,7 +62,7 @@ module Killbill #:nodoc:
60
62
  options = {}
61
63
 
62
64
  properties = merge_properties(properties, options)
63
- super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context)
65
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, properties, context, with_trace_num_and_order_id(properties))
64
66
  end
65
67
 
66
68
  def credit_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
@@ -68,7 +70,7 @@ module Killbill #:nodoc:
68
70
  options = {}
69
71
 
70
72
  properties = merge_properties(properties, options)
71
- super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
73
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, with_trace_num_and_order_id(properties))
72
74
  end
73
75
 
74
76
  def refund_payment(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
@@ -76,15 +78,15 @@ module Killbill #:nodoc:
76
78
  options = {}
77
79
 
78
80
  properties = merge_properties(properties, options)
79
- super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context)
81
+ super(kb_account_id, kb_payment_id, kb_payment_transaction_id, kb_payment_method_id, amount, currency, properties, context, with_trace_num_and_order_id(properties))
80
82
  end
81
83
 
82
84
  def get_payment_info(kb_account_id, kb_payment_id, properties, context)
83
- # Pass extra parameters for the gateway here
84
- options = {}
85
+ options = properties_to_hash(properties)
85
86
 
86
- properties = merge_properties(properties, options)
87
- super(kb_account_id, kb_payment_id, properties, context)
87
+ plugin_trxs_info = super(kb_account_id, kb_payment_id, properties, context)
88
+ return super(kb_account_id, kb_payment_id, properties, context) if try_fix_undefined_trxs(plugin_trxs_info, options, context)
89
+ plugin_trxs_info
88
90
  end
89
91
 
90
92
  def search_payments(search_key, offset, limit, properties, context)
@@ -142,6 +144,82 @@ module Killbill #:nodoc:
142
144
  def reset_payment_methods(kb_account_id, payment_methods, properties, context)
143
145
  super
144
146
  end
147
+
148
+ private
149
+
150
+ def try_fix_undefined_trxs(plugin_trxs_info, options, context)
151
+ stale = false
152
+ plugin_trxs_info.each do |plugin_trx_info|
153
+ next unless should_try_to_fix_trx plugin_trx_info, options
154
+ stale = true if fix_undefined_trx plugin_trx_info, context, options
155
+ end
156
+ stale
157
+ end
158
+
159
+ def should_try_to_fix_trx(plugin_trx_info, options)
160
+ plugin_trx_info.status == :UNDEFINED && pass_delay_time(plugin_trx_info, options)
161
+ end
162
+
163
+ def fix_undefined_trx(plugin_trx_info, context, options)
164
+ inquiry_response = inquiry(plugin_trx_info, context)
165
+ update_response_if_needed plugin_trx_info, inquiry_response, options
166
+ end
167
+
168
+ def update_response_if_needed(plugin_trx_info, inquiry_response, options)
169
+ response_id = find_value_from_properties(plugin_trx_info.properties, 'orbital_response_id')
170
+ response = OrbitalResponse.find_by(:id => response_id)
171
+ updated = false
172
+ if should_update_response inquiry_response, plugin_trx_info
173
+ logger.info("Fixing UNDEFINED kb_transaction_id='#{plugin_trx_info.kb_transaction_payment_id}', success='#{inquiry_response.success?}'")
174
+ response.update_and_create_transaction(inquiry_response)
175
+ updated = true
176
+ elsif should_cancel_payment plugin_trx_info, options
177
+ @logger.info("Canceling UNDEFINED kb_transaction_id='#{plugin_trx_info.kb_transaction_payment_id}'")
178
+ response.cancel
179
+ updated = true
180
+ end
181
+ updated
182
+ end
183
+
184
+ def should_update_response(inquiry_response, plugin_trx_info)
185
+ !inquiry_response.nil? && !inquiry_response.params.nil? && inquiry_response.params['order_id'] == plugin_trx_info.second_payment_reference_id
186
+ end
187
+
188
+ def should_cancel_payment(plugin_trx_info, options)
189
+ threshold = (Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :cancel_threshold) || ONE_HOUR_AGO).to_i
190
+ delay_since_trx(plugin_trx_info) >= threshold
191
+ end
192
+
193
+ def pass_delay_time(plugin_trx_info, options)
194
+ janitor_delay_threshold = (Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :janitor_delay_threshold) || FIVE_MINUTES_AGO).to_i
195
+ delay_since_trx(plugin_trx_info) >= janitor_delay_threshold
196
+ end
197
+
198
+ def delay_since_trx(plugin_trx_info)
199
+ delay_since_transaction = now - plugin_trx_info.created_date
200
+ delay_since_transaction < 0 ? 0 : delay_since_transaction
201
+ end
202
+
203
+ def now
204
+ Time.parse(@clock.get_clock.get_utc_now.to_s)
205
+ end
206
+
207
+ def inquiry(plugin_trx_info, context)
208
+ payment_processor_account_id = find_value_from_properties(plugin_trx_info.properties, 'payment_processor_account_id')
209
+ trace_number = find_value_from_properties(plugin_trx_info.properties, 'trace_number')
210
+ orbital_order_id = plugin_trx_info.second_payment_reference_id
211
+
212
+ return nil if trace_number.nil? || orbital_order_id.nil? || payment_processor_account_id.nil?
213
+
214
+ gateway = lookup_gateway(payment_processor_account_id, context.tenant_id)
215
+ gateway.inquiry(orbital_order_id, trace_number)
216
+ end
217
+
218
+ def with_trace_num_and_order_id(properties)
219
+ {:params_trace_number => find_value_from_properties(properties, :trace_number),
220
+ :params_order_id => find_value_from_properties(properties, :order_id)}.delete_if{|_, value| value.blank?}
221
+ end
222
+
145
223
  end
146
224
  end
147
225
  end
@@ -42,7 +42,7 @@ module ActiveMerchant
42
42
  'Content-Type' => 'application/PTI70')
43
43
  headers['X-Request-Id'] = x_r_id unless x_r_id.blank?
44
44
  headers.merge!('Trace-number' => trace_number.to_s,
45
- 'Merchant-Id' => @options[:merchant_id]) if @options[:retry_logic] && trace_number
45
+ 'Merchant-Id' => @options[:merchant_id]) if trace_number
46
46
  request = lambda { |url| parse(ssl_post(url, order, headers)) }
47
47
 
48
48
  # Failover URL will be attempted in the event of a connection error
@@ -59,7 +59,7 @@ module ActiveMerchant
59
59
  :authorization => authorization_string(response[:tx_ref_num], response[:order_id]),
60
60
  :test => self.test?,
61
61
  :avs_result => OrbitalGateway::AVSResult.new(response[:avs_resp_code]),
62
- :cvv_result => OrbitalGateway::CVVResult.new(response[:cvv2_resp_code])
62
+ :cvv_result => OrbitalGateway::CVVResult.new(response[:cvv2_resp_code]),
63
63
  })
64
64
  end
65
65
 
@@ -139,6 +139,24 @@ module ActiveMerchant
139
139
  commit(order, :credit, options[:trace_number])
140
140
  end
141
141
 
142
+ def inquiry(order_id, retry_num)
143
+ query = build_inquiry_request(order_id, retry_num, options)
144
+ commit(query, :inquiry, options[:trace_number])
145
+ end
146
+
147
+ def build_inquiry_request(order_id, retry_num, options)
148
+ xml = xml_envelope
149
+ xml.tag! :Request do
150
+ xml.tag! :Inquiry do
151
+ add_xml_credentials(xml)
152
+ add_bin_merchant_and_terminal(xml, options)
153
+ xml.tag! :OrderID, order_id
154
+ xml.tag! :InquiryRetryNumber, retry_num
155
+ end
156
+ end
157
+ xml.target!
158
+ end
159
+
142
160
  def build_new_order_xml_with_cc(operation, money, creditcard, options)
143
161
  build_new_order_xml(operation, money, options.merge(:creditcard=>creditcard)) do |xml|
144
162
  add_creditcard(xml, creditcard, options)
@@ -88,6 +88,69 @@ module Killbill #:nodoc:
88
88
  params_order_id
89
89
  end
90
90
 
91
+ def cancel
92
+ begin
93
+ error_details = JSON.parse(message)
94
+ original_message = nil
95
+ rescue
96
+ error_details = {}
97
+ original_message = message
98
+ end
99
+ error_details['original_message'] = original_message unless original_message.blank?
100
+ error_details['payment_plugin_status'] = 'CANCELED'
101
+
102
+ updated_attributes = {
103
+ :message => error_details.to_json,
104
+ :success => false,
105
+ :updated_at => Time.now.utc
106
+ }
107
+
108
+ # Update the response row
109
+ update!(updated_attributes)
110
+ end
111
+
112
+ def update_and_create_transaction(gw_response)
113
+ updated_attributes = {
114
+ :message => gw_response.message,
115
+ :authorization => gw_response.authorization,
116
+ :fraud_review => gw_response.fraud_review?,
117
+ :test => gw_response.test?,
118
+ :avs_result_code => gw_response.avs_result.kind_of?(::ActiveMerchant::Billing::AVSResult) ? gw_response.avs_result.code : gw_response.avs_result['code'],
119
+ :avs_result_message => gw_response.avs_result.kind_of?(::ActiveMerchant::Billing::AVSResult) ? gw_response.avs_result.message : gw_response.avs_result['message'],
120
+ :avs_result_street_match => gw_response.avs_result.kind_of?(::ActiveMerchant::Billing::AVSResult) ? gw_response.avs_result.street_match : gw_response.avs_result['street_match'],
121
+ :avs_result_postal_match => gw_response.avs_result.kind_of?(::ActiveMerchant::Billing::AVSResult) ? gw_response.avs_result.postal_match : gw_response.avs_result['postal_match'],
122
+ :cvv_result_code => gw_response.cvv_result.kind_of?(::ActiveMerchant::Billing::CVVResult) ? gw_response.cvv_result.code : gw_response.cvv_result['code'],
123
+ :cvv_result_message => gw_response.cvv_result.kind_of?(::ActiveMerchant::Billing::CVVResult) ? gw_response.cvv_result.message : gw_response.cvv_result['message'],
124
+ :success => gw_response.success?,
125
+ :updated_at => Time.now.utc
126
+ }.merge(OrbitalResponse.orbital_response_params(gw_response))
127
+
128
+ # Keep original values as much as possible
129
+ updated_attributes.delete_if { |k, v| v.blank? }
130
+
131
+ # Update the response row
132
+ update!(updated_attributes)
133
+
134
+ # Create the transaction row if needed (cannot have been created before or the state wouldn't have been UNDEFINED)
135
+ if gw_response.success?
136
+ amount = gw_response.params['amount']
137
+ currency = gw_response.params['currency']
138
+ amount_in_cents = amount.nil? ? nil : ::Monetize.from_numeric(amount.to_f, currency).cents.to_i
139
+ build_orbital_transaction(:kb_account_id => kb_account_id,
140
+ :kb_tenant_id => kb_tenant_id,
141
+ :amount_in_cents => amount_in_cents,
142
+ :currency => currency,
143
+ :api_call => api_call,
144
+ :kb_payment_id => kb_payment_id,
145
+ :kb_payment_transaction_id => kb_payment_transaction_id,
146
+ :transaction_type => transaction_type,
147
+ :payment_processor_account_id => payment_processor_account_id,
148
+ :txn_id => txn_id,
149
+ :created_at => updated_at,
150
+ :updated_at => updated_at).save!
151
+ end
152
+ end
153
+
91
154
  def self.auth_responses_from_kb_payment_id(kb_payment_id, kb_tenant_id)
92
155
  where(:kb_payment_id => kb_payment_id, :kb_tenant_id => kb_tenant_id, :api_call => 'authorize').order(:created_at)
93
156
  end
@@ -99,8 +162,8 @@ module Killbill #:nodoc:
99
162
  def to_transaction_info_plugin(transaction=nil)
100
163
  t_info_plugin = super(transaction)
101
164
  t_info_plugin.properties << create_plugin_property('processorResponse', params_host_resp_code)
102
-
103
- t_info_plugin.status = :CANCELED if t_info_plugin.status == :UNDEFINED
165
+ t_info_plugin.properties << create_plugin_property('orbital_response_id', id)
166
+ t_info_plugin.properties << create_plugin_property('trace_number', params_trace_number)
104
167
  t_info_plugin
105
168
  end
106
169
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: killbill-orbital
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kill Bill core team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-26 00:00:00.000000000 Z
11
+ date: 2018-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement