paysto-rails 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDZmN2Q3NWUxMmMwYzY0Njg0NzBkYzQxYTI5YmRkYTdmZjY3ZDUwZA==
4
+ NzRjM2IyMzliNGYwNjdhOGMyM2I1YmMyY2RhMzYwZDU0MzhjYWE5Yw==
5
5
  data.tar.gz: !binary |-
6
- YjFhYzZiMjFlOWJkMDNmOGI5Zjk0MTk5YTU5MmY0MTUxNmUxOGQwNw==
6
+ MDZjZDZhMzQxMDZmMDUzZmQ2MDA4YmMzMTQ3ZjQwMGE5YmMxNTFmMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZGU3YTliYzMwMmZhNTIyMmI3YzEyNWFhNzBkZTdjNTA5YTAzMmNiZDgwNGUw
10
- YjhhZTM0MTZjZWNlNWJiNmNlMTQwMTgzZGEzYTE4OTg4NDUyNGY3ODk3YjVj
11
- MWNhZTM3YjVkY2NkNDVhMjJmZjRlODBkODU2ODg3MzI3Yjc5ZWI=
9
+ NmQwMmU0MDBhZWFjZDJiNjBiNTNmOTc4NzRhNDFkNjliZDRlNDRkM2RmNWM3
10
+ MzhmNWRlMjRhM2RiMDYyYWQyMzJmMmU5ZTc3NTA3YjcxOTQ1Yjc4YmVmMjdm
11
+ MTY0OWU5NDFmZWEwMTgzMmU1OTFkY2FmODAzOGZiZDkwNDZlOWQ=
12
12
  data.tar.gz: !binary |-
13
- YjE4ZmI5NDY2MGNkNTBlYTY3NjBmOGQ1YjA2YzYwZWVhNDgyYjMzOGZhNDBl
14
- MTQxOTJkMmMwNDliOWZkNmQ0NzU4YjY5ZmNhYjZlZDQwMzExMzgwZmMyMjMy
15
- ODY4NDQxNzUzZjliZWQ5MjVkNWM3OWI1NTYyMTE1NTBjOTlkZDc=
13
+ OTA3NzQ3Zjk5MTFlMmRiOTcyMTAzNWRhZTVhZjM2MTBkNjMxYjE5MTVhYjAx
14
+ ZDVlZDY3MWJlNDE1NjA1NTI5M2FjOTI4MDM2ZDc1MmU3ZTlkOWU0ZGE1ZmFh
15
+ MGI1NGMzNGJlN2ExYTIwMzkxOTFlMDg3ZGYyMjY2Y2VkMzJiNzk=
data/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
  [![Gem Version](https://badge.fury.io/rb/paysto-rails.svg)](http://badge.fury.io/rb/paysto-rails)
3
3
  [![Code Climate](https://codeclimate.com/github/fbandrey/paysto-rails/badges/gpa.svg)](https://codeclimate.com/github/fbandrey/paysto-rails)
4
4
  [![Dependency Status](https://gemnasium.com/fbandrey/paysto-rails.svg)](https://gemnasium.com/fbandrey/paysto-rails)
5
+ [![security](https://hakiri.io/github/fbandrey/paysto-rails/master.svg)](https://hakiri.io/github/fbandrey/paysto-rails/master)
6
+ [![Inline docs](http://inch-ci.org/github/fbandrey/paysto-rails.png?branch=master)](http://inch-ci.org/github/fbandrey/paysto-rails)
5
7
 
6
- This is first implementation for passing payments through [Paysto](https://paysto.com) gateway.
7
-
8
- It works only with «[onlineMerchant](https://paysto.com/ru/products/onlineMerchant)», if you know what I mean. :)
8
+ This is first implementation for passing payments through [Paysto](https://paysto.com) gateway. It works only with «[onlineMerchant](https://paysto.com/ru/products/onlineMerchant)».
9
9
 
10
10
  ## Installation
11
11
 
@@ -65,35 +65,33 @@ In the simple case only what you should to do:
65
65
 
66
66
  That's all.
67
67
 
68
- Now you may customize models as you want, associate it with users or anything else...
69
-
70
- For more information check [payment workflow](https://github.com/fbandrey/paysto-rails/wiki/Payment-workflow) wiki.
71
-
72
68
  ## Usage
73
69
 
74
- You have 3 models and 1 controller now if you did everything right before. Check models and extend them with logic and associations, which you need in your application.
70
+ You have 3 models and 1 controller now if you did everything right before. Check models and extend them with logic or associations, which you need in your application.
75
71
 
76
- Controller by default [extended with concern](https://github.com/fbandrey/paysto-rails/blob/master/lib/paysto/controller.rb) and looks so:
72
+ Controller by default [extended with concern](https://github.com/fbandrey/paysto-rails/blob/master/lib/paysto/controller.rb) and contains all necessary methods:
77
73
  ```
78
74
  class PaystoController < ApplicationController
79
75
  include Paysto::Controller
80
76
  end
81
77
  ```
82
- But you may override methods here as you want. For example, if I want to redirect user to "/payments" URL when payment is passed:
78
+ But you may override methods as you want. For example, if you want to redirect user to custom URL when payment is passed:
83
79
  ```
84
80
  class PaystoController < ApplicationController
85
81
  include Paysto::Controller
86
82
 
87
83
  def success
88
84
  flash[:success] = I18n.t('paysto.success')
89
- redirect_to custom_payments_path
85
+ redirect_to any_custom_payments_path
90
86
  end
91
87
  end
92
88
  ```
93
89
 
94
- Also you can customize [check](https://github.com/fbandrey/paysto-rails/blob/master/lib/paysto/controller.rb#L9) or [callback](https://github.com/fbandrey/paysto-rails/blob/master/lib/paysto/controller.rb#L18) methods using Paysto module as you want, but we don't recommend it, do it only if you know what's going on there.
90
+ Also you can customize [check](https://github.com/fbandrey/paysto-rails/blob/master/lib/paysto/controller.rb#L9) or [callback](https://github.com/fbandrey/paysto-rails/blob/master/lib/paysto/controller.rb#L18) methods using Paysto module as you want, but do it only if you know what's going on there.
91
+
92
+ Check [payment workflow](https://github.com/fbandrey/paysto-rails/wiki/Payment-workflow) wiki for more information.
95
93
 
96
- ### Paysto methods
94
+ #### Paysto methods
97
95
 
98
96
  ```Paysto.balance``` – current balance in Paysto.
99
97
 
@@ -109,7 +107,7 @@ Also you can customize [check](https://github.com/fbandrey/paysto-rails/blob/mas
109
107
 
110
108
  ```Paysto.md5_valid?(params)``` – check whether the MD5 sign is valid.
111
109
 
112
- ```Paysto.pay_till``` – timestamp string in Paysto format.
110
+ ```Paysto.pay_till``` – timestamp string for payment expiration in Paysto format.
113
111
 
114
112
  ```Paysto.real_amount(amount)``` – real income amount without Paysto tax.
115
113
 
@@ -4,6 +4,7 @@ module Paysto
4
4
  class InstallGenerator < Rails::Generators::Base
5
5
  source_root File.expand_path('../../templates', __FILE__)
6
6
 
7
+ # Extend routes.rb with required routes.
7
8
  def add_paysto_routes
8
9
  paysto_route = <<-PAYSTO_ROUTES
9
10
  namespace :paysto do
@@ -14,18 +15,21 @@ PAYSTO_ROUTES
14
15
  route paysto_route
15
16
  end
16
17
 
18
+ # Copy general Paysto config.
17
19
  def copy_config
18
20
  template 'config/paysto.rb', 'config/initializers/paysto.rb'
19
21
  end
20
22
 
23
+ # Copy RU and EN locale files.
21
24
  def copy_locale
22
25
  template 'config/paysto.en.yml', 'config/locales/paysto.en.yml'
23
26
  template 'config/paysto.ru.yml', 'config/locales/paysto.ru.yml'
24
27
  end
25
28
 
29
+ # Copy default Paysto controller.
26
30
  def copy_controller
27
31
  template 'controllers/paysto_controller.rb', 'app/controllers/paysto_controller.rb'
28
32
  end
29
33
 
30
34
  end
31
- end
35
+ end
@@ -6,6 +6,7 @@ module Paysto
6
6
  include Rails::Generators::Migration
7
7
  source_root File.expand_path('../../templates', __FILE__)
8
8
 
9
+ # Migration timestamp.
9
10
  def self.next_migration_number(dirname)
10
11
  if ActiveRecord::Base.timestamped_migrations
11
12
  Time.new.utc.strftime("%Y%m%d%H%M%S")
@@ -14,14 +15,16 @@ module Paysto
14
15
  end
15
16
  end
16
17
 
18
+ # Create migration with required tables.
17
19
  def create_migration_file
18
20
  migration_template 'migration.rb', 'db/migrate/create_paysto_tables.rb'
19
21
  end
20
22
 
23
+ # Render configured models.
21
24
  def copy_models
22
25
  template 'models/payment.rb', "app/models/#{Paysto.payment_class_name.underscore}.rb"
23
26
  template 'models/invoice.rb', "app/models/#{Paysto.invoice_class_name.underscore}.rb"
24
27
  template 'models/invoice_notification.rb', "app/models/#{Paysto.invoice_notification_class_name.underscore}.rb"
25
28
  end
26
29
  end
27
- end
30
+ end
@@ -1,10 +1,11 @@
1
1
  Paysto.setup do |config|
2
2
 
3
- # === Put your Paysto credentials here
3
+ # === Put your real Paysto credentials here.
4
4
  config.id = 'SECRET-ID'
5
5
  config.secret = 'SECRET-KEY'
6
6
  config.description = 'CUSTOM-DESCRIPTION-FOR-PAYMENTS'
7
7
 
8
+ # === Paysto URLs.
8
9
  config.urls = {
9
10
  payment: 'https://paysto.com/ru/pay',
10
11
  currencies: 'https://paysto.com/api/Common/Currency',
@@ -12,6 +13,7 @@ Paysto.setup do |config|
12
13
  payments_list: 'https://paysto.com/api/Payment/GetList'
13
14
  }
14
15
 
16
+ # === Paysto server IPs.
15
17
  config.ips = [
16
18
  '66.226.72.66',
17
19
  '66.226.74.225',
@@ -20,10 +22,16 @@ Paysto.setup do |config|
20
22
  '66.226.74.228'
21
23
  ]
22
24
 
23
- # === Payments tax of your tariff plan in Paysto, default onlineMerchant "All inclusive" is 5%.
25
+ # === Payments tax of your tariff plan in Paysto. Default onlineMerchant "All inclusive" is 5%.
24
26
  config.tax = 0.05
25
27
 
26
- # === Customize model names as you want before they are will be generated
28
+ # === Minimal Paysto tax for each payment. Default: 10.
29
+ config.min_tax = 10
30
+
31
+ # === Payments expiration. Default: 1.day.
32
+ config.expiration = 1.day
33
+
34
+ # === Customize model names as you want before they are will be generated.
27
35
  config.payment_class_name = 'Payment'
28
36
  config.invoice_class_name = 'Invoice'
29
37
  config.invoice_notification_class_name = 'InvoiceNotification'
@@ -8,18 +8,22 @@ class <%= Paysto.invoice_class_name %> < ActiveRecord::Base
8
8
 
9
9
  validates :amount, presence: true
10
10
 
11
+ # 'Success' code for different gateways.
11
12
  SUCCESS_STATES = {
12
13
  'paysto' => 'RES_PAID'
13
14
  }
14
15
 
16
+ # Create <%= Paysto.invoice_notification_class_name %> with details.
15
17
  def notify(params, gateway)
16
18
  self.<%= Paysto.invoice_notification_class_name.underscore.pluralize %>.create(pay_data: info_by_gateway(params, gateway))
17
19
  end
18
20
 
21
+ # Check whether the <%= Paysto.invoice_class_name.underscore %> is should be paid.
19
22
  def need_to_be_paid?(gateway, payment_status, amount)
20
23
  !paid? && (payment_status == SUCCESS_STATES[gateway.to_s]) && (self.amount.to_f == amount.to_f)
21
24
  end
22
25
 
26
+ # Create <%= Paysto.payment_class_name %> record.
23
27
  def create_<%= Paysto.payment_class_name.underscore %>(payment_method, gateway_code, real_amount = nil)
24
28
  self.<%= Paysto.payment_class_name.underscore %> = <%= Paysto.payment_class_name %>.new(amount: self.amount,
25
29
  real_amount: real_amount,
@@ -32,12 +36,15 @@ class <%= Paysto.invoice_class_name %> < ActiveRecord::Base
32
36
  end
33
37
  end
34
38
 
39
+ # Whether the <%= Paysto.invoice_class_name.underscore %> is paid.
35
40
  def paid?
36
41
  !!paid_at
37
42
  end
38
43
 
39
44
  private
40
45
 
46
+ # Payment details string.
47
+ # You could extend this method for another gateways.
41
48
  def info_by_gateway(_params, _gateway)
42
49
  _keys = case _gateway
43
50
  when :paysto
@@ -51,4 +58,4 @@ class <%= Paysto.invoice_class_name %> < ActiveRecord::Base
51
58
  end.join(';')
52
59
  end
53
60
 
54
- end
61
+ end
data/lib/paysto/base.rb CHANGED
@@ -7,96 +7,115 @@ module Paysto
7
7
  :urls,
8
8
  :ips,
9
9
  :tax,
10
+ :min_tax,
11
+ :expiration,
10
12
  :payment_class_name,
11
13
  :invoice_class_name,
12
14
  :invoice_notification_class_name
13
15
 
14
16
  class << self
15
17
 
18
+ # Configuring module.
16
19
  def setup
17
20
  yield self
18
21
  end
19
22
 
23
+ # Payment class.
20
24
  def payment_class
21
25
  @@payment_class_name.constantize
22
26
  end
23
27
 
28
+ # Invoice class.
24
29
  def invoice_class
25
30
  @@invoice_class_name.constantize
26
31
  end
27
32
 
33
+ # InvoiceNotification class.
28
34
  def invoice_notification_class
29
35
  @@invoice_notification_class_name.constantize
30
36
  end
31
37
 
38
+ # List of available pay methods according to your tariff plan.
32
39
  def currencies
33
- https_request_to Paysto.urls[:currencies], base_params
40
+ https_request_to @@urls[:currencies], base_params
34
41
  end
35
42
 
43
+ # Your current balance in Paysto.
36
44
  def balance
37
- https_request_to Paysto.urls[:balance], base_params
45
+ https_request_to @@urls[:balance], base_params
38
46
  end
39
47
 
48
+ # Returns array of payments with details between dates.
49
+ # +from+ – from date.
50
+ # +to+ – to date.
40
51
  def get_payments(from, to)
41
- p = { 'PAYSTO_SHOP_ID' => Paysto.id,
52
+ p = { 'PAYSTO_SHOP_ID' => @@id,
42
53
  'FROM' => from.strftime('%Y%m%d%H%M'),
43
54
  'TO' => to.strftime('%Y%m%d%H%M') }
44
55
  p.merge!('PAYSTO_MD5' => generate_md5(p))
45
56
 
46
- res = https_request_to(Paysto.urls[:payments_list], p)
57
+ res = https_request_to(@@urls[:payments_list], p)
47
58
  CSV.parse(res)
48
59
  end
49
60
 
61
+ # Returns payment type or 'common' by default.
62
+ # +invoice_id+ – invoice ID of payment.
63
+ # +time+ – estimated payment execution time.
50
64
  def get_payment_type(invoice_id, time = Time.zone.now)
51
- _type = 'common'
52
65
  _payments = get_payments(time.utc - 30.minutes, time.utc + 5.minutes)
53
66
  if _payments.present?
54
67
  p = _payments.select{|_p| _p[2].eql?(invoice_id.to_s)}.first
55
68
  _type = p[7] if p
56
69
  end
57
- _type
70
+ _type || 'common'
58
71
  end
59
72
 
73
+ # Check whether the invoice is valid.
60
74
  def invoice_valid?(invoice)
61
- invoice && invoice.payment_id.blank? && invoice.paid_at.blank?
75
+ invoice && invoice.send("#{@@payment_class_name.underscore}_id").blank? && invoice.paid_at.blank?
62
76
  end
63
77
 
78
+ # Check whether the IP is permitted.
64
79
  def ip_valid?(ip)
65
- Paysto.ips.include?(ip)
80
+ @@ips.include?(ip)
66
81
  end
67
82
 
83
+ # Check whether the MD5 sign is valid.
68
84
  def md5_valid?(p)
69
- generate_md5(p.reject{|k,v| ['action', 'controller', 'PAYSTO_MD5'].include?(k)}) == p['PAYSTO_MD5']
85
+ except_keys = ['action', 'controller', 'PAYSTO_MD5']
86
+ generate_md5(p.reject{|k,v| except_keys.include?(k)}) == p['PAYSTO_MD5']
70
87
  end
71
88
 
89
+ # Timestamp string in Paysto format for payments expiration.
72
90
  def pay_till
73
- (Time.zone.now + 1.day + 1.minute).utc.strftime('%Y%m%d%H%M')
91
+ (Time.zone.now + @@expiration).utc.strftime('%Y%m%d%H%M')
74
92
  end
75
93
 
94
+ # Real income value without Paysto tax for any amount which you want to calculate.
95
+ # +str+ – amount string or numeric, does not matter.
76
96
  def real_amount(str)
77
97
  amount = str.to_f
78
- _tax = amount * Paysto.tax
79
- _tax = 10 if _tax < 10
98
+ _tax = amount * @@tax
99
+ _tax = @@min_tax if _tax < @@min_tax
80
100
  amount - _tax
81
101
  end
82
102
 
83
103
  private
84
104
 
105
+ # Generating MD5 sign according with received params.
85
106
  def generate_md5(p = {}, upcase = true)
86
107
  hash_str = p.to_a.sort_by{|pair| pair.first.downcase}.map{|pair| pair.join('=')}.join('&')
87
- md5 = Digest::MD5.hexdigest("#{hash_str}&#{Paysto.secret}")
88
- if upcase
89
- md5.upcase
90
- else
91
- md5
92
- end
108
+ md5 = Digest::MD5.hexdigest("#{hash_str}&#{@@secret}")
109
+ upcase ? md5.upcase : md5
93
110
  end
94
111
 
112
+ # Base set of params for requests.
95
113
  def base_params
96
- p = { 'PAYSTO_SHOP_ID' => Paysto.id }
114
+ p = { 'PAYSTO_SHOP_ID' => @@id }
97
115
  p.merge!('PAYSTO_MD5' => generate_md5(p))
98
116
  end
99
117
 
118
+ # Performing an HTTPS request.
100
119
  def https_request_to(url, params)
101
120
  uri = URI.parse(url)
102
121
  req = Net::HTTP::Post.new(uri.path)
@@ -110,4 +129,4 @@ module Paysto
110
129
  end
111
130
 
112
131
  end
113
- end
132
+ end
@@ -3,9 +3,12 @@ module Paysto
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
+ # Some callbacks does not requires verifications.
6
7
  skip_before_filter :verify_authenticity_token, only: [:callback, :check]
7
8
  end
8
9
 
10
+ # First step of payment workflow: Invoice, IP and MD5 verification.
11
+ # Render invoice ID if everything right or anything else if not.
9
12
  def check
10
13
  invoice = Paysto.invoice_class.find_by_id(params['PAYSTO_INVOICE_ID'])
11
14
  if Paysto.invoice_valid?(invoice) && Paysto.ip_valid?(request.remote_ip) && Paysto.md5_valid?(params)
@@ -15,6 +18,8 @@ module Paysto
15
18
  end
16
19
  end
17
20
 
21
+ # Second step of payment workflow: Payment creation.
22
+ # Render invoice ID if everything right or anything else if not.
18
23
  def callback
19
24
  invoice = Paysto.invoice_class.find_by_id(params['PAYSTO_INVOICE_ID'])
20
25
  if invoice && invoice.need_to_be_paid?(:paysto, params['PAYSTO_REQUEST_MODE'], params['PAYSTO_SUM']) && Paysto.ip_valid?(request.remote_ip) && Paysto.md5_valid?(params)
@@ -26,15 +31,17 @@ module Paysto
26
31
  end
27
32
  end
28
33
 
34
+ # Success callback.
29
35
  def success
30
36
  flash[:success] = I18n.t('paysto.success')
31
37
  redirect_to root_path
32
38
  end
33
39
 
40
+ # Fail callback.
34
41
  def fail
35
42
  flash[:alert] = I18n.t('paysto.fail')
36
43
  redirect_to root_path
37
44
  end
38
45
 
39
46
  end
40
- end
47
+ end
@@ -1,3 +1,3 @@
1
1
  module Paysto
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paysto-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Baiburin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-19 00:00:00.000000000 Z
11
+ date: 2014-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler