cloud_payments 0.0.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +12 -6
  3. data/Gemfile +2 -2
  4. data/README.md +88 -5
  5. data/Rakefile +1 -0
  6. data/cloud_payments.gemspec +8 -8
  7. data/config.ru +1 -0
  8. data/lib/cloud_payments.rb +6 -1
  9. data/lib/cloud_payments/client.rb +3 -2
  10. data/lib/cloud_payments/client/errors.rb +1 -0
  11. data/lib/cloud_payments/client/gateway_errors.rb +3 -1
  12. data/lib/cloud_payments/client/response.rb +2 -1
  13. data/lib/cloud_payments/client/serializer.rb +1 -0
  14. data/lib/cloud_payments/client/serializer/base.rb +9 -1
  15. data/lib/cloud_payments/client/serializer/multi_json.rb +1 -0
  16. data/lib/cloud_payments/config.rb +4 -0
  17. data/lib/cloud_payments/models.rb +8 -0
  18. data/lib/cloud_payments/models/like_subscription.rb +30 -0
  19. data/lib/cloud_payments/models/model.rb +9 -0
  20. data/lib/cloud_payments/models/on_fail.rb +31 -0
  21. data/lib/cloud_payments/models/on_kassa_receipt.rb +23 -0
  22. data/lib/cloud_payments/models/on_pay.rb +37 -0
  23. data/lib/cloud_payments/models/on_recurrent.rb +22 -0
  24. data/lib/cloud_payments/models/order.rb +14 -0
  25. data/lib/cloud_payments/models/secure3d.rb +1 -0
  26. data/lib/cloud_payments/models/subscription.rb +9 -32
  27. data/lib/cloud_payments/models/transaction.rb +13 -4
  28. data/lib/cloud_payments/namespaces.rb +12 -1
  29. data/lib/cloud_payments/namespaces/base.rb +2 -1
  30. data/lib/cloud_payments/namespaces/cards.rb +6 -0
  31. data/lib/cloud_payments/namespaces/kassa.rb +22 -0
  32. data/lib/cloud_payments/namespaces/orders.rb +15 -0
  33. data/lib/cloud_payments/namespaces/payments.rb +11 -0
  34. data/lib/cloud_payments/namespaces/subscriptions.rb +6 -0
  35. data/lib/cloud_payments/namespaces/tokens.rb +1 -0
  36. data/lib/cloud_payments/version.rb +2 -1
  37. data/lib/cloud_payments/webhooks.rb +42 -0
  38. data/spec/cloud_payments/client/response_spec.rb +3 -1
  39. data/spec/cloud_payments/client/serializer/multi_json_spec.rb +1 -0
  40. data/spec/cloud_payments/models/order_spec.rb +62 -0
  41. data/spec/cloud_payments/models/secure3d_spec.rb +1 -0
  42. data/spec/cloud_payments/models/subscription_spec.rb +1 -1
  43. data/spec/cloud_payments/models/transaction_spec.rb +25 -1
  44. data/spec/cloud_payments/namespaces/base_spec.rb +10 -3
  45. data/spec/cloud_payments/namespaces/cards_spec.rb +42 -2
  46. data/spec/cloud_payments/namespaces/kassa_spec.rb +43 -0
  47. data/spec/cloud_payments/namespaces/orders_spec.rb +57 -0
  48. data/spec/cloud_payments/namespaces/payments_spec.rb +119 -0
  49. data/spec/cloud_payments/namespaces/subscriptions_spec.rb +21 -1
  50. data/spec/cloud_payments/namespaces/tokens_spec.rb +1 -0
  51. data/spec/cloud_payments/namespaces_spec.rb +2 -1
  52. data/spec/cloud_payments/webhooks_spec.rb +272 -0
  53. data/spec/cloud_payments_spec.rb +27 -4
  54. data/spec/fixtures/apis/cards/post3ds/failed.yml +45 -0
  55. data/spec/fixtures/apis/cards/post3ds/successful.yml +48 -0
  56. data/spec/fixtures/apis/orders/cancel/failed.yml +6 -0
  57. data/spec/fixtures/apis/orders/cancel/successful.yml +6 -0
  58. data/spec/fixtures/apis/orders/create/successful.yml +20 -0
  59. data/spec/fixtures/apis/payments/find/failed.yml +45 -0
  60. data/spec/fixtures/apis/payments/find/failed_with_message.yml +6 -0
  61. data/spec/fixtures/apis/payments/find/successful.yml +48 -0
  62. data/spec/fixtures/apis/payments/get/failed.yml +46 -0
  63. data/spec/fixtures/apis/payments/get/failed_with_message.yml +6 -0
  64. data/spec/fixtures/apis/payments/get/refunded.yml +49 -0
  65. data/spec/fixtures/apis/payments/get/successful.yml +49 -0
  66. data/spec/fixtures/apis/subscriptions/find/successful.yml +4 -4
  67. data/spec/fixtures/apis/subscriptions/get/successful.yml +31 -0
  68. data/spec/spec_helper.rb +13 -24
  69. data/spec/support/examples.rb +1 -0
  70. data/spec/support/helpers.rb +3 -2
  71. metadata +62 -34
  72. data/spec/cloud_payments/client_spec.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 02f3745fb8ba27279fbc61b8457ea085e80a423e
4
- data.tar.gz: df63c5180c52eb51cfc4a59e009b428cc6b6c3bd
2
+ SHA256:
3
+ metadata.gz: '059f78713c51718c2fcc7474fe7e734b82dbf19a67b121ed86d3210caf061136'
4
+ data.tar.gz: 18c43e72122e00f883e41c0261ef614da2d2dd5474a68e1eb771c1b35bf8aa9b
5
5
  SHA512:
6
- metadata.gz: 52aea99410e9b050a7ed070e9b5642dba502fafa12a4ff034450aa74e319cf1f6767aa38f70399b42b466650da0896599ce234c843cc3eb37e884b657cd30605
7
- data.tar.gz: 2f8a19f58a38a67a62aa691b36382f3d23f67d9edee409f7d8d126eb840cc125f8fd81ad30daed3bc54e24526161655b74de76f3d6e8b51cbff17252e67a0fde
6
+ metadata.gz: a2071a9837d7c2545e0d0df976a964139cba78b85de31af0af556fb6b3335030ceda26ffc38be9aed7f553b67c6d0a6b3e1f21004680bbeeb5baaad0184759ce
7
+ data.tar.gz: 90c91193460f99b13aff8b04a9c4e325f118b44e99cec44ea33f1a668aa0dfd8afd7281d5481b4e15022c5b7208fb729c1f0b7d15776226139be4cce5c46ab99
@@ -1,8 +1,14 @@
1
1
  language: ruby
2
- env:
3
- - CODECLIMATE_REPO_TOKEN=8e9b89269d9aafc2dec2706a43825201de496b743505d7a7666068f7b22b07d
2
+
4
3
  rvm:
5
- - 1.9.3
6
- - 2.0.0
7
- - 2.1.3
8
- - rbx-2
4
+ - 2.3
5
+ - 2.4
6
+ - 2.5
7
+ - 2.6
8
+ - 2.7
9
+
10
+ cache: bundler
11
+
12
+ before_install: gem install bundler
13
+
14
+ script: bundle exec rspec
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
 
3
4
  # Specify your gem's dependencies in cloud_payments.gemspec
@@ -6,5 +7,4 @@ gemspec
6
7
  gem 'oj'
7
8
  gem 'pry'
8
9
  gem 'rack'
9
- gem 'webmock', require: 'webmock/rspec'
10
- gem "codeclimate-test-reporter", group: :test, require: nil
10
+ gem 'webmock'
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # CloudPayments
2
2
 
3
- CloudPayments ruby client (http://cloudpayments.eu/Docs/Integration)
3
+ CloudPayments ruby client (https://developers.cloudpayments.ru/en/)
4
4
 
5
- [![Build Status](https://travis-ci.org/undr/cloud_payments.svg)](https://travis-ci.org/undr/cloud_payments)
6
- [![Code Climate](https://codeclimate.com/github/undr/cloud_payments/badges/gpa.svg)](https://codeclimate.com/github/undr/cloud_payments)
7
- [![Test Coverage](https://codeclimate.com/github/undr/cloud_payments/badges/coverage.svg)](https://codeclimate.com/github/undr/cloud_payments)
5
+ [![Build Status](https://travis-ci.org/platmart/cloud_payments.svg)](https://travis-ci.org/platmart/cloud_payments)
8
6
 
9
7
  ## Installation
10
8
 
@@ -30,6 +28,8 @@ $ gem install cloud_payments
30
28
 
31
29
  ### Configuration
32
30
 
31
+ #### Global configuration
32
+
33
33
  ```ruby
34
34
  CloudPayments.configure do |c|
35
35
  c.host = 'http://localhost:3000' # By default, it is https://api.cloudpayments.ru
@@ -39,6 +39,28 @@ CloudPayments.configure do |c|
39
39
  c.logger = Logger.new('/dev/null') # By default, it writes logs to stdout
40
40
  c.raise_banking_errors = true # By default, it is not raising banking errors
41
41
  end
42
+
43
+ # API client
44
+ CloudPayments.client.payments.cards.charge(...)
45
+
46
+ # Webhooks
47
+ CloudPayments.webhooks.on_pay(...)
48
+ ```
49
+
50
+ #### Local configuration
51
+
52
+ ```ruby
53
+ config = CloudPayments::Config.new do |c|
54
+ # ...
55
+ end
56
+
57
+ # API client
58
+ client = CloudPayments::Client.new(config)
59
+ client.payments.cards.charge(...)
60
+
61
+ # Webhooks
62
+ webhooks = CloudPayments::Webhooks.new(config)
63
+ webhooks.on_pay(...)
42
64
  ```
43
65
 
44
66
  ### Test method
@@ -83,6 +105,7 @@ transaction = CloudPayments.client.payments.cards.charge(
83
105
  # :card_last_four=>"1111",
84
106
  # :card_type=>"Visa",
85
107
  # :card_type_code=>0,
108
+ # :issuer=>"Sberbank of Russia",
86
109
  # :issuer_bank_country=>"RU",
87
110
  # :status=>"Completed",
88
111
  # :status_code=>3,
@@ -97,9 +120,69 @@ transaction.token
97
120
  # => "a4e67841-abb0-42de-a364-d1d8f9f4b3c0"
98
121
  ```
99
122
 
123
+ ## Kassa Receipt
124
+
125
+ CloudPayments Kassa API (https://cloudpayments.ru/docs/api/kassa)
126
+
127
+ ```ruby
128
+ CloudPayments.client.kassa.receipt({
129
+ account_id: "user@example.com",
130
+ customer_receipt: {
131
+ items: [
132
+ {
133
+ amount: "13350.00",
134
+ ean13: nil,
135
+ label: "Good Description",
136
+ price: "13350.00",
137
+ quantity: 1.0,
138
+ vat: nil
139
+ }
140
+ ]
141
+ },
142
+ inn: "7708806666",
143
+ invoice_id: "231312312",
144
+ type: "Income"
145
+ })
146
+ ```
147
+
148
+ ## Webhooks
149
+
150
+ ```ruby
151
+ if CloudPayments.webhooks.data_valid?(payload, hmac_token)
152
+ event = CloudPayments.webhooks.on_recurrent(payload)
153
+ # or
154
+ event = CloudPayments.webhooks.on_pay(payload)
155
+ # or
156
+ event = CloudPayments.webhooks.on_fail(payload)
157
+ end
158
+ ```
159
+
160
+ with capturing of an exception
161
+
162
+ ```ruby
163
+ rescue_from CloudPayments::Webhooks::HMACError, :handle_hmac_error
164
+
165
+ before_action -> { CloudPayments.webhooks.validate_data!(payload, hmac_token) }
166
+
167
+ def pay
168
+ event = CloudPayments.webhooks.on_pay(payload)
169
+ # ...
170
+ end
171
+
172
+ def fail
173
+ event = CloudPayments.webhooks.on_fail(payload)
174
+ # ...
175
+ end
176
+
177
+ def recurrent
178
+ event = CloudPayments.webhooks.on_recurrent(payload)
179
+ # ...
180
+ end
181
+ ```
182
+
100
183
  ## Contributing
101
184
 
102
- 1. Fork it ( https://github.com/undr/cloud_payments/fork )
185
+ 1. Fork it ( https://github.com/platmart/cloud_payments/fork )
103
186
  2. Create your feature branch (`git checkout -b my-new-feature`)
104
187
  3. Commit your changes (`git commit -am 'Add some feature'`)
105
188
  4. Push to the branch (`git push origin my-new-feature`)
data/Rakefile CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'bundler/gem_tasks'
2
3
  require 'rspec/core/rake_task'
3
4
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
  lib = File.expand_path('../lib', __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'cloud_payments/version'
@@ -6,11 +7,11 @@ require 'cloud_payments/version'
6
7
  Gem::Specification.new do |spec|
7
8
  spec.name = 'cloud_payments'
8
9
  spec.version = CloudPayments::VERSION
9
- spec.authors = ['undr']
10
- spec.email = ['undr@yandex.ru']
10
+ spec.authors = ['undr', 'kirillplatonov']
11
+ spec.email = ['undr@yandex.ru', 'mail@kirillplatonov.com']
11
12
  spec.summary = %q{CloudPayments ruby client}
12
13
  spec.description = %q{CloudPayments ruby client}
13
- spec.homepage = ''
14
+ spec.homepage = 'https://github.com/platmart/cloud_payments'
14
15
  spec.license = 'MIT'
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0")
@@ -19,10 +20,9 @@ Gem::Specification.new do |spec|
19
20
  spec.require_paths = ['lib']
20
21
 
21
22
  spec.add_dependency 'faraday'
22
- spec.add_dependency 'multi_json'
23
- spec.add_dependency 'hashie'
23
+ spec.add_dependency 'multi_json', '~> 1.11'
24
+ spec.add_dependency 'hashie', '~> 3.4'
24
25
 
25
- spec.add_development_dependency 'bundler', '~> 1.7'
26
- spec.add_development_dependency 'rake', '~> 10.0'
27
- spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'rake', '~> 13.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.9'
28
28
  end
data/config.ru CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
3
  require 'cloud_payments'
3
4
  require 'rack'
@@ -1,13 +1,14 @@
1
+ # frozen_string_literal: true
1
2
  require 'date'
2
3
  require 'hashie'
3
4
  require 'faraday'
4
5
  require 'multi_json'
5
- require 'pp'
6
6
  require 'cloud_payments/version'
7
7
  require 'cloud_payments/config'
8
8
  require 'cloud_payments/namespaces'
9
9
  require 'cloud_payments/models'
10
10
  require 'cloud_payments/client'
11
+ require 'cloud_payments/webhooks'
11
12
 
12
13
  module CloudPayments
13
14
  extend self
@@ -31,4 +32,8 @@ module CloudPayments
31
32
  def client
32
33
  @client ||= Client.new
33
34
  end
35
+
36
+ def webhooks
37
+ @webhooks ||= Webhooks.new
38
+ end
34
39
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cloud_payments/client/errors'
2
3
  require 'cloud_payments/client/gateway_errors'
3
4
  require 'cloud_payments/client/response'
@@ -9,8 +10,8 @@ module CloudPayments
9
10
 
10
11
  attr_reader :config, :connection
11
12
 
12
- def initialize
13
- @config = CloudPayments.config
13
+ def initialize(config = nil)
14
+ @config = config || CloudPayments.config
14
15
  @connection = build_connection
15
16
  end
16
17
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CloudPayments
2
3
  class Client
3
4
  class Error < StandardError; end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
1
2
  module CloudPayments
2
3
  class Client
4
+ class ReasonedGatewayError < StandardError; end
3
5
  module GatewayErrors; end
4
6
 
5
7
  REASON_CODES = {
@@ -29,7 +31,7 @@ module CloudPayments
29
31
 
30
32
  GATEWAY_ERRORS = REASON_CODES.inject({}) do |result, error|
31
33
  status, name = error
32
- result[status] = GatewayErrors.const_set(name, Class.new(StandardError))
34
+ result[status] = GatewayErrors.const_set(name, Class.new(ReasonedGatewayError))
33
35
  result
34
36
  end
35
37
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CloudPayments
2
3
  class Client
3
4
  class Response
@@ -5,7 +6,7 @@ module CloudPayments
5
6
 
6
7
  def initialize(status, body, headers = {})
7
8
  @status, @origin_body, @headers = status, body, headers
8
- @origin_body = body.force_encoding('UTF-8') if body.respond_to?(:force_encoding)
9
+ @origin_body = body.dup.force_encoding('UTF-8') if body.respond_to?(:force_encoding)
9
10
  end
10
11
 
11
12
  def body
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'cloud_payments/client/serializer/base'
2
3
  require 'cloud_payments/client/serializer/multi_json'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CloudPayments
2
3
  class Client
3
4
  module Serializer
@@ -20,7 +21,14 @@ module CloudPayments
20
21
 
21
22
  def convert_keys_from_api(attributes)
22
23
  attributes.each_with_object({}) do |(key, value), result|
23
- value = convert_keys_from_api(value) if value.is_a?(Hash)
24
+ value = case value
25
+ when Hash
26
+ convert_keys_from_api(value)
27
+ when Array
28
+ value.map { |item| convert_keys_from_api(item) }
29
+ else
30
+ value
31
+ end
24
32
 
25
33
  key = key.to_s.gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
26
34
  key.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CloudPayments
2
3
  class Client
3
4
  module Serializer
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CloudPayments
2
3
  class Config
3
4
  attr_accessor :connection_options, :serializer, :log, :public_key, :secret_key, :host, :raise_banking_errors
@@ -17,6 +18,9 @@ module CloudPayments
17
18
  @connection_options = {}
18
19
  @connection_block = nil
19
20
  @host = 'https://api.cloudpayments.ru'
21
+ if block_given?
22
+ yield self
23
+ end
20
24
  end
21
25
 
22
26
  def logger
@@ -1,4 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  require 'cloud_payments/models/model'
3
+ require 'cloud_payments/models/like_subscription'
2
4
  require 'cloud_payments/models/secure3d'
3
5
  require 'cloud_payments/models/transaction'
4
6
  require 'cloud_payments/models/subscription'
7
+ require 'cloud_payments/models/order'
8
+
9
+ require 'cloud_payments/models/on_recurrent'
10
+ require 'cloud_payments/models/on_pay'
11
+ require 'cloud_payments/models/on_fail'
12
+ require 'cloud_payments/models/on_kassa_receipt'
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module CloudPayments
3
+ module LikeSubscription
4
+ ACTIVE = 'Active'
5
+ PAST_DUE = 'PastDue'
6
+ CANCELLED = 'Cancelled'
7
+ REJECTED = 'Rejected'
8
+ EXPIRED = 'Expired'
9
+
10
+ def active?
11
+ status == ACTIVE
12
+ end
13
+
14
+ def past_due?
15
+ status == PAST_DUE
16
+ end
17
+
18
+ def cancelled?
19
+ status == CANCELLED
20
+ end
21
+
22
+ def rejected?
23
+ status == REJECTED
24
+ end
25
+
26
+ def expired?
27
+ status == EXPIRED
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'bigdecimal'
3
+ require 'bigdecimal/util'
4
+
1
5
  module CloudPayments
2
6
  class Model < Hashie::Trash
3
7
  include Hashie::Extensions::IgnoreUndeclared
8
+
9
+ DateTimeTransform = ->(v) { DateTime.parse(v) if v && v.respond_to?(:to_s) }
10
+ DecimalTransform = ->(v) { v.to_d if v }
11
+ IntegralTransform = ->(v) { v.to_i if v }
12
+ BooleanTransform = ->(v) { (v == '0') ? false : !!v }
4
13
  end
5
14
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ module CloudPayments
3
+ # @see https://cloudpayments.ru/Docs/Notifications#fail CloudPayments API
4
+ class OnFail < Model
5
+ property :id, from: :transaction_id, required: true
6
+ property :amount, transform_with: DecimalTransform, required: true
7
+ property :currency, required: true
8
+ property :date_time, transform_with: DateTimeTransform
9
+ property :card_first_six, required: true
10
+ property :card_last_four, required: true
11
+ property :card_type, required: true
12
+ property :card_exp_date, required: true
13
+ property :test_mode, required: true
14
+ property :reason, required: true
15
+ property :reason_code, required: true
16
+ property :invoice_id
17
+ property :account_id
18
+ property :subscription_id
19
+ property :name
20
+ property :email
21
+ property :ip_address
22
+ property :ip_country
23
+ property :ip_city
24
+ property :ip_region
25
+ property :ip_district
26
+ property :issuer
27
+ property :issuer_bank_country
28
+ property :description
29
+ property :metadata, from: :data, default: {}
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ module CloudPayments
3
+ # @see https://cloudpayments.ru/Docs/Notifications#receipt CloudPayments API
4
+ class OnKassaReceipt < Model
5
+ property :id, required: true
6
+ property :document_number, required: true
7
+ property :session_number, required: true
8
+ property :fiscal_sign, required: true
9
+ property :device_number, required: true
10
+ property :reg_number, required: true
11
+ property :inn, required: true
12
+ property :type, required: true
13
+ property :ofd, required: true
14
+ property :url, required: true
15
+ property :qr_code_url, required: true
16
+ property :amount, transform_with: DecimalTransform, required: true
17
+ property :date_time, transform_with: DateTimeTransform
18
+ property :receipt
19
+ property :invoice_id
20
+ property :transaction_id
21
+ property :account_id
22
+ end
23
+ end