nmi_direct_post 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.simplecov +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/lib/nmi_direct_post.rb +7 -0
- data/lib/nmi_direct_post/base.rb +102 -0
- data/lib/nmi_direct_post/customer_vault.rb +245 -0
- data/lib/nmi_direct_post/logger.rb +17 -0
- data/lib/nmi_direct_post/transaction.rb +168 -0
- data/lib/nmi_direct_post/version.rb +3 -0
- data/nmi_direct_post.gemspec +30 -0
- data/spec/base_spec.rb +37 -0
- data/spec/customer_vault_spec.rb +243 -0
- data/spec/logger_spec.rb +77 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/credentials.rb.example +13 -0
- data/spec/support/test_credentials.rb +11 -0
- data/spec/transaction_spec.rb +303 -0
- metadata +217 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
module NmiDirectPost
|
4
|
+
class << self
|
5
|
+
def logger
|
6
|
+
@logger ||= defined?(::Rails.logger) ? Rails.logger : ::Logger.new(STDOUT)
|
7
|
+
end
|
8
|
+
def logger=(_)
|
9
|
+
raise ArgumentError, "NmiDirectPost logger must respond to :info and :debug" unless logger_responds(_)
|
10
|
+
@logger = _
|
11
|
+
end
|
12
|
+
private
|
13
|
+
def logger_responds(logger)
|
14
|
+
logger.respond_to?(:info) && logger.respond_to?(:debug)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require_relative 'customer_vault'
|
3
|
+
|
4
|
+
module NmiDirectPost
|
5
|
+
class TransactionNotFoundError < StandardError; end
|
6
|
+
|
7
|
+
class TransactionNotSavedError < StandardError; end
|
8
|
+
|
9
|
+
class Transaction < Base
|
10
|
+
SAFE_PARAMS = [:customer_vault_id, :type, :amount]
|
11
|
+
|
12
|
+
attr_reader *SAFE_PARAMS
|
13
|
+
attr_reader :auth_code, :avs_response, :cvv_response, :order_id, :type, :dup_seconds, :condition
|
14
|
+
attr_reader :transaction_id
|
15
|
+
|
16
|
+
validates_presence_of :customer_vault_id, :amount, :unless => :'finding_by_transaction_id?', :message => "%{attribute} cannot be blank"
|
17
|
+
validates_presence_of :customer_vault, :unless => 'customer_vault_id.blank?', :message => "%{attribute} with the given customer_vault could not be found"
|
18
|
+
validates_inclusion_of :type, :in => ["sale", "auth", "capture", "void", "refund", "credit", "validate", "update", ""]
|
19
|
+
validates_exclusion_of :type, :in => ["validate", "auth", "capture", "void"], :if => :'customer_vault_is_checking?', :message => "%{value} is not a valid action for a customer vault that uses a checking account"
|
20
|
+
validates_numericality_of :amount, :equal_to => 0, :if => :'is_validate?', :message => "%{attribute} must be 0 when validating a credit card"
|
21
|
+
validates_numericality_of :amount, :greater_than => 0, :if => :'is_sale?', :message => "%{attribute} cannot be 0 for a sale"
|
22
|
+
validates_numericality_of :amount, :greater_than => 0, :if => :'is_auth?', :message => "%{attribute} cannot be 0 for an authorization"
|
23
|
+
validate :voidable_transaction?, :if => :is_void?
|
24
|
+
validate :persisted?, :if => :is_void?
|
25
|
+
validate :save_successful?, :unless => 'response_text.blank?'
|
26
|
+
|
27
|
+
def initialize(attributes)
|
28
|
+
super()
|
29
|
+
@type, @amount = attributes[:type].to_s, attributes[:amount].to_f
|
30
|
+
@transaction_id = attributes[:transaction_id].to_i if attributes[:transaction_id]
|
31
|
+
@customer_vault_id = attributes[:customer_vault_id].to_i if attributes[:customer_vault_id]
|
32
|
+
reload if (finding_by_transaction_id? && self.valid?)
|
33
|
+
@type, @amount = attributes[:type].to_s, attributes[:amount].to_f if ['void', 'capture'].include?(attributes[:type].to_s)
|
34
|
+
end
|
35
|
+
|
36
|
+
def save
|
37
|
+
void! if ('void' == type && condition.blank?)
|
38
|
+
return false if self.invalid?
|
39
|
+
_safe_params = safe_params
|
40
|
+
logger.info { "Sending Direct Post Transaction to NMI: #{_safe_params}" }
|
41
|
+
post([_safe_params, transaction_params].join('&'))
|
42
|
+
valid?.tap { |_| reload if _ }
|
43
|
+
end
|
44
|
+
|
45
|
+
def save!
|
46
|
+
save || raise(TransactionNotSavedError)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.find_by_transaction_id(transaction_id)
|
50
|
+
raise StandardError, "TransactionID cannot be blank" if transaction_id.blank?
|
51
|
+
NmiDirectPost.logger.debug { "Looking up NMI transaction by transaction_id(#{transaction_id})" }
|
52
|
+
begin
|
53
|
+
new(:transaction_id => transaction_id)
|
54
|
+
rescue TransactionNotFoundError
|
55
|
+
return nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def pending?
|
60
|
+
'pendingsettlement' == condition
|
61
|
+
end
|
62
|
+
|
63
|
+
def cleared?
|
64
|
+
"complete" == condition
|
65
|
+
end
|
66
|
+
|
67
|
+
def failed?
|
68
|
+
"failed" == condition
|
69
|
+
end
|
70
|
+
|
71
|
+
def declined?
|
72
|
+
2 == response
|
73
|
+
end
|
74
|
+
|
75
|
+
def void!
|
76
|
+
@type='void'
|
77
|
+
if condition.blank?
|
78
|
+
return false if invalid?
|
79
|
+
reload
|
80
|
+
@type = 'void'
|
81
|
+
end
|
82
|
+
save
|
83
|
+
end
|
84
|
+
|
85
|
+
def customer_vault
|
86
|
+
@customer_vault ||= CustomerVault.find_by_customer_vault_id(@customer_vault_id) unless @customer_vault_id.blank?
|
87
|
+
end
|
88
|
+
|
89
|
+
def reload
|
90
|
+
get(transaction_params) if finding_by_transaction_id?
|
91
|
+
self
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
def safe_params
|
96
|
+
generate_query_string(SAFE_PARAMS)
|
97
|
+
end
|
98
|
+
|
99
|
+
def transaction_params
|
100
|
+
generate_query_string([AUTH_PARAMS, :transaction_id].flatten)
|
101
|
+
end
|
102
|
+
|
103
|
+
def get(query)
|
104
|
+
hash = self.class.get(query)["transaction"]
|
105
|
+
hash = hash.keep_if { |v| v['transaction_id'].to_s == self.transaction_id.to_s }.first if hash.is_a?(Array)
|
106
|
+
raise TransactionNotFoundError, "No transaction found for TransactionID #{@transaction_id}" if hash.nil?
|
107
|
+
@auth_code = hash["authorization_code"]
|
108
|
+
@customer_vault_id = hash["customerid"].to_i
|
109
|
+
@avs_response = hash["avs_response"]
|
110
|
+
@condition = hash["condition"]
|
111
|
+
action = hash["action"]
|
112
|
+
action = action.last unless action.is_a?(Hash)
|
113
|
+
@amount = action["amount"].to_f
|
114
|
+
@type = action["action_type"]
|
115
|
+
@response = action["success"].to_i if action.key?("success")
|
116
|
+
@response_code = action["response_code"].to_i if action.key?("response_code")
|
117
|
+
@response_text = action["response_text"]
|
118
|
+
end
|
119
|
+
|
120
|
+
def post(query)
|
121
|
+
response = self.class.post(query)
|
122
|
+
@response = response["response"].to_i if response.key?("response")
|
123
|
+
@response_code = response["response_code"].to_i if response.key?("response_code")
|
124
|
+
@response_text, @avs_response, @cvv_response = response["responsetext"], response["avsresponse"], response["cvvresponse"]
|
125
|
+
@dup_seconds, @order_id, @auth_code = response["dup_seconds"], response["orderid"], response["authcode"]
|
126
|
+
@transaction_id = response["transactionid"]
|
127
|
+
end
|
128
|
+
|
129
|
+
def customer_vault_is_checking?
|
130
|
+
!customer_vault.blank? && customer_vault.checking?
|
131
|
+
end
|
132
|
+
|
133
|
+
def finding_by_transaction_id?
|
134
|
+
!transaction_id.blank?
|
135
|
+
end
|
136
|
+
|
137
|
+
def is_validate?
|
138
|
+
!finding_by_transaction_id? && ('validate' == type.to_s)
|
139
|
+
end
|
140
|
+
|
141
|
+
def is_sale?
|
142
|
+
!finding_by_transaction_id? && (['sale', ''].include?(type.to_s))
|
143
|
+
end
|
144
|
+
|
145
|
+
def is_auth?
|
146
|
+
!finding_by_transaction_id? && ('auth' == type.to_s)
|
147
|
+
end
|
148
|
+
|
149
|
+
def is_void?
|
150
|
+
!customer_vault_is_checking? && ('void' == type.to_s)
|
151
|
+
end
|
152
|
+
|
153
|
+
def save_successful?
|
154
|
+
return if (success? || declined?)
|
155
|
+
self.errors.add(:response, response.to_s)
|
156
|
+
self.errors.add(:response_code, response_code.to_s)
|
157
|
+
self.errors.add(:response_text, response_text)
|
158
|
+
end
|
159
|
+
|
160
|
+
def voidable_transaction?
|
161
|
+
self.errors.add(:type, "Void is only a valid action for a pending or unsettled authorization, or an unsettled sale") if (finding_by_transaction_id? && !['pending', 'pendingsettlement'].include?(condition)) unless condition.blank?
|
162
|
+
end
|
163
|
+
|
164
|
+
def persisted?
|
165
|
+
self.errors.add(:type, "Void is only a valid action for a transaction that has already been sent to NMI") unless finding_by_transaction_id?
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'nmi_direct_post/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "nmi_direct_post"
|
8
|
+
spec.version = NmiDirectPost::VERSION
|
9
|
+
spec.authors = ["Isaac Betesh"]
|
10
|
+
spec.email = ["iybetesh@gmail.com"]
|
11
|
+
spec.description = %q{Gem that encapsulates the NMI Direct Post API in an ActiveRecord-like syntax}
|
12
|
+
spec.summary = `cat README.md`
|
13
|
+
spec.homepage = "https://github.com/betesh/nmi_direct_post"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", ">= 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "rspec-rails"
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
|
+
|
27
|
+
spec.add_dependency 'addressable'
|
28
|
+
spec.add_dependency 'activemodel'
|
29
|
+
spec.add_dependency 'activesupport', ' >= 3.0'
|
30
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe NmiDirectPost::Base do
|
4
|
+
def a_query
|
5
|
+
NmiDirectPost::CustomerVault.find_by_customer_vault_id(a_cc_customer_vault_id)
|
6
|
+
end
|
7
|
+
before(:each) do
|
8
|
+
NmiDirectPost::Base.establish_connection(nil, nil)
|
9
|
+
NmiDirectPost::CustomerVault.establish_connection(nil, nil)
|
10
|
+
end
|
11
|
+
let(:credentials) { TestCredentials::INSTANCE }
|
12
|
+
let(:a_cc_customer_vault_id) { credentials.cc_customer }
|
13
|
+
it "should raise exception when username is an empty string" do
|
14
|
+
NmiDirectPost::Base.establish_connection('', credentials.nmi_password)
|
15
|
+
expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
|
16
|
+
end
|
17
|
+
it "should raise exception when password is an empty string" do
|
18
|
+
NmiDirectPost::Base.establish_connection(credentials.nmi_username, nil)
|
19
|
+
expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
|
20
|
+
end
|
21
|
+
it "should raise exception when username is nil" do
|
22
|
+
NmiDirectPost::Base.establish_connection('', credentials.nmi_password)
|
23
|
+
expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
|
24
|
+
end
|
25
|
+
it "should raise exception when password is nil" do
|
26
|
+
NmiDirectPost::Base.establish_connection(credentials.nmi_username, nil)
|
27
|
+
expect{a_query}.to raise_error(StandardError, "Please set a username by calling NmiDirectPost::Base.establish_connection(ENV['NMI_USERNAME'], ENV['NMI_PASSWORD'])")
|
28
|
+
end
|
29
|
+
it "should find parent connection" do
|
30
|
+
NmiDirectPost::Base.establish_connection(credentials.nmi_username, credentials.nmi_password)
|
31
|
+
expect{a_query}.to_not raise_error
|
32
|
+
end
|
33
|
+
it "should find parent connection" do
|
34
|
+
NmiDirectPost::CustomerVault.establish_connection(credentials.nmi_username, credentials.nmi_password)
|
35
|
+
expect{a_query}.to_not raise_error
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe NmiDirectPost::CustomerVault do
|
4
|
+
def get_new_email
|
5
|
+
"someone#{Random.rand(1..1000)}@example.com"
|
6
|
+
end
|
7
|
+
|
8
|
+
CV = NmiDirectPost::CustomerVault
|
9
|
+
let(:a_cc_customer_vault_id) { TestCredentials::INSTANCE.cc_customer }
|
10
|
+
let(:a_cc_customer) { CV.find_by_customer_vault_id(a_cc_customer_vault_id) }
|
11
|
+
let(:a_checking_account_customer_vault_id) { TestCredentials::INSTANCE.ach_customer }
|
12
|
+
let(:a_checking_account_customer) { CV.find_by_customer_vault_id(a_checking_account_customer_vault_id) }
|
13
|
+
|
14
|
+
before :all do
|
15
|
+
credentials = TestCredentials::INSTANCE
|
16
|
+
NmiDirectPost::Base.establish_connection(credentials.nmi_username, credentials.nmi_password)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "find_by_customer_vault_id" do
|
20
|
+
it "should find a customer vault" do
|
21
|
+
expect(a_cc_customer.customer_vault_id).to eq(a_cc_customer_vault_id)
|
22
|
+
expect(a_cc_customer.first_name).not_to be_nil
|
23
|
+
expect(a_cc_customer.last_name).not_to be_nil
|
24
|
+
expect(a_cc_customer.email).not_to be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should raise exception when customer_vault_id is blank" do
|
28
|
+
expect{CV.find_by_customer_vault_id("")}.to raise_error(StandardError, "CustomerVaultID cannot be blank")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return exception when no customer is found" do
|
32
|
+
expect(CV.find_by_customer_vault_id("123456")).to be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "create" do
|
37
|
+
it "should not create a customer vault when no payment info is specified" do
|
38
|
+
new_email = get_new_email
|
39
|
+
@customer = CV.new(:first_name => "George", :last_name => "Washington")
|
40
|
+
expect(@customer.create).to eq(false)
|
41
|
+
expect(@customer.errors.full_messages).to eq(["Billing information Either :cc_number (a credit card number) and :cc_exp (the credit card expiration date), or :check_account, :check_aba (the routing number of the checking account) and :check_name (a nickname for the account), must be present"])
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not create a customer vault when a customer valut id is already present" do
|
45
|
+
new_email = get_new_email
|
46
|
+
@customer = CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :customer_vault_id => a_cc_customer_vault_id)
|
47
|
+
expect(@customer.create).to eq(false)
|
48
|
+
expect(@customer.errors.full_messages).to eq(["Customer vault You cannot specify a Customer vault ID when creating a new customer vault. NMI will assign one upon creating the record"])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should create a customer vault with an automatically assigned customer_vault_id when a credit card number and expiration date are specified" do
|
52
|
+
new_email = get_new_email
|
53
|
+
@customer = CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16")
|
54
|
+
expect(@customer.create).to eq(true)
|
55
|
+
expect(@customer.destroy).to be_success
|
56
|
+
expect(@customer.cc_exp).to eq("06/16")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should create a customer vault with an automatically assigned customer_vault_id when a checking account number and routing number are specified" do
|
60
|
+
new_email = get_new_email
|
61
|
+
@customer = CV.new(:first_name => "George", :last_name => "Washington", :check_aba => "123123123", :check_account => "123123123", :check_name => "my checking account")
|
62
|
+
expect(@customer.create).to eq(true)
|
63
|
+
expect(@customer.destroy).to be_success
|
64
|
+
end
|
65
|
+
|
66
|
+
[[:cc_number, :check_name], [:cc_number, :check_account], [:cc_number, :check_aba], [:cc_exp, :check_name], [:cc_exp, :check_account], [:cc_exp, :check_aba]].each do |attrs|
|
67
|
+
attributes = {:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :check_aba => "123123123", :check_account => "123123123", :check_name => "my checking account"}
|
68
|
+
attributes.delete(attrs.first)
|
69
|
+
attributes.delete(attrs.last)
|
70
|
+
it "should not create a customer vault when missing #{attrs.first} and #{attrs.last}" do
|
71
|
+
new_email = get_new_email
|
72
|
+
@customer = CV.new(attributes)
|
73
|
+
expect(@customer.create).to eq(false)
|
74
|
+
expect(@customer.errors.full_messages).to eq(["Billing information Either :cc_number (a credit card number) and :cc_exp (the credit card expiration date), or :check_account, :check_aba (the routing number of the checking account) and :check_name (a nickname for the account), must be present"])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "save" do
|
80
|
+
it "should update the customer vault with new shipping_email when shipping_email is set before calling save!" do
|
81
|
+
new_email = get_new_email
|
82
|
+
a_cc_customer.shipping_email = new_email
|
83
|
+
a_cc_customer.save!
|
84
|
+
expect(a_cc_customer.response_text).to eq("Customer Update Successful")
|
85
|
+
expect(a_cc_customer).to be_success
|
86
|
+
expect(a_cc_customer.shipping_email).to eq(new_email)
|
87
|
+
expect(a_cc_customer.reload.shipping_email).to eq(new_email)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "update" do
|
92
|
+
it "should update the customer vault with new merchant_defined_fields" do
|
93
|
+
new_field_1 = Random.rand(1..1000)
|
94
|
+
new_field_2 = Random.rand(1..1000)
|
95
|
+
a_cc_customer.update!(:merchant_defined_field_1 => new_field_1, :merchant_defined_field_2 => new_field_2)
|
96
|
+
expect(a_cc_customer.response_text).to eq("Customer Update Successful")
|
97
|
+
expect(a_cc_customer).to be_success
|
98
|
+
a_cc_customer.reload
|
99
|
+
expect(a_cc_customer.merchant_defined_field_1).to eq(new_field_1.to_s)
|
100
|
+
expect(a_cc_customer.merchant_defined_field_2).to eq(new_field_2.to_s)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should update the customer vault with new shipping_email when shipping_email is passed to update!" do
|
104
|
+
new_email = get_new_email
|
105
|
+
a_cc_customer.update!(:shipping_email => new_email)
|
106
|
+
expect(a_cc_customer.response_text).to eq("Customer Update Successful")
|
107
|
+
expect(a_cc_customer).to be_success
|
108
|
+
expect(a_cc_customer.shipping_email).to eq(new_email)
|
109
|
+
expect(a_cc_customer.reload.shipping_email).to eq(new_email)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should not update the customer vault with new shipping_email when shipping_email is set before calling update!" do
|
113
|
+
new_email = get_new_email
|
114
|
+
new_address = "#{Random.rand(1..1000)} Sesame Street"
|
115
|
+
old_email = a_cc_customer.shipping_email
|
116
|
+
a_cc_customer.shipping_email = new_email
|
117
|
+
a_cc_customer.update!(:shipping_address_1 => new_address)
|
118
|
+
expect(a_cc_customer.response_text).to eq("Customer Update Successful")
|
119
|
+
expect(a_cc_customer).to be_success
|
120
|
+
expect(a_cc_customer.shipping_email).to eq(new_email)
|
121
|
+
expect(a_cc_customer.reload.shipping_email).to eq(old_email)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should not allow updating the customer_vault_id" do
|
125
|
+
new_email = get_new_email
|
126
|
+
expect{a_cc_customer.update!(:customer_vault_id => '')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, "Cannot mass-assign the following attributes: customer_vault_id")
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should not interfere with other set variables" do
|
130
|
+
new_email = get_new_email
|
131
|
+
new_address = "#{Random.rand(1..1000)} Sesame Street"
|
132
|
+
old_email = a_cc_customer.shipping_email
|
133
|
+
a_cc_customer.shipping_email = new_email
|
134
|
+
a_cc_customer.update!(:shipping_address_1 => new_address)
|
135
|
+
expect(a_cc_customer.response_text).to eq("Customer Update Successful")
|
136
|
+
expect(a_cc_customer).to be_success
|
137
|
+
expect(a_cc_customer.shipping_email).to eq(new_email)
|
138
|
+
a_cc_customer.save!
|
139
|
+
expect(a_cc_customer.reload.shipping_email).to eq(new_email)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "reload" do
|
144
|
+
it "should not reload if customer vault id is missing" do
|
145
|
+
@customer = CV.new({})
|
146
|
+
expect(@customer.customer_vault_id).to be_nil
|
147
|
+
@customer.reload
|
148
|
+
expect(@customer).not_to be_success
|
149
|
+
expect(@customer.response).to be_nil
|
150
|
+
expect(@customer.errors.full_messages).to eq(["Customer vault You must specify a Customer vault ID when looking up an individual customer vault"])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "first/last/all" do
|
155
|
+
before(:all) do
|
156
|
+
@all_ids = CV.all_ids
|
157
|
+
end
|
158
|
+
it "should get all ids" do
|
159
|
+
expect(@all_ids).to be_a(Array)
|
160
|
+
expect(@all_ids).to eq(@all_ids.uniq)
|
161
|
+
@all_ids.each do |id|
|
162
|
+
expect(id).to be_a(Fixnum)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should get the first customer vault" do
|
167
|
+
expected = CV.find_by_customer_vault_id(@all_ids.first)
|
168
|
+
first = CV.first
|
169
|
+
expect(first).to be_a(CV)
|
170
|
+
expect(first).to have_same_attributes_as(expected)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should get the last customer vault" do
|
174
|
+
expected = CV.find_by_customer_vault_id(@all_ids.last)
|
175
|
+
last = CV.last
|
176
|
+
expect(last).to be_a(CV)
|
177
|
+
expect(last).to have_same_attributes_as(expected)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should get all customer vaults" do
|
181
|
+
customers = CV.all
|
182
|
+
expect(customers.count).to eq(@all_ids.count)
|
183
|
+
customers.each do |customer|
|
184
|
+
expect(customer).to be_a(CV)
|
185
|
+
expect(customer.customer_vault_id).not_to be_nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "cc_hash" do
|
191
|
+
it "should not be settable" do
|
192
|
+
expect(a_cc_customer.respond_to?('cc_hash=')).to eq(false)
|
193
|
+
end
|
194
|
+
it "should be a string on a CC customer" do
|
195
|
+
expect(a_cc_customer.cc_hash).to be_a(String)
|
196
|
+
end
|
197
|
+
it "should be nil on a checking customer" do
|
198
|
+
expect(a_checking_account_customer.cc_hash).to be_nil
|
199
|
+
end
|
200
|
+
it "should not be allowed in a mass assignment update" do
|
201
|
+
expect{a_cc_customer.update!(:cc_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: cc_hash')
|
202
|
+
end
|
203
|
+
it "should not be allowed when initialized" do
|
204
|
+
expect{CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :cc_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: cc_hash')
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "check_hash" do
|
209
|
+
it "should not be settable" do
|
210
|
+
expect(a_cc_customer.respond_to?('check_hash=')).to eq(false)
|
211
|
+
end
|
212
|
+
it "should be a string on a CC customer" do
|
213
|
+
expect(a_checking_account_customer.check_hash).to be_a(String)
|
214
|
+
end
|
215
|
+
it "should be nil on a checking customer" do
|
216
|
+
expect(a_cc_customer.check_hash).to be_nil
|
217
|
+
end
|
218
|
+
it "should not be allowed in a mass assignment update" do
|
219
|
+
expect{a_cc_customer.update!(:check_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: check_hash')
|
220
|
+
end
|
221
|
+
it "should not be allowed when initialized" do
|
222
|
+
expect{CV.new(:first_name => "George", :last_name => "Washington", :cc_number => "4111111111111111", :cc_exp => "06/16", :check_hash => 'abcdefg')}.to raise_error(NmiDirectPost::MassAssignmentSecurity::Error, 'Cannot mass-assign the following attributes: check_hash')
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "checking?" do
|
227
|
+
it "should be true for a checking account customer" do
|
228
|
+
expect(a_checking_account_customer).to be_checking
|
229
|
+
end
|
230
|
+
it "should be false for a CC customer" do
|
231
|
+
expect(a_cc_customer).not_to be_checking
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "credit_card?" do
|
236
|
+
it "should be true for a CC customer" do
|
237
|
+
expect(a_cc_customer).to be_credit_card
|
238
|
+
end
|
239
|
+
it "should be false for a checking account customer" do
|
240
|
+
expect(a_checking_account_customer).not_to be_credit_card
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|