cardinity 0.0.1 → 0.1.0
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 +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:
|