killbill-cybersource 5.0.1 → 5.1.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 +4 -4
- data/Gemfile.lock +8 -6
- data/NEWS +3 -0
- data/VERSION +1 -1
- data/cybersource.yml +4 -1
- data/db/ddl.sql +91 -91
- data/killbill-cybersource.gemspec +1 -0
- data/lib/cybersource/api.rb +24 -8
- data/lib/cybersource/cyber_source_on_demand.rb +12 -4
- data/pom.xml +1 -1
- data/spec/cybersource/cyber_source_on_demand_spec.rb +1 -1
- data/spec/cybersource/remote/integration_spec.rb +122 -56
- data/spec/spec_helper.rb +9 -5
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae2d49fdb4fd4bbe3b9be5e7b79ee0b14e12837a
|
|
4
|
+
data.tar.gz: 85d673ad015325da80051feb7bcaf67bbbcf243a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b69a139a422956d25ee6651d97e8504a87334d9d405244e74400754de906ffe12df6016363e7c6d8fb9085fe6dcbd98f7f493ef8cb37010ea305e454a243a47e
|
|
7
|
+
data.tar.gz: b33fa00be1629c68fa7233108180eabb9dd2e363cd80a2e11a7d1e4fbea8f7fc66281ff3bad33a8d33cb2b743e90c8dbf0f7e6dab23157d21a562fdcdc6c9884
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
killbill-cybersource (5.0
|
|
4
|
+
killbill-cybersource (5.1.0)
|
|
5
5
|
actionpack (~> 4.1.0)
|
|
6
6
|
actionview (~> 4.1.0)
|
|
7
7
|
activemerchant (~> 1.48.0)
|
|
@@ -57,7 +57,7 @@ GEM
|
|
|
57
57
|
descendants_tracker (~> 0.0.4)
|
|
58
58
|
ice_nine (~> 0.11.0)
|
|
59
59
|
thread_safe (~> 0.3, >= 0.3.1)
|
|
60
|
-
builder (3.2.
|
|
60
|
+
builder (3.2.3)
|
|
61
61
|
coercible (1.0.0)
|
|
62
62
|
descendants_tracker (~> 0.0.1)
|
|
63
63
|
descendants_tracker (0.0.4)
|
|
@@ -77,9 +77,10 @@ GEM
|
|
|
77
77
|
maven-tools (~> 1.1)
|
|
78
78
|
ruby-maven (~> 3.3, >= 3.3.8)
|
|
79
79
|
jdbc-mariadb (1.3.4)
|
|
80
|
+
jdbc-postgres (9.4.1206)
|
|
80
81
|
jdbc-sqlite3 (3.8.11.2)
|
|
81
82
|
jruby-openssl (0.9.18-java)
|
|
82
|
-
json (1.8.
|
|
83
|
+
json (1.8.6-java)
|
|
83
84
|
killbill (8.3.1)
|
|
84
85
|
rack (>= 1.5.2)
|
|
85
86
|
sinatra (~> 1.3.4)
|
|
@@ -87,12 +88,12 @@ GEM
|
|
|
87
88
|
tzinfo (~> 1.2.0)
|
|
88
89
|
maven-tools (1.1.6)
|
|
89
90
|
virtus (~> 1.0)
|
|
90
|
-
minitest (5.
|
|
91
|
+
minitest (5.10.1)
|
|
91
92
|
monetize (1.1.0)
|
|
92
93
|
money (~> 6.5.0)
|
|
93
94
|
money (6.5.1)
|
|
94
95
|
i18n (>= 0.6.4, <= 0.7.0)
|
|
95
|
-
nokogiri (1.
|
|
96
|
+
nokogiri (1.7.0.1-java)
|
|
96
97
|
offsite_payments (2.1.0)
|
|
97
98
|
actionpack (>= 3.2.20, < 5.0.0)
|
|
98
99
|
active_utils (~> 3.0.0)
|
|
@@ -140,10 +141,11 @@ PLATFORMS
|
|
|
140
141
|
DEPENDENCIES
|
|
141
142
|
jbundler (~> 0.9.2)
|
|
142
143
|
jdbc-mariadb (~> 1.1)
|
|
144
|
+
jdbc-postgres (~> 9.4)
|
|
143
145
|
jdbc-sqlite3 (~> 3.7)
|
|
144
146
|
killbill-cybersource!
|
|
145
147
|
rake (>= 10.0.0)
|
|
146
148
|
rspec (~> 2.12.0)
|
|
147
149
|
|
|
148
150
|
BUNDLED WITH
|
|
149
|
-
1.
|
|
151
|
+
1.14.3
|
data/NEWS
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.0
|
|
1
|
+
5.1.0
|
data/cybersource.yml
CHANGED
|
@@ -13,8 +13,11 @@
|
|
|
13
13
|
# SQLite (development)
|
|
14
14
|
:adapter: sqlite3
|
|
15
15
|
:database: test.db
|
|
16
|
+
# For PostgreSQL
|
|
17
|
+
# :adapter: postgresql
|
|
18
|
+
# :database: 'killbill'
|
|
16
19
|
# For MySQL
|
|
17
|
-
# :adapter:
|
|
20
|
+
# :adapter: mariadb
|
|
18
21
|
# :username: 'killbill'
|
|
19
22
|
# :password: 'killbill'
|
|
20
23
|
# :database: 'killbill' # or set the URL :
|
data/db/ddl.sql
CHANGED
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
CREATE TABLE
|
|
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
|
-
PRIMARY KEY (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
CREATE TABLE cybersource_payment_methods (
|
|
2
|
+
id serial unique,
|
|
3
|
+
kb_payment_method_id varchar(255) DEFAULT NULL,
|
|
4
|
+
token varchar(255) DEFAULT NULL,
|
|
5
|
+
cc_first_name varchar(255) DEFAULT NULL,
|
|
6
|
+
cc_last_name varchar(255) DEFAULT NULL,
|
|
7
|
+
cc_type varchar(255) DEFAULT NULL,
|
|
8
|
+
cc_exp_month varchar(255) DEFAULT NULL,
|
|
9
|
+
cc_exp_year varchar(255) DEFAULT NULL,
|
|
10
|
+
cc_number varchar(255) DEFAULT NULL,
|
|
11
|
+
cc_last_4 varchar(255) DEFAULT NULL,
|
|
12
|
+
cc_start_month varchar(255) DEFAULT NULL,
|
|
13
|
+
cc_start_year varchar(255) DEFAULT NULL,
|
|
14
|
+
cc_issue_number varchar(255) DEFAULT NULL,
|
|
15
|
+
cc_verification_value varchar(255) DEFAULT NULL,
|
|
16
|
+
cc_track_data varchar(255) DEFAULT NULL,
|
|
17
|
+
address1 varchar(255) DEFAULT NULL,
|
|
18
|
+
address2 varchar(255) DEFAULT NULL,
|
|
19
|
+
city varchar(255) DEFAULT NULL,
|
|
20
|
+
state varchar(255) DEFAULT NULL,
|
|
21
|
+
zip varchar(255) DEFAULT NULL,
|
|
22
|
+
country varchar(255) DEFAULT NULL,
|
|
23
|
+
is_deleted boolean NOT NULL DEFAULT '0',
|
|
24
|
+
created_at datetime NOT NULL,
|
|
25
|
+
updated_at datetime NOT NULL,
|
|
26
|
+
kb_account_id varchar(255) DEFAULT NULL,
|
|
27
|
+
kb_tenant_id varchar(255) DEFAULT NULL,
|
|
28
|
+
PRIMARY KEY (id)
|
|
29
|
+
) /*! ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin */;
|
|
30
|
+
CREATE INDEX index_cybersource_payment_methods_kb_account_id ON cybersource_payment_methods(kb_account_id);
|
|
31
|
+
CREATE INDEX index_cybersource_payment_methods_kb_payment_method_id ON cybersource_payment_methods(kb_payment_method_id);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE cybersource_transactions (
|
|
34
|
+
id serial unique,
|
|
35
|
+
cybersource_response_id bigint /*! unsigned */ NOT NULL,
|
|
36
|
+
api_call varchar(255) NOT NULL,
|
|
37
|
+
kb_payment_id varchar(255) NOT NULL,
|
|
38
|
+
kb_payment_transaction_id varchar(255) NOT NULL,
|
|
39
|
+
transaction_type varchar(255) NOT NULL,
|
|
40
|
+
payment_processor_account_id varchar(255) DEFAULT NULL,
|
|
41
|
+
txn_id varchar(255) DEFAULT NULL,
|
|
42
|
+
amount_in_cents int DEFAULT NULL,
|
|
43
|
+
currency varchar(255) DEFAULT NULL,
|
|
44
|
+
created_at datetime NOT NULL,
|
|
45
|
+
updated_at datetime NOT NULL,
|
|
46
|
+
kb_account_id varchar(255) NOT NULL,
|
|
47
|
+
kb_tenant_id varchar(255) NOT NULL,
|
|
48
|
+
PRIMARY KEY (id)
|
|
49
|
+
) /*! ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin */;
|
|
50
|
+
CREATE INDEX index_cybersource_transactions_kb_payment_id ON cybersource_transactions(kb_payment_id);
|
|
51
|
+
CREATE INDEX index_cybersource_transactions_cybersource_response_id ON cybersource_transactions(cybersource_response_id);
|
|
32
52
|
|
|
33
|
-
CREATE TABLE
|
|
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
|
-
`params_avs_code_raw` varchar(255) DEFAULT NULL,
|
|
74
|
-
`params_cv_code` varchar(255) DEFAULT NULL,
|
|
75
|
-
`params_authorized_date_time` varchar(255) DEFAULT NULL,
|
|
76
|
-
`params_processor_response` varchar(255) DEFAULT NULL,
|
|
77
|
-
`params_reconciliation_id` varchar(255) DEFAULT NULL,
|
|
78
|
-
`params_subscription_id` varchar(255) DEFAULT NULL,
|
|
79
|
-
`avs_result_code` varchar(255) DEFAULT NULL,
|
|
80
|
-
`avs_result_message` varchar(255) DEFAULT NULL,
|
|
81
|
-
`avs_result_street_match` varchar(255) DEFAULT NULL,
|
|
82
|
-
`avs_result_postal_match` varchar(255) DEFAULT NULL,
|
|
83
|
-
`cvv_result_code` varchar(255) DEFAULT NULL,
|
|
84
|
-
`cvv_result_message` varchar(255) DEFAULT NULL,
|
|
85
|
-
`success` tinyint(1) DEFAULT NULL,
|
|
86
|
-
`created_at` datetime NOT NULL,
|
|
87
|
-
`updated_at` datetime NOT NULL,
|
|
88
|
-
`kb_account_id` varchar(255) DEFAULT NULL,
|
|
89
|
-
`kb_tenant_id` varchar(255) DEFAULT NULL,
|
|
90
|
-
PRIMARY KEY (`id`),
|
|
91
|
-
KEY `index_cybersource_responses_on_kb_payment_id_kb_tenant_id` (`kb_payment_id`, `kb_tenant_id`)
|
|
92
|
-
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
|
53
|
+
CREATE TABLE cybersource_responses (
|
|
54
|
+
id serial unique,
|
|
55
|
+
api_call varchar(255) NOT NULL,
|
|
56
|
+
kb_payment_id varchar(255) DEFAULT NULL,
|
|
57
|
+
kb_payment_transaction_id varchar(255) DEFAULT NULL,
|
|
58
|
+
transaction_type varchar(255) DEFAULT NULL,
|
|
59
|
+
payment_processor_account_id varchar(255) DEFAULT NULL,
|
|
60
|
+
message text DEFAULT NULL,
|
|
61
|
+
authorisation varchar(255) DEFAULT NULL,
|
|
62
|
+
fraud_review boolean DEFAULT NULL,
|
|
63
|
+
test boolean DEFAULT NULL,
|
|
64
|
+
params_merchant_reference_code varchar(255) DEFAULT NULL,
|
|
65
|
+
params_request_id varchar(255) DEFAULT NULL,
|
|
66
|
+
params_decision varchar(255) DEFAULT NULL,
|
|
67
|
+
params_reason_code varchar(255) DEFAULT NULL,
|
|
68
|
+
params_request_token varchar(255) DEFAULT NULL,
|
|
69
|
+
params_currency varchar(255) DEFAULT NULL,
|
|
70
|
+
params_amount varchar(255) DEFAULT NULL,
|
|
71
|
+
params_authorization_code varchar(255) DEFAULT NULL,
|
|
72
|
+
params_avs_code varchar(255) DEFAULT NULL,
|
|
73
|
+
params_avs_code_raw varchar(255) DEFAULT NULL,
|
|
74
|
+
params_cv_code varchar(255) DEFAULT NULL,
|
|
75
|
+
params_authorized_date_time varchar(255) DEFAULT NULL,
|
|
76
|
+
params_processor_response varchar(255) DEFAULT NULL,
|
|
77
|
+
params_reconciliation_id varchar(255) DEFAULT NULL,
|
|
78
|
+
params_subscription_id varchar(255) DEFAULT NULL,
|
|
79
|
+
avs_result_code varchar(255) DEFAULT NULL,
|
|
80
|
+
avs_result_message varchar(255) DEFAULT NULL,
|
|
81
|
+
avs_result_street_match varchar(255) DEFAULT NULL,
|
|
82
|
+
avs_result_postal_match varchar(255) DEFAULT NULL,
|
|
83
|
+
cvv_result_code varchar(255) DEFAULT NULL,
|
|
84
|
+
cvv_result_message varchar(255) DEFAULT NULL,
|
|
85
|
+
success boolean DEFAULT NULL,
|
|
86
|
+
created_at datetime NOT NULL,
|
|
87
|
+
updated_at datetime NOT NULL,
|
|
88
|
+
kb_account_id varchar(255) DEFAULT NULL,
|
|
89
|
+
kb_tenant_id varchar(255) DEFAULT NULL,
|
|
90
|
+
PRIMARY KEY (id)
|
|
91
|
+
) /*! ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin */;
|
|
92
|
+
CREATE INDEX index_cybersource_responses_kb_payment_id_kb_tenant_id ON cybersource_responses(kb_payment_id, kb_tenant_id);
|
|
@@ -46,6 +46,7 @@ Gem::Specification.new do |s|
|
|
|
46
46
|
if defined?(JRUBY_VERSION)
|
|
47
47
|
s.add_development_dependency 'jdbc-sqlite3', '~> 3.7'
|
|
48
48
|
s.add_development_dependency 'jdbc-mariadb', '~> 1.1'
|
|
49
|
+
s.add_development_dependency 'jdbc-postgres', '~> 9.4'
|
|
49
50
|
else
|
|
50
51
|
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
|
51
52
|
end
|
data/lib/cybersource/api.rb
CHANGED
|
@@ -2,6 +2,7 @@ module Killbill #:nodoc:
|
|
|
2
2
|
module Cybersource #:nodoc:
|
|
3
3
|
class PaymentPlugin < ::Killbill::Plugin::ActiveMerchant::PaymentPlugin
|
|
4
4
|
|
|
5
|
+
FIVE_MINUTES_AGO = (1 * 300)
|
|
5
6
|
ONE_DAY_AGO = (1 * 86400)
|
|
6
7
|
SIXTY_DAYS_AGO = (60 * 86400)
|
|
7
8
|
|
|
@@ -120,6 +121,19 @@ module Killbill #:nodoc:
|
|
|
120
121
|
|
|
121
122
|
options = properties_to_hash(properties)
|
|
122
123
|
|
|
124
|
+
initial_transaction = nil
|
|
125
|
+
transaction_info_plugins.each do |transaction_info_plugin|
|
|
126
|
+
initial_transaction = transaction_info_plugin if transaction_info_plugin.transaction_type == :AUTHORIZE || transaction_info_plugin.transaction_type == :PURCHASE || transaction_info_plugin.transaction_type == :CREDIT
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Should never happen (maybe transaction_type wasn't saved?)...
|
|
130
|
+
initial_transaction = transaction_info_plugins.last if initial_transaction.nil?
|
|
131
|
+
|
|
132
|
+
authorization = find_value_from_properties(initial_transaction.properties, 'authorization')
|
|
133
|
+
order_id = Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :order_id)
|
|
134
|
+
# authorization is very likely nil, as we didn't get an answer from the gateway in the first place
|
|
135
|
+
order_id ||= authorization.split(';')[0] unless authorization.nil?
|
|
136
|
+
|
|
123
137
|
stale = false
|
|
124
138
|
transaction_info_plugins.each do |transaction_info_plugin|
|
|
125
139
|
# We only need to fix the UNDEFINED ones
|
|
@@ -132,18 +146,20 @@ module Killbill #:nodoc:
|
|
|
132
146
|
end
|
|
133
147
|
|
|
134
148
|
report_date = transaction_info_plugin.created_date
|
|
135
|
-
|
|
149
|
+
delay_since_transaction = now - report_date
|
|
150
|
+
delay_since_transaction = 0 if delay_since_transaction < 0
|
|
136
151
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
152
|
+
# Give some time for CyberSource to update their records
|
|
153
|
+
janitor_delay_threshold = (Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :janitor_delay_threshold) || FIVE_MINUTES_AGO).to_i
|
|
154
|
+
should_refresh_status = delay_since_transaction >= janitor_delay_threshold
|
|
155
|
+
next unless should_refresh_status
|
|
140
156
|
|
|
141
157
|
# Retrieve the report from CyberSource
|
|
142
158
|
if order_id.nil?
|
|
143
159
|
# order_id undetermined - try the defaults (see PaymentPlugin#dispatch_to_gateways)
|
|
144
|
-
report = get_report(
|
|
145
|
-
if report.nil?
|
|
146
|
-
kb_transaction = get_kb_transaction(kb_payment_id,
|
|
160
|
+
report = get_report(initial_transaction.kb_transaction_payment_id, report_date, options, context)
|
|
161
|
+
if report.nil? || report.empty?
|
|
162
|
+
kb_transaction = get_kb_transaction(kb_payment_id, initial_transaction.kb_transaction_payment_id, context.tenant_id)
|
|
147
163
|
report = get_report(kb_transaction.external_key, report_date, options, context)
|
|
148
164
|
end
|
|
149
165
|
else
|
|
@@ -154,7 +170,7 @@ module Killbill #:nodoc:
|
|
|
154
170
|
next if report.nil?
|
|
155
171
|
|
|
156
172
|
threshold = (Killbill::Plugin::ActiveMerchant::Utils.normalized(options, :cancel_threshold) || ONE_DAY_AGO).to_i
|
|
157
|
-
should_cancel_payment =
|
|
173
|
+
should_cancel_payment = delay_since_transaction >= threshold
|
|
158
174
|
if report.empty? && !should_cancel_payment
|
|
159
175
|
# We'll retry later
|
|
160
176
|
logger.info("Unable to fix UNDEFINED kb_transaction_id='#{transaction_info_plugin.kb_transaction_payment_id}' (not found in CyberSource)")
|
|
@@ -137,6 +137,9 @@ module Killbill #:nodoc:
|
|
|
137
137
|
:authorization => authorization,
|
|
138
138
|
:avs_result => {:code => params['avsCode']},
|
|
139
139
|
:cvv_result => params['cvCode'])
|
|
140
|
+
rescue => e
|
|
141
|
+
@logger.warn "Error '#{e.message}' parsing report: #{@hash_report}\n#{e.backtrace.join("\n")}"
|
|
142
|
+
raise e
|
|
140
143
|
end
|
|
141
144
|
|
|
142
145
|
def parse_report
|
|
@@ -148,8 +151,13 @@ module Killbill #:nodoc:
|
|
|
148
151
|
end
|
|
149
152
|
|
|
150
153
|
def parse_request(report)
|
|
151
|
-
|
|
152
|
-
|
|
154
|
+
if !report.nil? && !report['Requests'].nil?
|
|
155
|
+
requests = report['Requests']['Request']
|
|
156
|
+
# First one seems to be the last request made, assume it's the one we are looking for (no other easy way to tell unfortunately)
|
|
157
|
+
requests.is_a?(Hash) ? requests : requests.first
|
|
158
|
+
else
|
|
159
|
+
nil
|
|
160
|
+
end
|
|
153
161
|
end
|
|
154
162
|
|
|
155
163
|
# Note: for now, we only look at the response from CyberSource.
|
|
@@ -163,8 +171,8 @@ module Killbill #:nodoc:
|
|
|
163
171
|
|
|
164
172
|
success = true
|
|
165
173
|
application_replies.each do |application_reply|
|
|
166
|
-
success
|
|
167
|
-
#
|
|
174
|
+
success = (application_reply['RCode'].to_s == '1')
|
|
175
|
+
# Assume last entry is the one we are looking for (no other easy way to tell unfortunately)
|
|
168
176
|
msg = application_reply['RMsg']
|
|
169
177
|
end
|
|
170
178
|
[success, msg]
|
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.0
|
|
28
|
+
<version>5.1.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>
|
|
@@ -255,7 +255,7 @@ eos
|
|
|
255
255
|
eos
|
|
256
256
|
report = Killbill::Cybersource::CyberSourceOnDemand::CyberSourceOnDemandTransactionReport.new(xml_report, Logger.new(STDOUT))
|
|
257
257
|
response = report.response
|
|
258
|
-
response.success?.should
|
|
258
|
+
response.success?.should be_true
|
|
259
259
|
response.message.should == 'Score exceeds threshold. Score = 84'
|
|
260
260
|
response.params['merchantReferenceCode'].should == '1234'
|
|
261
261
|
response.params['requestID'].should == '2434465504100167904567'
|
|
@@ -7,13 +7,13 @@ describe Killbill::Cybersource::PaymentPlugin do
|
|
|
7
7
|
include ::Killbill::Plugin::ActiveMerchant::RSpec
|
|
8
8
|
|
|
9
9
|
before(:each) do
|
|
10
|
+
@plugin = build_plugin(::Killbill::Cybersource::PaymentPlugin, 'cybersource')
|
|
11
|
+
@plugin.start_plugin
|
|
12
|
+
|
|
10
13
|
::Killbill::Cybersource::CybersourcePaymentMethod.delete_all
|
|
11
14
|
::Killbill::Cybersource::CybersourceResponse.delete_all
|
|
12
15
|
::Killbill::Cybersource::CybersourceTransaction.delete_all
|
|
13
16
|
|
|
14
|
-
@plugin = build_plugin(::Killbill::Cybersource::PaymentPlugin, 'cybersource')
|
|
15
|
-
@plugin.start_plugin
|
|
16
|
-
|
|
17
17
|
@call_context = build_call_context
|
|
18
18
|
|
|
19
19
|
@properties = []
|
|
@@ -254,66 +254,126 @@ describe Killbill::Cybersource::PaymentPlugin do
|
|
|
254
254
|
check_response(payment_response, @amount, :PURCHASE, :PROCESSED, 'Successful transaction', '100')
|
|
255
255
|
end
|
|
256
256
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
shared_examples 'fix_undefined_payments' do
|
|
258
|
+
it 'should be able to fix UNDEFINED payments' do
|
|
259
|
+
payment_response = @plugin.purchase_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
|
|
260
|
+
check_response(payment_response, @amount, :PURCHASE, :PROCESSED, 'Successful transaction', '100')
|
|
260
261
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
response = Killbill::Cybersource::CybersourceResponse.last
|
|
264
|
-
response.update(:message => {:payment_plugin_status => 'UNDEFINED'}.to_json)
|
|
262
|
+
# Force a transition to :UNDEFINED
|
|
263
|
+
response, initial_auth = transition_last_response_to_UNDEFINED(1)
|
|
265
264
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
skip_gw.value = 'true'
|
|
269
|
-
properties_with_skip_gw = @properties.clone
|
|
270
|
-
properties_with_skip_gw << skip_gw
|
|
265
|
+
# Skip if the report API isn't configured
|
|
266
|
+
fix_transaction(0) if with_report_api
|
|
271
267
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
268
|
+
# Compare the state of the old and new response
|
|
269
|
+
check_old_new_response(response, :PURCHASE, 0, initial_auth)
|
|
270
|
+
|
|
271
|
+
break unless with_report_api
|
|
272
|
+
|
|
273
|
+
# Try a full refund
|
|
274
|
+
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)
|
|
275
|
+
check_response(refund_response, @amount, :REFUND, :PROCESSED, 'Successful transaction', '100')
|
|
276
|
+
|
|
277
|
+
# Force a transition to :UNDEFINED
|
|
278
|
+
response, initial_auth = transition_last_response_to_UNDEFINED(2)
|
|
279
|
+
|
|
280
|
+
fix_transaction(1)
|
|
281
|
+
|
|
282
|
+
# Compare the state of the old and new response
|
|
283
|
+
check_old_new_response(response, :REFUND, 1, initial_auth)
|
|
284
|
+
end
|
|
276
285
|
|
|
277
|
-
|
|
278
|
-
|
|
286
|
+
def transition_last_response_to_UNDEFINED(expected_nb_transactions)
|
|
287
|
+
Killbill::Cybersource::CybersourceTransaction.last.delete
|
|
288
|
+
response = Killbill::Cybersource::CybersourceResponse.last
|
|
289
|
+
initial_auth = response.authorization
|
|
290
|
+
response.update(:authorization => nil, :message => {:payment_plugin_status => 'UNDEFINED'}.to_json)
|
|
291
|
+
|
|
292
|
+
skip_gw = Killbill::Plugin::Model::PluginProperty.new
|
|
293
|
+
skip_gw.key = 'skip_gw'
|
|
294
|
+
skip_gw.value = 'true'
|
|
295
|
+
properties_with_skip_gw = @properties.clone
|
|
296
|
+
properties_with_skip_gw << skip_gw
|
|
297
|
+
|
|
298
|
+
# Set skip_gw=true, to avoid calling the report API
|
|
299
|
+
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_skip_gw, @call_context)
|
|
300
|
+
transaction_info_plugins.size.should == expected_nb_transactions
|
|
301
|
+
transaction_info_plugins.last.status.should eq(:UNDEFINED)
|
|
302
|
+
|
|
303
|
+
[response, initial_auth]
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def fix_transaction(transaction_nb)
|
|
279
307
|
# The report API can be delayed
|
|
280
|
-
await
|
|
308
|
+
await do
|
|
309
|
+
!@plugin.get_single_transaction_report(report_api, @kb_payment.transactions[0].id, Time.now.utc).empty? ||
|
|
310
|
+
!@plugin.get_single_transaction_report(report_api, @kb_payment.transactions[0].external_key, Time.now.utc).empty?
|
|
311
|
+
end
|
|
281
312
|
|
|
282
|
-
#
|
|
313
|
+
# Plugin delay hasn't been reached yet
|
|
283
314
|
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, @properties, @call_context)
|
|
284
|
-
transaction_info_plugins.size.should == 1
|
|
285
|
-
transaction_info_plugins.
|
|
315
|
+
transaction_info_plugins.size.should == transaction_nb + 1
|
|
316
|
+
transaction_info_plugins.last.status.should eq(:UNDEFINED)
|
|
317
|
+
|
|
318
|
+
# Fix it
|
|
319
|
+
janitor_delay_threshold = Killbill::Plugin::Model::PluginProperty.new
|
|
320
|
+
janitor_delay_threshold.key = 'janitor_delay_threshold'
|
|
321
|
+
janitor_delay_threshold.value = '0'
|
|
322
|
+
properties_with_janitor_delay_threshold = @properties.clone
|
|
323
|
+
properties_with_janitor_delay_threshold << janitor_delay_threshold
|
|
324
|
+
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_janitor_delay_threshold, @call_context)
|
|
325
|
+
transaction_info_plugins.size.should == transaction_nb + 1
|
|
326
|
+
transaction_info_plugins.last.status.should eq(:PROCESSED)
|
|
286
327
|
|
|
287
328
|
# Set skip_gw=true, to check the local state
|
|
329
|
+
skip_gw = Killbill::Plugin::Model::PluginProperty.new
|
|
330
|
+
skip_gw.key = 'skip_gw'
|
|
331
|
+
skip_gw.value = 'true'
|
|
332
|
+
properties_with_skip_gw = @properties.clone
|
|
333
|
+
properties_with_skip_gw << skip_gw
|
|
288
334
|
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_skip_gw, @call_context)
|
|
289
|
-
transaction_info_plugins.size.should == 1
|
|
290
|
-
transaction_info_plugins.
|
|
335
|
+
transaction_info_plugins.size.should == transaction_nb + 1
|
|
336
|
+
transaction_info_plugins.last.status.should eq(:PROCESSED)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def check_old_new_response(response, transaction_type, transaction_nb, initial_auth)
|
|
340
|
+
new_response = Killbill::Cybersource::CybersourceResponse.last
|
|
341
|
+
new_response.id.should == response.id
|
|
342
|
+
new_response.api_call.should == transaction_type.to_s.downcase
|
|
343
|
+
new_response.kb_tenant_id.should == @call_context.tenant_id
|
|
344
|
+
new_response.kb_account_id.should == @pm.kb_account_id
|
|
345
|
+
new_response.kb_payment_id.should == @kb_payment.id
|
|
346
|
+
new_response.kb_payment_transaction_id.should == @kb_payment.transactions[transaction_nb].id
|
|
347
|
+
new_response.transaction_type.should == transaction_type.to_s
|
|
348
|
+
new_response.payment_processor_account_id.should == 'default'
|
|
349
|
+
# The report API doesn't give us the token
|
|
350
|
+
new_response.authorization.split(';')[0..1].should == initial_auth.split(';')[0..1] if with_report_api
|
|
351
|
+
new_response.test.should be_true
|
|
352
|
+
new_response.params_merchant_reference_code.should == response.params_merchant_reference_code
|
|
353
|
+
new_response.params_decision.should == response.params_decision
|
|
354
|
+
new_response.params_request_token.should == response.params_request_token
|
|
355
|
+
new_response.params_currency.should == response.params_currency
|
|
356
|
+
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
|
|
360
|
+
new_response.params_reconciliation_id.should == response.params_reconciliation_id
|
|
361
|
+
new_response.success.should be_true
|
|
362
|
+
new_response.message.should == (with_report_api ? 'Request was processed successfully.' : '{"payment_plugin_status":"UNDEFINED"}')
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
describe 'with on demand API' do
|
|
367
|
+
context 'using defaults' do
|
|
368
|
+
it_behaves_like 'fix_undefined_payments'
|
|
291
369
|
end
|
|
292
370
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
new_response.kb_payment_id.should == @kb_payment.id
|
|
300
|
-
new_response.kb_payment_transaction_id.should == @kb_payment.transactions[0].id
|
|
301
|
-
new_response.transaction_type.should == 'PURCHASE'
|
|
302
|
-
new_response.payment_processor_account_id.should == 'default'
|
|
303
|
-
# The report API doesn't give us the token
|
|
304
|
-
new_response.authorization.split(';')[0..1].should == response.authorization.split(';')[0..1]
|
|
305
|
-
new_response.test.should be_true
|
|
306
|
-
new_response.params_merchant_reference_code.should == response.params_merchant_reference_code
|
|
307
|
-
new_response.params_decision.should == response.params_decision
|
|
308
|
-
new_response.params_request_token.should == response.params_request_token
|
|
309
|
-
new_response.params_currency.should == response.params_currency
|
|
310
|
-
new_response.params_amount.should == response.params_amount
|
|
311
|
-
new_response.params_authorization_code.should == response.params_authorization_code
|
|
312
|
-
new_response.params_avs_code.should == response.params_avs_code
|
|
313
|
-
new_response.params_avs_code_raw.should == response.params_avs_code_raw
|
|
314
|
-
new_response.params_reconciliation_id.should == response.params_reconciliation_id
|
|
315
|
-
new_response.success.should be_true
|
|
316
|
-
new_response.message.should == (with_report_api ? 'Request was processed successfully.' : '{"payment_plugin_status":"UNDEFINED"}')
|
|
371
|
+
context 'using external_key_as_order_id' do
|
|
372
|
+
before do
|
|
373
|
+
@properties << build_property('external_key_as_order_id', true)
|
|
374
|
+
end
|
|
375
|
+
it_behaves_like 'fix_undefined_payments'
|
|
376
|
+
end
|
|
317
377
|
end
|
|
318
378
|
|
|
319
379
|
it 'should eventually cancel UNDEFINED payments' do
|
|
@@ -330,14 +390,20 @@ describe Killbill::Cybersource::PaymentPlugin do
|
|
|
330
390
|
skip_gw = Killbill::Plugin::Model::PluginProperty.new
|
|
331
391
|
skip_gw.key = 'skip_gw'
|
|
332
392
|
skip_gw.value = 'true'
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id,
|
|
393
|
+
properties_with_skip_gw = @properties.clone
|
|
394
|
+
properties_with_skip_gw << skip_gw
|
|
395
|
+
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_skip_gw, @call_context)
|
|
336
396
|
transaction_info_plugins.size.should == 1
|
|
337
397
|
transaction_info_plugins.first.status.should eq(:UNDEFINED)
|
|
338
398
|
|
|
399
|
+
janitor_delay_threshold = Killbill::Plugin::Model::PluginProperty.new
|
|
400
|
+
janitor_delay_threshold.key = 'janitor_delay_threshold'
|
|
401
|
+
janitor_delay_threshold.value = '0'
|
|
402
|
+
properties_with_janitor_delay_threshold = @properties.clone
|
|
403
|
+
properties_with_janitor_delay_threshold << janitor_delay_threshold
|
|
404
|
+
|
|
339
405
|
# Call the reporting API (if configured) and verify the state still cannot be fixed
|
|
340
|
-
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id,
|
|
406
|
+
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_janitor_delay_threshold, @call_context)
|
|
341
407
|
transaction_info_plugins.size.should == 1
|
|
342
408
|
transaction_info_plugins.first.status.should eq(:UNDEFINED)
|
|
343
409
|
|
|
@@ -348,7 +414,7 @@ describe Killbill::Cybersource::PaymentPlugin do
|
|
|
348
414
|
cancel_threshold = Killbill::Plugin::Model::PluginProperty.new
|
|
349
415
|
cancel_threshold.key = 'cancel_threshold'
|
|
350
416
|
cancel_threshold.value = '0'
|
|
351
|
-
properties_with_cancel_threshold =
|
|
417
|
+
properties_with_cancel_threshold = properties_with_janitor_delay_threshold.clone
|
|
352
418
|
properties_with_cancel_threshold << cancel_threshold
|
|
353
419
|
transaction_info_plugins = @plugin.get_payment_info(@pm.kb_account_id, @kb_payment.id, properties_with_cancel_threshold, @call_context)
|
|
354
420
|
transaction_info_plugins.size.should == 1
|
data/spec/spec_helper.rb
CHANGED
|
@@ -12,11 +12,15 @@ RSpec.configure do |config|
|
|
|
12
12
|
config.formatter = 'documentation'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
require 'active_record'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
require defined?(JRUBY_VERSION) ? 'arjdbc' : 'active_record'
|
|
16
|
+
db_config = {
|
|
17
|
+
:adapter => ENV['AR_ADAPTER'] || 'sqlite3',
|
|
18
|
+
:database => ENV['AR_DATABASE'] || 'test.db',
|
|
19
|
+
}
|
|
20
|
+
db_config[:username] = ENV['AR_USERNAME'] if ENV['AR_USERNAME']
|
|
21
|
+
db_config[:password] = ENV['AR_PASSWORD'] if ENV['AR_PASSWORD']
|
|
22
|
+
ActiveRecord::Base.establish_connection(db_config)
|
|
23
|
+
|
|
20
24
|
# For debugging
|
|
21
25
|
#ActiveRecord::Base.logger = Logger.new(STDOUT)
|
|
22
26
|
# Create the schema
|
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.0
|
|
4
|
+
version: 5.1.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:
|
|
11
|
+
date: 2017-04-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -262,6 +262,20 @@ dependencies:
|
|
|
262
262
|
- - "~>"
|
|
263
263
|
- !ruby/object:Gem::Version
|
|
264
264
|
version: '1.1'
|
|
265
|
+
- !ruby/object:Gem::Dependency
|
|
266
|
+
requirement: !ruby/object:Gem::Requirement
|
|
267
|
+
requirements:
|
|
268
|
+
- - "~>"
|
|
269
|
+
- !ruby/object:Gem::Version
|
|
270
|
+
version: '9.4'
|
|
271
|
+
name: jdbc-postgres
|
|
272
|
+
prerelease: false
|
|
273
|
+
type: :development
|
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
275
|
+
requirements:
|
|
276
|
+
- - "~>"
|
|
277
|
+
- !ruby/object:Gem::Version
|
|
278
|
+
version: '9.4'
|
|
265
279
|
description: Kill Bill payment plugin for Cybersource.
|
|
266
280
|
email: killbilling-users@googlegroups.com
|
|
267
281
|
executables: []
|