coingate 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d075c6648cfd6b0ab997cc5866d827870494819d
4
+ data.tar.gz: 168806b81f0a8913d80f0d00728a989dc056bcc6
5
+ SHA512:
6
+ metadata.gz: d080344b9613674e51f6a4b412de00e6ccd7c069373646b4e11c1be6d15a4c63421e0f787f6b82203d10adf7bfac83e8669d9e6ff97c1083ae71365025912ba0
7
+ data.tar.gz: 978d9a44ac65cd7e6ba6578bac1340b589c7b633cb5d544965fc3509a8c351ecc7415f284462c700404f0cff5fd80a1018223ee22e2b1c8251fb492eb0dab319
@@ -0,0 +1,2 @@
1
+ /.idea
2
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ coingate (1.0.0)
5
+ rest-client
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.2.5)
11
+ domain_name (0.5.20160310)
12
+ unf (>= 0.0.5, < 1.0.0)
13
+ http-cookie (1.0.2)
14
+ domain_name (~> 0.5)
15
+ mime-types (2.99.1)
16
+ netrc (0.11.0)
17
+ rake (10.5.0)
18
+ rest-client (1.8.0)
19
+ http-cookie (>= 1.0.2, < 2.0)
20
+ mime-types (>= 1.16, < 3.0)
21
+ netrc (~> 0.7)
22
+ rspec (3.4.0)
23
+ rspec-core (~> 3.4.0)
24
+ rspec-expectations (~> 3.4.0)
25
+ rspec-mocks (~> 3.4.0)
26
+ rspec-core (3.4.4)
27
+ rspec-support (~> 3.4.0)
28
+ rspec-expectations (3.4.0)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.4.0)
31
+ rspec-mocks (3.4.1)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.4.0)
34
+ rspec-support (3.4.1)
35
+ unf (0.1.4)
36
+ unf_ext
37
+ unf_ext (0.0.7.2)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ bundler (~> 1.7)
44
+ coingate!
45
+ rake (~> 10.0)
46
+ rspec
47
+
48
+ BUNDLED WITH
49
+ 1.10.6
@@ -0,0 +1 @@
1
+ # coingate-ruby
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'coingate/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'coingate'
9
+ spec.version = CoinGate::VERSION
10
+ spec.authors = ['Tomas Achmedovas', 'Irmantas Bačiulis']
11
+ spec.email = ['info@coingate.com']
12
+ spec.summary = %q{Library for CoinGate}
13
+ spec.description = %q{Library for CoinGate}
14
+ spec.homepage = 'https://coingate.com'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'rest-client'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec'
27
+ end
@@ -0,0 +1,77 @@
1
+ require 'coingate/version'
2
+
3
+ require 'coingate/error_handler'
4
+ require 'coingate/api_error'
5
+
6
+ require 'coingate/merchant'
7
+ require 'coingate/merchant/order'
8
+
9
+ require 'openssl'
10
+ require 'rest_client'
11
+ require 'json'
12
+
13
+ module CoinGate
14
+ class << self
15
+ attr_accessor :app_id, :api_key, :api_secret, :environment
16
+
17
+ def config
18
+ yield self
19
+ end
20
+
21
+ def api_request(url, request_method = :post, params = {}, authentication = {})
22
+ app_id = authentication[:app_id] || self.app_id
23
+ api_key = authentication[:api_key] || self.api_key
24
+ api_secret = authentication[:api_secret] || self.api_secret
25
+ environment = authentication[:environment] || self.environment || 'live'
26
+
27
+ # Check if credentials was passed
28
+ if app_id.nil? || api_key.nil? || api_secret.nil?
29
+ CoinGate.raise_error(400, {'reason' => 'CredentialsMissing'})
30
+ end
31
+
32
+ # Check if right environment passed
33
+ environments = %w(live sandbox)
34
+
35
+ unless environments.include?(environment)
36
+ CoinGate.raise_error(400, {'reason' => 'BadEnvironment', 'message' => "Environment does not exist. Available environments: #{environments.join(', ')}"})
37
+ end
38
+
39
+ url = (
40
+ case environment
41
+ when 'sandbox'
42
+ 'https://sandbox.coingate.com/api/v1'
43
+ else
44
+ 'https://coingate.com/api/v1'
45
+ end) + url
46
+
47
+ nonce = (Time.now.to_f * 1e6).to_i
48
+ message = nonce.to_s + app_id.to_s + api_key
49
+ signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), api_secret, message)
50
+
51
+ headers = {
52
+ 'Access-Nonce' => nonce,
53
+ 'Access-Key' => api_key,
54
+ 'Access-Signature' => signature
55
+ }
56
+
57
+ begin
58
+ response = case request_method
59
+ when :get
60
+ RestClient.get(url, headers)
61
+ when :post
62
+ RestClient.post(url, params, headers.merge('Content-Type' => 'application/x-www-form-urlencoded'))
63
+ end
64
+
65
+ [response.code, JSON.parse(response.to_str)]
66
+ rescue => e
67
+ response = begin
68
+ JSON.parse(e.response)
69
+ rescue
70
+ {'reason' => nil, 'message' => e.response}
71
+ end
72
+
73
+ CoinGate.raise_error(e.http_code, response)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,25 @@
1
+ module CoinGate
2
+ class APIError < ::RuntimeError; end
3
+
4
+ # HTTP Status 400
5
+ class BadRequest < APIError; end
6
+ class CredentialsMissing < BadRequest; end
7
+ class BadEnvironment < BadRequest; end
8
+
9
+ # HTTP Status 401
10
+ class Unauthorized < APIError; end
11
+ class BadCredentials < Unauthorized; end
12
+
13
+ # HTTP Status 404
14
+ class NotFound < APIError; end
15
+ class PageNotFound < NotFound; end
16
+ class RecordNotFound < NotFound; end
17
+ class OrderNotFound < NotFound; end
18
+
19
+ # HTTP Status 422
20
+ class UnprocessableEntity < APIError; end
21
+ class OrderIsNotValid < UnprocessableEntity; end
22
+
23
+ # HTTP Status 500
24
+ class InternalServerError < APIError; end
25
+ end
@@ -0,0 +1,44 @@
1
+ module CoinGate
2
+ def self.format_error(error)
3
+ "#{error['reason']} #{error['message']}"
4
+ end
5
+
6
+ def self.raise_error(http_code, error={})
7
+ reason = error['reason']
8
+
9
+ raise (case http_code
10
+ when 400
11
+ case reason
12
+ when 'CredentialsMissing' then CredentialsMissing
13
+ when 'BadEnvironment' then BadEnvironment
14
+ else BadRequest
15
+ end
16
+
17
+ when 401 then
18
+ case reason
19
+ when 'BadCredentials' then BadCredentials
20
+ else Unauthorized
21
+ end
22
+
23
+ when 404 then
24
+ case reason
25
+ when 'PageNotFound' then PageNotFound
26
+ when 'RecordNotFound' then RecordNotFound
27
+ when 'OrderNotFound' then OrderNotFound
28
+ else NotFound
29
+ end
30
+
31
+
32
+ when 422
33
+ case reason
34
+ when 'OrderIsNotValid' then OrderIsNotValid
35
+ else UnprocessableEntity
36
+ end
37
+
38
+ when 500 then InternalServerError
39
+
40
+ else APIError
41
+ end), format_error(error)
42
+ end
43
+ end
44
+
@@ -0,0 +1,2 @@
1
+ module CoinGate::Merchant
2
+ end
@@ -0,0 +1,51 @@
1
+ class CoinGate::Merchant::Order
2
+ STATUSES = %w(pending confirming paid invalid canceled expired failed)
3
+
4
+ def initialize(params)
5
+ @order = params
6
+
7
+ @order.each do |name, value|
8
+ self.define_singleton_method name do
9
+ value
10
+ end
11
+ end
12
+ end
13
+
14
+ STATUSES.each do |type|
15
+ define_method "#{type}?" do
16
+ status == type
17
+ end
18
+ end
19
+
20
+ def to_hash
21
+ @order
22
+ end
23
+
24
+ def self.find!(order_id, authentication={}, options={})
25
+ response_code, order = CoinGate.api_request("/orders/#{order_id}", :get, {}, authentication)
26
+
27
+ if response_code == 200
28
+ self.new(order)
29
+ end
30
+ end
31
+
32
+ def self.find(order_id, authentication={}, options={})
33
+ find!(order_id, authentication, options)
34
+ rescue CoinGate::OrderNotFound
35
+ false
36
+ end
37
+
38
+ def self.create!(params, authentication={}, options={})
39
+ response_code, order = CoinGate.api_request('/orders', :post, params, authentication)
40
+
41
+ if response_code == 200
42
+ self.new(order)
43
+ end
44
+ end
45
+
46
+ def self.create(params, authentication={}, options={})
47
+ create!(params, authentication, options)
48
+ rescue CoinGate::OrderIsNotValid
49
+ false
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module CoinGate
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe CoinGate::Merchant::Order do
4
+ include_context 'shared'
5
+
6
+ let(:valid_order_params) do
7
+ {
8
+ order_id: 'ORDER-1412759367',
9
+ price: 1050.99,
10
+ currency: 'USD',
11
+ receive_currency: 'EUR',
12
+ callback_url: 'https://example.com/payments/callback?token=6tCENGUYI62ojkuzDPX7Jg',
13
+ cancel_url: 'https://example.com/cart',
14
+ success_url: 'https://example.com/account/orders',
15
+ description: 'Apple Iphone 6s'
16
+ }
17
+ end
18
+
19
+ before do
20
+ CoinGate.config do |config|
21
+ config.app_id = @authentication[:app_id]
22
+ config.api_key = @authentication[:api_key]
23
+ config.api_secret = @authentication[:api_secret]
24
+ config.environment = @authentication[:environment]
25
+ end
26
+ end
27
+
28
+ describe 'create order' do
29
+ context 'invalid' do
30
+ it { expect(CoinGate::Merchant::Order.create({})).to be false }
31
+ it { expect { CoinGate::Merchant::Order.create!({}) }.to raise_error CoinGate::OrderIsNotValid }
32
+ end
33
+
34
+ context 'valid' do
35
+ it { expect(CoinGate::Merchant::Order.create(valid_order_params).pending?).to be true }
36
+ it { expect(CoinGate::Merchant::Order.create!(valid_order_params).pending?).to be true }
37
+ end
38
+ end
39
+
40
+ describe 'find order' do
41
+ context 'order exists' do
42
+ it do
43
+ order = CoinGate::Merchant::Order.create(valid_order_params)
44
+
45
+ expect(CoinGate::Merchant::Order.find(order.id).pending?).to be true
46
+ expect(CoinGate::Merchant::Order.find!(order.id).pending?).to be true
47
+ end
48
+ end
49
+
50
+ context 'order does not exists' do
51
+ it { expect(CoinGate::Merchant::Order.find(0)).to be false }
52
+ it { expect { CoinGate::Merchant::Order.find!(0) }.to raise_error CoinGate::OrderNotFound }
53
+ end
54
+ end
55
+
56
+ describe 'passing auth params through arguments' do
57
+ before do
58
+ CoinGate.config do |config|
59
+ config.app_id = nil
60
+ config.api_key = nil
61
+ config.api_secret = nil
62
+ config.environment = nil
63
+ end
64
+ end
65
+
66
+ describe 'create order' do
67
+ context 'params not passed' do
68
+ it { expect { CoinGate::Merchant::Order.create({}) }.to raise_error CoinGate::CredentialsMissing }
69
+ it { expect { CoinGate::Merchant::Order.create!({}) }.to raise_error CoinGate::CredentialsMissing }
70
+ end
71
+
72
+ context 'invalid params passed' do
73
+ authentication = {
74
+ app_id: 1,
75
+ api_key: 'a',
76
+ api_secret: 'a'
77
+ }
78
+
79
+ it { expect { CoinGate::Merchant::Order.create({}, authentication) }.to raise_error CoinGate::BadCredentials }
80
+ it { expect { CoinGate::Merchant::Order.create!({}, authentication) }.to raise_error CoinGate::BadCredentials }
81
+ end
82
+
83
+ context 'valid params passed' do
84
+ it { expect(CoinGate::Merchant::Order.create({}, @authentication)).to be false }
85
+ it { expect { CoinGate::Merchant::Order.create!({}, @authentication) }.to raise_error CoinGate::OrderIsNotValid }
86
+ end
87
+ end
88
+
89
+ describe 'find order' do
90
+ context 'params not passed' do
91
+ it { expect { CoinGate::Merchant::Order.find(0) }.to raise_error CoinGate::CredentialsMissing }
92
+ it { expect { CoinGate::Merchant::Order.find!(0) }.to raise_error CoinGate::CredentialsMissing }
93
+ end
94
+
95
+ context 'invalid params passed' do
96
+ authentication = {
97
+ app_id: 1,
98
+ api_key: 'a',
99
+ api_secret: 'a'
100
+ }
101
+
102
+ it { expect { CoinGate::Merchant::Order.find(0, authentication) }.to raise_error CoinGate::BadCredentials }
103
+ it { expect { CoinGate::Merchant::Order.find!(0, authentication) }.to raise_error CoinGate::BadCredentials }
104
+ end
105
+
106
+ context 'valid params passed' do
107
+ it { expect(CoinGate::Merchant::Order.find(0, @authentication)).to be false }
108
+ it { expect { CoinGate::Merchant::Order.find!(0, @authentication) }.to raise_error CoinGate::OrderNotFound }
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,10 @@
1
+ RSpec.shared_context 'shared' do
2
+ before(:all) do
3
+ @authentication = {
4
+ app_id: 1,
5
+ api_key: 'iob0ctFgeHLajvfxzYnIPB',
6
+ api_secret: 'ytaqXRWZ17ONlpshPTQuF50rIVLwBbmi',
7
+ environment: 'sandbox'
8
+ }
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'coingate'
3
+ require 'shared'
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coingate
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tomas Achmedovas
8
+ - Irmantas Bačiulis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-04-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.7'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.7'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '10.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '10.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: Library for CoinGate
71
+ email:
72
+ - info@coingate.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - README.md
81
+ - Rakefile
82
+ - coingate.gemspec
83
+ - lib/coingate.rb
84
+ - lib/coingate/api_error.rb
85
+ - lib/coingate/error_handler.rb
86
+ - lib/coingate/merchant.rb
87
+ - lib/coingate/merchant/order.rb
88
+ - lib/coingate/version.rb
89
+ - spec/merchant/order_spec.rb
90
+ - spec/shared.rb
91
+ - spec/spec_helper.rb
92
+ homepage: https://coingate.com
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.4.5.1
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Library for CoinGate
116
+ test_files:
117
+ - spec/merchant/order_spec.rb
118
+ - spec/shared.rb
119
+ - spec/spec_helper.rb