vaulted_billing 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/LICENSE +19 -0
  2. data/lib/vaulted_billing/gateways/bogus.rb +2 -0
  3. data/lib/vaulted_billing/version.rb +1 -1
  4. data/spec/certification/ipcommerce/README.md +9 -0
  5. data/spec/certification/ipcommerce/TODO.md +1 -0
  6. data/spec/certification/ipcommerce/host_capture_ecommerce.rb +318 -0
  7. data/spec/certification/ipcommerce/ipcommerce_transaction.rb +28 -0
  8. data/spec/certification/ipcommerce/terminal_capture_ecommerce.rb +298 -0
  9. data/spec/config.example.yml +18 -0
  10. data/spec/factories/credit_cards.rb +38 -0
  11. data/spec/factories/customers.rb +7 -0
  12. data/spec/factories/sequences.rb +22 -0
  13. data/spec/fixtures/net/authorize_net_cim/add_customer/failure.yml +38 -0
  14. data/spec/fixtures/net/authorize_net_cim/add_customer/success.yml +39 -0
  15. data/spec/fixtures/net/authorize_net_cim/add_customer_credit_card/failure.yml +83 -0
  16. data/spec/fixtures/net/authorize_net_cim/add_customer_credit_card/success.yml +81 -0
  17. data/spec/fixtures/net/authorize_net_cim/authorize/failure.yml +121 -0
  18. data/spec/fixtures/net/authorize_net_cim/authorize/success.yml +121 -0
  19. data/spec/fixtures/net/authorize_net_cim/capture/failure.yml +161 -0
  20. data/spec/fixtures/net/authorize_net_cim/capture/success.yml +160 -0
  21. data/spec/fixtures/net/authorize_net_cim/purchase/failure.yml +122 -0
  22. data/spec/fixtures/net/authorize_net_cim/purchase/success.yml +122 -0
  23. data/spec/fixtures/net/authorize_net_cim/refund/failure.yml +123 -0
  24. data/spec/fixtures/net/authorize_net_cim/refund/failure_2.yml +43 -0
  25. data/spec/fixtures/net/authorize_net_cim/remove_customer/failure.yml +76 -0
  26. data/spec/fixtures/net/authorize_net_cim/remove_customer/success.yml +75 -0
  27. data/spec/fixtures/net/authorize_net_cim/remove_customer_credit_card/failure.yml +156 -0
  28. data/spec/fixtures/net/authorize_net_cim/remove_customer_credit_card/success.yml +118 -0
  29. data/spec/fixtures/net/authorize_net_cim/update_customer/failure.yml +77 -0
  30. data/spec/fixtures/net/authorize_net_cim/update_customer/success.yml +76 -0
  31. data/spec/fixtures/net/authorize_net_cim/update_customer_credit_card/failure.yml +125 -0
  32. data/spec/fixtures/net/authorize_net_cim/update_customer_credit_card/success.yml +124 -0
  33. data/spec/fixtures/net/authorize_net_cim/void/success.yml +159 -0
  34. data/spec/fixtures/net/ipcommerce/add_customer_credit_card/failure.yml +53 -0
  35. data/spec/fixtures/net/ipcommerce/add_customer_credit_card/success.yml +103 -0
  36. data/spec/fixtures/net/ipcommerce/authorize/existing/failure.yml +51 -0
  37. data/spec/fixtures/net/ipcommerce/authorize/existing/success.yml +105 -0
  38. data/spec/fixtures/net/ipcommerce/authorize/new/avs/bad_format.yml +53 -0
  39. data/spec/fixtures/net/ipcommerce/authorize/new/avs/issuer_not_certified.yml +53 -0
  40. data/spec/fixtures/net/ipcommerce/authorize/new/avs/match.yml +53 -0
  41. data/spec/fixtures/net/ipcommerce/authorize/new/avs/no_match.yml +53 -0
  42. data/spec/fixtures/net/ipcommerce/authorize/new/avs/no_response_from_card_association.yml +53 -0
  43. data/spec/fixtures/net/ipcommerce/authorize/new/avs/not_included.yml +53 -0
  44. data/spec/fixtures/net/ipcommerce/authorize/new/avs/not_sent.yml +53 -0
  45. data/spec/fixtures/net/ipcommerce/authorize/new/avs/not_verified.yml +53 -0
  46. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/invalid.yml +53 -0
  47. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/issuer_not_certified.yml +53 -0
  48. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/no_code_present.yml +53 -0
  49. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/no_match.yml +53 -0
  50. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/no_response.yml +53 -0
  51. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/not_applicable.yml +53 -0
  52. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/not_processed.yml +53 -0
  53. data/spec/fixtures/net/ipcommerce/authorize/new/cvv/should_have_been_present.yml +53 -0
  54. data/spec/fixtures/net/ipcommerce/authorize/new/failure.yml +53 -0
  55. data/spec/fixtures/net/ipcommerce/authorize/new/success.yml +53 -0
  56. data/spec/fixtures/net/ipcommerce/capture/failure.yml +78 -0
  57. data/spec/fixtures/net/ipcommerce/capture/invalid.yml +78 -0
  58. data/spec/fixtures/net/ipcommerce/capture/success.yml +78 -0
  59. data/spec/fixtures/net/ipcommerce/failover.yml +53 -0
  60. data/spec/fixtures/net/ipcommerce/purchase/existing/failure.yml +51 -0
  61. data/spec/fixtures/net/ipcommerce/purchase/existing/success.yml +105 -0
  62. data/spec/fixtures/net/ipcommerce/purchase/new/failure.yml +53 -0
  63. data/spec/fixtures/net/ipcommerce/purchase/new/success.yml +53 -0
  64. data/spec/fixtures/net/ipcommerce/refund/failure.yml +78 -0
  65. data/spec/fixtures/net/ipcommerce/refund/success.yml +80 -0
  66. data/spec/fixtures/net/ipcommerce/update_customer_credit_card/failure.yml +53 -0
  67. data/spec/fixtures/net/ipcommerce/update_customer_credit_card/success.yml +103 -0
  68. data/spec/fixtures/net/ipcommerce/void/failure.yml +78 -0
  69. data/spec/fixtures/net/ipcommerce/void/success.yml +78 -0
  70. data/spec/fixtures/net/nmi_customer_vault/add_customer_credit_card/failure.yml +26 -0
  71. data/spec/fixtures/net/nmi_customer_vault/add_customer_credit_card/success.yml +26 -0
  72. data/spec/fixtures/net/nmi_customer_vault/authorize/decline.yml +51 -0
  73. data/spec/fixtures/net/nmi_customer_vault/authorize/success.yml +51 -0
  74. data/spec/fixtures/net/nmi_customer_vault/capture/failure.yml +76 -0
  75. data/spec/fixtures/net/nmi_customer_vault/capture/success.yml +76 -0
  76. data/spec/fixtures/net/nmi_customer_vault/purchase/decline.yml +51 -0
  77. data/spec/fixtures/net/nmi_customer_vault/purchase/success.yml +51 -0
  78. data/spec/fixtures/net/nmi_customer_vault/refund/failure.yml +101 -0
  79. data/spec/fixtures/net/nmi_customer_vault/remove_customer_credit_card/failure.yml +26 -0
  80. data/spec/fixtures/net/nmi_customer_vault/remove_customer_credit_card/success.yml +51 -0
  81. data/spec/fixtures/net/nmi_customer_vault/update_customer_credit_card/success.yml +51 -0
  82. data/spec/fixtures/net/nmi_customer_vault/void/failure.yml +26 -0
  83. data/spec/fixtures/net/nmi_customer_vault/void/success.yml +76 -0
  84. data/spec/models/vaulted_billing/configuration_spec.rb +62 -0
  85. data/spec/models/vaulted_billing/core_ext/hash_spec.rb +47 -0
  86. data/spec/models/vaulted_billing/credit_card_spec.rb +61 -0
  87. data/spec/models/vaulted_billing/gateway_spec.rb +115 -0
  88. data/spec/models/vaulted_billing/http_spec.rb +154 -0
  89. data/spec/models/vaulted_billing/transaction_spec.rb +60 -0
  90. data/spec/models/vaulted_billing_spec.rb +16 -0
  91. data/spec/requests/authorize_net_cim_spec.rb +506 -0
  92. data/spec/requests/bogus_spec.rb +144 -0
  93. data/spec/requests/ipcommerce_spec.rb +518 -0
  94. data/spec/requests/nmi_customer_vault_spec.rb +390 -0
  95. data/spec/spec_helper.rb +12 -0
  96. data/spec/support/_vaulted_billing.rb +8 -0
  97. data/spec/support/factory_girl.rb +5 -0
  98. data/spec/support/faker.rb +1 -0
  99. data/spec/support/helpers.rb +46 -0
  100. data/spec/support/logging.rb +2 -0
  101. data/spec/support/test_exception.rb +1 -0
  102. data/spec/support/vcr.rb +49 -0
  103. data/spec/support/webmock.rb +7 -0
  104. metadata +312 -37
@@ -0,0 +1,144 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe VaultedBilling::Gateways::Bogus do
4
+ let(:gateway) { VaultedBilling::Gateways::Bogus.new }
5
+ let(:customer) { Factory.build(:customer) }
6
+ let(:credit_card) { Factory.build(:credit_card) }
7
+
8
+ context 'add_customer' do
9
+ subject { gateway.add_customer(customer) }
10
+ it_should_behave_like 'a customer request'
11
+
12
+ it 'is successful' do
13
+ subject.should be_success
14
+ end
15
+ end
16
+
17
+ context 'update_customer' do
18
+ let(:customer) { Factory.build(:existing_customer) }
19
+ subject { gateway.update_customer(customer) }
20
+ it_should_behave_like 'a customer request'
21
+
22
+ it 'is successful' do
23
+ subject.should be_success
24
+ end
25
+ end
26
+
27
+ context 'remove_customer' do
28
+ let(:customer) { Factory.build(:existing_customer) }
29
+ subject { gateway.remove_customer(customer) }
30
+ it_should_behave_like 'a customer request'
31
+
32
+ it 'is successful' do
33
+ subject.should be_success
34
+ end
35
+ end
36
+
37
+ context 'update_customer_credit_card' do
38
+ let(:customer) { Factory.build(:existing_customer) }
39
+ let(:credit_card) { Factory.build(:existing_credit_card) }
40
+ subject { gateway.update_customer_credit_card(customer, credit_card) }
41
+ it_should_behave_like 'a credit card request'
42
+
43
+ it 'is successful' do
44
+ subject.should be_success
45
+ end
46
+ end
47
+
48
+ context 'add_customer_credit_card' do
49
+ subject { gateway.add_customer_credit_card(customer, credit_card) }
50
+ it_should_behave_like 'a credit card request'
51
+
52
+ it 'is successful' do
53
+ subject.should be_success
54
+ end
55
+ end
56
+
57
+ context 'remove_customer_credit_card' do
58
+ let(:customer) { Factory.build(:existing_customer) }
59
+ let(:credit_card) { Factory.build(:existing_credit_card) }
60
+ subject { gateway.remove_customer_credit_card(customer, credit_card) }
61
+ it_should_behave_like 'a credit card request'
62
+
63
+ it 'is successful' do
64
+ subject.should be_success
65
+ end
66
+ end
67
+
68
+ context 'authorize' do
69
+ let(:customer) { Factory.build(:existing_customer) }
70
+ let(:amount) { 1 }
71
+ subject { gateway.authorize(customer, credit_card, amount) }
72
+
73
+ context 'with a non-failure card' do
74
+ let(:credit_card) { Factory.build(:existing_credit_card) }
75
+
76
+ it_should_behave_like 'a transaction request'
77
+ it { should be_success }
78
+ its(:authcode) { should be_present }
79
+ its(:masked_card_number) { should be_present }
80
+ end
81
+
82
+ context 'with a failure card' do
83
+ let(:amount) { 3.00 }
84
+ let(:credit_card) { Factory.build(:failure_credit_card) }
85
+
86
+ it_should_behave_like 'a transaction request'
87
+ it { should_not be_success }
88
+ its(:authcode) { should_not be_present }
89
+ its(:masked_card_number) { should be_present }
90
+ its(:message) { should == 'This transaction has been declined.' }
91
+ its(:response_message) { should == 'This transaction has been declined.' }
92
+ end
93
+ end
94
+
95
+ context 'capture' do
96
+ subject { gateway.capture('transaction_id', 1) }
97
+ it_should_behave_like 'a transaction request'
98
+
99
+ it { should be_success }
100
+ its(:masked_card_number) { should be_present }
101
+ end
102
+
103
+ context 'purchase' do
104
+ let(:customer) { Factory.build(:existing_customer) }
105
+ let(:amount) { 1 }
106
+ subject { gateway.purchase(customer, credit_card, amount) }
107
+
108
+ context 'with a non-failure card' do
109
+ let(:credit_card) { Factory.build(:existing_credit_card) }
110
+
111
+ it_should_behave_like 'a transaction request'
112
+ it { should be_success }
113
+ its(:authcode) { should be_present }
114
+ its(:masked_card_number) { should be_present }
115
+ end
116
+
117
+ context 'with a failure card' do
118
+ let(:amount) { 3.00 }
119
+ let(:credit_card) { Factory.build(:failure_credit_card) }
120
+
121
+ it_should_behave_like 'a transaction request'
122
+ it { should_not be_success }
123
+ its(:authcode) { should_not be_present }
124
+ its(:masked_card_number) { should be_present }
125
+ its(:message) { should == 'This transaction has been declined.' }
126
+ end
127
+ end
128
+
129
+ context 'void' do
130
+ subject { gateway.void('transaction_id') }
131
+ it_should_behave_like 'a transaction request'
132
+
133
+ it { should be_success }
134
+ its(:masked_card_number) { should be_present }
135
+ end
136
+
137
+ context 'refund' do
138
+ subject { gateway.refund('transaction_id', 1) }
139
+ it_should_behave_like 'a transaction request'
140
+
141
+ it { should be_success }
142
+ its(:masked_card_number) { should be_present }
143
+ end
144
+ end
@@ -0,0 +1,518 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe VaultedBilling::Gateways::Ipcommerce do
5
+ let(:gateway) { VaultedBilling.gateway(:ipcommerce).new }
6
+ let(:merchant_profile_id) { 'TicketTest_E4FB800001' }
7
+
8
+ it { should be_a VaultedBilling::Gateway }
9
+
10
+ shared_examples_for 'a no-op' do |expected_return_class|
11
+ it { should be_success }
12
+ it { should be_a expected_return_class }
13
+
14
+ it 'does not make a service request' do
15
+ expect { subject }.
16
+ to_not raise_error(WebMock::NetConnectNotAllowedError)
17
+ end
18
+ end
19
+
20
+ context '#add_customer' do
21
+ let(:customer) { Factory.build(:customer) }
22
+ subject { gateway.add_customer(customer) }
23
+ it_should_behave_like 'a no-op', VaultedBilling::Customer
24
+ end
25
+
26
+ context '#add_customer_credit_card' do
27
+ let(:customer) { Factory.build(:customer) }
28
+ subject { gateway.add_customer_credit_card(customer, credit_card, { :merchant_profile_id => merchant_profile_id }) }
29
+
30
+ context 'when successful' do
31
+ let(:credit_card) { gateway.add_customer_credit_card customer, Factory.build(:ipcommerce_credit_card) }
32
+ use_vcr_cassette 'ipcommerce/add_customer_credit_card/success'
33
+
34
+ it_should_behave_like 'a credit card request'
35
+ it { should be_success }
36
+ end
37
+
38
+ context 'with a failure' do
39
+ let(:credit_card) { Factory.build(:invalid_credit_card) }
40
+ use_vcr_cassette 'ipcommerce/add_customer_credit_card/failure'
41
+
42
+ it { should be_a VaultedBilling::CreditCard }
43
+ it { should_not be_success }
44
+ its(:vault_id) { should be_nil }
45
+ end
46
+ end
47
+
48
+ context '#remove_customer' do
49
+ let(:customer) { gateway.add_customer(Factory.build(:customer)) }
50
+ subject { gateway.remove_customer(customer) }
51
+ it_should_behave_like 'a no-op', VaultedBilling::Customer
52
+ end
53
+
54
+ context '#remove_customer_credit_card' do
55
+ let(:customer) { Factory.build(:customer) }
56
+ let(:credit_card) { Factory.build(:credit_card) }
57
+ subject { gateway.remove_customer_credit_card(customer, credit_card) }
58
+ it_should_behave_like 'a no-op', VaultedBilling::CreditCard
59
+ end
60
+
61
+ context '#update_customer' do
62
+ let(:customer) { gateway.add_customer(Factory.build(:customer)) }
63
+ subject { gateway.update_customer(customer) }
64
+ it_should_behave_like 'a no-op', VaultedBilling::Customer
65
+ end
66
+
67
+ context '#update_customer_credit_card' do
68
+ let(:customer) { Factory.build(:customer) }
69
+ let(:credit_card) { Factory.build(:credit_card) }
70
+ subject { gateway.update_customer_credit_card(customer, credit_card) }
71
+
72
+ let(:customer) { Factory.build(:customer) }
73
+ subject { gateway.add_customer_credit_card(customer, credit_card, { :merchant_profile_id => merchant_profile_id }) }
74
+
75
+ context 'when successful' do
76
+ let(:credit_card) { gateway.add_customer_credit_card customer, Factory.build(:ipcommerce_credit_card) }
77
+ use_vcr_cassette 'ipcommerce/update_customer_credit_card/success'
78
+
79
+ it_should_behave_like 'a credit card request'
80
+ it { should be_success }
81
+ end
82
+
83
+ context 'with a failure' do
84
+ let(:credit_card) { Factory.build(:invalid_credit_card) }
85
+ use_vcr_cassette 'ipcommerce/update_customer_credit_card/failure'
86
+
87
+ it { should be_a VaultedBilling::CreditCard }
88
+ it { should_not be_success }
89
+ its(:vault_id) { should be_nil }
90
+ end
91
+ end
92
+
93
+ context '#authorize' do
94
+ let(:customer) { gateway.add_customer Factory.build(:customer) }
95
+ let(:authorization) { gateway.authorize(customer, credit_card, 11.00, { :merchant_profile_id => merchant_profile_id }) }
96
+ subject { authorization }
97
+
98
+ context 'with a new credit card' do
99
+ context 'when successful' do
100
+ context 'for a general success' do
101
+ use_vcr_cassette 'ipcommerce/authorize/new/success'
102
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card) }
103
+
104
+ it_should_behave_like 'a transaction request'
105
+ it { should be_success }
106
+ its(:id) { should_not be_nil }
107
+ its(:masked_card_number) { should be_present }
108
+ its(:authcode) { should_not be_nil }
109
+ its(:message) { should == "APPROVED" }
110
+ its(:code) { should == 1 }
111
+ end
112
+
113
+ context 'with AVS Responses' do
114
+ context 'with match' do
115
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/match'
116
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :street_address => '1000 1st Av', :postal_code => '10101') }
117
+ it_should_behave_like 'a transaction request'
118
+ it { should be_success }
119
+
120
+ context 'the avs response' do
121
+ subject { OpenStruct.new(authorization.avs_response) }
122
+ its(:result) { should == 'Y' }
123
+ its(:address) { should == 'Match' }
124
+ its(:postal_code) { should == 'Match' }
125
+ end
126
+ end
127
+
128
+ context 'with no match' do
129
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/no_match'
130
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card) }
131
+ it_should_behave_like 'a transaction request'
132
+ it { should be_success }
133
+
134
+ context 'the avs response' do
135
+ subject { OpenStruct.new(authorization.avs_response) }
136
+ its(:result) { should == 'N' }
137
+ its(:address) { should == 'No Match' }
138
+ its(:postal_code) { should == 'No Match' }
139
+ end
140
+ end
141
+
142
+ context 'without AVS sent' do
143
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/not_sent'
144
+ let(:credit_card) { Factory.build(:blank_credit_card, :card_number => '5454545454545454',
145
+ :expires_on => Date.new(2010, 12, 31)) }
146
+ it_should_behave_like 'a transaction request'
147
+ it { should be_success }
148
+ its(:avs_response) { should be_nil }
149
+ end
150
+
151
+ context 'with not included' do
152
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/not_included'
153
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :street_address => nil) }
154
+ it_should_behave_like 'a transaction request'
155
+ it { should be_success }
156
+
157
+ context 'the avs response' do
158
+ subject { OpenStruct.new(authorization.avs_response) }
159
+ its(:result) { should == 'N' }
160
+ its(:address) { should == 'Not Included' }
161
+ its(:postal_code) { should == 'No Match' }
162
+ end
163
+ end
164
+
165
+ context 'with issuer not certified' do
166
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/issuer_not_certified'
167
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :street_address => "2000 2nd Av", :postal_code => '20202') }
168
+ it_should_behave_like 'a transaction request'
169
+ it { should be_success }
170
+
171
+ context 'the avs response' do
172
+ subject { OpenStruct.new(authorization.avs_response) }
173
+ its(:result) { should == 'E' }
174
+ its(:address) { should == 'Issuer Not Certified' }
175
+ its(:postal_code) { should == 'Issuer Not Certified' }
176
+ end
177
+ end
178
+
179
+ context 'with no response from card association' do
180
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/no_response_from_card_association'
181
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :street_address => "3000 3rd Av", :postal_code => '30303') }
182
+ it_should_behave_like 'a transaction request'
183
+ it { should be_success }
184
+
185
+ context 'the avs response' do
186
+ subject { OpenStruct.new(authorization.avs_response) }
187
+ its(:result) { should == 'R' }
188
+ its(:address) { should == 'No Response From Card Association' }
189
+ its(:postal_code) { should == 'No Response From Card Association' }
190
+ end
191
+ end
192
+
193
+ context 'with not verified' do
194
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/not_verified'
195
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :street_address => "4000 4th Av", :postal_code => '40404') }
196
+ it_should_behave_like 'a transaction request'
197
+ it { should be_success }
198
+
199
+ context 'the avs response' do
200
+ subject { OpenStruct.new(authorization.avs_response) }
201
+ its(:result) { should == 'S' }
202
+ its(:address) { should == 'Not Verified' }
203
+ its(:postal_code) { should == 'Not Verified' }
204
+ end
205
+ end
206
+
207
+ context 'with bad format' do
208
+ use_vcr_cassette 'ipcommerce/authorize/new/avs/bad_format'
209
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :street_address => "5000 5th Av", :postal_code => '50505') }
210
+ it_should_behave_like 'a transaction request'
211
+ it { should be_success }
212
+
213
+ context 'the avs response' do
214
+ subject { OpenStruct.new(authorization.avs_response) }
215
+ its(:result) { should == 'F' }
216
+ its(:address) { should == 'Bad Format' }
217
+ its(:postal_code) { should == 'Bad Format' }
218
+ end
219
+ end
220
+ end
221
+
222
+ # The various reasons that a card can be declined. We need to return them all.
223
+ context 'with CVV Responses' do
224
+ context 'with no match' do
225
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/no_match'
226
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '222') }
227
+ it_should_behave_like 'a transaction request'
228
+ it { should be_success }
229
+ its(:cvv_response) { should == "No Match" }
230
+ end
231
+
232
+ context 'with not processed' do
233
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/not_processed'
234
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '333') }
235
+ it_should_behave_like 'a transaction request'
236
+ it { should be_success }
237
+ its(:cvv_response) { should == "Not Processed" }
238
+ end
239
+
240
+ context 'with merchant ind no code present' do
241
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/no_code_present'
242
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '444') }
243
+ it_should_behave_like 'a transaction request'
244
+ it { should be_success }
245
+ its(:cvv_response) { should == "No Code Present" }
246
+ end
247
+
248
+ context 'with should have been present' do
249
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/should_have_been_present'
250
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '555') }
251
+ it_should_behave_like 'a transaction request'
252
+ it { should be_success }
253
+ its(:cvv_response) { should == "Should Have Been Present" }
254
+ end
255
+
256
+ context 'with issuer not certified' do
257
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/issuer_not_certified'
258
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '666') }
259
+ it_should_behave_like 'a transaction request'
260
+ it { should be_success }
261
+ its(:cvv_response) { should == "Issuer Not Certified" }
262
+ end
263
+
264
+ context 'with invalid' do
265
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/invalid'
266
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '777') }
267
+ it_should_behave_like 'a transaction request'
268
+ it { should be_success }
269
+ its(:cvv_response) { should == "Invalid" }
270
+ end
271
+
272
+ context 'with no response from card association' do
273
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/no_response'
274
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '888') }
275
+ it_should_behave_like 'a transaction request'
276
+ it { should be_success }
277
+ its(:cvv_response) { should == "No Response" }
278
+ end
279
+
280
+ context 'with not applicable' do
281
+ use_vcr_cassette 'ipcommerce/authorize/new/cvv/not_applicable'
282
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :cvv_number => '999') }
283
+ it_should_behave_like 'a transaction request'
284
+ it { should be_success }
285
+ its(:cvv_response) { should == "Not Applicable" }
286
+ end
287
+ end
288
+ end
289
+
290
+ context 'with a failure' do
291
+ context 'due to an invalid card number' do
292
+ let(:credit_card) { Factory.build(:invalid_credit_card) }
293
+ use_vcr_cassette 'ipcommerce/authorize/new/failure'
294
+
295
+ it_should_behave_like 'a transaction request'
296
+ it { should_not be_success }
297
+ its(:message) { should_not == "APPROVED" }
298
+ end
299
+ end
300
+ end
301
+
302
+ context 'with a credit card on file' do
303
+ let(:credit_card) { gateway.add_customer_credit_card customer, Factory.build(:ipcommerce_credit_card) }
304
+
305
+ context 'when successful' do
306
+ use_vcr_cassette 'ipcommerce/authorize/existing/success'
307
+ let(:credit_card) { gateway.add_customer_credit_card(customer, Factory.build(:ipcommerce_credit_card, :street_address => '1000 1st Av', :postal_code => '10101'), { :merchant_profile_id => merchant_profile_id }) }
308
+
309
+ it_should_behave_like 'a transaction request'
310
+ it { should be_success }
311
+ its(:id) { should_not be_nil }
312
+ its(:masked_card_number) { should be_present }
313
+ its(:authcode) { should_not be_nil }
314
+ its(:message) { should == "APPROVED" }
315
+ its(:code) { should == 1 }
316
+
317
+ context 'the avs response' do
318
+ subject { OpenStruct.new(authorization.avs_response) }
319
+ its(:result) { should == 'Y' }
320
+ its(:address) { should == 'Match' }
321
+ its(:postal_code) { should == 'Match' }
322
+ end
323
+ end
324
+
325
+ context 'for a card with zero-padded last four digits' do # regression test (bug #4)
326
+ use_vcr_cassette 'ipcommerce/authorize/existing/success'
327
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :card_number => '0000000000000099', :vault_id => 'TESTID') }
328
+
329
+ before do
330
+ tv = credit_card.to_vaulted_billing
331
+ tv.stub(:card_number).and_return('0099')
332
+ credit_card.stub(:to_vaulted_billing).and_return(tv)
333
+ end
334
+
335
+ it 'does not raise an ArgumentError' do
336
+ expect { subject }.not_to raise_error(ArgumentError, /invalid value/i)
337
+ end
338
+ end
339
+
340
+ context 'with a failure' do
341
+ use_vcr_cassette 'ipcommerce/authorize/existing/failure'
342
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :vault_id => "incorrect") }
343
+ it { should be_kind_of(VaultedBilling::Transaction) }
344
+ it { should_not be_success }
345
+ its(:message) { should_not == "APPROVED" }
346
+ end
347
+ end
348
+ end
349
+
350
+ context '#capture' do
351
+ let(:amount) { 11.00 }
352
+ let(:customer) { Factory.build(:customer) }
353
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card) }
354
+ let(:authorization) { gateway.authorize(customer, credit_card, 11.00, { :merchant_profile_id => merchant_profile_id }) }
355
+
356
+ context 'when successful' do
357
+ subject { gateway.capture(authorization.id, amount)}
358
+ use_vcr_cassette 'ipcommerce/capture/success'
359
+
360
+ it_should_behave_like 'a transaction request'
361
+ it { should be_success }
362
+ its(:id) { should_not be_nil }
363
+ its(:authcode) { should be_nil }
364
+ its(:message) { should == "APPROVED" }
365
+ its(:code) { should == 1 }
366
+ end
367
+
368
+ context 'with an invalid request' do
369
+ subject { gateway.capture(authorization.id + "t", amount)}
370
+ use_vcr_cassette 'ipcommerce/capture/invalid'
371
+
372
+ it { should be_a VaultedBilling::Transaction }
373
+ it { should_not be_success }
374
+ its(:message) { should =~ /^Unable to retrieve serialized transaction for transactionId: .+/ }
375
+ end
376
+
377
+ context 'with a failure' do
378
+ subject { gateway.capture(authorization.id, amount * -1)}
379
+ use_vcr_cassette 'ipcommerce/capture/failure'
380
+
381
+ it { should be_a VaultedBilling::Transaction }
382
+ it { should_not be_success }
383
+ its(:message) { should =~ /^Amount must be a minimum of 1 and a maximum of 10 numbers followed by a decimal point and exactly 2 decimal places/mi }
384
+ end
385
+ end
386
+
387
+ context '#purchase' do
388
+ let(:customer) { gateway.add_customer Factory.build(:customer) }
389
+ subject { gateway.purchase(customer, credit_card, 10.00, { :merchant_profile_id => merchant_profile_id }) }
390
+
391
+ context 'with a new credit card' do
392
+ context 'when successful' do
393
+ use_vcr_cassette 'ipcommerce/purchase/new/success'
394
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card) }
395
+
396
+ it_should_behave_like 'a transaction request'
397
+ it { should be_success }
398
+ its(:id) { should_not be_nil }
399
+ its(:authcode) { should_not be_nil }
400
+ its(:message) { should == "APPROVED" }
401
+ its(:code) { should == 1 }
402
+ end
403
+
404
+ context 'with a failure' do
405
+ use_vcr_cassette 'ipcommerce/purchase/new/failure'
406
+ let(:credit_card) { Factory.build(:invalid_credit_card) }
407
+
408
+ it_should_behave_like 'a transaction request'
409
+ it { should_not be_success }
410
+ its(:message) { should_not == "APPROVED" }
411
+ end
412
+ end
413
+
414
+ context 'with a credit card on file' do
415
+ let(:credit_card) { gateway.add_customer_credit_card customer, Factory.build(:ipcommerce_credit_card) }
416
+
417
+ context 'when successful' do
418
+ use_vcr_cassette 'ipcommerce/purchase/existing/success'
419
+ let(:credit_card) { gateway.add_customer_credit_card(customer, Factory.build(:ipcommerce_credit_card), { :merchant_profile_id => merchant_profile_id }) }
420
+
421
+ it_should_behave_like 'a transaction request'
422
+ it { should be_success }
423
+ its(:id) { should_not be_nil }
424
+ its(:masked_card_number) { should be_present }
425
+ its(:authcode) { should_not be_nil }
426
+ its(:message) { should == "APPROVED" }
427
+ its(:code) { should == 1 }
428
+ end
429
+
430
+ context 'with a failure' do
431
+ use_vcr_cassette 'ipcommerce/purchase/existing/failure'
432
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card, :vault_id => "incorrect") }
433
+ it { should be_kind_of(VaultedBilling::Transaction) }
434
+ it { should_not be_success }
435
+ its(:message) { should_not == "APPROVED" }
436
+ end
437
+ end
438
+
439
+ end
440
+
441
+ # Returning funds from a captured transaction
442
+ context '#refund' do
443
+ let(:amount) { 5.00 }
444
+ let(:customer) { Factory.build(:customer) }
445
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card) }
446
+ let(:purchase) { gateway.purchase(customer, credit_card, amount, { :merchant_profile_id => merchant_profile_id }) }
447
+
448
+ context 'with a successful result' do
449
+ subject { gateway.refund(purchase.id, amount) }
450
+ use_vcr_cassette 'ipcommerce/refund/success'
451
+
452
+ it_should_behave_like 'a transaction request'
453
+ it { should be_success }
454
+ its(:id) { should_not be_nil }
455
+ its(:authcode) { should_not be_nil }
456
+ its(:message) { should == "APPROVED" }
457
+ its(:code) { should == 1 }
458
+ end
459
+
460
+ context 'with a failure' do
461
+ subject { gateway.refund(purchase.id, amount + 1) }
462
+ use_vcr_cassette 'ipcommerce/refund/failure'
463
+
464
+ it { should be_a VaultedBilling::Transaction }
465
+ it { should_not be_success }
466
+ its(:message) { should == "Attempt to return more than original authorization." }
467
+ its(:code) { should eql '326' }
468
+ end
469
+ end
470
+
471
+ # Releasing funds from an authorized but uncaptured transaction
472
+ context '#void' do
473
+ let(:customer) { gateway.add_customer(Factory.build(:customer)) }
474
+ let(:credit_card) { Factory.build(:ipcommerce_credit_card) }
475
+ let(:authorization) { gateway.authorize(customer, credit_card, 5.00, { :merchant_profile_id => merchant_profile_id }) }
476
+
477
+ context 'with a successful result' do
478
+ subject { gateway.void(authorization.id, { :merchant_profile_id => merchant_profile_id, :credit_card => credit_card }) }
479
+ use_vcr_cassette 'ipcommerce/void/success'
480
+
481
+ it_should_behave_like 'a transaction request'
482
+ it { should be_success }
483
+ its(:id) { should_not be_nil }
484
+ its(:authcode) { should_not be_nil }
485
+ its(:message) { should == "APPROVED" }
486
+ its(:code) { should == 1 }
487
+ end
488
+
489
+ context 'with a failure' do
490
+ subject { gateway.void(authorization.id + "_bad", { :merchant_profile_id => merchant_profile_id, :credit_card => credit_card }) }
491
+ use_vcr_cassette 'ipcommerce/void/failure'
492
+
493
+ it { should be_a VaultedBilling::Transaction }
494
+ it { should_not be_success }
495
+ its(:message) { should =~ /^Unable to retrieve serialized transaction for transactionId: .+/ }
496
+ end
497
+ end
498
+
499
+ it 'fails over to secondary end point with a connection error on the first' do
500
+ VCR.use_cassette('ipcommerce/failover') do
501
+ WebMock.stub_request(:any, %r{^https://.*?@cws-01\.cert\.ipcommerce\.com/}).to_timeout
502
+ customer = Factory.build(:customer)
503
+ credit_card = Factory.build(:ipcommerce_credit_card)
504
+ result = gateway.authorize(customer, credit_card, 11.00, { :merchant_profile_id => merchant_profile_id })
505
+ result.should be_success
506
+ end
507
+ WebMock.should have_requested(:get, %r{^https://.*?@cws-02\.cert\.ipcommerce\.com/})
508
+ end
509
+
510
+ it 'raises an UnavailableKeyError when a session key cannot be acquired' do
511
+ WebMock.stub_request(:any, /.*/).to_timeout
512
+ expect {
513
+ customer = gateway.add_customer Factory.build(:customer)
514
+ credit_card = gateway.add_customer_credit_card customer, Factory.build(:ipcommerce_credit_card)
515
+ result = gateway.authorize(customer, credit_card, 11.00, { :merchant_profile_id => merchant_profile_id })
516
+ }.to raise_error(VaultedBilling::Gateways::Ipcommerce::ServiceKeyStore::UnavailableKeyError)
517
+ end
518
+ end