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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f11054ae9a4a74c663c741d1d6e53cc679b9684b
4
- data.tar.gz: ed309c4fd81fbdd4f3af840e8e0e619855933167
3
+ metadata.gz: 1792daaf31ee88c7c270dc6e00bd625007923fe6
4
+ data.tar.gz: e09efc856cd5332d1dadede05177006f5dda970e
5
5
  SHA512:
6
- metadata.gz: 7821197020d3a79e12a511dfe02696a6e5f39a13f87e03f506e6198b33a8c98f08028adf90f5c9f2317ea173b0b1238876b30b9b1e39b0f244698e55768e949e
7
- data.tar.gz: 14516824e4ebe5136e28151004ade1c86fcbc1850b68860f015aae50f63916b5683dd7b779f5e60c950a5adb5cb4b375d512be4f218e5f517bc3c3b6260c5c11
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
- TODO: Write usage instructions here
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
 
@@ -21,4 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.11"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "minitest", "~> 5.0"
24
+
25
+ spec.add_runtime_dependency 'rest-client', '~> 2.0'
24
26
  end
@@ -1,5 +1,75 @@
1
- require "cardinity/version"
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
- # Your code goes here...
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
@@ -1,3 +1,3 @@
1
1
  module Cardinity
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
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.1
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-10 00:00:00.000000000 Z
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: