rocketgate-ruby 0.0.1.pre
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +14 -0
- data/.travis.yml +20 -0
- data/Gemfile +3 -0
- data/Guardfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +161 -0
- data/Rakefile +14 -0
- data/lib/rocketgate.rb +52 -0
- data/lib/rocketgate/authorization.rb +31 -0
- data/lib/rocketgate/configuration.rb +53 -0
- data/lib/rocketgate/connection.rb +30 -0
- data/lib/rocketgate/credit_card.rb +42 -0
- data/lib/rocketgate/customer.rb +33 -0
- data/lib/rocketgate/hashable.rb +63 -0
- data/lib/rocketgate/request.rb +48 -0
- data/lib/rocketgate/response.rb +64 -0
- data/lib/rocketgate/response_code.rb +148 -0
- data/lib/rocketgate/transaction.rb +75 -0
- data/lib/rocketgate/validatable.rb +52 -0
- data/lib/rocketgate/version.rb +3 -0
- data/rocketgate-ruby.gemspec +34 -0
- data/spec/authorization_spec.rb +87 -0
- data/spec/configuration_spec.rb +33 -0
- data/spec/connection_spec.rb +65 -0
- data/spec/credit_card_spec.rb +73 -0
- data/spec/customer_spec.rb +57 -0
- data/spec/hashable_spec.rb +85 -0
- data/spec/integration_spec.rb +131 -0
- data/spec/request_spec.rb +92 -0
- data/spec/response_spec.rb +190 -0
- data/spec/rocketgate_spec.rb +108 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/transaction_spec.rb +250 -0
- data/spec/validatable_spec.rb +79 -0
- metadata +261 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e174cdc0ab9153dd12a64e537d7f49da9e44b49d
|
4
|
+
data.tar.gz: 64b9018aa9f8c1266aa234e638c18772a563d147
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a1cbd4b6a8ebc773c8c3847ad26619e69624fd268703ff23f741b6b2440be5fe919605db38dafd7c51eef12cfb177e80af48e008aa0e74458b4d3bd29778bb8c
|
7
|
+
data.tar.gz: 3c1695751188219814e250c6966ee38052205fbfaf79c82dc91ffe95f485def41eb263c8bc3c9bc2e4aaba7f61c271e7986cc5f03e6fadf2983621a93179d100
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
|
4
|
+
rvm:
|
5
|
+
- 1.9.3
|
6
|
+
- 2.0.0
|
7
|
+
- 2.1.1
|
8
|
+
- jruby-19mode
|
9
|
+
- jruby-head
|
10
|
+
- rbx-2
|
11
|
+
- ruby-head
|
12
|
+
|
13
|
+
script: 'bundle exec rake'
|
14
|
+
|
15
|
+
notifications:
|
16
|
+
email:
|
17
|
+
recipients:
|
18
|
+
- ccashwell@gmail.com
|
19
|
+
on_failure: change
|
20
|
+
on_success: never
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Chris Cashwell
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# rocketgate-ruby
|
2
|
+
|
3
|
+
[](https://travis-ci.org/ccashwell/rocketgate-ruby)
|
4
|
+
[](https://coveralls.io/r/ccashwell/rocketgate-ruby)
|
5
|
+
[](https://codeclimate.com/github/ccashwell/rocketgate-ruby)
|
6
|
+
|
7
|
+
RocketGate's Payment Gateway, minus the painful integration.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'rocketgate-ruby'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install rocketgate-ruby
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
### Configuration
|
28
|
+
|
29
|
+
Before you can jump in, you need to configure the gem with your RocketGate credentials:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
RocketGate.configure do |config|
|
33
|
+
config.merchant_id = 'rocketgate_merchant_id'
|
34
|
+
config.merchant_password = 'rocketgate_merchant_password'
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
You can also supply other configuration settings:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
RocketGate.configure do |config|
|
42
|
+
config.merchant_id = 'rocketgate_merchant_id'
|
43
|
+
config.merchant_password = 'rocketgate_merchant_password'
|
44
|
+
config.currency = 'USD'
|
45
|
+
config.request_host = 'special-gateway.rocketgate.com'
|
46
|
+
config.request_path = '/specialServlet'
|
47
|
+
config.request_port = 8080
|
48
|
+
config.request_timeout = 5
|
49
|
+
config.request_version = 'R2.0'
|
50
|
+
config.require_avs = false
|
51
|
+
config.require_cvv = false
|
52
|
+
config.require_scrub = false
|
53
|
+
config.require_ssl = false
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
And if you want to test something against the sandbox gateway:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
RocketGate.configuration.testing!
|
61
|
+
```
|
62
|
+
|
63
|
+
### Making an Authorization Request
|
64
|
+
|
65
|
+
In order to get an authorization, you'll need to send a request to the gateway.
|
66
|
+
|
67
|
+
1. Build a [`Customer`](https://github.com/ccashwell/rocketgate-ruby/blob/master/lib/rocketgate/customer.rb) and [`CreditCard`](https://github.com/ccashwell/rocketgate-ruby/blob/master/lib/rocketgate/credit_card.rb) so we know who and how to charge:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
customer = RocketGate::Customer.new('John', 'Doe', '123 Main St', 'Beverly Hills', 'CA', '90210')
|
71
|
+
credit_card = RocketGate::CreditCard.new('4111-1111-1111-1111', '08', '2042', '012')
|
72
|
+
```
|
73
|
+
|
74
|
+
1. Build a [`Transaction`](https://github.com/ccashwell/rocketgate-ruby/blob/master/lib/rocketgate/transaction.rb)
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
transaction = RocketGate::Transaction.new(9.99, customer, credit_card)
|
78
|
+
```
|
79
|
+
|
80
|
+
1. Set the transaction type
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
transaction.type = RocketGate::Transaction::TYPE[:purchase]
|
84
|
+
```
|
85
|
+
|
86
|
+
1. Optionally, add an identifier that ties the transaction and customer to something relevant for you, like a `User` or `Invoice`. (A UUID will be generated if not.)
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
credit_card.id = User.id
|
90
|
+
transaction.id = Invoice.id
|
91
|
+
```
|
92
|
+
|
93
|
+
1. Build a [`Request`](https://github.com/ccashwell/rocketgate-ruby/blob/master/lib/rocketgate/request.rb)
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
request = RocketGate::Request.new(transaction)
|
97
|
+
```
|
98
|
+
|
99
|
+
1. Send the request to the gateway
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
response = RocketGate.send_request!(request)
|
103
|
+
```
|
104
|
+
|
105
|
+
1. Check the [`Response`](https://github.com/ccashwell/rocketgate-ruby/blob/master/lib/rocketgate/response.rb)
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
response.authorized? # => true (authorization OK)
|
109
|
+
response.success? # => true (authorization + gateway response OK)
|
110
|
+
```
|
111
|
+
|
112
|
+
1. Confirm receipt of the transaction response (**Note: RocketGate will cancel your transaction if you don't confirm it!**)
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
response.confirm! # => returns a Response like the original request
|
116
|
+
```
|
117
|
+
|
118
|
+
### Authorizations
|
119
|
+
|
120
|
+
In the section above you created and sent a request, then looked at the response. The response's [`Authorization`](https://github.com/ccashwell/rocketgate-ruby/blob/master/lib/rocketgate/authorization.rb) has lots of great information, too.
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
authorization = response.authorization
|
124
|
+
|
125
|
+
authorization.avs_ok? # => AVS check OK or disabled
|
126
|
+
authorization.cvv_ok? # => CVV check OK or disabled
|
127
|
+
authorization.success? # => AVS check + CVV check + reason code OK
|
128
|
+
authorization.declined? # => opposite of success?
|
129
|
+
authorization.auth_code # => authorization code from gateway, may be blank
|
130
|
+
authorization.reason_code # => descriptive(ish) reason for the response
|
131
|
+
authorization.approved_amount # => dollar amount of authorization (should match transaction)
|
132
|
+
authorization.approved_currency # => currency the authorization settled in (should match transaction)
|
133
|
+
authorization.card_hash # => unique hash of the card data which can be used later
|
134
|
+
authorization.card_expiration # => 4-digit representation of the card expiration
|
135
|
+
authorization.card_last_four # => the last four digits of the card charged
|
136
|
+
authorization.reference_id # => unique reference ID used to confirm, void or reverse the request
|
137
|
+
```
|
138
|
+
|
139
|
+
## Not Yet Implemented (Future Plans)
|
140
|
+
|
141
|
+
- Rebill functionality
|
142
|
+
|
143
|
+
## Compatibility
|
144
|
+
|
145
|
+
This library supports Ruby >= 1.9.3 on a variety of platforms.
|
146
|
+
|
147
|
+
[Travis CI](https://travis-ci.org/ccashwell/rocketgate-ruby) builds every commit under [these environments](https://github.com/ccashwell/rocketgate-ruby/blob/master/.travis.yml):
|
148
|
+
|
149
|
+
- MRI 1.9.3, 2.0.0, 2.1.1 and HEAD
|
150
|
+
- JRuby 1.7.11 (1.9 mode) and HEAD
|
151
|
+
- Rubinius 2.2.1
|
152
|
+
|
153
|
+
Other interpreters and earlier versions of MRI, JRuby and RBX are not supported.
|
154
|
+
|
155
|
+
## Contributing
|
156
|
+
|
157
|
+
1. Fork it ( https://github.com/ccashwell/rocketgate-ruby/fork )
|
158
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
159
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
160
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
161
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
# Default directory to look in is `/specs`
|
5
|
+
# Run with `rake spec`
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
7
|
+
task.rspec_opts = ['--color', '--format', 'documentation', '--tag', '~integration']
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:integration) do |task|
|
11
|
+
task.rspec_opts = ['--color', '--format', 'documentation', '--tag', 'integration']
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => :spec
|
data/lib/rocketgate.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module RocketGate
|
2
|
+
autoload :VERSION, 'rocketgate/version'
|
3
|
+
|
4
|
+
autoload :Authorization, 'rocketgate/authorization'
|
5
|
+
autoload :Configuration, 'rocketgate/configuration'
|
6
|
+
autoload :Connection, 'rocketgate/connection'
|
7
|
+
autoload :CreditCard, 'rocketgate/credit_card'
|
8
|
+
autoload :Customer, 'rocketgate/customer'
|
9
|
+
autoload :Request, 'rocketgate/request'
|
10
|
+
autoload :Response, 'rocketgate/response'
|
11
|
+
autoload :ResponseCode, 'rocketgate/response_code'
|
12
|
+
autoload :Transaction, 'rocketgate/transaction'
|
13
|
+
|
14
|
+
autoload :Hashable, 'rocketgate/hashable'
|
15
|
+
autoload :Validatable, 'rocketgate/validatable'
|
16
|
+
|
17
|
+
AuthorizationError = Class.new(StandardError)
|
18
|
+
ValidationError = Class.new(StandardError)
|
19
|
+
GatewayRequestError = Class.new(StandardError)
|
20
|
+
GatewayResponseError = Class.new(StandardError)
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def configuration
|
24
|
+
@configuration ||= Configuration.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def configure
|
28
|
+
yield(configuration)
|
29
|
+
end
|
30
|
+
|
31
|
+
def connection
|
32
|
+
configuration.validate!
|
33
|
+
@connection ||= Connection.new(configuration.request_host,
|
34
|
+
configuration.request_port,
|
35
|
+
configuration.request_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset!
|
39
|
+
@configuration, @connection = nil, nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def send_request!(request)
|
43
|
+
response = connection.make_request!(request.build_gateway_request)
|
44
|
+
|
45
|
+
if response.code.to_i == 200
|
46
|
+
return Response.from_xml(response.body)
|
47
|
+
else
|
48
|
+
raise GatewayRequestError.new("Unexpected status code in gateway response: #{response.code}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RocketGate
|
2
|
+
class Authorization
|
3
|
+
attr_accessor :auth_code, :avs_response, :cvv_response, :reason_code,
|
4
|
+
:approved_amount, :approved_currency, :card_hash,
|
5
|
+
:card_expiration, :card_last_four, :reference_id
|
6
|
+
|
7
|
+
def avs_ok?
|
8
|
+
if RocketGate.configuration.require_avs
|
9
|
+
RocketGate::ResponseCode::AVS_SUCCESSES.include?(avs_response)
|
10
|
+
else
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def cvv_ok?
|
16
|
+
if RocketGate.configuration.require_cvv
|
17
|
+
RocketGate::ResponseCode::CVV_SUCCESSES.include?(cvv_response)
|
18
|
+
else
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def declined?
|
24
|
+
!success?
|
25
|
+
end
|
26
|
+
|
27
|
+
def success?
|
28
|
+
avs_ok? && cvv_ok? && reason_code == :success
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module RocketGate
|
2
|
+
class Configuration
|
3
|
+
include Validatable
|
4
|
+
|
5
|
+
attr_accessor :currency,
|
6
|
+
:merchant_id,
|
7
|
+
:merchant_password,
|
8
|
+
:request_timeout,
|
9
|
+
:request_host,
|
10
|
+
:request_path,
|
11
|
+
:request_port,
|
12
|
+
:request_version,
|
13
|
+
:require_avs,
|
14
|
+
:require_cvv,
|
15
|
+
:require_scrub,
|
16
|
+
:require_ssl
|
17
|
+
|
18
|
+
validatable :currency, :merchant_id, :merchant_password, :request_host,
|
19
|
+
:request_path, :request_port, :request_timeout, :request_version,
|
20
|
+
:require_avs, :require_cvv, :require_scrub, :require_ssl
|
21
|
+
|
22
|
+
GATEWAY_LIVE_HOST = 'gw-16.rocketgate.com'
|
23
|
+
GATEWAY_TEST_HOST = 'dev-gw.rocketgate.com'
|
24
|
+
GATEWAY_PORT = 443
|
25
|
+
GATEWAY_SERVLET = '/gateway/servlet/ServiceDispatcherAccess'
|
26
|
+
GATEWAY_VERSION = 'R1.2'
|
27
|
+
DEFAULT_TIMEOUT = 10
|
28
|
+
DEFAULT_CURRENCY = 'USD'
|
29
|
+
USER_AGENT_STRING = "rocketgate-ruby/#{RocketGate::VERSION}"
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@currency = DEFAULT_CURRENCY
|
33
|
+
@request_host = GATEWAY_LIVE_HOST
|
34
|
+
@request_path = GATEWAY_SERVLET
|
35
|
+
@request_port = GATEWAY_PORT
|
36
|
+
@request_timeout = DEFAULT_TIMEOUT
|
37
|
+
@request_version = GATEWAY_VERSION
|
38
|
+
@require_avs = true
|
39
|
+
@require_cvv = true
|
40
|
+
@require_scrub = true
|
41
|
+
@require_ssl = true
|
42
|
+
end
|
43
|
+
|
44
|
+
def testing!
|
45
|
+
@request_host = GATEWAY_TEST_HOST
|
46
|
+
@request_port = GATEWAY_PORT
|
47
|
+
@merchant_id = '1'
|
48
|
+
@merchant_password = 'testpassword'
|
49
|
+
|
50
|
+
self
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module RocketGate
|
4
|
+
class Connection
|
5
|
+
def initialize(server, port, path)
|
6
|
+
@server, @port, @path = server, port, path
|
7
|
+
@client = Net::HTTP.new(server, port)
|
8
|
+
|
9
|
+
@client.open_timeout = RocketGate.configuration.request_timeout
|
10
|
+
@client.read_timeout = RocketGate.configuration.request_timeout
|
11
|
+
|
12
|
+
if RocketGate.configuration.require_ssl
|
13
|
+
@client.use_ssl = true
|
14
|
+
@client.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def make_request!(request_body)
|
19
|
+
request = Net::HTTP::Post.new(@path, {
|
20
|
+
'Accept' => 'text/xml',
|
21
|
+
'Content-Type' => 'text/xml',
|
22
|
+
'User-Agent' => "rocketgate-ruby/#{RocketGate::VERSION}"
|
23
|
+
})
|
24
|
+
|
25
|
+
request.body = request_body
|
26
|
+
|
27
|
+
@client.request(request)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module RocketGate
|
2
|
+
class CreditCard
|
3
|
+
include Hashable, Validatable
|
4
|
+
|
5
|
+
attr_accessor :cvv, :exp_month, :exp_year, :number, :card_hash
|
6
|
+
|
7
|
+
validatable :number, :exp_month, :exp_year
|
8
|
+
|
9
|
+
hashable({
|
10
|
+
cardNo: :number,
|
11
|
+
expireMonth: :exp_month,
|
12
|
+
expireYear: :exp_year,
|
13
|
+
cvv2: :cvv
|
14
|
+
})
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
@number, @exp_month, @exp_year, @cvv = *args
|
18
|
+
|
19
|
+
clean_number! if @number
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_card_hash(card_hash)
|
23
|
+
new.tap do |cc|
|
24
|
+
cc.card_hash = card_hash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_hash
|
29
|
+
card_hash ? { cardHash: card_hash } : super
|
30
|
+
end
|
31
|
+
|
32
|
+
def valid?
|
33
|
+
!card_hash.nil? || super
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def clean_number!
|
39
|
+
@number.delete!("^0-9")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|