killbill-cybersource 5.2.0 → 5.2.1

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.
@@ -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