killbill-cybersource 5.1.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/VERSION +1 -1
- data/lib/cybersource/api.rb +8 -1
- data/lib/cybersource/cyber_source_on_demand.rb +4 -0
- data/pom.xml +1 -1
- data/spec/cybersource/remote/integration_spec.rb +69 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0156e88d591e65a124e91d54707a6c35058e7cf4
|
4
|
+
data.tar.gz: 69163de4f9aa3c74d5325a6c561abab2f8e9efc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c505cfb2f367215a4ec6b42fcc8edb5d33da5732cb9392bb5d862eb45b6f841e648c68fc572bff89b216c52ae169da79efeef80935d4d5b7763e7b2b4b05709c
|
7
|
+
data.tar.gz: 8d502c587dfc6a4fd41d28813e92bcc35875d85e68e7ffd8a545df043a0a51aa696716414dd51e4a8bdeee30dd1b49bac8968598671bdf1d7a844257fada10ad
|
data/Gemfile.lock
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.
|
1
|
+
5.2.0
|
data/lib/cybersource/api.rb
CHANGED
@@ -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
|
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.
|
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(
|
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(
|
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.
|
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-
|
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
|