nmi_direct_post 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +9 -3
- data/lib/nmi_direct_post/base.rb +4 -3
- data/lib/nmi_direct_post/customer_vault.rb +8 -8
- data/lib/nmi_direct_post/transaction.rb +8 -8
- data/lib/nmi_direct_post/version.rb +1 -1
- data/nmi_direct_post.gemspec +1 -2
- data/spec/base_spec.rb +4 -0
- data/spec/transaction_spec.rb +167 -180
- metadata +26 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a7f96e99aff57d1745c1e1b1cd90619eca8d45b
|
4
|
+
data.tar.gz: 7b5faf05b492e67293278a702f1f8832e1ba617a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5584f91061e4ebf5d372a96efc7f2ca061134fc79b9e5c6c130e9220573c7bd978416e88f769038fbab0f7f391cea24cea9e0bf752d49032b9f0a3a4c2f6701
|
7
|
+
data.tar.gz: b5c1bb5556057f1df9acae2bf22b2b1ed462275e81c52ea811150cc365e1425b0f650746b7a35a044624e14071f0439add3b0a406184bba4455996ddec6d7084
|
data/README.md
CHANGED
@@ -22,17 +22,21 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
1) Before you
|
25
|
+
1) Before you query or post, you probably want to set a default username and password:
|
26
26
|
|
27
27
|
NmiDirectPost::Base.establish_connection("MY_NMI_USERNAME", "MY_NMI_PASSWORD")
|
28
28
|
|
29
|
+
If you don't set a default, you'll need to include the username and password in the hash passed to the initializer when instantiating a new Transaction or CustomerVault.
|
30
|
+
|
29
31
|
Theoretically, you can use a different connection for NmiDirectPost::Transaction or NmiDirectPost::CustomerVault by calling establish_connection on either of those derived classes, instead of on Base.
|
30
32
|
However, it's hard to imagine a case where this would be useful; the option is only present to mimic the syntax of ActiveRecord.
|
31
33
|
|
32
34
|
2) Query the API:
|
33
35
|
|
34
|
-
NmiDirectPost::Transaction.find_by_transaction_id(123456789)
|
35
|
-
NmiDirectPost::
|
36
|
+
NmiDirectPost::Transaction.find_by_transaction_id(123456789, "MyUsername", "MyPassword")
|
37
|
+
NmiDirectPost::Transaction.find_by_transaction_id(123456789) # If you've already called establish_connection
|
38
|
+
|
39
|
+
NmiDirectPost::CustomerVault.find_by_customer_vault_id(123123123) # Note that there is no way to pass a username and password to this method. You must call establish_connection beforehand.
|
36
40
|
|
37
41
|
3) Create a CustomerVault:
|
38
42
|
|
@@ -69,6 +73,8 @@ However, it's hard to imagine a case where this would be useful; the option is o
|
|
69
73
|
NmiDirectPost::CustomerVault.last
|
70
74
|
NmiDirectPost::CustomerVault.all # Returns very, very big array. This method had very poor performance and could be optimized significantly in a future version of this gem.
|
71
75
|
|
76
|
+
Note that there is no way to pass a username and password to these methods. You must call establish_connection beforehand.
|
77
|
+
|
72
78
|
8) Create a Transaction:
|
73
79
|
|
74
80
|
parking_ticket = NmiDirectPost::Transaction(:type => :sale, :amount => 150.01, :customer_vault_id => george.customer_vault_id)
|
data/lib/nmi_direct_post/base.rb
CHANGED
@@ -28,8 +28,9 @@ module NmiDirectPost
|
|
28
28
|
include ActiveModel::Conversion
|
29
29
|
validates_presence_of :username, :password
|
30
30
|
|
31
|
-
def initialize
|
32
|
-
@username
|
31
|
+
def initialize(attributes)
|
32
|
+
@username = attributes[:username] || attributes["username"] || self.class.username
|
33
|
+
@password = attributes[:password] || attributes["password"] || self.class.password
|
33
34
|
end
|
34
35
|
|
35
36
|
def persisted?
|
@@ -80,7 +81,7 @@ module NmiDirectPost
|
|
80
81
|
url = URI.parse(uri)
|
81
82
|
http = Net::HTTP.new(url.host, url.port)
|
82
83
|
http.use_ssl = true
|
83
|
-
http.ssl_version = :
|
84
|
+
http.ssl_version = :TLSv1_2
|
84
85
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
85
86
|
http.request(request)
|
86
87
|
end
|
@@ -39,7 +39,7 @@ module NmiDirectPost
|
|
39
39
|
:if => Proc.new { |record| :add_customer == record.customer_vault }
|
40
40
|
|
41
41
|
def initialize(attributes)
|
42
|
-
super
|
42
|
+
super
|
43
43
|
if attributes[:customer_vault_id].blank?
|
44
44
|
set_attributes(attributes.dup) unless attributes.empty?
|
45
45
|
else
|
@@ -84,7 +84,7 @@ module NmiDirectPost
|
|
84
84
|
begin
|
85
85
|
safe_params = customer_vault_instance_params
|
86
86
|
logger.debug { "Loading NMI customer vault from customer_vault_id(#{customer_vault_id}) using query: #{safe_params}" }
|
87
|
-
response = self.class.get(self.class.all_params(safe_params))["customer_vault"]
|
87
|
+
response = self.class.get(self.class.all_params(safe_params, self))["customer_vault"]
|
88
88
|
raise CustomerVaultNotFoundError, "No record found for customer vault ID #{self.customer_vault_id}" if response.nil?
|
89
89
|
attributes = response["customer"].with_indifferent_access
|
90
90
|
READ_ONLY_ATTRIBUTES.each do |a|
|
@@ -115,7 +115,7 @@ module NmiDirectPost
|
|
115
115
|
@report_type = :customer_vault
|
116
116
|
safe_params = generate_query_string(MERCHANT_DEFINED_FIELDS + [:last_name, :email, :report_type]) # These are the only fields you can use when looking up without a customer_vault_id
|
117
117
|
logger.info { "Querying NMI customer vault: #{safe_params}" }
|
118
|
-
@customer_vault_id = self.class.get(self.class.all_params(safe_params))['customer_vault'][0]['customer_vault_id'] # This assumes there is only 1 result.
|
118
|
+
@customer_vault_id = self.class.get(self.class.all_params(safe_params, self))['customer_vault'][0]['customer_vault_id'] # This assumes there is only 1 result.
|
119
119
|
# TODO: When there are multiple results, we don't know which one you want. Maybe raise an error in that case?
|
120
120
|
reload
|
121
121
|
ensure
|
@@ -126,10 +126,10 @@ module NmiDirectPost
|
|
126
126
|
class << self
|
127
127
|
attr_reader :report_type
|
128
128
|
|
129
|
-
def find_by_customer_vault_id(customer_vault_id)
|
129
|
+
def find_by_customer_vault_id(customer_vault_id, username=nil, password=nil)
|
130
130
|
raise StandardError, "CustomerVaultID cannot be blank" if customer_vault_id.blank?
|
131
131
|
begin
|
132
|
-
new(:customer_vault_id
|
132
|
+
new(customer_vault_id: customer_vault_id, username: username, password: password)
|
133
133
|
rescue CustomerVaultNotFoundError
|
134
134
|
return nil
|
135
135
|
end
|
@@ -161,8 +161,8 @@ module NmiDirectPost
|
|
161
161
|
limit
|
162
162
|
end
|
163
163
|
|
164
|
-
def all_params(safe_params)
|
165
|
-
[safe_params, generate_query_string(Base::AUTH_PARAMS)].join('&')
|
164
|
+
def all_params(safe_params, target=self)
|
165
|
+
[safe_params, generate_query_string(Base::AUTH_PARAMS, target)].join('&')
|
166
166
|
end
|
167
167
|
|
168
168
|
private
|
@@ -178,7 +178,7 @@ module NmiDirectPost
|
|
178
178
|
|
179
179
|
def post(safe_params)
|
180
180
|
logger.info { "Sending Direct Post to NMI: #{safe_params}" }
|
181
|
-
response = self.class.post(self.class.all_params(safe_params))
|
181
|
+
response = self.class.post(self.class.all_params(safe_params, self))
|
182
182
|
@response, @response_text, @response_code = response["response"].to_i, response["responsetext"], response["response_code"].to_i
|
183
183
|
@customer_vault_id = response["customer_vault_id"].to_i if :add_customer == self.customer_vault
|
184
184
|
end
|
@@ -25,7 +25,7 @@ module NmiDirectPost
|
|
25
25
|
validate :save_successful?, :unless => 'response_text.blank?'
|
26
26
|
|
27
27
|
def initialize(attributes)
|
28
|
-
super
|
28
|
+
super
|
29
29
|
@type, @amount = attributes[:type].to_s, attributes[:amount].to_f
|
30
30
|
@transaction_id = attributes[:transaction_id].to_i if attributes[:transaction_id]
|
31
31
|
@customer_vault_id = attributes[:customer_vault_id].to_i if attributes[:customer_vault_id]
|
@@ -34,8 +34,13 @@ module NmiDirectPost
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def save
|
37
|
-
|
38
|
-
|
37
|
+
return false if invalid?
|
38
|
+
if condition.blank?
|
39
|
+
if 'void' == type
|
40
|
+
reload
|
41
|
+
@type = 'void'
|
42
|
+
end
|
43
|
+
end
|
39
44
|
_safe_params = safe_params
|
40
45
|
logger.info { "Sending Direct Post Transaction to NMI: #{_safe_params}" }
|
41
46
|
post([_safe_params, transaction_params].join('&'))
|
@@ -74,11 +79,6 @@ module NmiDirectPost
|
|
74
79
|
|
75
80
|
def void!
|
76
81
|
@type='void'
|
77
|
-
if condition.blank?
|
78
|
-
return false if invalid?
|
79
|
-
reload
|
80
|
-
@type = 'void'
|
81
|
-
end
|
82
82
|
save
|
83
83
|
end
|
84
84
|
|
data/nmi_direct_post.gemspec
CHANGED
data/spec/base_spec.rb
CHANGED
@@ -34,4 +34,8 @@ describe NmiDirectPost::Base do
|
|
34
34
|
NmiDirectPost::CustomerVault.establish_connection(credentials.nmi_username, credentials.nmi_password)
|
35
35
|
expect{a_query}.to_not raise_error
|
36
36
|
end
|
37
|
+
it "should allow the record to set its own username/password" do
|
38
|
+
a_query = ->{ NmiDirectPost::CustomerVault.find_by_customer_vault_id(a_cc_customer_vault_id, "ABC", "DEF") }
|
39
|
+
expect(a_query).not_to raise_error
|
40
|
+
end
|
37
41
|
end
|
data/spec/transaction_spec.rb
CHANGED
@@ -4,153 +4,151 @@ require_relative 'spec_helper'
|
|
4
4
|
describe NmiDirectPost::Transaction do
|
5
5
|
let(:a_cc_customer_vault_id) { TestCredentials::INSTANCE.cc_customer }
|
6
6
|
let(:a_checking_account_customer_vault_id) { TestCredentials::INSTANCE.ach_customer }
|
7
|
-
let(:amount) {
|
7
|
+
let(:amount) { Random.rand(50.0..500.0).round(2) }
|
8
|
+
let(:credentials) { TestCredentials::INSTANCE }
|
9
|
+
let(:cc_implicit_sale) { NmiDirectPost::Transaction.new(customer_vault_id: a_cc_customer_vault_id, amount: amount) }
|
10
|
+
let(:ach_implicit_sale) { NmiDirectPost::Transaction.new(customer_vault_id: a_checking_account_customer_vault_id, amount: amount) }
|
11
|
+
let(:cc_validation) { NmiDirectPost::Transaction.new(customer_vault_id: a_cc_customer_vault_id, amount: 0, type: :validate) }
|
8
12
|
|
9
|
-
before
|
10
|
-
credentials = TestCredentials::INSTANCE
|
13
|
+
before(:each) do
|
11
14
|
NmiDirectPost::Base.establish_connection(credentials.nmi_username, credentials.nmi_password)
|
12
|
-
@amount_generator = Random.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def given_a_sale_for_customer_vault_id customer_vault_id
|
16
|
-
@transaction = NmiDirectPost::Transaction.new(:customer_vault_id => customer_vault_id, :amount => amount.call)
|
17
|
-
expect(@transaction.save).to eq(true), "Transaction failed to save for the following reasons: #{@transaction.errors.messages.inspect}"
|
18
|
-
end
|
19
|
-
|
20
|
-
def expect_response_to_be response, response_code
|
21
|
-
expect(@transaction.response).to eq(response), @transaction.inspect
|
22
|
-
expect(@transaction.response_code).to eq(response_code), @transaction.inspect
|
23
|
-
end
|
24
|
-
|
25
|
-
def if_the_transaction_succeeds
|
26
|
-
expect(@transaction.response).to eq(1), @transaction.inspect
|
27
|
-
end
|
28
|
-
|
29
|
-
def it_should_find_the_transaction
|
30
|
-
@queried_transaction = NmiDirectPost::Transaction.find_by_transaction_id(@transaction.transaction_id)
|
31
|
-
expect(@queried_transaction).not_to be_nil
|
32
|
-
expect(@queried_transaction.amount).to eq @transaction.amount
|
33
|
-
expect(@queried_transaction.customer_vault_id).to eq @transaction.customer_vault_id
|
34
|
-
expect(@queried_transaction.customer_vault).not_to be_nil
|
35
|
-
expect(@queried_transaction.customer_vault.first_name).to eq(@transaction.customer_vault.first_name)
|
36
15
|
end
|
37
16
|
|
38
17
|
it "should allow saving with a bang" do
|
39
|
-
|
40
|
-
expect{@transaction.save!}.not_to raise_error
|
18
|
+
expect{cc_implicit_sale.save!}.not_to raise_error
|
41
19
|
end
|
42
20
|
|
43
21
|
it "should fail validation when no customer_vault_id and no transaction_id are given" do
|
44
|
-
|
45
|
-
expect{
|
22
|
+
transaction = NmiDirectPost::Transaction.new(amount: amount)
|
23
|
+
expect{transaction.save!}.to raise_error(NmiDirectPost::TransactionNotSavedError)
|
46
24
|
end
|
47
25
|
|
48
26
|
it "should respond with a success code when given a valid customer_vault_id" do
|
49
|
-
|
50
|
-
|
51
|
-
expect(
|
52
|
-
expect(
|
27
|
+
expect(cc_implicit_sale.save).to eq(true), "Transaction failed to save for the following reasons: #{cc_implicit_sale.errors.messages.inspect}"
|
28
|
+
expect(cc_implicit_sale.response).to eq(1), cc_implicit_sale.inspect
|
29
|
+
expect(cc_implicit_sale.response_code).to eq(100), cc_implicit_sale.inspect
|
30
|
+
expect(cc_implicit_sale.response_text).to eq("SUCCESS"), cc_implicit_sale.inspect
|
31
|
+
expect(cc_implicit_sale).to be_success, cc_implicit_sale.inspect
|
53
32
|
end
|
54
33
|
|
55
34
|
it "should fail validation when given an invalid customer_vault_id" do
|
56
|
-
|
57
|
-
expect(
|
58
|
-
expect(
|
59
|
-
expect(
|
60
|
-
expect(
|
35
|
+
transaction = NmiDirectPost::Transaction.new(customer_vault_id: 1000, amount: amount)
|
36
|
+
expect(transaction.save).to eq(false)
|
37
|
+
expect(transaction.errors.size).to eq(1)
|
38
|
+
expect(transaction.errors[:customer_vault].size).to eq(1)
|
39
|
+
expect(transaction.errors[:customer_vault]).to include("Customer vault with the given customer_vault could not be found")
|
61
40
|
end
|
62
41
|
|
63
|
-
|
64
|
-
|
65
|
-
if_the_transaction_succeeds
|
66
|
-
it_should_find_the_transaction
|
67
|
-
expect(@queried_transaction.type).to eq "sale"
|
68
|
-
end
|
42
|
+
describe "finding an existing transaction" do
|
43
|
+
let(:queried_transaction) { NmiDirectPost::Transaction.find_by_transaction_id(transaction.transaction_id) }
|
69
44
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
45
|
+
def it_should_find_the_transaction
|
46
|
+
expect(queried_transaction).not_to be_nil
|
47
|
+
expect(queried_transaction.amount).to eq transaction.amount
|
48
|
+
expect(queried_transaction.customer_vault_id).to eq transaction.customer_vault_id
|
49
|
+
expect(queried_transaction.customer_vault).not_to be_nil
|
50
|
+
expect(queried_transaction.customer_vault.first_name).to eq(transaction.customer_vault.first_name)
|
51
|
+
end
|
77
52
|
|
78
|
-
|
79
|
-
|
80
|
-
end
|
53
|
+
describe "a sale" do
|
54
|
+
let(:transaction) { cc_implicit_sale }
|
81
55
|
|
82
|
-
|
83
|
-
|
84
|
-
|
56
|
+
it "should be found" do
|
57
|
+
expect(cc_implicit_sale.save).to eq(true), "Transaction failed to save for the following reasons: #{cc_implicit_sale.errors.messages.inspect}"
|
58
|
+
expect(cc_implicit_sale.response).to eq(1), cc_implicit_sale.inspect
|
59
|
+
it_should_find_the_transaction
|
60
|
+
expect(queried_transaction.type).to eq "sale"
|
61
|
+
end
|
62
|
+
end
|
85
63
|
|
86
|
-
|
87
|
-
|
64
|
+
describe "a validate" do
|
65
|
+
let(:transaction) { cc_validation }
|
66
|
+
|
67
|
+
it "should be found" do
|
68
|
+
cc_validation.save
|
69
|
+
expect(cc_validation.response).to eq(1), cc_validation.inspect
|
70
|
+
it_should_find_the_transaction
|
71
|
+
expect(queried_transaction.type).to eq cc_validation.type
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should raise an error when transaction_id is blank" do
|
76
|
+
expect{ NmiDirectPost::Transaction.find_by_transaction_id("") }.to raise_error(StandardError, "TransactionID cannot be blank")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should raise an error when transaction is not found using instance" do
|
80
|
+
expect{ NmiDirectPost::Transaction.new(transaction_id: 12345) }.to raise_error(NmiDirectPost::TransactionNotFoundError, "No transaction found for TransactionID 12345")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return nil when transaction is not found using class method" do
|
84
|
+
expect(NmiDirectPost::Transaction.find_by_transaction_id(12345)).to be_nil
|
85
|
+
end
|
88
86
|
end
|
89
87
|
|
90
88
|
it "should add response, response_code and response to errors when charge cannot be saved" do
|
91
|
-
|
92
|
-
|
93
|
-
expect(
|
94
|
-
expect(
|
95
|
-
expect(
|
96
|
-
expect(
|
97
|
-
expect(
|
98
|
-
expect(
|
99
|
-
expect(
|
100
|
-
expect(transaction.errors[:response_text]).to include('Authentication Failed'), transaction.errors.inspect
|
89
|
+
cc_validation.instance_variable_set("@password", '12345')
|
90
|
+
expect(cc_validation.save).to eq(false)
|
91
|
+
expect(cc_validation.errors.size).to eq(3), cc_validation.errors.inspect
|
92
|
+
expect(cc_validation.errors[:response].size).to eq(1), cc_validation.errors[:response].inspect
|
93
|
+
expect(cc_validation.errors[:response]).to include('3'), cc_validation.errors.inspect
|
94
|
+
expect(cc_validation.errors[:response_code].size).to eq(1), cc_validation.errors[:response_code].inspect
|
95
|
+
expect(cc_validation.errors[:response_code]).to include('300'), cc_validation.errors.inspect
|
96
|
+
expect(cc_validation.errors[:response_text].size).to eq(1), cc_validation.errors[:response_text].inspect
|
97
|
+
expect(cc_validation.errors[:response_text]).to include('Authentication Failed'), cc_validation.errors.inspect
|
101
98
|
end
|
102
99
|
|
103
100
|
describe "customer_vault" do
|
104
101
|
it "should find when it exists" do
|
105
|
-
|
106
|
-
expect(@transaction.customer_vault).to have_same_attributes_as(NmiDirectPost::CustomerVault.find_by_customer_vault_id(a_cc_customer_vault_id))
|
102
|
+
expect(cc_implicit_sale.customer_vault).to have_same_attributes_as(NmiDirectPost::CustomerVault.find_by_customer_vault_id(a_cc_customer_vault_id))
|
107
103
|
end
|
108
104
|
|
109
105
|
it "should be nil when it doesn't exist" do
|
110
|
-
|
111
|
-
expect(
|
106
|
+
transaction = NmiDirectPost::Transaction.new(customer_vault_id: '123456', amount: amount)
|
107
|
+
expect(transaction.customer_vault).to be_nil
|
112
108
|
end
|
113
109
|
end
|
114
110
|
|
115
111
|
describe "type" do
|
112
|
+
let(:cc_transaction) { NmiDirectPost::Transaction.new(customer_vault_id: a_cc_customer_vault_id, amount: amount, type: transaction_type) }
|
113
|
+
let(:cc_transaction_amount_0) { NmiDirectPost::Transaction.new(customer_vault_id: a_cc_customer_vault_id, amount: 0, type: transaction_type) }
|
114
|
+
let(:ach_transaction) { NmiDirectPost::Transaction.new(customer_vault_id: a_checking_account_customer_vault_id, amount: amount, type: transaction_type) }
|
115
|
+
let(:ach_transaction_amount_0) { NmiDirectPost::Transaction.new(customer_vault_id: a_checking_account_customer_vault_id, amount: 0, type: transaction_type) }
|
116
|
+
|
116
117
|
describe "sale" do
|
118
|
+
let(:transaction_type) { :sale }
|
117
119
|
it "should allow non-zero amounts for credit card customer vaults" do
|
118
|
-
|
119
|
-
expect(transaction.save).to eq(true), transaction.errors.inspect
|
120
|
+
expect(cc_transaction.save).to eq(true), cc_transaction.errors.inspect
|
120
121
|
end
|
121
122
|
it "should not allow amount to be 0 for credit card customer vaults" do
|
122
|
-
|
123
|
-
expect(
|
124
|
-
expect(
|
125
|
-
expect(
|
126
|
-
expect(transaction.errors[:amount]).to include('Amount cannot be 0 for a sale')
|
123
|
+
expect(cc_transaction_amount_0.save).to eq(false)
|
124
|
+
expect(cc_transaction_amount_0.errors.size).to eq(1)
|
125
|
+
expect(cc_transaction_amount_0.errors[:amount].size).to eq(1)
|
126
|
+
expect(cc_transaction_amount_0.errors[:amount]).to include('Amount cannot be 0 for a sale')
|
127
127
|
end
|
128
128
|
it "should allow non-zero amounts for checking account customer vaults" do
|
129
|
-
expect(
|
129
|
+
expect(ach_transaction.save).to eq(true)
|
130
130
|
end
|
131
131
|
it "should not allow amount to be 0 for checking account customer vaults" do
|
132
|
-
|
133
|
-
expect(
|
134
|
-
expect(
|
135
|
-
expect(
|
136
|
-
expect(transaction.errors[:amount]).to include('Amount cannot be 0 for a sale')
|
132
|
+
expect(ach_transaction_amount_0.save).to eq(false)
|
133
|
+
expect(ach_transaction_amount_0.errors.size).to eq(1)
|
134
|
+
expect(ach_transaction_amount_0.errors[:amount].size).to eq(1)
|
135
|
+
expect(ach_transaction_amount_0.errors[:amount]).to include('Amount cannot be 0 for a sale')
|
137
136
|
end
|
138
137
|
it "should allow non-zero amounts for credit card customer vaults when sale is implied" do
|
139
|
-
|
140
|
-
expect(transaction.save).to eq(true), transaction.errors.inspect
|
138
|
+
expect(cc_implicit_sale.save).to eq(true), cc_implicit_sale.errors.inspect
|
141
139
|
end
|
142
140
|
it "should not allow amount to be 0 for credit card customer vaults when sale is implied" do
|
143
|
-
transaction = NmiDirectPost::Transaction.new(:
|
141
|
+
transaction = NmiDirectPost::Transaction.new(customer_vault_id: a_cc_customer_vault_id, amount: 0)
|
144
142
|
expect(transaction.save).to eq(false)
|
145
143
|
expect(transaction.errors.size).to eq(1)
|
146
144
|
expect(transaction.errors[:amount].size).to eq(1)
|
147
145
|
expect(transaction.errors[:amount]).to include('Amount cannot be 0 for a sale')
|
148
146
|
end
|
149
147
|
it "should allow non-zero amounts for checking account customer vaults when sale is implied" do
|
150
|
-
expect(
|
148
|
+
expect(ach_implicit_sale.save).to eq(true)
|
151
149
|
end
|
152
150
|
it "should not allow amount to be 0 for checking account customer vaults when sale is implied" do
|
153
|
-
transaction = NmiDirectPost::Transaction.new(:
|
151
|
+
transaction = NmiDirectPost::Transaction.new(customer_vault_id: a_checking_account_customer_vault_id, amount: 0)
|
154
152
|
expect(transaction.save).to eq(false)
|
155
153
|
expect(transaction.errors.size).to eq(1)
|
156
154
|
expect(transaction.errors[:amount].size).to eq(1)
|
@@ -159,134 +157,124 @@ describe NmiDirectPost::Transaction do
|
|
159
157
|
end
|
160
158
|
|
161
159
|
describe "validate" do
|
160
|
+
let(:transaction_type) { :validate }
|
162
161
|
it "should not allow non-zero amounts" do
|
163
|
-
|
164
|
-
expect(
|
165
|
-
expect(
|
166
|
-
expect(
|
167
|
-
expect(transaction.errors[:amount]).to include('Amount must be 0 when validating a credit card')
|
162
|
+
expect(cc_transaction.save).to eq(false)
|
163
|
+
expect(cc_transaction.errors.size).to eq(1)
|
164
|
+
expect(cc_transaction.errors[:amount].size).to eq(1)
|
165
|
+
expect(cc_transaction.errors[:amount]).to include('Amount must be 0 when validating a credit card')
|
168
166
|
end
|
169
167
|
it "should allow amount to be 0" do
|
170
|
-
expect(
|
168
|
+
expect(cc_transaction_amount_0.save).to eq(true)
|
171
169
|
end
|
172
170
|
it "should not be allowed for checking account customer vaults" do
|
173
|
-
|
174
|
-
expect(
|
175
|
-
expect(
|
176
|
-
expect(
|
177
|
-
expect(transaction.errors[:type]).to include('validate is not a valid action for a customer vault that uses a checking account')
|
171
|
+
expect(ach_transaction_amount_0.save).to eq(false)
|
172
|
+
expect(ach_transaction_amount_0.errors.size).to eq(1)
|
173
|
+
expect(ach_transaction_amount_0.errors[:type].size).to eq(1)
|
174
|
+
expect(ach_transaction_amount_0.errors[:type]).to include('validate is not a valid action for a customer vault that uses a checking account')
|
178
175
|
end
|
179
176
|
end
|
180
177
|
|
181
178
|
describe "auth" do
|
179
|
+
let(:transaction_type) { :auth }
|
182
180
|
it "should allow non-zero amounts for credit card customer vaults" do
|
183
|
-
|
184
|
-
expect(transaction.save).to eq(true), transaction.errors.inspect
|
181
|
+
expect(cc_transaction.save).to eq(true), cc_transaction.errors.inspect
|
185
182
|
end
|
186
183
|
it "should not allow amount to be 0 for credit card customer vaults" do
|
187
|
-
|
188
|
-
expect(
|
189
|
-
expect(
|
190
|
-
expect(
|
191
|
-
expect(transaction.errors[:amount]).to include('Amount cannot be 0 for an authorization')
|
184
|
+
expect(cc_transaction_amount_0.save).to eq(false)
|
185
|
+
expect(cc_transaction_amount_0.errors.size).to eq(1)
|
186
|
+
expect(cc_transaction_amount_0.errors[:amount].size).to eq(1)
|
187
|
+
expect(cc_transaction_amount_0.errors[:amount]).to include('Amount cannot be 0 for an authorization')
|
192
188
|
end
|
193
189
|
it "should not be allowed for checking account customer vaults" do
|
194
|
-
|
195
|
-
expect(
|
196
|
-
expect(
|
197
|
-
expect(
|
198
|
-
expect(transaction.errors[:type]).to include('auth is not a valid action for a customer vault that uses a checking account')
|
190
|
+
expect(ach_transaction.save).to eq(false)
|
191
|
+
expect(ach_transaction.errors.size).to eq(1)
|
192
|
+
expect(ach_transaction.errors[:type].size).to eq(1)
|
193
|
+
expect(ach_transaction.errors[:type]).to include('auth is not a valid action for a customer vault that uses a checking account')
|
199
194
|
end
|
200
195
|
end
|
201
196
|
|
202
197
|
describe "void" do
|
198
|
+
let(:cc_auth) { NmiDirectPost::Transaction.new(customer_vault_id: a_cc_customer_vault_id, amount: amount, type: :auth) }
|
203
199
|
it "should be allowed for a pending sale" do
|
204
|
-
|
205
|
-
|
206
|
-
expect(transaction.void!).to eq(true)
|
200
|
+
cc_implicit_sale.save!
|
201
|
+
expect(cc_implicit_sale.void!).to eq(true)
|
207
202
|
end
|
208
203
|
it "should not be allowed for validates" do
|
209
|
-
|
210
|
-
|
211
|
-
expect(
|
212
|
-
expect(
|
213
|
-
expect(
|
214
|
-
expect(transaction.errors[:type]).to include('Void is only a valid action for a pending or unsettled authorization, or an unsettled sale')
|
204
|
+
cc_validation.save!
|
205
|
+
expect(cc_validation.void!).to eq(false)
|
206
|
+
expect(cc_validation.errors.size).to eq(1), cc_validation.errors.inspect
|
207
|
+
expect(cc_validation.errors[:type].size).to eq(1), cc_validation.errors.inspect
|
208
|
+
expect(cc_validation.errors[:type]).to include('Void is only a valid action for a pending or unsettled authorization, or an unsettled sale')
|
215
209
|
end
|
216
210
|
it "should be allowed for authorizations when saved and voided on same instantiation" do
|
217
|
-
|
218
|
-
expect(
|
219
|
-
expect(
|
220
|
-
expect(transaction.errors).to be_empty, transaction.errors.inspect
|
211
|
+
expect(cc_auth.save).to eq(true), cc_auth.inspect
|
212
|
+
expect(cc_auth.void!).to eq(true), cc_auth.inspect
|
213
|
+
expect(cc_auth.errors).to be_empty, cc_auth.errors.inspect
|
221
214
|
end
|
222
215
|
it "should be allowed for authorizations when found by transaction ID" do
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
expect(
|
227
|
-
expect(transaction.errors).to be_empty, transaction.errors.inspect
|
216
|
+
cc_auth.save!
|
217
|
+
void = NmiDirectPost::Transaction.find_by_transaction_id(cc_auth.transaction_id)
|
218
|
+
expect(void.void!).to eq(true), void.inspect
|
219
|
+
expect(void.errors).to be_empty, void.errors.inspect
|
228
220
|
end
|
229
221
|
it "should be allowed for authorizations when instantiated as a void" do
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
expect(
|
234
|
-
expect(transaction.errors).to be_empty, transaction.errors.inspect
|
222
|
+
cc_auth.save!
|
223
|
+
void = NmiDirectPost::Transaction.new(transaction_id: cc_auth.transaction_id, type: :void)
|
224
|
+
expect(void.save).to eq(true), cc_auth.errors.inspect
|
225
|
+
expect(void.errors).to be_empty, cc_auth.errors.inspect
|
235
226
|
end
|
236
227
|
it "should not be allowed for an unpersisted transaction" do
|
237
|
-
|
238
|
-
expect(
|
239
|
-
expect(
|
240
|
-
expect(
|
241
|
-
expect(transaction.errors[:type]).to include('Void is only a valid action for a transaction that has already been sent to NMI')
|
228
|
+
expect(cc_auth.void!).to eq(false), cc_auth.inspect
|
229
|
+
expect(cc_auth.errors.size).to eq(1), cc_auth.errors.inspect
|
230
|
+
expect(cc_auth.errors[:type].size).to eq(1), cc_auth.errors.inspect
|
231
|
+
expect(cc_auth.errors[:type]).to include('Void is only a valid action for a transaction that has already been sent to NMI')
|
242
232
|
end
|
243
|
-
|
244
|
-
|
245
|
-
transaction.save!
|
246
|
-
expect(transaction.void!).to eq(true)
|
247
|
-
expect(transaction.void!).to eq(false)
|
233
|
+
|
234
|
+
def expect_error_on_void_for(transaction)
|
248
235
|
expect(transaction.errors.size).to eq(1), transaction.errors.inspect
|
249
236
|
expect(transaction.errors[:type].size).to eq(1), transaction.errors.inspect
|
250
237
|
expect(transaction.errors[:type]).to include('Void is only a valid action for a pending or unsettled authorization, or an unsettled sale')
|
251
238
|
end
|
239
|
+
|
240
|
+
it "should not be allowed for a voided sale" do
|
241
|
+
cc_implicit_sale.save!
|
242
|
+
expect(cc_implicit_sale.void!).to eq(true)
|
243
|
+
expect(cc_implicit_sale.void!).to eq(false)
|
244
|
+
expect_error_on_void_for(cc_implicit_sale)
|
245
|
+
void = NmiDirectPost::Transaction.new(transaction_id: cc_implicit_sale.transaction_id, type: :void)
|
246
|
+
expect(void.save).to eq(false)
|
247
|
+
expect_error_on_void_for(void)
|
248
|
+
end
|
252
249
|
it "should not be allowed for a voided auth" do
|
253
|
-
|
254
|
-
|
255
|
-
expect(
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
expect(
|
250
|
+
cc_auth.save!
|
251
|
+
expect(cc_auth.void!).to eq(true)
|
252
|
+
expect(cc_auth.void!).to eq(false)
|
253
|
+
expect_error_on_void_for(cc_auth)
|
254
|
+
|
255
|
+
void = NmiDirectPost::Transaction.new(transaction_id: cc_auth.transaction_id, type: :void)
|
256
|
+
expect(void.save).to eq(false)
|
257
|
+
expect_error_on_void_for(void)
|
260
258
|
end
|
261
259
|
end
|
262
260
|
end
|
263
261
|
|
264
262
|
describe "condition" do
|
265
|
-
def given_a_check_transaction
|
266
|
-
transaction = NmiDirectPost::Transaction.new(:customer_vault_id => a_checking_account_customer_vault_id, :amount => amount.call)
|
267
|
-
transaction.save!
|
268
|
-
@amount = transaction.amount
|
269
|
-
@transaction = NmiDirectPost::Transaction.find_by_transaction_id(transaction.transaction_id)
|
270
|
-
end
|
271
|
-
def given_a_cc_transaction
|
272
|
-
transaction = NmiDirectPost::Transaction.new(:customer_vault_id => a_cc_customer_vault_id, :amount => amount.call)
|
273
|
-
transaction.save!
|
274
|
-
@amount = transaction.amount
|
275
|
-
@transaction = NmiDirectPost::Transaction.find_by_transaction_id(transaction.transaction_id)
|
276
|
-
end
|
277
263
|
it "should be pendingsettlement on a new check" do
|
278
|
-
|
279
|
-
|
280
|
-
expect(
|
281
|
-
expect(
|
282
|
-
expect(
|
264
|
+
ach_implicit_sale.save!
|
265
|
+
transaction = NmiDirectPost::Transaction.find_by_transaction_id(ach_implicit_sale.transaction_id)
|
266
|
+
expect(transaction.condition).to eq("pendingsettlement")
|
267
|
+
expect(transaction).to be_pending
|
268
|
+
expect(transaction).not_to be_cleared
|
269
|
+
expect(transaction.amount).to eq(amount)
|
283
270
|
end
|
284
271
|
it "should be pending on a new CC charge" do
|
285
|
-
|
286
|
-
|
287
|
-
expect(
|
288
|
-
expect(
|
289
|
-
expect(
|
272
|
+
cc_implicit_sale.save!
|
273
|
+
transaction = NmiDirectPost::Transaction.find_by_transaction_id(cc_implicit_sale.transaction_id)
|
274
|
+
expect(transaction.condition).to eq("pendingsettlement")
|
275
|
+
expect(transaction).to be_pending
|
276
|
+
expect(transaction).not_to be_cleared
|
277
|
+
expect(transaction.amount).to eq(amount)
|
290
278
|
end
|
291
279
|
it "should be approved on an existing CC charge" do
|
292
280
|
transaction = NmiDirectPost::Transaction.find_by_transaction_id(TestCredentials::INSTANCE.cc_transaction)
|
@@ -297,7 +285,6 @@ describe NmiDirectPost::Transaction do
|
|
297
285
|
end
|
298
286
|
|
299
287
|
it "should not reload when transaction_id is missing" do
|
300
|
-
|
301
|
-
expect{transaction.reload}.not_to raise_error
|
288
|
+
expect{cc_implicit_sale.reload}.not_to raise_error
|
302
289
|
end
|
303
290
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nmi_direct_post
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Isaac Betesh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -100,28 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :runtime
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: activesupport
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '3.0'
|
103
|
+
version: '4.0'
|
118
104
|
type: :runtime
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
108
|
- - ">="
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
110
|
+
version: '4.0'
|
125
111
|
description: Gem that encapsulates the NMI Direct Post API in an ActiveRecord-like
|
126
112
|
syntax
|
127
113
|
email:
|
@@ -171,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
157
|
version: '0'
|
172
158
|
requirements: []
|
173
159
|
rubyforge_project:
|
174
|
-
rubygems_version: 2.4.
|
160
|
+
rubygems_version: 2.4.8
|
175
161
|
signing_key:
|
176
162
|
specification_version: 4
|
177
163
|
summary: '# NmiDirectPost NmiDirectPost is a gem that encapsulates the NMI Direct
|
@@ -181,14 +167,20 @@ summary: '# NmiDirectPost NmiDirectPost is a gem that encapsulates the NMI Dire
|
|
181
167
|
the boundary between NMI''s Direct Post API and its Query API. This fuzziness is
|
182
168
|
part of the encapsulation. ## Installation Add this line to your application''s
|
183
169
|
Gemfile: gem ''nmi_direct_post'' And then execute: $ bundle Or install it yourself
|
184
|
-
as: $ gem install nmi_direct_post ## Usage 1) Before you
|
185
|
-
|
186
|
-
you
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
170
|
+
as: $ gem install nmi_direct_post ## Usage 1) Before you query or post, you probably
|
171
|
+
want to set a default username and password: NmiDirectPost::Base.establish_connection("MY_NMI_USERNAME",
|
172
|
+
"MY_NMI_PASSWORD") If you don''t set a default, you''ll need to include the username
|
173
|
+
and password in the hash passed to the initializer when instantiating a new Transaction
|
174
|
+
or CustomerVault. Theoretically, you can use a different connection for NmiDirectPost::Transaction
|
175
|
+
or NmiDirectPost::CustomerVault by calling establish_connection on either of those
|
176
|
+
derived classes, instead of on Base. However, it''s hard to imagine a case where
|
177
|
+
this would be useful; the option is only present to mimic the syntax of ActiveRecord. 2)
|
178
|
+
Query the API: NmiDirectPost::Transaction.find_by_transaction_id(123456789, "MyUsername",
|
179
|
+
"MyPassword") NmiDirectPost::Transaction.find_by_transaction_id(123456789) # If
|
180
|
+
you''ve already called establish_connection NmiDirectPost::CustomerVault.find_by_customer_vault_id(123123123)
|
181
|
+
# Note that there is no way to pass a username and password to this method. You
|
182
|
+
must call establish_connection beforehand. 3) Create a CustomerVault: george =
|
183
|
+
NmiDirectPostCustomerVault.new(:first_name => ''George'', :last_name => ''Washington'',
|
192
184
|
:cc_number => ''4111111111111111'', :cc_exp => ''03/17'') george.create 4) Update
|
193
185
|
a CustomerVault: george.update!(:email => ''el_primero_presidente@whitehouse.gov'',
|
194
186
|
:address_1 => ''1600 Pennsylvania Ave NW'', :city => ''Washington'', :state => ''DC'',
|
@@ -201,12 +193,13 @@ summary: '# NmiDirectPost NmiDirectPost is a gem that encapsulates the NMI Dire
|
|
201
193
|
# Returns array of `customer_vault_id`s NmiDirectPost::CustomerVault.first NmiDirectPost::CustomerVault.last
|
202
194
|
NmiDirectPost::CustomerVault.all # Returns very, very big array. This method had
|
203
195
|
very poor performance and could be optimized significantly in a future version of
|
204
|
-
this gem.
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
196
|
+
this gem. Note that there is no way to pass a username and password to these methods. You
|
197
|
+
must call establish_connection beforehand. 8) Create a Transaction: parking_ticket
|
198
|
+
= NmiDirectPost::Transaction(:type => :sale, :amount => 150.01, :customer_vault_id
|
199
|
+
=> george.customer_vault_id) parking_ticket.save! # Returns true ## Contributing 1.
|
200
|
+
Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit
|
201
|
+
your changes (`git commit -am ''Add some feature''`) 4. Push to the branch (`git
|
202
|
+
push origin my-new-feature`) 5. Create new Pull Request'
|
210
203
|
test_files:
|
211
204
|
- spec/base_spec.rb
|
212
205
|
- spec/customer_vault_spec.rb
|