rocketgate-ruby 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/ccashwell/rocketgate-ruby.svg?branch=master)](https://travis-ci.org/ccashwell/rocketgate-ruby)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/ccashwell/rocketgate-ruby/badge.png)](https://coveralls.io/r/ccashwell/rocketgate-ruby)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/ccashwell/rocketgate-ruby/badges/gpa.svg)](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
|