killbill-cybersource 5.1.0 → 5.2.0

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: ae2d49fdb4fd4bbe3b9be5e7b79ee0b14e12837a
4
- data.tar.gz: 85d673ad015325da80051feb7bcaf67bbbcf243a
3
+ metadata.gz: 0156e88d591e65a124e91d54707a6c35058e7cf4
4
+ data.tar.gz: 69163de4f9aa3c74d5325a6c561abab2f8e9efc3
5
5
  SHA512:
6
- metadata.gz: b69a139a422956d25ee6651d97e8504a87334d9d405244e74400754de906ffe12df6016363e7c6d8fb9085fe6dcbd98f7f493ef8cb37010ea305e454a243a47e
7
- data.tar.gz: b33fa00be1629c68fa7233108180eabb9dd2e363cd80a2e11a7d1e4fbea8f7fc66281ff3bad33a8d33cb2b743e90c8dbf0f7e6dab23157d21a562fdcdc6c9884
6
+ metadata.gz: c505cfb2f367215a4ec6b42fcc8edb5d33da5732cb9392bb5d862eb45b6f841e648c68fc572bff89b216c52ae169da79efeef80935d4d5b7763e7b2b4b05709c
7
+ data.tar.gz: 8d502c587dfc6a4fd41d28813e92bcc35875d85e68e7ffd8a545df043a0a51aa696716414dd51e4a8bdeee30dd1b49bac8968598671bdf1d7a844257fada10ad
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- killbill-cybersource (5.1.0)
4
+ killbill-cybersource (5.2.0)
5
5
  actionpack (~> 4.1.0)
6
6
  actionview (~> 4.1.0)
7
7
  activemerchant (~> 1.48.0)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 5.1.0
1
+ 5.2.0
@@ -134,6 +134,8 @@ module Killbill #:nodoc:
134
134
  # authorization is very likely nil, as we didn't get an answer from the gateway in the first place
135
135
  order_id ||= authorization.split(';')[0] unless authorization.nil?
136
136
 
137
+ existing_request_ids = transaction_info_plugins.map{|trx_info| trx_info.first_payment_reference_id}.compact
138
+
137
139
  stale = false
138
140
  transaction_info_plugins.each do |transaction_info_plugin|
139
141
  # We only need to fix the UNDEFINED ones
@@ -171,7 +173,7 @@ module Killbill #:nodoc:
171
173
 
172
174
  threshold = (Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :cancel_threshold) || ONE_DAY_AGO).to_i
173
175
  should_cancel_payment = delay_since_transaction >= threshold
174
- if report.empty? && !should_cancel_payment
176
+ if (report.empty? || report_not_match(report, transaction_info_plugin.first_payment_reference_id, existing_request_ids)) && !should_cancel_payment
175
177
  # We'll retry later
176
178
  logger.info("Unable to fix UNDEFINED kb_transaction_id='#{transaction_info_plugin.kb_transaction_payment_id}' (not found in CyberSource)")
177
179
  next
@@ -445,6 +447,11 @@ module Killbill #:nodoc:
445
447
  # We might want a 'util' function to make the conversion Joda DateTime to a Ruby Time object
446
448
  Time.parse(@clock.get_clock.get_utc_now.to_s)
447
449
  end
450
+
451
+ def report_not_match(report, request_id, existing_request_ids)
452
+ # Check if the response's request id is the request_id of a previous request. If so, then this report does not match.
453
+ report.request_id.nil? || (request_id != report.request_id && existing_request_ids.include?(report.request_id))
454
+ end
448
455
  end
449
456
  end
450
457
  end
@@ -94,6 +94,10 @@ module Killbill #:nodoc:
94
94
  @response.params['merchantReferenceCode'].nil?
95
95
  end
96
96
 
97
+ def request_id
98
+ @response.params['requestID']
99
+ end
100
+
97
101
  private
98
102
 
99
103
  def parse
data/pom.xml CHANGED
@@ -25,7 +25,7 @@
25
25
  <groupId>org.kill-bill.billing.plugin.ruby</groupId>
26
26
  <artifactId>cybersource-plugin</artifactId>
27
27
  <packaging>pom</packaging>
28
- <version>5.1.0</version>
28
+ <version>5.2.0</version>
29
29
  <name>cybersource-plugin</name>
30
30
  <url>http://github.com/killbill/killbill-cybersource-plugin</url>
31
31
  <description>Plugin for accessing Cybersource as a payment gateway</description>
@@ -266,7 +266,7 @@ describe Killbill::Cybersource::PaymentPlugin do
266
266
  fix_transaction(0) if with_report_api
267
267
 
268
268
  # Compare the state of the old and new response
269
- check_old_new_response(response, :PURCHASE, 0, initial_auth)
269
+ check_old_new_response(response, :PURCHASE, 0, initial_auth, payment_response.first_payment_reference_id)
270
270
 
271
271
  break unless with_report_api
272
272
 
@@ -280,14 +280,72 @@ describe Killbill::Cybersource::PaymentPlugin do
280
280
  fix_transaction(1)
281
281
 
282
282
  # Compare the state of the old and new response
283
- check_old_new_response(response, :REFUND, 1, initial_auth)
283
+ check_old_new_response(response, :REFUND, 1, initial_auth, refund_response.first_payment_reference_id)
284
+ end
285
+
286
+ it 'should fix UNDEFINED captures' do
287
+ @plugin.authorize_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
288
+ payment_response = @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
289
+ check_response(payment_response, @amount, :CAPTURE, :PROCESSED, 'Successful transaction', '100')
290
+
291
+ # Force a transition to :UNDEFINED
292
+ response, initial_auth = transition_last_response_to_UNDEFINED(2)
293
+
294
+ # Skip if the report API isn't configured
295
+ fix_transaction(1) if with_report_api
296
+
297
+ # Compare the state of the old and new response
298
+ check_old_new_response(response, :CAPTURE, 1, initial_auth, payment_response.first_payment_reference_id)
299
+
300
+ break unless with_report_api
301
+
302
+ # Try a full refund
303
+ refund_response = @plugin.refund_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
304
+ check_response(refund_response, @amount, :REFUND, :PROCESSED, 'Successful transaction', '100')
305
+ end
306
+
307
+ it 'should not fix UNDEFINED captures if the report only covers the previous request' do
308
+ @plugin.authorize_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
309
+
310
+ # Skip gw call so that on_demand report api won't return a record for this call
311
+ skip_gw = Killbill::Plugin::Model::PluginProperty.new
312
+ skip_gw.key = 'skip_gw'
313
+ skip_gw.value = 'true'
314
+ properties_with_skip_gw = @properties.clone
315
+ properties_with_skip_gw << skip_gw
316
+ @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @amount, @currency, properties_with_skip_gw, @call_context)
317
+
318
+ # Force a transition to :UNDEFINED
319
+ transition_last_response_to_UNDEFINED(2)
320
+
321
+ # Shouldn't be able to fix the capture because it skipped the gateway call
322
+ fix_transaction(1, :UNDEFINED) if with_report_api
323
+ end
324
+
325
+ it 'should not fix UNDEFINED refunds if the report only covers the previous requests' do
326
+ @plugin.authorize_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
327
+ @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
328
+
329
+ # Skip gw call so that on_demand report api won't return a record for this call
330
+ skip_gw = Killbill::Plugin::Model::PluginProperty.new
331
+ skip_gw.key = 'skip_gw'
332
+ skip_gw.value = 'true'
333
+ properties_with_skip_gw = @properties.clone
334
+ properties_with_skip_gw << skip_gw
335
+ @plugin.refund_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @amount, @currency, properties_with_skip_gw, @call_context)
336
+
337
+ # Force a transition to :UNDEFINED
338
+ transition_last_response_to_UNDEFINED(3)
339
+
340
+ # Shouldn't be able to fix the capture because it skipped the gateway call
341
+ fix_transaction(2, :UNDEFINED) if with_report_api
284
342
  end
285
343
 
286
344
  def transition_last_response_to_UNDEFINED(expected_nb_transactions)
287
345
  Killbill::Cybersource::CybersourceTransaction.last.delete
288
346
  response = Killbill::Cybersource::CybersourceResponse.last
289
347
  initial_auth = response.authorization
290
- response.update(:authorization => nil, :message => {:payment_plugin_status => 'UNDEFINED'}.to_json)
348
+ response.update(:authorization => nil, :params_request_id => nil, :message => {:payment_plugin_status => 'UNDEFINED'}.to_json)
291
349
 
292
350
  skip_gw = Killbill::Plugin::Model::PluginProperty.new
293
351
  skip_gw.key = 'skip_gw'
@@ -303,7 +361,7 @@ describe Killbill::Cybersource::PaymentPlugin do
303
361
  [response, initial_auth]
304
362
  end
305
363
 
306
- def fix_transaction(transaction_nb)
364
+ def fix_transaction(transaction_nb, expected_state=:PROCESSED)
307
365
  # The report API can be delayed
308
366
  await do
309
367
  !@plugin.get_single_transaction_report(report_api, @kb_payment.transactions[0].id, Time.now.utc).empty? ||
@@ -323,7 +381,7 @@ describe Killbill::Cybersource::PaymentPlugin do
323
381
  properties_with_janitor_delay_threshold << janitor_delay_threshold
324
382
  transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_janitor_delay_threshold, @call_context)
325
383
  transaction_info_plugins.size.should == transaction_nb + 1
326
- transaction_info_plugins.last.status.should eq(:PROCESSED)
384
+ transaction_info_plugins.last.status.should eq(expected_state)
327
385
 
328
386
  # Set skip_gw=true, to check the local state
329
387
  skip_gw = Killbill::Plugin::Model::PluginProperty.new
@@ -333,10 +391,10 @@ describe Killbill::Cybersource::PaymentPlugin do
333
391
  properties_with_skip_gw << skip_gw
334
392
  transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_skip_gw, @call_context)
335
393
  transaction_info_plugins.size.should == transaction_nb + 1
336
- transaction_info_plugins.last.status.should eq(:PROCESSED)
394
+ transaction_info_plugins.last.status.should eq(expected_state)
337
395
  end
338
396
 
339
- def check_old_new_response(response, transaction_type, transaction_nb, initial_auth)
397
+ def check_old_new_response(response, transaction_type, transaction_nb, initial_auth, request_id)
340
398
  new_response = Killbill::Cybersource::CybersourceResponse.last
341
399
  new_response.id.should == response.id
342
400
  new_response.api_call.should == transaction_type.to_s.downcase
@@ -354,12 +412,13 @@ describe Killbill::Cybersource::PaymentPlugin do
354
412
  new_response.params_request_token.should == response.params_request_token
355
413
  new_response.params_currency.should == response.params_currency
356
414
  new_response.params_amount.should == response.params_amount
357
- new_response.params_authorization_code.should == response.params_authorization_code
358
- new_response.params_avs_code.should == response.params_avs_code
359
- new_response.params_avs_code_raw.should == response.params_avs_code_raw
415
+ new_response.params_authorization_code.should == response.params_authorization_code unless response.params_authorization_code.nil?
416
+ new_response.params_avs_code.should == response.params_avs_code unless response.params_avs_code.nil?
417
+ new_response.params_avs_code_raw.should == response.params_avs_code_raw unless response.params_avs_code.nil?
360
418
  new_response.params_reconciliation_id.should == response.params_reconciliation_id
361
419
  new_response.success.should be_true
362
420
  new_response.message.should == (with_report_api ? 'Request was processed successfully.' : '{"payment_plugin_status":"UNDEFINED"}')
421
+ new_response.params_request_id.should == request_id if with_report_api
363
422
  end
364
423
  end
365
424
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: killbill-cybersource
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0
4
+ version: 5.2.0
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-04-10 00:00:00.000000000 Z
11
+ date: 2017-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement