brickwall 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6c9fd89e226f905056fcca8acebc7be7c81ba8ed
4
+ data.tar.gz: fc61d20ec491870c9ea332c2f39bb6c5e5eff21a
5
+ SHA512:
6
+ metadata.gz: db5ad4cd28ca40b3fa74c7e232bd454ca35c97fc23546d56cb27432a943b2596509a9870424499aa7cb46c50a66ef15fb6ab31160bcba535abcd17496e4fe4c5
7
+ data.tar.gz: ac4b751ae6fe237d48aba738dc35b6b8f2ce2b41f353a05d91c573c56949495e444b8985d806113cddbc64fc2e1c162407905812c29e8554034d36d2a68a7ddf
data/.gitignore ADDED
@@ -0,0 +1,36 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/bundle
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ Gemfile.lock
32
+ .ruby-version
33
+ .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 R&D Allm Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # brickwall
2
+
3
+ [![Code Climate](https://codeclimate.com/github/sujrd/brickwall/badges/gpa.svg)](https://codeclimate.com/github/sujrd/brickwall)
4
+ [![Gem Version](http://img.shields.io/gem/v/brickwall.svg)](https://rubygems.org/gems/brickwall)
5
+
6
+ Unofficial Paymentwall Brick API wrapper Ruby gem.
7
+
8
+ ## Installation
9
+
10
+ $ gem install brickwall
11
+
12
+ ## Usage
13
+
14
+ Example barebones integration with Rails:
15
+
16
+ ```ruby
17
+ # config/initializer/brickwall.rb
18
+ Brickwall.configure do |config|
19
+ config.brick_public_key = Rails.application.secrets.paymentwall_brick_public_key
20
+ config.brick_private_key = Rails.application.secrets.paymentwall_brick_private_key
21
+ config.widget_project_key = Rails.application.secrets.paymentwall_widget_project_key
22
+ config.widget_secret_key = Rails.application.secrets.paymentwall_widget_secret_key
23
+ config.application_domain = Rails.application.secrets.paymentwall_application_domain
24
+ end
25
+
26
+ # app/controllers/payments_controller.rb
27
+ class PaymentsController < ActionController::Base
28
+
29
+ def create
30
+ response_data = Brickwall::API::Charge.create({
31
+ email: 'foo@example.com',
32
+ amount: 3.50,
33
+ currency: 'USD',
34
+ token: params[:brick_token],
35
+ fingerprint: params[:brick_fingerprint],
36
+ description: 'Order #123',
37
+ })
38
+ if response_data['type'] == 'Error'
39
+ render json: response_data, status: :unprocessable_entity
40
+ else
41
+ # Record result in DB
42
+ render json: response_data, status: :created
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ # app/controllers/pingback_controller.rb
49
+ class PingbackController < ActionController::Base
50
+
51
+ def index
52
+ if Brickwall::Pingback.whitelisted_ip? request.remote_ip
53
+ sig = Brickwall::Signature.calculate_v3 pingback_params
54
+ if ActiveSupport::SecurityUtils.secure_compare sig, params[:sig]
55
+ # Record result in DB
56
+ render plain: 'OK'
57
+ else
58
+ raise ActionController::RoutingError, 'Not Found'
59
+ end
60
+ else
61
+ raise ActionController::RoutingError, 'Not Found'
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def pingback_params
68
+ params.slice(:goodsid, :is_test, :ref, :sign_version, :slength,
69
+ :speriod, :type, :uid, :currency, :reason)
70
+ end
71
+
72
+ end
73
+ ```
74
+
75
+ ## License
76
+
77
+ This gem is available under the MIT license. See the LICENSE file for more info.
data/brickwall.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+ require 'brickwall/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'brickwall'
6
+ s.version = Brickwall::VERSION
7
+ s.date = Time.now.strftime('%Y-%m-%d')
8
+ s.summary = 'Unofficial Paymentwall Brick API wrapper'
9
+ s.description = s.summary
10
+ s.homepage = 'http://github.com/sujrd/brickwall'
11
+ s.authors = ['Douglas Teoh']
12
+ s.email = 'douglas@dteoh.com'
13
+ s.has_rdoc = false
14
+ s.files = `git ls-files -z`.split("\x0")
15
+ s.require_paths = %w(lib)
16
+ s.license = 'MIT'
17
+
18
+ s.add_dependency 'rest-client', '~> 1.8'
19
+ end
data/lib/brickwall.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'digest'
2
+ require 'openssl'
3
+ require 'json'
4
+ require 'net/http'
5
+
6
+ require 'rest-client'
7
+
8
+ module Brickwall
9
+ class << self
10
+ attr_writer :configuration
11
+
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def configure
17
+ yield configuration
18
+ end
19
+ end
20
+
21
+ class Configuration
22
+ attr_accessor :brick_public_key, :brick_private_key,
23
+ :widget_project_key, :widget_secret_key,
24
+ :application_domain
25
+
26
+ def configured?
27
+ present?(brick_public_key) &&
28
+ present?(brick_private_key) &&
29
+ present?(widget_project_key) &&
30
+ present?(widget_secret_key)
31
+ end
32
+
33
+ private
34
+
35
+ def present?(str)
36
+ str != nil && str.match(/\A\s*\z/) == nil
37
+ end
38
+ end
39
+ end
40
+
41
+ require 'brickwall/version'
42
+ require 'brickwall/pingback'
43
+ require 'brickwall/signature'
44
+ require 'brickwall/api'
@@ -0,0 +1,12 @@
1
+ module Brickwall
2
+ module API
3
+ def self.url(fragment)
4
+ "https://api.paymentwall.com/api/brick/#{fragment}"
5
+ end
6
+ end
7
+ end
8
+
9
+ require 'brickwall/api/error'
10
+ require 'brickwall/api/charge'
11
+ require 'brickwall/api/one_time_token'
12
+ require 'brickwall/api/subscription'
@@ -0,0 +1,48 @@
1
+ module Brickwall
2
+ module API
3
+ module Charge
4
+ def self.create(params = {})
5
+ api_params = params
6
+ if api_params.has_key?('browser_ip') && !api_params.has_key?('browser_domain')
7
+ api_params = params.clone
8
+ api_params['browser_domain'] = Brickwall.configuration.application_domain
9
+ end
10
+ response = RestClient.post API.url('charge'), api_params, {
11
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
12
+ }
13
+ JSON.parse response
14
+ rescue RestClient::Exception => e
15
+ err = JSON.parse e.response
16
+ Error.new err['type'], err['error'], err['code']
17
+ end
18
+
19
+ def self.get(charge_id)
20
+ response = RestClient.get API.url("charge/#{charge_id}"), {
21
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
22
+ }
23
+ JSON.parse response
24
+ end
25
+
26
+ def self.refund(charge_id)
27
+ response = RestClient.post API.url("charge/#{charge_id}/refund"), {}, {
28
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
29
+ }
30
+ JSON.parse response
31
+ end
32
+
33
+ def self.capture(charge_id)
34
+ response = RestClient.post API.url("charge/#{charge_id}/capture"), {}, {
35
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
36
+ }
37
+ JSON.parse response
38
+ end
39
+
40
+ def self.void(charge_id)
41
+ response = RestClient.post API.url("charge/#{charge_id}/void"), {}, {
42
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
43
+ }
44
+ JSON.parse response
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ module Brickwall
2
+ module API
3
+ class Error < Struct.new(:type, :error, :code)
4
+
5
+ # From https://www.paymentwall.com/en/documentation/Brick/2968#list-of-error-codes
6
+ def user_error?
7
+ case code
8
+ when 3003..3112 then true
9
+ when 3200 then true
10
+ when 5000 then true
11
+ else false
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Brickwall
2
+ module API
3
+ class OneTimeToken
4
+
5
+ def self.create(card = {})
6
+ response = RestClient.post API.url('token'), {
7
+ public_key: Brickwall.configuration.brick_public_key,
8
+ card: card
9
+ }, {
10
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
11
+ }
12
+ JSON.parse response
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ module Brickwall
2
+ module API
3
+ class Subscription
4
+
5
+ def self.create(params = {})
6
+ response = RestClient.post API.url('subscription'), params, {
7
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
8
+ }
9
+ JSON.parse response
10
+ rescue RestClient::Exception => e
11
+ err = JSON.parse e.response
12
+ Error.new err['type'], err['error'], err['code']
13
+ end
14
+
15
+ def self.get(subscription_id)
16
+ response = RestClient.get API.url("subscription/#{subscription_id}"), {
17
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
18
+ }
19
+ JSON.parse response
20
+ end
21
+
22
+ def self.cancel(subscription_id)
23
+ response = RestClient.post API.url("subscription/#{subscription_id}/cancel"), {}, {
24
+ 'X-ApiKey' => Brickwall.configuration.brick_private_key
25
+ }
26
+ JSON.parse response
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Brickwall
2
+ module Pingback
3
+ IP_WHITELIST = %w(
4
+ 174.36.92.186
5
+ 174.36.92.187
6
+ 174.36.92.192
7
+ 174.36.96.66
8
+ 174.37.14.28
9
+ )
10
+
11
+ def self.whitelisted_ip?(ip_address)
12
+ if ip_address.start_with? '174.3'
13
+ IP_WHITELIST.any? { |address| ip_address == address }
14
+ else
15
+ false
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module Brickwall
2
+ module Signature
3
+ class << self
4
+ def calculate_v2(params = {})
5
+ data = string_params(sorted_params!(params.to_a)) + Brickwall.configuration.widget_secret_key
6
+ Digest.hexencode OpenSSL::Digest::MD5.digest data
7
+ end
8
+
9
+ def calculate_v3(params = {})
10
+ data = string_params(sorted_params!(params.to_a)) + Brickwall.configuration.widget_secret_key
11
+ Digest.hexencode OpenSSL::Digest::SHA256.digest data
12
+ end
13
+
14
+ private
15
+
16
+ def sorted_params!(arr_params)
17
+ arr_params.sort! { |(k1,_), (k2,_)| k1 <=> k2 }
18
+ end
19
+
20
+ def string_params(arr_params)
21
+ str = StringIO.new
22
+ arr_params.each do |(k, v)|
23
+ str << k.to_s
24
+ str << '='
25
+ str << v.to_s
26
+ end
27
+ str.string
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Brickwall
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brickwall
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Douglas Teoh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ description: Unofficial Paymentwall Brick API wrapper
28
+ email: douglas@dteoh.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ".gitignore"
34
+ - Gemfile
35
+ - LICENSE
36
+ - README.md
37
+ - brickwall.gemspec
38
+ - lib/brickwall.rb
39
+ - lib/brickwall/api.rb
40
+ - lib/brickwall/api/charge.rb
41
+ - lib/brickwall/api/error.rb
42
+ - lib/brickwall/api/one_time_token.rb
43
+ - lib/brickwall/api/subscription.rb
44
+ - lib/brickwall/pingback.rb
45
+ - lib/brickwall/signature.rb
46
+ - lib/brickwall/version.rb
47
+ homepage: http://github.com/sujrd/brickwall
48
+ licenses:
49
+ - MIT
50
+ metadata: {}
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 2.5.1
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Unofficial Paymentwall Brick API wrapper
71
+ test_files: []