coingate 1.0.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.
@@ -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