cardflex-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +125 -0
- data/cardflex.gemspec +14 -0
- data/lib/cardflex.rb +32 -0
- data/lib/cardflex/base_module.rb +34 -0
- data/lib/cardflex/configuration.rb +96 -0
- data/lib/cardflex/customer_vault.rb +35 -0
- data/lib/cardflex/customer_vault_gateway.rb +26 -0
- data/lib/cardflex/error_response.rb +18 -0
- data/lib/cardflex/errors.rb +11 -0
- data/lib/cardflex/gateway.rb +35 -0
- data/lib/cardflex/http.rb +68 -0
- data/lib/cardflex/plan.rb +22 -0
- data/lib/cardflex/plan_gateway.rb +23 -0
- data/lib/cardflex/subscription.rb +24 -0
- data/lib/cardflex/subscription_gateway.rb +22 -0
- data/lib/cardflex/success_response.rb +15 -0
- data/lib/cardflex/test/test_values.rb +26 -0
- data/lib/cardflex/three_step.rb +42 -0
- data/lib/cardflex/three_step_gateway.rb +41 -0
- data/lib/cardflex/transaction.rb +52 -0
- data/lib/cardflex/transaction_gateway.rb +23 -0
- data/lib/cardflex/version.rb +9 -0
- data/lib/cardflex/xml.rb +11 -0
- data/lib/cardflex/xml/parser.rb +48 -0
- data/lib/cardflex/xml/serializer.rb +70 -0
- data/lib/ssl/ca-certificates.ca.crt +4190 -0
- data/spec/integration/cardflex/http_spec.rb +72 -0
- data/spec/integration/cardflex/plan_spec.rb +24 -0
- data/spec/integration/cardflex/three_step_gateway_spec.rb +47 -0
- data/spec/integration/cardflex/three_step_spec.rb +37 -0
- data/spec/integration/spec_helper.rb +24 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/ssl/certificate.crt +21 -0
- data/spec/ssl/geotrust_global.crt +20 -0
- data/spec/ssl/private_key.pem +30 -0
- data/spec/unit/cardflex/base_module_spec.rb +34 -0
- data/spec/unit/cardflex/configuration_spec.rb +61 -0
- data/spec/unit/cardflex/customer_vault_gateway_spec.rb +10 -0
- data/spec/unit/cardflex/errors_spec.rb +8 -0
- data/spec/unit/cardflex/gateway_spec.rb +11 -0
- data/spec/unit/cardflex/http_spec.rb +18 -0
- data/spec/unit/cardflex/three_step_gateway_spec.rb +29 -0
- data/spec/unit/cardflex/xml_spec.rb +90 -0
- data/spec/unit/spec_helper.rb +1 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3ef2bceb03de84a741378a2761eb5bb7c6736316
|
4
|
+
data.tar.gz: afb94e6ff243cee5a76ec19051fdedb46b1dbfda
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2169e2f0d1cbb395ad6099b5b66a74160270dc3de4a577d4189434fe85c61952b378119b4b6a59170f3f2792f715ae21877a52d596155ed5ce1b4ac81722341e
|
7
|
+
data.tar.gz: 7e894a100ca40369a959849ab5efb8fefef68d9f2e80bd1c2f11f038da2ce259fb61fd943e4ed1bac7e06434129d7a9fb7cbddf3a438385d9a66e421ced08a9f
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Tom King
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# Cardflex Ruby Client Library (Unofficial)
|
2
|
+
|
3
|
+
This gem provides client integration with the Cardflex API: https://secure.cardflexonline.com/gw/merchants/resources/integration/integration_portal.php. Currently, only the operations under the Three Step Integration are supported. This gem is supported by the community and is not associated with Cardflex.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```shell
|
8
|
+
gem install cardflex-ruby
|
9
|
+
```
|
10
|
+
|
11
|
+
Or add this line to your Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem "cardflex-ruby"
|
15
|
+
```
|
16
|
+
|
17
|
+
And run a bundle install
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Before you can perform any actions, you must set your api_key:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
Cardflex::Configuration.api_key = "my_api_key"
|
25
|
+
```
|
26
|
+
|
27
|
+
You can also change the logger (default is stdout):
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
Cardflex::Configuration.logger
|
31
|
+
```
|
32
|
+
|
33
|
+
To start step 1 of a transaction, use the Three Step API to initiatialize the request process, and use the result to set the form URL for part 2:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# See Cardflex documentation for required parameters
|
37
|
+
step_one = Cardflex::ThreeStep.sale({
|
38
|
+
:redirect_url => "https://example.com",
|
39
|
+
:amount => 5.00
|
40
|
+
})
|
41
|
+
|
42
|
+
if step_one.success?
|
43
|
+
@form_url = step_one.three_step.form_url
|
44
|
+
else
|
45
|
+
@error_message = step_one.result_text
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
During step 2, you will present to your users a form that will POST to Cardflex using the form_url you received from Cardflex in step 1. Then, the user will be redirected to the :redirect_url supplied in the initial request, with a token_id that you send back to Cardflex to complete the transaction in the query string:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
token_id = params['token_id']
|
53
|
+
|
54
|
+
result = Cardflex::ThreeStep.complete(token_id)
|
55
|
+
|
56
|
+
if result.success?
|
57
|
+
# payment has been processed, send user the all clear
|
58
|
+
else
|
59
|
+
@error_message = step_one.result_text
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
The library will automatically add your api key to each request. You can also access these methods via the ThreeStep API:
|
64
|
+
|
65
|
+
```
|
66
|
+
# Transactional Methods
|
67
|
+
ThreeStep#sale
|
68
|
+
ThreeStep#credit
|
69
|
+
ThreeStep#auth
|
70
|
+
ThreeStep#offline
|
71
|
+
ThreeStep#validate
|
72
|
+
|
73
|
+
# Recurring Methods
|
74
|
+
ThreeStep#add_subscription
|
75
|
+
ThreeStep#update_subscription
|
76
|
+
|
77
|
+
# Customer Vault Methods
|
78
|
+
ThreeStep#add_customer
|
79
|
+
ThreeStep#update_customer
|
80
|
+
ThreeStep#add_billing
|
81
|
+
ThreeStep#update_billing
|
82
|
+
```
|
83
|
+
|
84
|
+
The methods above exist for your convenience, and take care of adding the root level XML node to the request. If you want to control the full XML request, you can use this method to do it all yourself (api key is still added):
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
# Step One
|
88
|
+
Cardflex::ThreeStep.get_form_url(:sale => {
|
89
|
+
:redirect_url => "https://example.com",
|
90
|
+
:amount => 5.00
|
91
|
+
})
|
92
|
+
```
|
93
|
+
|
94
|
+
## Other Features
|
95
|
+
|
96
|
+
In addition to supporting the Three Step API, you can also perform a few other actions that do not involve sensitive information, and so you are freed from having to use the Three Step process:
|
97
|
+
|
98
|
+
```
|
99
|
+
Plan#create
|
100
|
+
Subscription#delete
|
101
|
+
CustomerVault#sale
|
102
|
+
CustomerVault#credit
|
103
|
+
CustomerVault#auth
|
104
|
+
CustomerVault#offline
|
105
|
+
CustomerVault#delete_customer
|
106
|
+
CustomerVault#delete_billing
|
107
|
+
Transaction#void
|
108
|
+
Transaction#capture
|
109
|
+
Transaction#refund
|
110
|
+
```
|
111
|
+
|
112
|
+
## More Information
|
113
|
+
|
114
|
+
You can find all the Cardflex documentation here: https://secure.cardflexonline.com/gw/merchants/resources/integration/integration_portal.php
|
115
|
+
|
116
|
+
## Tests
|
117
|
+
|
118
|
+
The tests run against the Cardflex API using the testing account. You will need an internet connection to run some of the tests.
|
119
|
+
|
120
|
+
## Contributing
|
121
|
+
|
122
|
+
All pull requests that add tests, clean up the code, add features, or fix issues are welcome. Be sure to write tests for any and all changes to the code base, and make sure all tests pass before submitting.
|
123
|
+
|
124
|
+
## License
|
125
|
+
MIT. See LICENSE file.
|
data/cardflex.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require 'cardflex/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "cardflex-ruby"
|
6
|
+
s.summary = "Cardflex gateway ruby client library"
|
7
|
+
s.version = Cardflex::Version::Full
|
8
|
+
s.license = "MIT"
|
9
|
+
s.author = "Tom King"
|
10
|
+
s.homepage = "https://github.com/twking7/cardflex-ruby"
|
11
|
+
s.has_rdoc = false
|
12
|
+
s.files = Dir.glob ["README.md", "LICENSE", "lib/**/*.{rb,crt}", "spec/**/*", "*.gemspec"]
|
13
|
+
s.add_dependency "builder", ">= 2.0.0"
|
14
|
+
end
|
data/lib/cardflex.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Libraries
|
2
|
+
require 'logger'
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
|
6
|
+
require 'builder'
|
7
|
+
|
8
|
+
# Test Values
|
9
|
+
require 'cardflex/test/test_values'
|
10
|
+
|
11
|
+
# Cardflex
|
12
|
+
require 'cardflex/version'
|
13
|
+
require 'cardflex/configuration'
|
14
|
+
require 'cardflex/errors'
|
15
|
+
require 'cardflex/xml/parser'
|
16
|
+
require 'cardflex/xml/serializer'
|
17
|
+
require 'cardflex/xml'
|
18
|
+
require 'cardflex/http'
|
19
|
+
require 'cardflex/base_module'
|
20
|
+
require 'cardflex/success_response'
|
21
|
+
require 'cardflex/error_response'
|
22
|
+
require 'cardflex/gateway'
|
23
|
+
require 'cardflex/transaction_gateway'
|
24
|
+
require 'cardflex/transaction'
|
25
|
+
require 'cardflex/plan_gateway'
|
26
|
+
require 'cardflex/plan'
|
27
|
+
require 'cardflex/subscription_gateway'
|
28
|
+
require 'cardflex/subscription'
|
29
|
+
require 'cardflex/customer_vault'
|
30
|
+
require 'cardflex/customer_vault_gateway'
|
31
|
+
require 'cardflex/three_step_gateway'
|
32
|
+
require 'cardflex/three_step'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Cardflex
|
2
|
+
module BaseModule
|
3
|
+
module ClassMethods
|
4
|
+
def set_instance_variables_from_hash(hash)
|
5
|
+
hash.each do |k, v|
|
6
|
+
instance_variable_set("@#{k}", v)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def snakecase(str)
|
11
|
+
str.gsub('-', '_').downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
# takes a module that contains constants with method names.
|
15
|
+
# create class methods using these names that add the root
|
16
|
+
# xml node to the request. these methods are just sugar
|
17
|
+
def create_helper_methods(type)
|
18
|
+
method_names = type.constants.map { |t| type.const_get(t) }
|
19
|
+
|
20
|
+
method_names.each do |name|
|
21
|
+
define_singleton_method(name) do |attributes|
|
22
|
+
yield(name => attributes)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.extend(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
include ClassMethods
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Cardflex
|
2
|
+
class Configuration
|
3
|
+
API_VERSION = 3
|
4
|
+
SERVER = "secure.cardflexonline.com"
|
5
|
+
PORT = 443
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_writer :logger, :api_key
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :api_key
|
12
|
+
|
13
|
+
def self.expectant_reader(*attributes)
|
14
|
+
attributes.each do |attribute|
|
15
|
+
(class << self; self; end).send(:define_method, attribute) do
|
16
|
+
value = instance_variable_get("@#{attribute}")
|
17
|
+
raise ConfigurationError.new(attribute.to_s, "needs to be set") unless value
|
18
|
+
value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
expectant_reader :api_key, :environment
|
23
|
+
|
24
|
+
def initialize(options={})
|
25
|
+
[:environment, :api_key, :logger].each do |attr|
|
26
|
+
instance_variable_set("@#{attr}", options[attr])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.environment=(env)
|
31
|
+
unless [:development, :test, :production].include?(env)
|
32
|
+
raise ArgumentError, "#{env} is not a valid environment"
|
33
|
+
end
|
34
|
+
|
35
|
+
@environment = env
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.gateway
|
39
|
+
Cardflex::Gateway.new(instantiate)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.instantiate
|
43
|
+
config = new(
|
44
|
+
:environment => @environment,
|
45
|
+
:logger => logger,
|
46
|
+
:api_key => api_key
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def ca_file
|
51
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", "ssl", "ca-certificates.ca.crt"))
|
52
|
+
end
|
53
|
+
|
54
|
+
def http
|
55
|
+
Http.new(self)
|
56
|
+
end
|
57
|
+
|
58
|
+
def three_step_path
|
59
|
+
"/api/v2/three-step"
|
60
|
+
end
|
61
|
+
|
62
|
+
def server
|
63
|
+
SERVER
|
64
|
+
end
|
65
|
+
|
66
|
+
def protocol
|
67
|
+
"https"
|
68
|
+
end
|
69
|
+
|
70
|
+
def port
|
71
|
+
PORT
|
72
|
+
end
|
73
|
+
|
74
|
+
def ssl?
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def api_version
|
79
|
+
API_VERSION
|
80
|
+
end
|
81
|
+
|
82
|
+
def logger
|
83
|
+
@logger ||= self.class._default_logger
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.logger
|
87
|
+
@logger ||= _default_logger
|
88
|
+
end
|
89
|
+
|
90
|
+
def self._default_logger
|
91
|
+
logger = Logger.new(STDOUT)
|
92
|
+
logger.level = Logger::INFO
|
93
|
+
logger
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Cardflex
|
2
|
+
class CustomerVault
|
3
|
+
include BaseModule
|
4
|
+
|
5
|
+
module Type
|
6
|
+
Sale = 'sale'
|
7
|
+
Auth = 'auth'
|
8
|
+
Credit = 'credit'
|
9
|
+
Offline = 'offline'
|
10
|
+
DeleteCustomer = 'delete_customer'
|
11
|
+
DeleteBilling = 'delete_billing'
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :config
|
15
|
+
attr_reader :result, :result_text, :result_code, :action_type
|
16
|
+
attr_reader :customer_vault_id
|
17
|
+
attr_reader :type, :billing, :shipping
|
18
|
+
|
19
|
+
def initialize(gateway, attributes)
|
20
|
+
@gateway = gateway
|
21
|
+
@config = gateway.config
|
22
|
+
@type = attributes[:action_type]
|
23
|
+
|
24
|
+
set_instance_variables_from_hash(attributes)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.request(attributes)
|
28
|
+
Configuration.gateway.customer_vault.request(attributes)
|
29
|
+
end
|
30
|
+
|
31
|
+
create_helper_methods(Type) do |attributes|
|
32
|
+
request(attributes)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Cardflex
|
2
|
+
class CustomerVaultGateway
|
3
|
+
attr_reader :config
|
4
|
+
|
5
|
+
def initialize(gateway)
|
6
|
+
@gateway = gateway
|
7
|
+
@config = gateway.config
|
8
|
+
end
|
9
|
+
|
10
|
+
def request(attributes)
|
11
|
+
root = attributes.keys[0]
|
12
|
+
raise ArgumentError, 'missing redirect_url' unless attributes[root][:redirect_url]
|
13
|
+
raise ArgumentError, 'missing customer_vault_id' unless attributes[root][:customer_vault_id]
|
14
|
+
|
15
|
+
@config.http.post(attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def _handle_response(res)
|
19
|
+
if res[:response][:result] == '1'
|
20
|
+
SuccessResponse.new(:customer_vault => CustomerVault.new(@gateway, res[:response]))
|
21
|
+
else
|
22
|
+
ErrorResponse.new(@gateway, res[:response])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Cardflex
|
2
|
+
class ErrorResponse
|
3
|
+
include BaseModule
|
4
|
+
|
5
|
+
attr_reader :result, :result_code, :result_text
|
6
|
+
|
7
|
+
def initialize(gateway, hash={})
|
8
|
+
@gateway = gateway
|
9
|
+
@result = hash[:result].to_i
|
10
|
+
@result_code = hash[:result_code]
|
11
|
+
@result_text = hash[:result_text]
|
12
|
+
end
|
13
|
+
|
14
|
+
def success?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Cardflex
|
2
|
+
class CardflexError < ::StandardError; end
|
3
|
+
|
4
|
+
class ConfigurationError < CardflexError
|
5
|
+
def initialize(setting, message)
|
6
|
+
super "Cardflex::Configuration.#{setting} #{message}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class SSLCertificateError < CardflexError; end
|
11
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Cardflex
|
2
|
+
class Gateway
|
3
|
+
attr_reader :config
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
if config.is_a? Hash
|
7
|
+
@config = Configuration.new(config)
|
8
|
+
elsif config.is_a? Configuration
|
9
|
+
@config = config
|
10
|
+
else
|
11
|
+
raise ArgumentError, "config is an invalid type"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def transaction
|
16
|
+
TransactionGateway.new(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def plan
|
20
|
+
PlanGateway.new(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def three_step
|
24
|
+
ThreeStepGateway.new(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def customer_vault
|
28
|
+
CustomerVaultGateway.new(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def subscription
|
32
|
+
SubscriptionGateway.new(self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|