killbill-cybersource 5.2.0 → 5.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,53 +0,0 @@
1
- version = File.read(File.expand_path('../VERSION', __FILE__)).strip
2
-
3
- Gem::Specification.new do |s|
4
- s.name = 'killbill-cybersource'
5
- s.version = version
6
- s.summary = 'Plugin to use Cybersource as a gateway.'
7
- s.description = 'Kill Bill payment plugin for Cybersource.'
8
-
9
- s.required_ruby_version = '>= 1.9.3'
10
-
11
- s.license = 'Apache License (2.0)'
12
-
13
- s.author = 'Kill Bill core team'
14
- s.email = 'killbilling-users@googlegroups.com'
15
- s.homepage = 'http://killbill.io'
16
-
17
- s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.bindir = 'bin'
20
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
21
- s.require_paths = ['lib']
22
-
23
- s.rdoc_options << '--exclude' << '.'
24
-
25
- s.add_dependency 'killbill', '~> 8.0'
26
-
27
- s.add_dependency 'sinatra', '~> 1.3.4'
28
- s.add_dependency 'thread_safe', '~> 0.3.4'
29
- s.add_dependency 'activerecord', '~> 4.1.0'
30
- if defined?(JRUBY_VERSION)
31
- s.add_dependency 'activerecord-bogacs', '~> 0.3'
32
- s.add_dependency 'activerecord-jdbc-adapter', '~> 1.3'
33
- # Required to avoid errors like java.lang.NoClassDefFoundError: org/bouncycastle/asn1/DERBoolean
34
- s.add_dependency 'jruby-openssl', '~> 0.9.6'
35
- end
36
- s.add_dependency 'actionpack', '~> 4.1.0'
37
- s.add_dependency 'actionview', '~> 4.1.0'
38
- s.add_dependency 'activemerchant', '~> 1.48.0'
39
- s.add_dependency 'offsite_payments', '~> 2.1.0'
40
- s.add_dependency 'monetize', '~> 1.1.0'
41
- s.add_dependency 'money', '~> 6.5.1'
42
-
43
- s.add_development_dependency 'jbundler', '~> 0.9.2'
44
- s.add_development_dependency 'rake', '>= 10.0.0'
45
- s.add_development_dependency 'rspec', '~> 2.12.0'
46
- if defined?(JRUBY_VERSION)
47
- s.add_development_dependency 'jdbc-sqlite3', '~> 3.7'
48
- s.add_development_dependency 'jdbc-mariadb', '~> 1.1'
49
- s.add_development_dependency 'jdbc-postgres', '~> 9.4'
50
- else
51
- s.add_development_dependency 'sqlite3', '~> 1.3.7'
52
- end
53
- end
data/killbill.properties DELETED
@@ -1,3 +0,0 @@
1
- mainClass=Killbill::Cybersource::PaymentPlugin
2
- require=cybersource
3
- pluginType=PAYMENT
data/pom.xml DELETED
@@ -1,44 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!--
3
- ~ Copyright 2014-2015 The Billing Project, LLC
4
- ~
5
- ~ The Billing Project licenses this file to you under the Apache License, version 2.0
6
- ~ (the "License"); you may not use this file except in compliance with the
7
- ~ License. You may obtain a copy of the License at:
8
- ~
9
- ~ http://www.apache.org/licenses/LICENSE-2.0
10
- ~
11
- ~ Unless required by applicable law or agreed to in writing, software
12
- ~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
- ~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
- ~ License for the specific language governing permissions and limitations
15
- ~ under the License.
16
- -->
17
-
18
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19
- <parent>
20
- <groupId>org.sonatype.oss</groupId>
21
- <artifactId>oss-parent</artifactId>
22
- <version>5</version>
23
- </parent>
24
- <modelVersion>4.0.0</modelVersion>
25
- <groupId>org.kill-bill.billing.plugin.ruby</groupId>
26
- <artifactId>cybersource-plugin</artifactId>
27
- <packaging>pom</packaging>
28
- <version>5.2.0</version>
29
- <name>cybersource-plugin</name>
30
- <url>http://github.com/killbill/killbill-cybersource-plugin</url>
31
- <description>Plugin for accessing Cybersource as a payment gateway</description>
32
- <licenses>
33
- <license>
34
- <name>Apache License 2.0</name>
35
- <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
36
- <distribution>repo</distribution>
37
- </license>
38
- </licenses>
39
- <scm>
40
- <connection>scm:git:git://github.com/killbill/killbill-cybersource-plugin.git</connection>
41
- <url>https://github.com/killbill/killbill-cybersource-plugin/</url>
42
- <developerConnection>scm:git:git@github.com:killbill/killbill-cybersource-plugin.git</developerConnection>
43
- </scm>
44
- </project>
data/release.sh DELETED
@@ -1,61 +0,0 @@
1
- set -e
2
-
3
- BUNDLE=${BUNDLE-"bundle exec"}
4
- MVN=${MVN-"mvn"}
5
-
6
- if [ 'GNU' != "$(tar --help | grep GNU | head -1 | awk '{print $1}')" ]; then
7
- echo 'Unable to release: make sure to use GNU tar'
8
- exit 1
9
- fi
10
-
11
- if $(ruby -e'require "java"'); then
12
- # Good
13
- echo 'Detected JRuby'
14
- else
15
- echo 'Unable to release: make sure to use JRuby'
16
- exit 1
17
- fi
18
-
19
- VERSION=`grep -E '<version>([0-9]+\.[0-9]+\.[0-9]+)</version>' pom.xml | sed 's/[\t \n]*<version>\(.*\)<\/version>[\t \n]*/\1/'`
20
- if [[ -z "$NO_RELEASE" && "$VERSION" != "$(cat $PWD/VERSION)" ]]; then
21
- echo 'Unable to release: make sure the versions in pom.xml and VERSION match'
22
- exit 1
23
- fi
24
-
25
- echo 'Cleaning up'
26
- $BUNDLE rake killbill:clean
27
-
28
- echo 'Building gem'
29
- $BUNDLE rake build
30
-
31
- if [[ -z "$NO_RELEASE" ]]; then
32
- echo 'Pushing the gem to Rubygems'
33
- $BUNDLE rake release
34
- fi
35
-
36
- echo 'Building artifact'
37
- $BUNDLE rake killbill:package
38
-
39
- ARTIFACT="$PWD/pkg/killbill-cybersource-$VERSION.tar.gz"
40
- echo "Pushing $ARTIFACT to Maven Central"
41
-
42
- if [[ -z "$NO_RELEASE" ]]; then
43
- GOAL=gpg:sign-and-deploy-file
44
- REPOSITORY_ID=ossrh-releases
45
- URL=https://oss.sonatype.org/service/local/staging/deploy/maven2/
46
- else
47
- GOAL=deploy:deploy-file
48
- REPOSITORY_ID=sonatype-nexus-snapshots
49
- URL=https://oss.sonatype.org/content/repositories/snapshots/
50
- VERSION="$VERSION-SNAPSHOT"
51
- fi
52
-
53
- $MVN $GOAL \
54
- -DgroupId=org.kill-bill.billing.plugin.ruby \
55
- -DartifactId=cybersource-plugin \
56
- -Dversion=$VERSION \
57
- -Dpackaging=tar.gz \
58
- -DrepositoryId=$REPOSITORY_ID \
59
- -Durl=$URL \
60
- -Dfile=$ARTIFACT \
61
- -DpomFile=pom.xml
@@ -1,465 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Killbill::Cybersource::PaymentPlugin do
4
-
5
- include ::Killbill::Plugin::ActiveMerchant::RSpec
6
-
7
- before(:each) do
8
- Dir.mktmpdir do |dir|
9
- file = File.new(File.join(dir, 'cybersource.yml'), 'w+')
10
- file.write(<<-eos)
11
- :cybersource:
12
- :test: true
13
- # As defined by spec_helper.rb
14
- :database:
15
- :adapter: 'sqlite3'
16
- :database: 'test.db'
17
- eos
18
- file.close
19
-
20
- @plugin = build_plugin(::Killbill::Cybersource::PaymentPlugin, 'cybersource', File.dirname(file))
21
-
22
- # Start the plugin here - since the config file will be deleted
23
- @plugin.start_plugin
24
- end
25
- end
26
-
27
- let(:expected_successful_params) do
28
- {
29
- :params_merchant_reference_code => 'b0a6cf9aa07f1a8495f89c364bbd6a9a',
30
- :params_request_id => '2004333231260008401927',
31
- :params_decision => 'ACCEPT',
32
- :params_reason_code => '100',
33
- :params_request_token => 'Afvvj7Ke2Fmsbq0wHFE2sM6R4GAptYZ0jwPSA+R9PhkyhFTb0KRjoE4+ynthZrG6tMBwjAtT',
34
- :params_currency => 'USD',
35
- :params_amount => '1.00',
36
- :params_authorization_code => '123456',
37
- :params_avs_code => 'Y',
38
- :params_avs_code_raw => 'Y',
39
- :params_cv_code => 'M',
40
- :params_authorized_date_time => '2008-01-15T21:42:03Z',
41
- :params_processor_response => '00',
42
- :params_reconciliation_id => 'ABCDEF',
43
- :params_subscription_id => 'XXYYZZ'
44
- }
45
- end
46
-
47
- it 'should start and stop correctly' do
48
- @plugin.stop_plugin
49
- end
50
-
51
- it 'should detect when to credit refunds' do
52
- context = build_call_context
53
- kb_payment_id = SecureRandom.uuid
54
-
55
- @plugin.should_credit?(SecureRandom.uuid, context).should be_false
56
-
57
- with_transaction(kb_payment_id, :AUTHORIZE, 60.days.ago, build_call_context(SecureRandom.uuid)) { @plugin.should_credit?(kb_payment_id, context).should be_false }
58
- with_transaction(kb_payment_id, :AUTHORIZE, 59.days.ago, context) { @plugin.should_credit?(kb_payment_id, context).should be_false }
59
- with_transaction(kb_payment_id, :VOID, 60.days.ago, context) { @plugin.should_credit?(kb_payment_id, context).should be_false }
60
- with_transaction(SecureRandom.uuid, :AUTHORIZE, 60.days.ago, context) { @plugin.should_credit?(kb_payment_id, context).should be_false }
61
-
62
- with_transaction(kb_payment_id, :AUTHORIZE, 61.days.ago, context) do
63
- @plugin.should_credit?(kb_payment_id, context, {:disable_auto_credit => true}).should be_false
64
- @plugin.should_credit?(kb_payment_id, context, {:auto_credit_threshold => 61 * 86400 + 3600 + 10}).should be_false
65
-
66
- options = {}
67
- @plugin.should_credit?(kb_payment_id, context, options).should be_true
68
- options[:payment_processor_account_id].should == 'GOOD'
69
-
70
- options = {:payment_processor_account_id => 'OVERRIDDEN'}
71
- @plugin.should_credit?(kb_payment_id, context, options).should be_true
72
- options[:payment_processor_account_id].should == 'OVERRIDDEN'
73
- end
74
- end
75
-
76
- context 'Business Rules' do
77
-
78
- it 'does not ignore AVS nor CVN' do
79
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
80
- request_body.should_not match('<ignoreAVSResult>')
81
- request_body.should_not match('<ignoreCVResult>')
82
- successful_purchase_response
83
- end
84
- purchase_with_token(:PROCESSED, [], expected_successful_params)
85
- purchase_with_token(:PROCESSED, [build_property('ignore_avs', 'false'), build_property('ignore_cvv', 'false')], expected_successful_params)
86
- end
87
-
88
- it 'ignores AVS and CVN' do
89
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
90
- request_body.should match('<ignoreAVSResult>')
91
- request_body.should match('<ignoreCVResult>')
92
- successful_purchase_response
93
- end
94
- purchase_with_token(:PROCESSED, [build_property('ignore_avs', 'true'), build_property('ignore_cvv', 'true')], expected_successful_params)
95
- end
96
-
97
- it 'ignores AVS but not CVN' do
98
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
99
- request_body.should match('<ignoreAVSResult>')
100
- request_body.should_not match('<ignoreCVResult>')
101
- successful_purchase_response
102
- end
103
- purchase_with_token(:PROCESSED, [build_property('ignore_avs', 'true')], expected_successful_params)
104
- purchase_with_token(:PROCESSED, [build_property('ignore_avs', 'true'), build_property('ignore_cvv', 'false')], expected_successful_params)
105
- end
106
-
107
- it 'ignores CVN but not AVS' do
108
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
109
- request_body.should_not match('<ignoreAVSResult>')
110
- request_body.should match('<ignoreCVResult>')
111
- successful_purchase_response
112
- end
113
- purchase_with_token(:PROCESSED, [build_property('ignore_cvv', 'true')], expected_successful_params)
114
- purchase_with_token(:PROCESSED, [build_property('ignore_avs', 'false'), build_property('ignore_cvv', 'true')], expected_successful_params)
115
- end
116
- end
117
-
118
- context 'Override parameters' do
119
-
120
- it 'has a default commerceIndicator' do
121
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
122
- request_body.should_not match('<commerceIndicator>')
123
- successful_purchase_response
124
- end
125
- purchase_with_token(:PROCESSED, [], expected_successful_params)
126
- end
127
-
128
- it 'can override commerceIndicator for card-on-file' do
129
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
130
- request_body.should match('<commerceIndicator>recurring</commerceIndicator>')
131
- successful_purchase_response
132
- end
133
- purchase_with_card(:PROCESSED, [build_property('commerce_indicator', 'recurring')], expected_successful_params)
134
- end
135
-
136
- it 'has a default commerceIndicator for Apple Pay' do
137
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
138
- request_body.should_not match('<commerceIndicator>internet</commerceIndicator>')
139
- request_body.should match('<commerceIndicator>vbv</commerceIndicator>')
140
- successful_purchase_response
141
- end
142
- purchase_with_network_tokenization(:PROCESSED, [], expected_successful_params)
143
- end
144
-
145
- it 'can override commerceIndicator for Apple Pay' do
146
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
147
- request_body.should_not match('<commerceIndicator>vbv</commerceIndicator>')
148
- request_body.should match('<commerceIndicator>internet</commerceIndicator>')
149
- successful_purchase_response
150
- end
151
- purchase_with_network_tokenization(:PROCESSED, [build_property('commerce_indicator', 'internet')], expected_successful_params)
152
- end
153
- end
154
-
155
- context 'Errors handling' do
156
-
157
- it 'handles proxy errors as UNDEFINED transactions' do
158
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |_, _|
159
- raise ::ActiveMerchant::ResponseError.new(OpenStruct.new(:body => 'Oops', :code => 502))
160
- end
161
- purchase_with_token(:UNDEFINED).gateway_error.should == 'Failed with 502 '
162
- end
163
-
164
- it 'handles generic 500 errors as UNDEFINED transactions' do
165
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |_, _|
166
- raise ::ActiveMerchant::ResponseError.new(OpenStruct.new(:body => nil, :code => 500))
167
- end
168
- purchase_with_token(:UNDEFINED).gateway_error.should == 'Failed with 500 '
169
- end
170
-
171
- it 'handles CyberSource errors as CANCELED transactions' do
172
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |_, _|
173
- raise ::ActiveMerchant::ResponseError.new(OpenStruct.new(:body => one_or_more_fields_contains_invalid_data, :code => 500))
174
- end
175
- purchase_with_token(:CANCELED).gateway_error.should == 'One or more fields contains invalid data'
176
- end
177
-
178
- it 'handles expired passwords as CANCELED transactions' do
179
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post).and_return(password_expired_response)
180
- purchase_with_token(:CANCELED).gateway_error.should == 'wsse:FailedCheck: Security Data : Merchant password has expired.'
181
- end
182
-
183
- it 'handles bad passwords as CANCELED transactions' do
184
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post).and_return(bad_password_response)
185
- purchase_with_token(:CANCELED).gateway_error.should == 'wsse:FailedCheck: Security Data : UsernameToken authentication failed.'
186
- end
187
-
188
- it 'handles unsuccessful authorizations as ERROR transactions' do
189
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post).and_return(unsuccessful_authorization_response)
190
- purchase_with_token(:ERROR).gateway_error.should == 'Invalid account number'
191
- end
192
-
193
- it 'parses correctly authorization reversal errors' do
194
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post).and_return(unsuccessful_auth_reversal_response)
195
- payment_response = purchase_with_token(:CANCELED)
196
- payment_response.gateway_error.should == 'One or more fields contains invalid data'
197
- payment_response.gateway_error_code.should == '102'
198
- end
199
-
200
- it 'cancels UNDEFINED transactions with a JSON message' do
201
- response = Killbill::Cybersource::CybersourceResponse.create(:api_call => 'authorization',
202
- :message => '{"exception_message":"Timeout","payment_plugin_status":"UNDEFINED"}',
203
- :created_at => Time.now,
204
- :updated_at => Time.now)
205
- response.cancel
206
- response.message.should == '{"exception_message":"Timeout","payment_plugin_status":"CANCELED"}'
207
- end
208
-
209
- it 'cancels UNDEFINED transactions with a plain test message' do
210
- response = Killbill::Cybersource::CybersourceResponse.create(:api_call => 'authorization',
211
- :message => 'Internal error',
212
- :created_at => Time.now,
213
- :updated_at => Time.now)
214
- response.cancel
215
- response.message.should == '{"original_message":"Internal error","payment_plugin_status":"CANCELED"}'
216
- end
217
-
218
- it 'cancels UNDEFINED transactions with no message' do
219
- response = Killbill::Cybersource::CybersourceResponse.create(:api_call => 'authorization',
220
- :created_at => Time.now,
221
- :updated_at => Time.now)
222
- response.cancel
223
- response.message.should == '{"payment_plugin_status":"CANCELED"}'
224
- end
225
- end
226
-
227
- def stub_gateway_for_invoice_header(invoice_match_status)
228
- ::ActiveMerchant::Billing::CyberSourceGateway.any_instance.stub(:ssl_post) do |host, request_body|
229
- case(invoice_match_status)
230
- when :none
231
- request_body.should_not match('<invoiceHeader>')
232
- when :all
233
- request_body.should match('<invoiceHeader>\n <merchantDescriptor>Ray Qiu </merchantDescriptor>\n <merchantDescriptorContact>650-888-3161</merchantDescriptorContact>\n </invoiceHeader>')
234
- when :except_authorize
235
- if request_body.index('ccAuthService').present?
236
- request_body.should_not match('<invoiceHeader>\n <amexDataTAA1>Ray Qiu</amexDataTAA1>\n <amexDataTAA2>6508883161</amexDataTAA2>')
237
- else
238
- request_body.should match('<invoiceHeader>\n <amexDataTAA1>Ray Qiu</amexDataTAA1>\n <amexDataTAA2>6508883161</amexDataTAA2>')
239
- end
240
- end
241
- successful_purchase_response
242
- end
243
- end
244
-
245
- shared_examples 'full payment' do
246
- before do
247
- send(add_payment_properties, txn_properties, card_type)
248
- stub_gateway_for_invoice_header(invoice_match_status)
249
- end
250
-
251
- it 'should met expectations' do
252
- auth_responses = create_transaction(card_type, :authorize, nil, :PROCESSED, txn_properties, expected_successful_params)
253
- capture_responses = create_transaction(card_type, :capture, auth_responses, :PROCESSED, txn_properties, expected_successful_params)
254
- create_transaction(card_type, :refund, capture_responses, :PROCESSED, txn_properties, expected_successful_params)
255
- end
256
- end
257
-
258
- shared_examples 'invoice header example' do
259
- let(:card_type){ :visa }
260
- let(:txn_properties){ [] }
261
-
262
- context 'while no descriptor provided' do
263
- let(:invoice_match_status){ :none }
264
-
265
- context 'visa' do
266
- it_behaves_like 'full payment'
267
- end
268
-
269
- context 'amex' do
270
- let(:card_type){ :amex }
271
- it_behaves_like 'full payment'
272
- end
273
- end
274
-
275
- context 'while descriptor provided' do
276
- before{ txn_properties << build_property('merchant_descriptor', {"name"=>"Ray Qiu", "contact"=>"6508883161"}.to_json) }
277
-
278
- context 'visa' do
279
- let(:invoice_match_status){ :all }
280
- it_behaves_like 'full payment'
281
- end
282
-
283
- context 'amex' do
284
- let(:card_type){ :amex }
285
- let(:invoice_match_status){ :except_authorize }
286
- it_behaves_like 'full payment'
287
- end
288
- end
289
- end
290
-
291
- context 'Invoice Header' do
292
- context 'payments with card' do
293
- let(:add_payment_properties){ :add_card_property }
294
- it_behaves_like 'invoice header example'
295
- end
296
-
297
- context 'payments with network tokenization' do
298
- let(:add_payment_properties){ :add_network_tokenization_properties }
299
- it_behaves_like 'invoice header example'
300
- end
301
- end
302
-
303
- private
304
-
305
- def with_transaction(kb_payment_id, transaction_type, created_at, context)
306
- t = ::Killbill::Cybersource::CybersourceTransaction.create(:kb_payment_id => kb_payment_id,
307
- :transaction_type => transaction_type,
308
- :kb_tenant_id => context.tenant_id,
309
- :created_at => created_at,
310
- :payment_processor_account_id => 'GOOD',
311
- # The data below doesn't matter
312
- :updated_at => created_at,
313
- :kb_account_id => SecureRandom.uuid,
314
- :kb_payment_transaction_id => SecureRandom.uuid,
315
- :api_call => :refund,
316
- :cybersource_response_id => 1)
317
- t.should_not be_nil
318
- yield t if block_given?
319
- ensure
320
- t.destroy! unless t.nil?
321
- end
322
-
323
- def add_card_property(properties, card_type = :visa)
324
- properties << build_property('email', 'foo@bar.com')
325
- if card_type == :amex
326
- properties << build_property('cc_number', '378282246310005')
327
- else
328
- properties << build_property('cc_number', '4111111111111111')
329
- end
330
- end
331
-
332
- def add_token_property(properties)
333
- properties << build_property('email', 'foo@bar.com')
334
- properties << build_property('token', '1234')
335
- end
336
-
337
- def add_network_tokenization_properties(properties, card_type = :visa)
338
- if card_type == :amex
339
- properties << build_property('cc_number', '378282246310005')
340
- properties << build_property('brand', 'american_express')
341
- properties << build_property('payment_cryptogram', Base64.encode64('111111111100cryptogram'))
342
- else
343
- properties << build_property('cc_number', '4111111111111111')
344
- properties << build_property('brand', 'visa')
345
- properties << build_property('payment_cryptogram', '111111111100cryptogram')
346
- end
347
- properties << build_property('email', 'foo@bar.com')
348
- properties << build_property('eci', '05')
349
- end
350
-
351
- def purchase_with_card(expected_status = :PROCESSED, properties = [], expected_params = {})
352
- add_card_property(properties)
353
- purchase(expected_status, properties, expected_params)
354
- end
355
-
356
- def purchase_with_token(expected_status = :PROCESSED, properties = [], expected_params = {})
357
- add_token_property(properties)
358
- purchase(expected_status, properties, expected_params)
359
- end
360
-
361
- def purchase_with_network_tokenization(expected_status = :PROCESSED, properties = [], expected_params = {})
362
- add_network_tokenization_properties(properties)
363
- purchase(expected_status, properties, expected_params)
364
- end
365
-
366
- def verify_response(payment_response, expected_status, expected_params)
367
- payment_response.status.should eq(expected_status), payment_response.gateway_error
368
-
369
- gw_response = Killbill::Cybersource::CybersourceResponse.last
370
- expected_params.each do |k, v|
371
- gw_response.send(k.to_sym).should == v
372
- end
373
- end
374
-
375
- def create_transaction(card_type = :visa, txn_type = :authorize, previous_response = nil, expected_status = :PROCESSED, properties = [], expected_params = {})
376
- if txn_type == :authorize
377
- authorize(expected_status, properties, expected_params)
378
- else
379
- previous_response.shift
380
- send(txn_type, *previous_response, expected_status, properties, expected_params)
381
- end
382
- end
383
-
384
- def authorize(expected_status = :PROCESSED, properties = [], expected_params = {})
385
- kb_account_id = SecureRandom.uuid
386
- kb_payment_method_id = SecureRandom.uuid
387
- kb_payment_id = SecureRandom.uuid
388
- kb_payment = @plugin.kb_apis.proxied_services[:payment_api].add_payment(kb_payment_id)
389
- kb_transaction_id = kb_payment.transactions[0].id
390
-
391
- payment_response = @plugin.authorize_payment(kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id, BigDecimal.new('100'), 'USD', properties, build_call_context)
392
- verify_response(payment_response, expected_status, expected_params)
393
- return payment_response, kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id
394
- end
395
-
396
- def capture(kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id, expected_status = :PROCESSED, properties = [], expected_params = {})
397
- payment_response = @plugin.capture_payment(kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id, BigDecimal.new('100'), 'USD', properties, build_call_context)
398
- verify_response(payment_response, expected_status, expected_params)
399
- return payment_response, kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id
400
- end
401
-
402
- def refund(kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id, expected_status = :PROCESSED, properties = [], expected_params = {})
403
- payment_response = @plugin.refund_payment(kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id, BigDecimal.new('100'), 'USD', properties, build_call_context)
404
- verify_response(payment_response, expected_status, expected_params)
405
- return payment_response, kb_account_id, kb_payment_id, kb_transaction_id, kb_payment_method_id
406
- end
407
-
408
- def purchase(expected_status = :PROCESSED, properties = [], expected_params = {})
409
- kb_payment_id = SecureRandom.uuid
410
- kb_payment = @plugin.kb_apis.proxied_services[:payment_api].add_payment(kb_payment_id)
411
- kb_transaction_id = kb_payment.transactions[0].id
412
-
413
- payment_response = @plugin.purchase_payment(SecureRandom.uuid, kb_payment_id, kb_transaction_id, SecureRandom.uuid, BigDecimal.new('100'), 'USD', properties, build_call_context)
414
- verify_response(payment_response, expected_status, expected_params)
415
- payment_response
416
- end
417
-
418
- def successful_purchase_response
419
- <<-XML
420
- <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
421
- <soap:Header>
422
- <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-2636690"><wsu:Created>2008-01-15T21:42:03.343Z</wsu:Created></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><c:replyMessage xmlns:c="urn:schemas-cybersource-com:transaction-data-1.26"><c:merchantReferenceCode>b0a6cf9aa07f1a8495f89c364bbd6a9a</c:merchantReferenceCode><c:requestID>2004333231260008401927</c:requestID><c:decision>ACCEPT</c:decision><c:reasonCode>100</c:reasonCode><c:requestToken>Afvvj7Ke2Fmsbq0wHFE2sM6R4GAptYZ0jwPSA+R9PhkyhFTb0KRjoE4+ynthZrG6tMBwjAtT</c:requestToken><c:purchaseTotals><c:currency>USD</c:currency></c:purchaseTotals><c:ccAuthReply><c:reasonCode>100</c:reasonCode><c:amount>1.00</c:amount><c:authorizationCode>123456</c:authorizationCode><c:avsCode>Y</c:avsCode><c:avsCodeRaw>Y</c:avsCodeRaw><c:cvCode>M</c:cvCode><c:cvCodeRaw>M</c:cvCodeRaw><c:authorizedDateTime>2008-01-15T21:42:03Z</c:authorizedDateTime><c:processorResponse>00</c:processorResponse><c:reconciliationID>ABCDEF</c:reconciliationID><c:authFactorCode>U</c:authFactorCode></c:ccAuthReply><c:paySubscriptionCreateReply><c:reasonCode>100</c:reasonCode><c:subscriptionID>XXYYZZ</c:subscriptionID></c:paySubscriptionCreateReply></c:replyMessage></soap:Body></soap:Envelope>
423
- XML
424
- end
425
-
426
- def password_expired_response
427
- <<-XML
428
- <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
429
- <soap:Header>
430
- <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-2636690"><wsu:Created>2008-01-15T21:42:03.343Z</wsu:Created></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><soap:Fault xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:c="urn:schemas-cybersource-com:transaction-data-1.0"><faultcode>wsse:FailedCheck</faultcode><faultstring>Security Data : Merchant password has expired.</faultstring></soap:Fault></soap:Body></soap:Envelope>
431
- XML
432
- end
433
-
434
- def bad_password_response
435
- <<-XML
436
- <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
437
- <soap:Header>
438
- <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-2636690"><wsu:Created>2008-01-15T21:42:03.343Z</wsu:Created></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><soap:Fault xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:c="urn:schemas-cybersource-com:transaction-data-1.0"><faultcode>wsse:FailedCheck</faultcode><faultstring>Security Data : UsernameToken authentication failed.</faultstring></soap:Fault></soap:Body></soap:Envelope>
439
- XML
440
- end
441
-
442
- def unsuccessful_authorization_response
443
- <<-XML
444
- <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
445
- <soap:Header>
446
- <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-28121162"><wsu:Created>2008-01-15T21:50:41.580Z</wsu:Created></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><c:replyMessage xmlns:c="urn:schemas-cybersource-com:transaction-data-1.26"><c:merchantReferenceCode>a1efca956703a2a5037178a8a28f7357</c:merchantReferenceCode><c:requestID>2004338415330008402434</c:requestID><c:decision>REJECT</c:decision><c:reasonCode>231</c:reasonCode><c:requestToken>Afvvj7KfIgU12gooCFE2/DanQIApt+G1OgTSA+R9PTnyhFTb0KRjgFY+ynyIFNdoKKAghwgx</c:requestToken><c:ccAuthReply><c:reasonCode>231</c:reasonCode></c:ccAuthReply></c:replyMessage></soap:Body></soap:Envelope>
447
- XML
448
- end
449
-
450
- def unsuccessful_auth_reversal_response
451
- <<-XML
452
- <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
453
- <soap:Header>
454
- <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-28121162"><wsu:Created>2008-01-15T21:50:41.580Z</wsu:Created></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><c:replyMessage xmlns:c="urn:schemas-cybersource-com:transaction-data-1.26"><c:merchantReferenceCode>a1efca956703a2a5037178a8a28f7357</c:merchantReferenceCode><c:requestID>2004338415330008402434</c:requestID><c:decision>REJECT</c:decision><c:reasonCode>102</c:reasonCode><c:requestToken>Afvvj7KfIgU12gooCFE2/DanQIApt+G1OgTSA+R9PTnyhFTb0KRjgFY+ynyIFNdoKKAghwgx</c:requestToken><c:ccAuthReversalReply><c:reasonCode>102</c:reasonCode></c:ccAuthReversalReply><c:originalTransaction><c:amount>0.00</c:amount><c:reasonCode>100</c:reasonCode></c:originalTransaction></c:replyMessage></soap:Body></soap:Envelope>
455
- XML
456
- end
457
-
458
- def one_or_more_fields_contains_invalid_data
459
- <<-XML
460
- <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
461
- <soap:Header>
462
- <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-28121162"><wsu:Created>2008-01-15T21:50:41.580Z</wsu:Created></wsu:Timestamp></wsse:Security></soap:Header><soap:Body><c:replyMessage xmlns:c="urn:schemas-cybersource-com:transaction-data-1.26"><c:requestID>12345</c:requestID><c:decision>REJECT</c:decision><c:reasonCode>102</c:reasonCode><c:invalidField>c:billTo/c:state</c:invalidField><c:requestToken>Afvvj7KfIgU12gooCFE2/DanQIApt+G1OgTSA+R9PTnyhFTb0KRjgFY+ynyIFNdoKKAghwgx</c:requestToken></c:replyMessage></soap:Body></soap:Envelope>
463
- XML
464
- end
465
- end