wizypay-api-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 25e3c4eb158ef8bd15bcbdf79419abc1506c6294
4
+ data.tar.gz: ec3ced582b40b8778d49c70c5f5a3dde956fb375
5
+ SHA512:
6
+ metadata.gz: b69685a587d3c6f1a9a9df75a99f19df876fb5e4c8511f39547d5a22d3d7f49ec2bc98fb4ecfc14cb4e075d6e9142392a7d452cc01e564103321e9c60135c3bb
7
+ data.tar.gz: 96ad24fc1c985821ce4c1935c9e4cf1d09571c065e74531120bce597298743d964253e9fab2c85f5fbe86470cfa06bc51f4f5c798001c9e17cfc73c25776c7d3
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2015 Wizypay
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -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
data/lib/wizypay.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'time'
2
+ require 'base64'
3
+ require 'openssl'
4
+ require 'securerandom'
5
+ require 'rest-client'
6
+ require 'simple-hmac'
7
+ require 'json'
8
+ require_relative 'wizypay/client'
9
+ require_relative 'wizypay/card'
10
+
11
+ module Wizypay
12
+ def self.setup(api_key, api_secret, api_endpoint = 'https://api.wizypay.com')
13
+ Wizypay::Client.api_endpoint = api_endpoint
14
+ Wizypay::Client.api_key = api_key
15
+ Wizypay::Client.api_secret = api_secret
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Wizypay
2
+ class Card
3
+ def self.create(reference, amount, currency, merchant_id, user)
4
+ user = user.to_json if user.is_a?(Hash)
5
+ payload = { amount: amount, currency: currency, merchant_id: merchant_id, reference: reference, user: user }
6
+ Client.post('/cards', payload)
7
+ end
8
+
9
+ def self.cancel(reference)
10
+ Client.post("/cards/#{URI::encode_www_form_component reference}/cancel")
11
+ end
12
+
13
+ def self.url(reference)
14
+ timestamp = Time.now.utc.httpdate
15
+ security = Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', Client.api_secret, "#{reference}\n#{timestamp}"))
16
+ query_string = {
17
+ key: Client.api_key,
18
+ timestamp: timestamp,
19
+ reference: reference,
20
+ security: security
21
+ }.map { |k, v| "#{k}=#{URI::encode_www_form_component(v)}" }.join('&')
22
+ "#{Client.api_endpoint}/widget?#{query_string}"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ module Wizypay
2
+ class Client
3
+ class << self
4
+ attr_accessor :api_endpoint, :api_key, :api_secret
5
+
6
+ def post(path, payload = {})
7
+ execute(path, { method: :post, payload: payload })
8
+ end
9
+
10
+ def get(path)
11
+ execute(path, { method: :get })
12
+ end
13
+
14
+ def execute(path, req_params)
15
+ req_params.merge!(
16
+ url: "#{api_endpoint}#{path}",
17
+ headers: { accept: :json }
18
+ )
19
+ req = RestClient::Request.new(req_params)
20
+ req.sign!(api_key, api_secret)
21
+ parse_response req.execute
22
+ end
23
+
24
+ private
25
+
26
+ def parse_response(response)
27
+ Hash[JSON::parse(response).map { |k,v| [k.to_sym, v] }]
28
+ rescue JSON::ParserError
29
+ response
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module Wizypay
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'DistributionApi::cancel_card' do
4
+
5
+ let(:api_key) { 'key' }
6
+ let(:api_secret) { 'secret' }
7
+ let(:api_endpoint) { 'https://api.wizypay.com' }
8
+ let(:reference) { '85fb584c-72cb-4f35-b307-ac5442ef7153' }
9
+ let(:cancel_request) { stub_request(:post, "#{api_endpoint}/cards/#{reference}/cancel").
10
+ with(headers: { 'Accept' => 'application/json',
11
+ 'Authorization' => /WIZYPAY #{api_key}:.*/,
12
+ 'Content-Type' => 'application/x-www-form-urlencoded' }) }
13
+ before do
14
+ Wizypay.setup(api_key, api_secret, api_endpoint)
15
+ end
16
+
17
+ context 'success' do
18
+ it 'returns empty body' do
19
+ request = cancel_request.to_return(status: 200, body: '')
20
+ response = Wizypay::Card.cancel(reference)
21
+ expect(request).to have_been_made
22
+ expect(response).to be_empty
23
+ end
24
+ end
25
+
26
+ context 'failure' do
27
+ context '4XX' do
28
+ it "throws #{RestClient::Exception}" do
29
+ request = cancel_request.to_return(status: 401, body: { errors: { base: ['authentication_failed'] } }.to_json)
30
+ expect do
31
+ Wizypay::Card.cancel(reference)
32
+ end.to raise_error(RestClient::Exception)
33
+ expect(request).to have_been_made
34
+ end
35
+ end
36
+
37
+ context 'timeout' do
38
+ it "throws #{RestClient::Exception}" do
39
+ request = cancel_request.to_timeout
40
+ expect do
41
+ Wizypay::Card.cancel(reference)
42
+ end.to raise_error(RestClient::Exception)
43
+ expect(request).to have_been_made
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'time'
3
+
4
+ RSpec.describe 'DistributionApi::create_card' do
5
+
6
+ let(:api_key) { 'key' }
7
+ let(:api_secret) { 'secret' }
8
+ let(:api_endpoint) { 'https://api.wizypay.com' }
9
+ let(:reference) { '85fb584c-72cb-4f35-b307-ac5442ef7153' }
10
+
11
+ before do
12
+ Wizypay.setup(api_key, api_secret, api_endpoint)
13
+ end
14
+
15
+ it 'returns' do
16
+ t = Time.new('2015-10-30T21:00:00+001')
17
+ Timecop.freeze(t) do
18
+ url = Wizypay::Card.url(reference)
19
+ expect(url).to eq("#{api_endpoint}/widget?key=#{URI::encode_www_form_component api_key}"+
20
+ "&timestamp=#{URI::encode_www_form_component t.httpdate}" +
21
+ "&reference=#{URI::encode_www_form_component reference}"+
22
+ "&security=0fKNCz6hux0IjNCz31JHgzh35gqLTAIM8z3iNhSkC7g%3D")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'DistributionApi::create_card' do
4
+
5
+ let(:api_key) { 'key' }
6
+ let(:api_secret) { 'secret' }
7
+ let(:api_endpoint) { 'https://api.wizypay.com' }
8
+ let(:user) { { id: 33, first_name: 'Nicolas', last_name: 'Cage' } }
9
+ let(:reference) { '85fb584c-72cb-4f35-b307-ac5442ef7153' }
10
+ let(:merchant_id) { '91' }
11
+ let(:amount) { '5000' }
12
+ let(:currency) { 'EUR' }
13
+ let(:create_request) { stub_request(:post, "#{api_endpoint}/cards").
14
+ with(body: { amount: amount, currency: currency, merchant_id: merchant_id,
15
+ reference: reference, user: user.to_json },
16
+ headers: { 'Accept' => 'application/json',
17
+ 'Authorization' => /WIZYPAY #{api_key}:.*/,
18
+ 'Content-Type' => 'application/x-www-form-urlencoded' }) }
19
+ before do
20
+ Wizypay.setup(api_key, api_secret, api_endpoint)
21
+ end
22
+
23
+ context 'success' do
24
+ it 'returns response as hash' do
25
+ response_body = {
26
+ reference: reference,
27
+ type: 'Mastercard',
28
+ amount: amount,
29
+ currency: currency,
30
+ merchant_id: merchant_id,
31
+ user_id: user[:id]
32
+ }
33
+ request = create_request.to_return(status: 200, body: response_body.to_json)
34
+ response = Wizypay::Card.create(reference, amount, currency, merchant_id, user)
35
+ expect(request).to have_been_made
36
+ expect(response).to match(response_body)
37
+ end
38
+ end
39
+
40
+ context 'failure' do
41
+ context '4XX' do
42
+ it "throws #{RestClient::Exception}" do
43
+ request = create_request.to_return(status: 401, body: { errors: { base: ['authentication_failed'] } }.to_json)
44
+ expect do
45
+ Wizypay::Card.create(reference, amount, currency, merchant_id, user)
46
+ end.to raise_error(RestClient::Exception)
47
+ expect(request).to have_been_made
48
+ end
49
+ end
50
+
51
+ context 'timeout' do
52
+ it "throws #{RestClient::Exception}" do
53
+ request = create_request.to_timeout
54
+ expect do
55
+ Wizypay::Card.create(reference, amount, currency, merchant_id, user)
56
+ end.to raise_error(RestClient::Exception)
57
+ expect(request).to have_been_made
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,92 @@
1
+ require 'wizypay'
2
+ require 'webmock/rspec'
3
+ require 'timecop'
4
+ # This file was generated by the `rspec --init` command. Conventionally, all
5
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
6
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
7
+ # file to always be loaded, without a need to explicitly require it in any files.
8
+ #
9
+ # Given that it is always loaded, you are encouraged to keep this file as
10
+ # light-weight as possible. Requiring heavyweight dependencies from this file
11
+ # will add to the boot time of your test suite on EVERY test run, even for an
12
+ # individual file that may not need all of that loaded. Instead, consider making
13
+ # a separate helper file that requires the additional dependencies and performs
14
+ # the additional setup, and require it from the spec files that actually need it.
15
+ #
16
+ # The `.rspec` file also contains a few flags that are not defaults but that
17
+ # users commonly want.
18
+ #
19
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
20
+ RSpec.configure do |config|
21
+ # rspec-expectations config goes here. You can use an alternate
22
+ # assertion/expectation library such as wrong or the stdlib/minitest
23
+ # assertions if you prefer.
24
+ config.expect_with :rspec do |expectations|
25
+ # This option will default to `true` in RSpec 4. It makes the `description`
26
+ # and `failure_message` of custom matchers include text for helper methods
27
+ # defined using `chain`, e.g.:
28
+ # be_bigger_than(2).and_smaller_than(4).description
29
+ # # => "be bigger than 2 and smaller than 4"
30
+ # ...rather than:
31
+ # # => "be bigger than 2"
32
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
33
+ end
34
+
35
+ # rspec-mocks config goes here. You can use an alternate test double
36
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
37
+ config.mock_with :rspec do |mocks|
38
+ # Prevents you from mocking or stubbing a method that does not exist on
39
+ # a real object. This is generally recommended, and will default to
40
+ # `true` in RSpec 4.
41
+ mocks.verify_partial_doubles = true
42
+ end
43
+
44
+ # The settings below are suggested to provide a good initial experience
45
+ # with RSpec, but feel free to customize to your heart's content.
46
+ # These two settings work together to allow you to limit a spec run
47
+ # to individual examples or groups you care about by tagging them with
48
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
+ # get run.
50
+ config.filter_run :focus
51
+ config.run_all_when_everything_filtered = true
52
+
53
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
54
+ # For more details, see:
55
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
56
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
57
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
58
+ config.disable_monkey_patching!
59
+
60
+ # This setting enables warnings. It's recommended, but in some cases may
61
+ # be too noisy due to issues in dependencies.
62
+ config.warnings = true
63
+
64
+ # Many RSpec users commonly either run the entire suite or an individual
65
+ # file, and it's useful to allow more verbose output when running an
66
+ # individual spec file.
67
+ if config.files_to_run.one?
68
+ # Use the documentation formatter for detailed output,
69
+ # unless a formatter has already been configured
70
+ # (e.g. via a command-line flag).
71
+ config.default_formatter = 'doc'
72
+ end
73
+
74
+ # Print the 10 slowest examples and example groups at the
75
+ # end of the spec run, to help surface which specs are running
76
+ # particularly slow.
77
+ config.profile_examples = 10
78
+
79
+ # Run specs in random order to surface order dependencies. If you find an
80
+ # order dependency and want to debug it, you can fix the order by providing
81
+ # the seed, which is printed after each run.
82
+ # --seed 1234
83
+ config.order = :random
84
+
85
+ # Seed global randomization in this process using the `--seed` CLI option.
86
+ # Setting this allows you to use `--seed` to deterministically reproduce
87
+ # test failures related to randomization by passing the same `--seed` value
88
+ # as the one that triggered the failure.
89
+ Kernel.srand config.seed
90
+ end
91
+
92
+ Timecop.safe_mode = true
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wizypay-api-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chaker Nakhli
8
+ - Marc-Yervant Halard
9
+ - Joel Cogen
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2016-01-21 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: simple-hmac
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '0.4'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '0.4'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rest-client
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '1.8'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '1.8'
43
+ - !ruby/object:Gem::Dependency
44
+ name: bundler
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.10'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '1.10'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rake
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '10.4'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '10.4'
71
+ - !ruby/object:Gem::Dependency
72
+ name: rspec
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '3.3'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '3.3'
85
+ - !ruby/object:Gem::Dependency
86
+ name: webmock
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '1.22'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: '1.22'
99
+ - !ruby/object:Gem::Dependency
100
+ name: timecop
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: '0.8'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: '0.8'
113
+ description:
114
+ email:
115
+ - chaker@wizypay.com
116
+ - marc-yervant@wizypay.com
117
+ - joel@wizypay.com
118
+ executables: []
119
+ extensions: []
120
+ extra_rdoc_files: []
121
+ files:
122
+ - LICENSE.txt
123
+ - Rakefile
124
+ - lib/wizypay.rb
125
+ - lib/wizypay/card.rb
126
+ - lib/wizypay/client.rb
127
+ - lib/wizypay/version.rb
128
+ - spec/card/cancel_card_spec.rb
129
+ - spec/card/card_url_spec.rb
130
+ - spec/card/create_card_spec.rb
131
+ - spec/spec_helper.rb
132
+ homepage: http://developers.wizypay.com
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options:
138
+ - "--charset=UTF-8"
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 2.2.0
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.4.5.1
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Programmatic API to access Wizypay's API.
157
+ test_files:
158
+ - spec/card/cancel_card_spec.rb
159
+ - spec/card/card_url_spec.rb
160
+ - spec/card/create_card_spec.rb
161
+ - spec/spec_helper.rb