paysafe 0.6.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env.sample +5 -0
- data/.travis.yml +4 -4
- data/CHANGELOG.md +28 -0
- data/README.md +64 -26
- data/bin/setup +8 -7
- data/lib/paysafe/address.rb +9 -0
- data/lib/paysafe/authorization.rb +14 -0
- data/lib/paysafe/birth_date.rb +7 -0
- data/lib/paysafe/card.rb +13 -0
- data/lib/paysafe/card_expiry.rb +7 -0
- data/lib/paysafe/error.rb +6 -7
- data/lib/paysafe/profile.rb +13 -0
- data/lib/paysafe/refinements/camel_case.rb +40 -0
- data/lib/paysafe/refinements/snake_case.rb +45 -0
- data/lib/paysafe/rest/client.rb +89 -120
- data/lib/paysafe/result.rb +86 -0
- data/lib/paysafe/single_use_token.rb +10 -0
- data/lib/paysafe/verification.rb +13 -0
- data/lib/paysafe/version.rb +1 -1
- data/lib/paysafe.rb +10 -0
- data/paysafe.gemspec +6 -4
- metadata +32 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6bbfa2b88d67e16221b48a7fdc9e2048f3e83e2
|
4
|
+
data.tar.gz: f4e8670f77a2ca5a406b5a52794a446f87f2dabe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd143b165e5467ae27d084c9011ce710d80dd40eff19fbd2896a4514b6a3d1dff4ccefea27ee533aa05b2c37825970a3644bd7cd14111ec313ba4192fdd725f6
|
7
|
+
data.tar.gz: f577618983eaa4dc510f5fa4def95780be2c85c8ec791d35ea8c300018acbc56780f3f58a7fbf6e5c0558e9ce6d8114cc5fc89c7c8b96d34b69ce77b2205eeb0
|
data/.env.sample
CHANGED
@@ -1,3 +1,8 @@
|
|
1
1
|
PAYSAFE_ACCOUNT_NUMBER="YOUR_ACCOUNT_NUMBER"
|
2
2
|
PAYSAFE_API_KEY="YOUR_API_KEY"
|
3
3
|
PAYSAFE_API_SECRET="YOUR_API_SECRET"
|
4
|
+
|
5
|
+
# This is only needed if you want to generate your own Single
|
6
|
+
# Use Tokens which utilize a different API key and secret.
|
7
|
+
PAYSAFE_SUT_API_KEY="YOUR_SINGLE_USE_TOKEN_API_KEY"
|
8
|
+
PAYSAFE_SUT_API_SECRET="YOUR_SINGLE_USE_TOKEN_API_SECRET"
|
data/.travis.yml
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.
|
4
|
-
- 2.
|
5
|
-
before_install: gem install bundler
|
3
|
+
- 2.3.4
|
4
|
+
- 2.4.1
|
5
|
+
before_install: gem install bundler
|
6
6
|
cache: bundler
|
7
7
|
sudo: false
|
8
8
|
fast_finish: true
|
9
9
|
env:
|
10
|
-
-
|
10
|
+
- SKIP_INTEGRATION=true
|
11
11
|
notifications:
|
12
12
|
email:
|
13
13
|
on_success: always
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Changelog
|
2
|
+
=========
|
3
|
+
|
4
|
+
## 0.9.0 (2017-04-19)
|
5
|
+
|
6
|
+
This is a major update with breaking changes so moving the version up quite a bit since I'd also like to move to a 1.0 release soon after.
|
7
|
+
|
8
|
+
* Requires Ruby 2.3 and up.
|
9
|
+
* All API methods now accept params in snake_case and are converted to camelCase.
|
10
|
+
* Responses are now typed with classes using snake_case properties (converted from camelCase) handling nested complex objects and lazily loaded. No more hashes.
|
11
|
+
* Field names match Paysafe API docs except when making requests and working with responses, its all in snake_case.
|
12
|
+
* Renamed config `timeout_options` renamed to `timeouts`.
|
13
|
+
* Removed default value for `timeouts` config.
|
14
|
+
* Added new methods to work with single use tokens:
|
15
|
+
* `create_single_use_token` (requires different API key and secret)
|
16
|
+
* `create_verification_from_token`
|
17
|
+
* `create_profile_from_token`
|
18
|
+
* `create_card_from_token`
|
19
|
+
* Updated `bin/setup` script.
|
20
|
+
* Updated API base domain to paysafe.com.
|
21
|
+
|
22
|
+
## 0.6.2 (2016-04-25)
|
23
|
+
|
24
|
+
* Upgrade http gem to v2.0
|
25
|
+
|
26
|
+
## 0.6.1 (2016-03-02)
|
27
|
+
|
28
|
+
* Add `update_profile` method to client
|
data/README.md
CHANGED
@@ -3,54 +3,88 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/paysafe.svg)][gem]
|
4
4
|
[![Build Status](https://travis-ci.org/javierjulio/paysafe.svg?branch=master)][travis]
|
5
5
|
|
6
|
-
[
|
7
|
-
[travis]: https://travis-ci.org/javierjulio/paysafe
|
8
|
-
|
9
|
-
A tested Ruby interface to the Paysafe REST API (formerly Optimal Payments). Note: requires Ruby 2.1 and up. Not all API actions are supported yet.
|
6
|
+
A well tested Ruby interface to the [Paysafe REST API](paysafe_api_reference) (formerly Optimal Payments). Requires Ruby 2.3 and up. Not all API actions are supported yet. Since the Paysafe API uses camelCase, this gem will handle converting to and from snake_case for you.
|
10
7
|
|
11
8
|
## Installation
|
12
9
|
|
13
|
-
Add
|
10
|
+
Add the following to your application's Gemfile:
|
14
11
|
|
15
12
|
```ruby
|
16
13
|
gem 'paysafe'
|
17
14
|
```
|
18
15
|
|
19
|
-
|
16
|
+
Or install directly with `gem install paysafe`.
|
20
17
|
|
21
|
-
|
18
|
+
To try out the gem, just follow the Development section instructions as the built in setup script will direct you on how to provide the necessary API info.
|
22
19
|
|
23
|
-
|
20
|
+
## Usage
|
24
21
|
|
25
|
-
|
22
|
+
### Client Configuration
|
26
23
|
|
27
|
-
|
24
|
+
Create and configure a client with your API authentication.
|
28
25
|
|
29
|
-
|
26
|
+
```ruby
|
27
|
+
client = Paysafe::REST::Client.new do |config|
|
28
|
+
config.account_number = '1234567890'
|
29
|
+
config.api_key = 'api_key'
|
30
|
+
config.api_secret = 'api_secret'
|
31
|
+
# Enable production requests
|
32
|
+
# config.test_mode = false
|
33
|
+
# Provide explicit timeouts
|
34
|
+
# config.timeouts = { connect: 2, read: 5, write: 10 }
|
35
|
+
end
|
36
|
+
```
|
30
37
|
|
31
|
-
|
38
|
+
### Making Requests
|
32
39
|
|
33
|
-
|
40
|
+
Make an API request with a payload in the structure documented by the [Paysafe REST API](paysafe_api_reference) but using snake_case. The request payload will be converted to camelCase for you.
|
34
41
|
|
35
|
-
|
36
|
-
|
42
|
+
```ruby
|
43
|
+
profile = client.create_profile(
|
44
|
+
merchant_customer_id: '123',
|
45
|
+
locale: 'en_US',
|
46
|
+
card: {
|
47
|
+
card_num: '4111111111111111',
|
48
|
+
card_expiry: {
|
49
|
+
month: 12,
|
50
|
+
year: 2020
|
51
|
+
}
|
52
|
+
}
|
53
|
+
)
|
54
|
+
```
|
37
55
|
|
38
|
-
|
39
|
-
gem update
|
40
|
-
gem install bundler --no-rdoc --no-ri
|
56
|
+
### Handling Responses
|
41
57
|
|
42
|
-
|
43
|
-
4. Run `./bin/console` for an interactive prompt with an authenticated client for you to experiment:
|
58
|
+
Response data is in snake_case (converted from camelCase) typed with individual methods and predicates, including nested complex objects and array of objects as shown below:
|
44
59
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
60
|
+
```ruby
|
61
|
+
profile.id?
|
62
|
+
# => true
|
63
|
+
profile.id
|
64
|
+
# => b088ac37...
|
65
|
+
profile.cards.first.card_expiry.year
|
66
|
+
# => 2020
|
67
|
+
```
|
68
|
+
|
69
|
+
Further API methods are provided in the `Paysafe::REST::Client` object.
|
70
|
+
|
71
|
+
## Development
|
72
|
+
|
73
|
+
1. `git clone https://github.com/javierjulio/paysafe.git`
|
74
|
+
2. Run `./bin/setup` to install dependencies and fill out API key info
|
75
|
+
3. Run `./bin/console` for an interactive prompt with an authenticated client for you to experiment:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
profile = client.create_profile(merchant_customer_id: '123', locale: 'en_US')
|
79
|
+
puts profile.id
|
80
|
+
# => b088ac37...
|
81
|
+
```
|
82
|
+
|
83
|
+
All code is written in snake_case since requests and responses are converted to and from camelCase for you.
|
50
84
|
|
51
85
|
### Tests
|
52
86
|
|
53
|
-
Run `bundle exec rake test` or to skip integration tests run with `
|
87
|
+
Run `bundle exec rake test` or to skip integration tests run with `SKIP_INTEGRATION=true`.
|
54
88
|
|
55
89
|
### Releasing
|
56
90
|
|
@@ -63,3 +97,7 @@ Bug reports and pull requests for missing API support are welcome on GitHub at h
|
|
63
97
|
## License
|
64
98
|
|
65
99
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
100
|
+
|
101
|
+
[gem]: https://rubygems.org/gems/paysafe
|
102
|
+
[travis]: https://travis-ci.org/javierjulio/paysafe
|
103
|
+
[paysafe_api_reference]: https://developer.paysafe.com/en/api-reference/
|
data/bin/setup
CHANGED
@@ -4,15 +4,16 @@ IFS=$'\n\t'
|
|
4
4
|
|
5
5
|
bundle install
|
6
6
|
|
7
|
-
read -r -p 'Do you have an
|
7
|
+
read -r -p 'Do you have an Paysafe Developer account? (y/n) ' has_account
|
8
8
|
|
9
9
|
if [[ "$has_account" =~ ^(Yes|yes|Y|y)$ ]]; then
|
10
10
|
echo "Great! You can get your account credentials from:"
|
11
|
-
echo " https://
|
11
|
+
echo " https://login.test.netbanx.com/office/public/preLogin.htm"
|
12
12
|
echo
|
13
13
|
else
|
14
|
-
echo "Then you'll need to create an account first
|
15
|
-
echo "
|
14
|
+
echo "Then you'll need to create an account first."
|
15
|
+
echo "Click the 'Sign Up' button on the following page:"
|
16
|
+
echo " https://developer.paysafe.com/"
|
16
17
|
echo
|
17
18
|
read -s -p "Press Enter key if you're ready to continue..."
|
18
19
|
echo
|
@@ -24,8 +25,8 @@ read -p 'API Key: ' api_key
|
|
24
25
|
read -p 'API Secret: ' api_secret
|
25
26
|
|
26
27
|
cp .env.sample .env
|
27
|
-
sed -i -e s/YOUR_ACCOUNT_NUMBER
|
28
|
-
sed -i -e s/YOUR_API_KEY
|
29
|
-
sed -i -e s/YOUR_API_SECRET
|
28
|
+
sed -i '' -e "s/YOUR_ACCOUNT_NUMBER/$account_number/g" .env
|
29
|
+
sed -i '' -e "s/YOUR_API_KEY/$api_key/g" .env
|
30
|
+
sed -i '' -e "s/YOUR_API_SECRET/$api_secret/g" .env
|
30
31
|
|
31
32
|
echo "Done."
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'paysafe/result'
|
2
|
+
|
3
|
+
module Paysafe
|
4
|
+
class Authorization < Result
|
5
|
+
attributes :id, :merchant_ref_num, :amount, :settle_with_auth,
|
6
|
+
:pre_auth, :available_to_settle, :child_account_num, :auth_code,
|
7
|
+
:recurring, :customer_ip, :dup_check, :description, :txn_time,
|
8
|
+
:currency_code, :avs_response, :cvv_verification, :status, :keywords
|
9
|
+
|
10
|
+
object_attribute :Card, :card
|
11
|
+
object_attribute :Profile, :profile
|
12
|
+
object_attribute :Address, :billing_details
|
13
|
+
end
|
14
|
+
end
|
data/lib/paysafe/card.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'paysafe/result'
|
2
|
+
|
3
|
+
module Paysafe
|
4
|
+
class Card < Result
|
5
|
+
attributes :id, :nick_name, :merchant_ref_num, :holder_name,
|
6
|
+
:card_num, :card_bin, :last_digits, :card_type, :billing_address_id,
|
7
|
+
:default_card_indicator, :payment_token, :single_use_token, :status,
|
8
|
+
:cvv, :track1, :track2, :type
|
9
|
+
|
10
|
+
object_attribute :CardExpiry, :card_expiry
|
11
|
+
object_attribute :Address, :billing_address
|
12
|
+
end
|
13
|
+
end
|
data/lib/paysafe/error.rb
CHANGED
@@ -81,22 +81,21 @@ module Paysafe
|
|
81
81
|
# @param body [String]
|
82
82
|
# @param code [Integer]
|
83
83
|
# @return [Paysafe::Error]
|
84
|
-
def
|
84
|
+
def from_response(body, code)
|
85
85
|
klass = ERRORS[code] || Paysafe::Error
|
86
86
|
message, error_code = parse_error(body)
|
87
87
|
klass.new(message: message, code: error_code, response: body)
|
88
88
|
end
|
89
89
|
|
90
|
-
|
90
|
+
private
|
91
91
|
|
92
92
|
def parse_error(body)
|
93
|
-
if body.
|
94
|
-
[
|
95
|
-
|
96
|
-
[
|
93
|
+
if body.is_a?(Hash)
|
94
|
+
[ body.dig(:error, :message), body.dig(:error, :code) ]
|
95
|
+
else
|
96
|
+
[ '', nil ]
|
97
97
|
end
|
98
98
|
end
|
99
|
-
|
100
99
|
end
|
101
100
|
|
102
101
|
# Initializes a new Error object
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'paysafe/result'
|
2
|
+
|
3
|
+
module Paysafe
|
4
|
+
class Profile < Result
|
5
|
+
attributes :id, :status, :merchant_customer_id, :locale,
|
6
|
+
:ip, :first_name, :middle_name, :last_name, :gender,
|
7
|
+
:nationality, :email, :phone, :cell_phone, :payment_token
|
8
|
+
|
9
|
+
object_attribute :BirthDate, :date_of_birth
|
10
|
+
object_attribute :Card, :cards
|
11
|
+
object_attribute :Address, :addresses
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Paysafe
|
2
|
+
module Refinements
|
3
|
+
module CamelCase
|
4
|
+
refine Hash do
|
5
|
+
|
6
|
+
def to_camel_case(data = self)
|
7
|
+
case data
|
8
|
+
when Array
|
9
|
+
data.map { |value| to_camel_case(value) }
|
10
|
+
when Hash
|
11
|
+
data.map { |key, value| [camel_case_key(key), to_camel_case(value)] }.to_h
|
12
|
+
else
|
13
|
+
data
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def camel_case_key(key)
|
20
|
+
case key
|
21
|
+
when Symbol
|
22
|
+
camel_case(key.to_s).to_sym
|
23
|
+
when String
|
24
|
+
camel_case(key).to_sym
|
25
|
+
else
|
26
|
+
key
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def camel_case(string)
|
31
|
+
@__memoize_camelcase ||= {}
|
32
|
+
return @__memoize_camelcase[string] if @__memoize_camelcase[string]
|
33
|
+
@__memoize_camelcase[string] = string.gsub(/(?:_+)([a-z])/) { $1.upcase }
|
34
|
+
@__memoize_camelcase[string]
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Paysafe
|
2
|
+
module Refinements
|
3
|
+
module SnakeCase
|
4
|
+
refine Hash do
|
5
|
+
|
6
|
+
def to_snake_case(data = self)
|
7
|
+
case data
|
8
|
+
when Array
|
9
|
+
data.map { |value| to_snake_case(value) }
|
10
|
+
when Hash
|
11
|
+
data.map { |key, value| [underscore_key(key), to_snake_case(value)] }.to_h
|
12
|
+
else
|
13
|
+
data
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def underscore_key(key)
|
20
|
+
case key
|
21
|
+
when Symbol
|
22
|
+
underscore(key.to_s).to_sym
|
23
|
+
when String
|
24
|
+
underscore(key).to_sym
|
25
|
+
else
|
26
|
+
key
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def underscore(string)
|
31
|
+
@__memoize_underscore ||= {}
|
32
|
+
return @__memoize_underscore[string] if @__memoize_underscore[string]
|
33
|
+
@__memoize_underscore[string] =
|
34
|
+
string.gsub(/::/, '/')
|
35
|
+
.gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
36
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
37
|
+
.tr('-', '_')
|
38
|
+
.downcase
|
39
|
+
@__memoize_underscore[string]
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/paysafe/rest/client.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'http'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Paysafe
|
4
5
|
module REST
|
5
6
|
class Client
|
6
7
|
|
7
|
-
API_TEST = 'https://api.test.
|
8
|
-
API_LIVE = 'https://api.
|
8
|
+
API_TEST = 'https://api.test.paysafe.com'
|
9
|
+
API_LIVE = 'https://api.paysafe.com'
|
9
10
|
|
10
11
|
HEADERS = {
|
11
12
|
'Content-Type' => 'application/json',
|
@@ -14,7 +15,10 @@ module Paysafe
|
|
14
15
|
'X-Ruby-Platform' => RUBY_PLATFORM
|
15
16
|
}
|
16
17
|
|
17
|
-
|
18
|
+
using Refinements::CamelCase
|
19
|
+
using Refinements::SnakeCase
|
20
|
+
|
21
|
+
attr_accessor :account_number, :api_key, :api_secret, :test_mode, :timeouts
|
18
22
|
attr_reader :api_base
|
19
23
|
|
20
24
|
# Initializes a new Client object
|
@@ -23,7 +27,6 @@ module Paysafe
|
|
23
27
|
# @return [Paysafe::REST::Client]
|
24
28
|
def initialize(options={})
|
25
29
|
@test_mode = true
|
26
|
-
@timeout_options = { write: 2, connect: 5, read: 10 }
|
27
30
|
|
28
31
|
options.each do |key, value|
|
29
32
|
instance_variable_set("@#{key}", value)
|
@@ -36,11 +39,7 @@ module Paysafe
|
|
36
39
|
|
37
40
|
# @return [Hash]
|
38
41
|
def credentials
|
39
|
-
{
|
40
|
-
account_number: account_number,
|
41
|
-
api_key: api_key,
|
42
|
-
api_secret: api_secret
|
43
|
-
}
|
42
|
+
{ api_key: api_key, api_secret: api_secret }
|
44
43
|
end
|
45
44
|
|
46
45
|
# @return [Boolean]
|
@@ -48,157 +47,132 @@ module Paysafe
|
|
48
47
|
credentials.values.all?
|
49
48
|
end
|
50
49
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
50
|
+
def create_single_use_token(data)
|
51
|
+
response = post(path: "/customervault/v1/singleusetokens", data: data.to_camel_case)
|
52
|
+
process_response(response, SingleUseToken)
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_profile_from_token(data)
|
56
|
+
response = post(path: "/customervault/v1/profiles", data: data.to_camel_case)
|
57
|
+
process_response(response, Profile)
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_profile(merchant_customer_id:, locale:, **args)
|
61
|
+
data = args.merge({
|
62
|
+
merchant_customer_id: merchant_customer_id,
|
63
|
+
locale: locale
|
64
|
+
}).to_camel_case
|
60
65
|
|
61
66
|
response = post(path: "/customervault/v1/profiles", data: data)
|
62
|
-
|
63
|
-
fail_or_return_response_body(response.code, response_body)
|
67
|
+
process_response(response, Profile)
|
64
68
|
end
|
65
69
|
|
66
70
|
def delete_profile(id:)
|
67
71
|
response = delete(path: "/customervault/v1/profiles/#{id}")
|
68
|
-
|
72
|
+
process_response(response)
|
69
73
|
end
|
70
74
|
|
71
75
|
def get_profile(id:, fields: [])
|
72
|
-
fields.keep_if { |field| field == :cards || field == :addresses }
|
73
|
-
|
74
76
|
path = "/customervault/v1/profiles/#{id}"
|
75
|
-
|
76
|
-
if !fields.empty?
|
77
|
-
path += "?fields=#{fields.join(',')}"
|
78
|
-
end
|
77
|
+
path += "?fields=#{fields.join(',')}" if !fields.empty?
|
79
78
|
|
80
79
|
response = get(path: path)
|
81
|
-
|
82
|
-
fail_or_return_response_body(response.code, response_body)
|
80
|
+
process_response(response, Profile)
|
83
81
|
end
|
84
82
|
|
85
|
-
def update_profile(id:,
|
86
|
-
data = {
|
87
|
-
|
88
|
-
locale: locale
|
89
|
-
|
90
|
-
lastName: args[:lastName],
|
91
|
-
email: args[:email]
|
92
|
-
}
|
83
|
+
def update_profile(id:, merchant_customer_id:, locale:, **args)
|
84
|
+
data = args.merge({
|
85
|
+
merchant_customer_id: merchant_customer_id,
|
86
|
+
locale: locale
|
87
|
+
}).to_camel_case
|
93
88
|
|
94
89
|
response = put(path: "/customervault/v1/profiles/#{id}", data: data)
|
95
|
-
|
96
|
-
fail_or_return_response_body(response.code, response_body)
|
90
|
+
process_response(response, Profile)
|
97
91
|
end
|
98
92
|
|
99
93
|
def create_address(profile_id:, country:, zip:, **args)
|
100
|
-
data = {
|
101
|
-
nickName: args[:nickName],
|
102
|
-
street: args[:street],
|
103
|
-
city: args[:city],
|
104
|
-
country: country,
|
105
|
-
state: args[:state],
|
106
|
-
zip: zip
|
107
|
-
}
|
108
|
-
|
94
|
+
data = args.merge({ country: country, zip: zip }).to_camel_case
|
109
95
|
response = post(path: "/customervault/v1/profiles/#{profile_id}/addresses", data: data)
|
110
|
-
|
111
|
-
|
96
|
+
process_response(response, Address)
|
97
|
+
end
|
98
|
+
|
99
|
+
def create_card_from_token(profile_id:, token:)
|
100
|
+
data = { single_use_token: token }.to_camel_case
|
101
|
+
response = post(path: "/customervault/v1/profiles/#{profile_id}/cards", data: data)
|
102
|
+
process_response(response, Card)
|
112
103
|
end
|
113
104
|
|
114
105
|
def create_card(profile_id:, number:, month:, year:, **args)
|
115
|
-
data = {
|
116
|
-
|
117
|
-
|
106
|
+
data = args.merge({
|
107
|
+
card_num: number,
|
108
|
+
card_expiry: {
|
118
109
|
month: month,
|
119
110
|
year: year
|
120
|
-
}
|
121
|
-
|
122
|
-
holderName: args[:holderName],
|
123
|
-
merchantRefNum: args[:merchantRefNum],
|
124
|
-
billingAddressId: args[:billingAddressId],
|
125
|
-
defaultCardIndicator: args[:defaultCardIndicator]
|
126
|
-
}.reject { |key, value| value.nil? }
|
111
|
+
}
|
112
|
+
}).reject { |key, value| value.nil? }.to_camel_case
|
127
113
|
|
128
114
|
response = post(path: "/customervault/v1/profiles/#{profile_id}/cards", data: data)
|
129
|
-
|
130
|
-
fail_or_return_response_body(response.code, response_body)
|
115
|
+
process_response(response, Card)
|
131
116
|
end
|
132
117
|
|
133
118
|
def delete_card(profile_id:, id:)
|
134
119
|
response = delete(path: "/customervault/v1/profiles/#{profile_id}/cards/#{id}")
|
135
|
-
|
136
|
-
fail_or_return_response_body(response.code, response_body)
|
120
|
+
process_response(response)
|
137
121
|
end
|
138
122
|
|
139
123
|
def get_card(profile_id:, id:)
|
140
124
|
response = get(path: "/customervault/v1/profiles/#{profile_id}/cards/#{id}")
|
141
|
-
|
142
|
-
fail_or_return_response_body(response.code, response_body)
|
125
|
+
process_response(response, Card)
|
143
126
|
end
|
144
127
|
|
145
128
|
def update_card(profile_id:, id:, month:, year:, **args)
|
146
|
-
data = {
|
147
|
-
|
129
|
+
data = args.merge({
|
130
|
+
card_expiry: {
|
148
131
|
month: month,
|
149
132
|
year: year
|
150
|
-
}
|
151
|
-
|
152
|
-
holderName: args[:holderName],
|
153
|
-
merchantRefNum: args[:merchantRefNum],
|
154
|
-
billingAddressId: args[:billingAddressId],
|
155
|
-
defaultCardIndicator: args[:defaultCardIndicator]
|
156
|
-
}.reject { |key, value| value.nil? }
|
133
|
+
}
|
134
|
+
}).reject { |key, value| value.nil? }.to_camel_case
|
157
135
|
|
158
136
|
response = put(path: "/customervault/v1/profiles/#{profile_id}/cards/#{id}", data: data)
|
159
|
-
|
160
|
-
fail_or_return_response_body(response.code, response_body)
|
137
|
+
process_response(response, Card)
|
161
138
|
end
|
162
139
|
|
163
|
-
def purchase(amount:, token:,
|
140
|
+
def purchase(amount:, token:, merchant_ref_num:, **args)
|
164
141
|
data = {
|
165
142
|
amount: amount,
|
166
|
-
|
167
|
-
|
143
|
+
merchant_ref_num: merchant_ref_num,
|
144
|
+
settle_with_auth: true,
|
168
145
|
card: {
|
169
|
-
|
146
|
+
payment_token: token
|
170
147
|
}
|
171
|
-
}
|
148
|
+
}.to_camel_case
|
172
149
|
|
173
150
|
response = post(path: "/cardpayments/v1/accounts/#{account_number}/auths", data: data)
|
174
|
-
|
175
|
-
fail_or_return_response_body(response.code, response_body)
|
151
|
+
process_response(response, Authorization)
|
176
152
|
end
|
177
153
|
|
178
|
-
def
|
179
|
-
data = {
|
180
|
-
|
154
|
+
def create_verification_from_token(merchant_ref_num:, token:)
|
155
|
+
data = { merchant_ref_num: merchant_ref_num, card: { payment_token: token } }.to_camel_case
|
156
|
+
response = post(path: "/cardpayments/v1/accounts/#{account_number}/verifications", data: data)
|
157
|
+
process_response(response, Verification)
|
158
|
+
end
|
159
|
+
|
160
|
+
def verify_card(merchant_ref_num:, number:, month:, year:, cvv:, address:, **args)
|
161
|
+
data = args.merge({
|
162
|
+
merchant_ref_num: merchant_ref_num,
|
163
|
+
billing_details: address,
|
181
164
|
card: {
|
182
|
-
|
183
|
-
|
165
|
+
card_num: number,
|
166
|
+
cvv: cvv,
|
167
|
+
card_expiry: {
|
184
168
|
month: month,
|
185
169
|
year: year
|
186
|
-
}
|
187
|
-
|
188
|
-
|
189
|
-
profile: {
|
190
|
-
firstName: args[:firstName],
|
191
|
-
lastName: args[:lastName],
|
192
|
-
email: args[:email]
|
193
|
-
},
|
194
|
-
billingDetails: args[:address],
|
195
|
-
customerIp: args[:customerIp],
|
196
|
-
description: args[:description]
|
197
|
-
}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}).to_camel_case
|
198
173
|
|
199
174
|
response = post(path: "/cardpayments/v1/accounts/#{account_number}/verifications", data: data)
|
200
|
-
|
201
|
-
fail_or_return_response_body(response.code, response_body)
|
175
|
+
process_response(response, Verification)
|
202
176
|
end
|
203
177
|
|
204
178
|
private
|
@@ -206,7 +180,7 @@ module Paysafe
|
|
206
180
|
def http_client
|
207
181
|
HTTP
|
208
182
|
.headers(HEADERS)
|
209
|
-
.timeout(@
|
183
|
+
.timeout(@timeouts ? @timeouts : :null)
|
210
184
|
.basic_auth(user: @api_key, pass: @api_secret)
|
211
185
|
end
|
212
186
|
|
@@ -226,25 +200,20 @@ module Paysafe
|
|
226
200
|
http_client.put("#{api_base}#{path}", json: data)
|
227
201
|
end
|
228
202
|
|
229
|
-
def
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
object[key.to_sym] = symbolize_keys!(object.delete(key))
|
237
|
-
end
|
203
|
+
def process_response(response, klass=nil)
|
204
|
+
data = parse_response_body(response.to_s)
|
205
|
+
|
206
|
+
if response.status.success?
|
207
|
+
klass&.new(data)
|
208
|
+
else
|
209
|
+
fail Error.from_response(data, response.code)
|
238
210
|
end
|
239
|
-
object
|
240
211
|
end
|
241
212
|
|
242
|
-
def
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
end
|
247
|
-
body
|
213
|
+
def parse_response_body(body)
|
214
|
+
return nil if body.strip.empty?
|
215
|
+
JSON.parse(body, symbolize_names: true)&.to_snake_case
|
216
|
+
rescue JSON::ParserError
|
248
217
|
end
|
249
218
|
|
250
219
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Paysafe
|
2
|
+
class Result
|
3
|
+
|
4
|
+
class << self
|
5
|
+
# Define methods that retrieve the value from attributes
|
6
|
+
#
|
7
|
+
# @param attrs [Array, Symbol]
|
8
|
+
def attributes(*attrs)
|
9
|
+
attrs.each do |attr|
|
10
|
+
define_attribute_method(attr)
|
11
|
+
define_predicate_method(attr)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Define object methods from attributes
|
16
|
+
#
|
17
|
+
# @param klass [Symbol]
|
18
|
+
# @param key1 [Symbol]
|
19
|
+
def object_attribute(klass, key1)
|
20
|
+
define_attribute_method(key1, klass)
|
21
|
+
define_predicate_method(key1)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Dynamically define a method for an attribute
|
25
|
+
#
|
26
|
+
# @param key1 [Symbol]
|
27
|
+
# @param klass [Symbol]
|
28
|
+
def define_attribute_method(key1, klass = nil)
|
29
|
+
define_method(key1) do
|
30
|
+
if instance_variable_defined?("@#{key1}")
|
31
|
+
return instance_variable_get("@#{key1}")
|
32
|
+
end
|
33
|
+
instance_variable_set("@#{key1}", get_value_by(key1, klass))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Dynamically define a predicate method for an attribute
|
38
|
+
#
|
39
|
+
# @param key1 [Symbol]
|
40
|
+
# @param key2 [Symbol]
|
41
|
+
def define_predicate_method(key1, key2 = key1)
|
42
|
+
define_method(:"#{key1}?") do
|
43
|
+
!attr_falsey_or_empty?(key2)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initializes a new object
|
49
|
+
#
|
50
|
+
# @param attributes [Hash]
|
51
|
+
# @return [Paysafe::Result]
|
52
|
+
def initialize(attributes={})
|
53
|
+
@attributes = attributes || {}
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Hash]
|
57
|
+
attr_reader :attributes
|
58
|
+
|
59
|
+
# @return [Boolean]
|
60
|
+
def empty?
|
61
|
+
@attributes.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def attr_falsey_or_empty?(key)
|
67
|
+
!@attributes[key] || @attributes[key].respond_to?(:empty?) && @attributes[key].empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_value_by(key, klass = nil)
|
71
|
+
return @attributes[key] if klass.nil?
|
72
|
+
|
73
|
+
case @attributes[key]
|
74
|
+
when Hash
|
75
|
+
Paysafe.const_get(klass).new(@attributes[key])
|
76
|
+
when Array
|
77
|
+
@attributes[key].map do |value|
|
78
|
+
Paysafe.const_get(klass).new(value)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
@attributes[key]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'paysafe/result'
|
2
|
+
|
3
|
+
module Paysafe
|
4
|
+
class Verification < Result
|
5
|
+
attributes :id, :merchant_ref_num, :child_account_num,
|
6
|
+
:auth_code, :customer_ip, :dup_check, :description, :txn_time,
|
7
|
+
:currency_code, :avs_response, :cvv_verification, :status
|
8
|
+
|
9
|
+
object_attribute :Profile, :profile
|
10
|
+
object_attribute :Card, :card
|
11
|
+
object_attribute :Address, :billing_details
|
12
|
+
end
|
13
|
+
end
|
data/lib/paysafe/version.rb
CHANGED
data/lib/paysafe.rb
CHANGED
@@ -1,3 +1,13 @@
|
|
1
1
|
require "paysafe/version"
|
2
2
|
require "paysafe/error"
|
3
|
+
require "paysafe/single_use_token"
|
4
|
+
require "paysafe/profile"
|
5
|
+
require "paysafe/birth_date"
|
6
|
+
require "paysafe/address"
|
7
|
+
require "paysafe/card"
|
8
|
+
require "paysafe/card_expiry"
|
9
|
+
require "paysafe/verification"
|
10
|
+
require "paysafe/authorization"
|
11
|
+
require "paysafe/refinements/camel_case"
|
12
|
+
require "paysafe/refinements/snake_case"
|
3
13
|
require "paysafe/rest/client"
|
data/paysafe.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Javier Julio"]
|
10
10
|
spec.email = ["jjfutbol@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
12
|
+
spec.summary = "A Ruby interface to the Paysafe REST API."
|
13
|
+
spec.description = "A Ruby interface to the Paysafe REST API."
|
14
14
|
spec.homepage = "https://github.com/javierjulio/paysafe"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -19,6 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
+
spec.required_ruby_version = '>= 2.3.0'
|
23
|
+
|
24
|
+
spec.add_dependency "http", '~> 2.0'
|
25
|
+
|
22
26
|
spec.add_development_dependency "bundler", "~> 1.10"
|
23
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
28
|
spec.add_development_dependency "dotenv"
|
@@ -27,6 +31,4 @@ Gem::Specification.new do |spec|
|
|
27
31
|
spec.add_development_dependency "vcr"
|
28
32
|
spec.add_development_dependency "webmock"
|
29
33
|
|
30
|
-
spec.add_dependency "http", '~> 2.0'
|
31
|
-
|
32
34
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paysafe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javier Julio
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: http
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,21 +122,7 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
|
-
|
112
|
-
name: http
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '2.0'
|
118
|
-
type: :runtime
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '2.0'
|
125
|
-
description: Gem to wrap Paysafe REST API
|
125
|
+
description: A Ruby interface to the Paysafe REST API.
|
126
126
|
email:
|
127
127
|
- jjfutbol@gmail.com
|
128
128
|
executables: []
|
@@ -132,6 +132,7 @@ files:
|
|
132
132
|
- ".env.sample"
|
133
133
|
- ".gitignore"
|
134
134
|
- ".travis.yml"
|
135
|
+
- CHANGELOG.md
|
135
136
|
- CODE_OF_CONDUCT.md
|
136
137
|
- Gemfile
|
137
138
|
- LICENSE.txt
|
@@ -140,8 +141,19 @@ files:
|
|
140
141
|
- bin/console
|
141
142
|
- bin/setup
|
142
143
|
- lib/paysafe.rb
|
144
|
+
- lib/paysafe/address.rb
|
145
|
+
- lib/paysafe/authorization.rb
|
146
|
+
- lib/paysafe/birth_date.rb
|
147
|
+
- lib/paysafe/card.rb
|
148
|
+
- lib/paysafe/card_expiry.rb
|
143
149
|
- lib/paysafe/error.rb
|
150
|
+
- lib/paysafe/profile.rb
|
151
|
+
- lib/paysafe/refinements/camel_case.rb
|
152
|
+
- lib/paysafe/refinements/snake_case.rb
|
144
153
|
- lib/paysafe/rest/client.rb
|
154
|
+
- lib/paysafe/result.rb
|
155
|
+
- lib/paysafe/single_use_token.rb
|
156
|
+
- lib/paysafe/verification.rb
|
145
157
|
- lib/paysafe/version.rb
|
146
158
|
- paysafe.gemspec
|
147
159
|
homepage: https://github.com/javierjulio/paysafe
|
@@ -156,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
168
|
requirements:
|
157
169
|
- - ">="
|
158
170
|
- !ruby/object:Gem::Version
|
159
|
-
version:
|
171
|
+
version: 2.3.0
|
160
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
173
|
requirements:
|
162
174
|
- - ">="
|
@@ -164,8 +176,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
176
|
version: '0'
|
165
177
|
requirements: []
|
166
178
|
rubyforge_project:
|
167
|
-
rubygems_version: 2.
|
179
|
+
rubygems_version: 2.6.8
|
168
180
|
signing_key:
|
169
181
|
specification_version: 4
|
170
|
-
summary:
|
182
|
+
summary: A Ruby interface to the Paysafe REST API.
|
171
183
|
test_files: []
|