payonline 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ffecc72ab316af139858d166bad9f2f061fee703
4
- data.tar.gz: e37aa7b384f956ab5a019081a9a8da21efbe042d
3
+ metadata.gz: 4eeed6efaf2e7fdf7739e8ffce53c6d490a43407
4
+ data.tar.gz: 8ae885feb0eafc060bebf8c39dd39f730b11cd03
5
5
  SHA512:
6
- metadata.gz: 73e84b51ee88012b49eb71a948b7676a285dcc1a7000a0d1d5bd0ae9b81ce9432f6d01af43dde8933516dbefc2c6986442e5edf079e24fcca7bf72b53265f0b6
7
- data.tar.gz: fa5ad0967fc1ed6b014ea35140332bfb9f89f5a2ec1496aeb3e22b97306aa9bec0a024fd4ea3111f3db45d8037e484b88dd54ac26b7f64ae2bc85677044e3f39
6
+ metadata.gz: 04328df7d7d41d4528fdf46456cce0e6d4707e0ab6398d0210a3ac785a0af96a435530d6a57110144d78692a194316f849600528b19616aa6ad082a33c392040
7
+ data.tar.gz: 0489c355b5f137c6015d5000fa6185bbcce0bd031c65a31acb10b7f74910536e5cce539b21746944eea9d22e222ab2c16e05a67fb0164fc1b06e60a2d049870c
data/.hound.yml ADDED
@@ -0,0 +1,2 @@
1
+ ruby:
2
+ config_file: .rubocop.yml
data/.rubocop.yml ADDED
@@ -0,0 +1,16 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+ Documentation:
4
+ Enabled: false
5
+ NumericLiterals:
6
+ Enabled: false
7
+ ClassAndModuleChildren:
8
+ Enabled: false
9
+ SingleLineBlockParams:
10
+ Enabled: false
11
+ FrozenStringLiteralComment:
12
+ Enabled: false
13
+ MutableConstant:
14
+ Enabled: false
15
+ MultilineMethodCallIndentation:
16
+ EnforcedStyle: indented
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ## Payonline
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/payonline.svg)](http://badge.fury.io/rb/payonline) [![Code Climate](https://codeclimate.com/github/yuri-zubov/payonline/badges/gpa.svg)](https://codeclimate.com/github/yuri-zubov/payonline)
4
+
3
5
  This is a thin wrapper library that makes using PayOnline API a bit easier.
4
6
 
5
7
  ## Installation
@@ -18,37 +20,40 @@ $ bundle
18
20
 
19
21
  ## Configuring
20
22
 
21
- Create initialize file. This file is usually located at /config/initializers/payonline.rb
23
+ Create an initializer: `config/initializers/payonline.rb`:
24
+
22
25
  ```ruby
23
- Payonline.config do |c|
24
- c.merchant_id = '12345'
25
- c.private_security_key = '3844908d-4c2a-42e1-9be0-91bb5d068d22'
26
- c.return_url = 'http://you_domain/payments/success'
27
- c.fail_url = 'http://you_domain/payments/failed'
26
+ Payonline.config do |config|
27
+ config.merchant_id = '12345'
28
+ config.private_security_key = 'your-private-security-key'
29
+ config.return_url = 'https://example.com/payments/success'
30
+ config.fail_url = 'https://example.com/payments/fail'
28
31
  end
29
32
  ```
30
33
 
31
34
  ## Usage
32
35
 
33
- Get payment link
36
+ Get payment URL:
34
37
 
35
38
  ```ruby
36
- Payonline::PaymentGateway.new(order_id: 56789, amount: 9.99 , currency: 'USD').get_payment_url
39
+ Payonline::PaymentGateway.new(order_id: 1, amount: 2.0, currency: 'RUB').payment_url
37
40
  ```
38
41
 
39
- Check Call-back
42
+ Implement a callback action that will be called by PayOnline after a transaction is completed:
43
+
40
44
  ```ruby
41
- @paymant_response = Payonline::PaymentResponse.new(prms)
42
- if paymant_response.valid_payment?
43
- Order.find(@paymant_response.order_id).pay
44
- end
45
+ @response = Payonline::PaymentResponse.new(params)
46
+
47
+ if @response.valid_payment?
48
+ Order.find(@response.order_id).set_paid!
49
+ end
45
50
  ```
46
51
 
47
52
  ## Contributing
48
53
 
49
54
  1. Fork it
50
- 2. Clone it `git clone http://github.com/path/to/your/fork`
55
+ 2. Clone it `git clone https://github.com/SumatoSoft/payonline`
51
56
  3. Create your feature branch `git checkout -b my-new-feature`
52
- 4. Commit your changes `git commit -am 'Add some feature`
57
+ 4. Commit your changes `git commit -am 'Add some feature'`
53
58
  5. Push to the branch `git push origin my-new-feature`
54
59
  6. Create new pull request through Github
data/Rakefile CHANGED
@@ -1 +1 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
@@ -1,70 +1,44 @@
1
1
  module Payonline
2
2
  class PaymentGateway
3
- class Params < SimpleDelegator
4
-
5
- REQUIED_PARAMS = %w(order_id amount currency valid_until order_description return_url fail_url return_url)
6
-
7
- def initialize(params)
8
- @params = prepare_params(params)
9
-
10
- filter_params
11
-
12
- __setobj__ @params
13
- end
14
-
15
- def to_query
16
- @params.each_with_object({}) do |(k, v), params|
17
- params[k.camelize] = v
18
- end.to_query
19
- end
20
-
21
- private
22
-
23
- def prepare_params(params)
24
- params[:amount] = '%.2f' % params[:amount]
25
-
26
- default_params = { return_url: return_url, fail_url: fail_url }
27
- params.merge(default_params)
28
- end
29
-
30
- def filter_params
31
- @params.select! { |k, v| REQUIED_PARAMS.include?(k) && v }
32
- end
33
-
34
- def return_url
35
- @return_url ||= Payonline.configuration.return_url
36
- end
37
-
38
- def fail_url
39
- @fail_url ||= Payonline.configuration.fail_url
40
- end
41
- end
3
+ BASE_URL = 'https://secure.payonlinesystem.com'
42
4
 
43
5
  SIGNED_PARAMS = %w(order_id amount currency valid_until order_description)
44
-
45
- def initialize(params={})
46
- @params = Params.new(params.with_indifferent_access)
6
+ PERMITTED_PARAMS = %w(
7
+ order_id amount currency valid_until order_description return_url fail_url
8
+ )
9
+
10
+ PAYMENT_TYPE_URL = {
11
+ qiwi: 'select/qiwi/',
12
+ webmoney: 'select/webmoney/',
13
+ yandexmoney: 'select/yandexmoney/',
14
+ masterpass: 'select/masterpass/'
15
+ }
16
+
17
+ def initialize(params = {})
18
+ @params = prepare_params(params)
47
19
  end
48
20
 
49
- def get_payment_url(type = 'card')
50
- params = Payonline::Signature.sign_params(@params, SIGNED_PARAMS)
21
+ def payment_url(type: :card, language: :ru)
22
+ params = Payonline::Signature.new(@params, SIGNED_PARAMS).sign
51
23
 
52
- "#{url_by_kind_of_payment(type)}?#{params.to_query}"
24
+ "#{BASE_URL}/#{language}/payment/#{PAYMENT_TYPE_URL[type]}?#{params.to_query}"
53
25
  end
54
26
 
55
27
  private
56
28
 
57
- def url_by_kind_of_payment(type, language = 'ru')
58
- case type.to_s
59
- when 'qiwi'
60
- "https://secure.payonlinesystem.com/#{language}/payment/select/qiwi/"
61
- when 'webmoney'
62
- "https://secure.payonlinesystem.com/#{language}/payment/select/webmoney/"
63
- when 'yandexmoney'
64
- "https://secure.payonlinesystem.com/#{language}/payment/select/webmoney/"
65
- when 'card'
66
- "https://secure.payonlinesystem.com/#{language}/payment/"
67
- end
29
+ def prepare_params(params)
30
+ params
31
+ .with_indifferent_access
32
+ .slice(*PERMITTED_PARAMS)
33
+ .merge(default_params){ |_, important, _| important }
34
+ .merge(amount: format('%.2f', params[:amount]))
35
+ end
36
+
37
+ def default_params
38
+ {
39
+ return_url: Payonline.configuration.return_url,
40
+ fail_url: Payonline.configuration.fail_url
41
+ }
68
42
  end
69
43
  end
70
44
  end
@@ -2,31 +2,28 @@ module Payonline
2
2
  class PaymentResponse
3
3
  extend Forwardable
4
4
 
5
- attr_accessor :response, :params
5
+ attr_accessor :data, :params
6
6
 
7
- RESPONSE_PARAMS = %w(date_time transaction_id order_id amount currency)
7
+ SIGNED_PARAMS = %i(date_time transaction_id order_id amount currency)
8
8
 
9
- def_delegators :params, *RESPONSE_PARAMS
9
+ def_delegators :data, *SIGNED_PARAMS
10
10
 
11
- def initialize(response = {})
12
- self.response = response
13
- self.params = OpenStruct.new(normalize_params)
11
+ def initialize(params = {})
12
+ @params = prepare_params(params)
13
+ @data = OpenStruct.new(@params)
14
14
  end
15
15
 
16
16
  def valid_payment?
17
- keys = RESPONSE_PARAMS.each_with_object([]).each do |key, array|
18
- array << response.keys.select{ |e| e.underscore == key }.first
19
- end
20
-
21
- params.security_key == Payonline::Signature.digest(response, keys)
17
+ keys = SIGNED_PARAMS.select { |key| @params.key?(key) }
18
+ @params[:security_key] == Payonline::Signature.new(@params, keys, false).digest
22
19
  end
23
20
 
24
21
  private
25
22
 
26
- def normalize_params
27
- result = response.each_with_object({}) do |(k, v), params|
28
- params[k.underscore] = v
29
- end.with_indifferent_access
23
+ def prepare_params(params)
24
+ params
25
+ .transform_keys { |key| key.to_s.underscore }
26
+ .with_indifferent_access
30
27
  end
31
28
  end
32
29
  end
@@ -0,0 +1,40 @@
1
+ module Payonline
2
+ class RebillGateway
3
+ SIGNED_PARAMS = %w(rebill_anchor order_id amount currency)
4
+ PERMITTED_PARAMS = %w(rebill_anchor order_id amount currency)
5
+ BASE_URL = 'https://secure.payonlinesystem.com'
6
+
7
+ def initialize(params = {})
8
+ @params = prepare_params(params)
9
+ end
10
+
11
+ # Perform the rebill operation and return the response
12
+ def rebill
13
+ response = HTTParty.get(rebill_url)
14
+ return false unless response.success?
15
+
16
+ Payonline::RebillResponse.new(response.body).success?
17
+ end
18
+
19
+ # Return the URL without performing a request
20
+ def rebill_url
21
+ params = Payonline::Signature.new(@params, SIGNED_PARAMS).sign
22
+
23
+ "#{BASE_URL}/payment/transaction/rebill/?#{params.to_query}"
24
+ end
25
+
26
+ private
27
+
28
+ def prepare_params(params)
29
+ params
30
+ .with_indifferent_access
31
+ .slice(*PERMITTED_PARAMS)
32
+ .merge(default_params)
33
+ .merge(amount: format('%.2f', params[:amount]))
34
+ end
35
+
36
+ def default_params
37
+ {}
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ module Payonline
2
+ class RebillResponse
3
+ SUCCESS_CODE = 'OK'
4
+
5
+ def initialize(response)
6
+ @response = parse_response(response)
7
+ end
8
+
9
+ def success?
10
+ @response[:result] == SUCCESS_CODE
11
+ end
12
+
13
+ def failure?
14
+ !success?
15
+ end
16
+
17
+ private
18
+
19
+ def parse_response(response)
20
+ CGI.parse(response)
21
+ .transform_keys { |key| key.to_s.underscore }
22
+ .transform_values(&:first)
23
+ .with_indifferent_access
24
+ end
25
+ end
26
+ end
@@ -1,23 +1,48 @@
1
1
  module Payonline
2
2
  class Signature
3
- def self.digest(sign_params, keys=[])
4
- if keys.present?
5
- sign_params = sign_params.slice(*keys)
6
- end
3
+ def initialize(params, keys, add_merchant_id = true)
4
+ @keys = keys
5
+
6
+ # The order of parameter keys matters
7
+ @params = prepare_params(params, add_merchant_id)
8
+
9
+ # Permitted content_type values: text, xml
10
+ @params[:security_key] = digest
11
+ @params[:content_type] = 'text'
12
+ end
13
+
14
+ # A signed copy of params
15
+ def sign
16
+ @params.transform_keys { |key| key.to_s.camelize }
17
+ end
7
18
 
8
- sign_params.merge!({ private_security_key: Payonline.configuration.private_security_key })
9
- Digest::MD5.hexdigest(sign_params.each.map{|k, v| "#{k.to_s.camelize}=#{v}"}.join('&'))
19
+ def digest
20
+ Digest::MD5.hexdigest(digest_data)
10
21
  end
11
22
 
12
- def self.sign_params(params, keys=[], add_merchant_id = true)
13
- params.reverse_merge!({ 'merchant_id' => Payonline.configuration.merchant_id }) if add_merchant_id
14
- if keys.present?
15
- keys.unshift 'merchant_id' if add_merchant_id
23
+ private
24
+
25
+ # Prepend params hash with merchant_id
26
+ def prepare_params(params, add_merchant_id = true)
27
+ if add_merchant_id
28
+ params.reverse_merge!(merchant_id: Payonline.configuration.merchant_id)
29
+ @keys.unshift(:merchant_id)
16
30
  end
17
- digest = self.digest(params, keys)
18
- params.merge!({ 'security_key' => digest, 'content_type' => 'text' })
19
31
 
20
- params
32
+ params.with_indifferent_access
33
+ end
34
+
35
+ # Prepare params for digest
36
+ def digest_data
37
+ digest_params = @params.slice(*@keys) if @keys.present?
38
+ digest_params[:private_security_key] = Payonline.configuration.private_security_key
39
+
40
+ # HACK: PayOnline sends OrderId but TransactionID (notice the letter case)
41
+ digest_params
42
+ .transform_keys { |key| key.to_s.camelize }
43
+ .transform_keys { |key| key == 'TransactionId' ? 'TransactionID' : key }
44
+ .map { |key, value| "#{key}=#{value}" }
45
+ .join('&')
21
46
  end
22
47
  end
23
48
  end
@@ -1,3 +1,3 @@
1
1
  module Payonline
2
- VERSION = "0.1.0"
2
+ VERSION = '0.1.1'
3
3
  end
data/lib/payonline.rb CHANGED
@@ -1,12 +1,14 @@
1
- require 'yaml'
1
+ require 'active_support/all'
2
+ require 'httparty'
3
+
2
4
  require 'payonline/config'
3
5
  require 'payonline/payment_gateway'
4
6
  require 'payonline/payment_response'
7
+ require 'payonline/rebill_gateway'
8
+ require 'payonline/rebill_response'
5
9
  require 'payonline/signature'
6
10
 
7
11
  module Payonline
8
- extend self
9
-
10
12
  def self.configuration
11
13
  @configuration ||= Config.new
12
14
  end
data/payonline.gemspec CHANGED
@@ -1,24 +1,25 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
4
5
  require 'payonline/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "payonline"
8
+ spec.name = 'payonline'
8
9
  spec.version = Payonline::VERSION
9
- spec.authors = ["Yuri Zubov"]
10
- spec.email = ["I0Result86@gmail.com"]
10
+ spec.authors = ['Yuri Zubov', 'SumatoSoft']
11
+ spec.email = ['I0Result86@gmail.com']
11
12
 
12
- spec.summary = %q{This is a thin wrapper library that makes using PayOnline API a bit easier.}
13
- spec.description = %q{This is a thin wrapper library that makes using PayOnline API a bit easier.}
14
- spec.homepage = "https://github.com/I0Result/payonline"
15
- spec.license = "MIT"
13
+ spec.summary = 'PayOnline API wrapper.'
14
+ spec.description = 'This is a thin wrapper library that makes using PayOnline API a bit easier.'
15
+ spec.homepage = 'https://github.com/SumatoSoft/payonline'
16
+ spec.license = 'MIT'
16
17
 
17
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
- spec.bindir = "exe"
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec)/}) }
19
+ spec.bindir = 'exe'
19
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
- spec.require_paths = ["lib"]
21
+ spec.require_paths = ['lib']
21
22
 
22
- spec.add_development_dependency "bundler", "~> 1.9"
23
- spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency 'activesupport', '>= 4.2'
24
+ spec.add_development_dependency 'rake', '~> 11.2'
24
25
  end
metadata CHANGED
@@ -1,43 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: payonline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuri Zubov
8
+ - SumatoSoft
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2015-04-08 00:00:00.000000000 Z
12
+ date: 2017-01-16 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: bundler
15
+ name: activesupport
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - ~>
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: '1.9'
20
+ version: '4.2'
20
21
  type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - ~>
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: '1.9'
27
+ version: '4.2'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: rake
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - ~>
32
+ - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: '10.0'
34
+ version: '11.2'
34
35
  type: :development
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - ~>
39
+ - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: '10.0'
41
+ version: '11.2'
41
42
  description: This is a thin wrapper library that makes using PayOnline API a bit easier.
42
43
  email:
43
44
  - I0Result86@gmail.com
@@ -45,7 +46,9 @@ executables: []
45
46
  extensions: []
46
47
  extra_rdoc_files: []
47
48
  files:
48
- - .gitignore
49
+ - ".gitignore"
50
+ - ".hound.yml"
51
+ - ".rubocop.yml"
49
52
  - Gemfile
50
53
  - README.md
51
54
  - Rakefile
@@ -53,10 +56,12 @@ files:
53
56
  - lib/payonline/config.rb
54
57
  - lib/payonline/payment_gateway.rb
55
58
  - lib/payonline/payment_response.rb
59
+ - lib/payonline/rebill_gateway.rb
60
+ - lib/payonline/rebill_response.rb
56
61
  - lib/payonline/signature.rb
57
62
  - lib/payonline/version.rb
58
63
  - payonline.gemspec
59
- homepage: https://github.com/I0Result/payonline
64
+ homepage: https://github.com/SumatoSoft/payonline
60
65
  licenses:
61
66
  - MIT
62
67
  metadata: {}
@@ -66,18 +71,18 @@ require_paths:
66
71
  - lib
67
72
  required_ruby_version: !ruby/object:Gem::Requirement
68
73
  requirements:
69
- - - ! '>='
74
+ - - ">="
70
75
  - !ruby/object:Gem::Version
71
76
  version: '0'
72
77
  required_rubygems_version: !ruby/object:Gem::Requirement
73
78
  requirements:
74
- - - ! '>='
79
+ - - ">="
75
80
  - !ruby/object:Gem::Version
76
81
  version: '0'
77
82
  requirements: []
78
83
  rubyforge_project:
79
- rubygems_version: 2.4.2
84
+ rubygems_version: 2.4.6
80
85
  signing_key:
81
86
  specification_version: 4
82
- summary: This is a thin wrapper library that makes using PayOnline API a bit easier.
87
+ summary: PayOnline API wrapper.
83
88
  test_files: []