cardinity 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -1
- data/cardinity.gemspec +2 -0
- data/lib/cardinity.rb +72 -2
- data/lib/cardinity/auth.rb +69 -0
- data/lib/cardinity/utils.rb +69 -0
- data/lib/cardinity/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1792daaf31ee88c7c270dc6e00bd625007923fe6
|
4
|
+
data.tar.gz: e09efc856cd5332d1dadede05177006f5dda970e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b031d6b90c243e431ca5a7e3d957d43f2fd002cce7c630bf15ced922cea8959a71897ab8861613c6afb39996089d4cfe4138f04c5751601872bae0064e55e7fc
|
7
|
+
data.tar.gz: 165cfbd858971f0b65d7c89134224889a7cab3ee10fd4c24ce69d765437b69bcbf1f117018f376caf2c90089ecefefa1bcce39cad28fa9b7c4a7c2b5c02a80e7
|
data/README.md
CHANGED
@@ -18,7 +18,33 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
### Configuration
|
22
|
+
|
23
|
+
Cardinity.configure!(options)
|
24
|
+
|
25
|
+
Where options should contain:
|
26
|
+
- key
|
27
|
+
- secret
|
28
|
+
- api_base (optional, if you want to point the requests somewhere else than Cardinity servers)
|
29
|
+
|
30
|
+
### Creating Payments
|
31
|
+
|
32
|
+
Cardinity.create_payment(payment_data)
|
33
|
+
|
34
|
+
Where `payment_data` is a plain `Hash`. See rdoc or [Cardinity API doc](https://developers.cardinity.com/api/v1/) to see
|
35
|
+
what attributes are allowed and required.
|
36
|
+
|
37
|
+
Cardinity.finalize_payment(payment_id, authorization_data)
|
38
|
+
|
39
|
+
Where `payment_id` is an id of previously created payment and `authorization_data` is
|
40
|
+
a `Hash` with single key `authorize_data`.
|
41
|
+
|
42
|
+
### Other stuff
|
43
|
+
|
44
|
+
Cardinity.payments
|
45
|
+
|
46
|
+
Returns the last 10 payments made.
|
47
|
+
|
22
48
|
|
23
49
|
## Development
|
24
50
|
|
data/cardinity.gemspec
CHANGED
data/lib/cardinity.rb
CHANGED
@@ -1,5 +1,75 @@
|
|
1
|
-
require
|
1
|
+
require 'cardinity/version'
|
2
|
+
require 'cardinity/utils'
|
3
|
+
require 'cardinity/auth'
|
4
|
+
require 'rest-client'
|
5
|
+
require 'json'
|
2
6
|
|
3
7
|
module Cardinity
|
4
|
-
|
8
|
+
|
9
|
+
DEFAULT_API_BASE = 'https://api.cardinity.com/v1/'
|
10
|
+
|
11
|
+
API_PAYMENTS = 'payments'
|
12
|
+
|
13
|
+
STATUS_PENDING = 'pending'
|
14
|
+
STATUS_APPROVED = 'approved'
|
15
|
+
STATUS_DECLINED = 'declined'
|
16
|
+
|
17
|
+
TYPE_AUTHORIZATION = 'authorization'
|
18
|
+
TYPE_PURCHASE = 'purchase'
|
19
|
+
TYPE_ERROR = 'https://developers.cardinity.com/api/v1/'
|
20
|
+
|
21
|
+
def self.configure!(options)
|
22
|
+
@config = {
|
23
|
+
# key and secret to be supplied from outsite
|
24
|
+
api_base: DEFAULT_API_BASE
|
25
|
+
}
|
26
|
+
@config.merge! options
|
27
|
+
@auth = Cardinity::Auth.new(@config)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates a Payment object
|
31
|
+
#
|
32
|
+
# Accepted attributes:
|
33
|
+
# - amount (#0.00, two decimals required)
|
34
|
+
# - currency (EUR,USD)
|
35
|
+
# - settle (boolean, default true, false means just pre-authorize and finish later)
|
36
|
+
# - order_id (not required)
|
37
|
+
# - description (not required)
|
38
|
+
# - country (country of customer, required)
|
39
|
+
# - payment_method (required, only supported value is card)
|
40
|
+
# - payment_instrument (card details)
|
41
|
+
# - pan (card number)
|
42
|
+
# - exp_year
|
43
|
+
# - exp_month
|
44
|
+
# - cvc
|
45
|
+
# - holder
|
46
|
+
#
|
47
|
+
# Returns:
|
48
|
+
# - updated payment object on success
|
49
|
+
# - error object on error
|
50
|
+
def self.create_payment(payment_hash)
|
51
|
+
checked_payment_data = check_payment_data(payment_hash)
|
52
|
+
parse post(payments_uri, serialize(checked_payment_data))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Finalizes a Payment
|
56
|
+
#
|
57
|
+
# This is necessary for 3D secure payments, when the customer has completed
|
58
|
+
# the 3D secure redirects and authorization.
|
59
|
+
#
|
60
|
+
# Accepted attributes:
|
61
|
+
# - authorize_data (PaRes string received from 3D secure)
|
62
|
+
#
|
63
|
+
# Returns:
|
64
|
+
# - updated payment object on success
|
65
|
+
# - error object on error
|
66
|
+
def self.finalize_payment(payment_id, authorize_hash)
|
67
|
+
parse patch(payment_uri(payment_id), serialize(authorize_hash))
|
68
|
+
end
|
69
|
+
|
70
|
+
# Get list of all payments
|
71
|
+
def self.payments
|
72
|
+
parse get(payments_uri)
|
73
|
+
end
|
74
|
+
|
5
75
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl/digest'
|
3
|
+
require 'uri'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
class Cardinity::Auth
|
7
|
+
|
8
|
+
OAUTH_VERSION = '1.0'
|
9
|
+
RESERVED_CHARACTERS = /[^a-zA-Z0-9\-._~]/
|
10
|
+
SIGNATURE_METHOD = 'HMAC-SHA1'
|
11
|
+
|
12
|
+
def initialize(config)
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
def sign_request(method, uri)
|
17
|
+
params = {
|
18
|
+
oauth_consumer_key: @config[:key],
|
19
|
+
oauth_nonce: generate_key,
|
20
|
+
oauth_signature_method: SIGNATURE_METHOD,
|
21
|
+
oauth_timestamp: generate_timestamp,
|
22
|
+
oauth_version: OAUTH_VERSION
|
23
|
+
}
|
24
|
+
params[:oauth_signature] = request_signature(method, uri, params)
|
25
|
+
params_str = params.collect { |k, v| "#{k}=\"#{escape(v)}\"" }.join(', ')
|
26
|
+
"OAuth #{params_str}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def request_signature(method, uri, params)
|
30
|
+
base_str = generate_base_string(method, uri, params)
|
31
|
+
encoded_digest(base_str)
|
32
|
+
end
|
33
|
+
|
34
|
+
def encoded_digest(string)
|
35
|
+
Base64.strict_encode64(digest(string))
|
36
|
+
end
|
37
|
+
|
38
|
+
def digest(string)
|
39
|
+
key = escape(@config[:secret]) + '&'
|
40
|
+
OpenSSL::HMAC.digest(
|
41
|
+
OpenSSL::Digest.new('sha1'),
|
42
|
+
key,
|
43
|
+
string)
|
44
|
+
end
|
45
|
+
|
46
|
+
def escape(string)
|
47
|
+
URI.escape(string, RESERVED_CHARACTERS)
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_base_string(method, url, params)
|
51
|
+
base = [method.to_s.upcase, url, normalized_params(params)]
|
52
|
+
base.map { |v| escape(v) }.join('&')
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def generate_key(size=32)
|
58
|
+
Base64.strict_encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
|
59
|
+
end
|
60
|
+
|
61
|
+
def generate_timestamp
|
62
|
+
Time.now.to_i.to_s
|
63
|
+
end
|
64
|
+
|
65
|
+
def normalized_params(params)
|
66
|
+
params.collect { |k, v| "#{k}=#{v}" }.sort.join("&")
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Cardinity
|
2
|
+
|
3
|
+
CODES_WITH_RESPONSE = [200, 201, 202, 400, 402]
|
4
|
+
|
5
|
+
def self.check_payment_data(payment)
|
6
|
+
payment = payment.dup
|
7
|
+
if payment[:payment_method].nil?
|
8
|
+
payment[:payment_method] = 'card'
|
9
|
+
end
|
10
|
+
if payment[:amount].is_a?(Numeric)
|
11
|
+
payment[:amount] = '%.2f' % payment[:amount]
|
12
|
+
end
|
13
|
+
payment
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.payments_uri
|
17
|
+
"#{api_base}#{API_PAYMENTS}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.payment_uri(payment_id)
|
21
|
+
"#{api_base}#{API_PAYMENTS}/#{payment_id}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.parse(response)
|
25
|
+
JSON.parse response.body
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.serialize(data)
|
29
|
+
JSON.generate(data)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.handle_error_response(e)
|
33
|
+
if CODES_WITH_RESPONSE.index e.response.code
|
34
|
+
e.response
|
35
|
+
else
|
36
|
+
raise e
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.get(uri)
|
41
|
+
RestClient.get uri, headers(:get, uri)
|
42
|
+
rescue RestClient::ExceptionWithResponse => e
|
43
|
+
handle_error_response e
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.post(uri, body)
|
47
|
+
RestClient.post uri, body, headers(:post, uri)
|
48
|
+
rescue RestClient::ExceptionWithResponse => e
|
49
|
+
handle_error_response e
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.patch(uri, body)
|
53
|
+
RestClient.patch uri, body, headers(:patch, uri)
|
54
|
+
rescue RestClient::ExceptionWithResponse => e
|
55
|
+
handle_error_response e
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.headers(method, uri)
|
59
|
+
{
|
60
|
+
content_type: 'application/json',
|
61
|
+
authorization: @auth.sign_request(method, uri)
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.api_base
|
66
|
+
@config[:api_base]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/cardinity/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cardinity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Sterba
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rest-client
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
55
69
|
description:
|
56
70
|
email:
|
57
71
|
- info@jansterba.com
|
@@ -70,6 +84,8 @@ files:
|
|
70
84
|
- bin/setup
|
71
85
|
- cardinity.gemspec
|
72
86
|
- lib/cardinity.rb
|
87
|
+
- lib/cardinity/auth.rb
|
88
|
+
- lib/cardinity/utils.rb
|
73
89
|
- lib/cardinity/version.rb
|
74
90
|
homepage: https://github.com/honzasterba/cardinity
|
75
91
|
licenses:
|