walletone 0.1.2 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5afa0d525c38be77b98d36d334e2a26bede7ca55
4
- data.tar.gz: dc8fe82e3a77fc8566d0fd90cf26559b6263c54e
3
+ metadata.gz: 2b0bdb40bad763d10f9d0b928d801527887dea09
4
+ data.tar.gz: bd4f7256beceb5f27bd5867ef4989c009e0016cf
5
5
  SHA512:
6
- metadata.gz: a1f78edea3a44df7fa8eac66123c37a0b2bde7b505b7e960670b76cc004d897e17555f18a852e072ec04b825f880625fe714c2e368cc4dee310bdc64b3ea610f
7
- data.tar.gz: 153a3def129ee5fe3041834c71ec6225d98f68fb1f111c357e7c49639a94c92a94397a12412f30f6deb14d3fbb6c5315b203407cc5d8e6048e3e063c6e49beea
6
+ metadata.gz: 5858ba537300604f708e9fa3f8337731897335abf55f5cce5fe2e337a9f221bbbe3ba048495bc2ee861090411aba7042c19aa9ff72f908d64bd3ac3726c3b5f5
7
+ data.tar.gz: 25e8bcb648e34a2c71f89ea9cea5f2ef1bc9bd095f5297ff754b5b2cf70c38018362aae2d6e0b3773ca853d9d4ccf9d0d8fe37f3b8c706b2fbcfb79c93c8b7a5
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/BrandyMint/walletone.svg)](https://travis-ci.org/BrandyMint/walletone)
4
4
  [![Code Climate](https://codeclimate.com/github/BrandyMint/walletone/badges/gpa.svg)](https://codeclimate.com/github/BrandyMint/walletone)
5
+ [![Test
6
+ Coverage](https://codeclimate.com/github/BrandyMint/walletone/badges/coverage.svg)](https://codeclimate.com/github/BrandyMint/walletone)
5
7
 
6
8
  ---
7
9
 
@@ -116,6 +118,10 @@ form = payment.form
116
118
 
117
119
  1. [Walletone Open API](https://api.w1.ru/OpenApi/)
118
120
  2. [Документация (API)](http://www.walletone.com/ru/merchant/documentation/)
121
+ 3. [Доставка redexpress](http://www.walletone.com/en/merchant/delivery/about/)
122
+ 4. [Рекуренты](https://docs.google.com/document/d/1_1HponT9Xv5dJ10Lqh23JyNGhqhNq9myb4xXl-gUOCI/pub?embedded=true)
123
+ 5.
124
+ [InvoicingAPI](https://docs.google.com/document/d/18YaYbAwHo5jKCx88ox3okj1RJqcPF_2gSDdzpK2XHDI/pub?embedded=true)
119
125
 
120
126
  Sponsored by http://taaasty.com and http://kiiiosk.ru
121
127
  Developers are http://brandymint.com
@@ -129,3 +135,4 @@ Developers are http://brandymint.com
129
135
  3. Commit your changes (`git commit -am 'add some feature'`)
130
136
  4. Push to the branch (`git push origin my-new-feature`)
131
137
  5. Create new Pull Request
138
+
@@ -5,6 +5,9 @@ require 'walletone/payment'
5
5
  require 'walletone/notification'
6
6
  require 'walletone/form'
7
7
  require 'walletone/middleware/base'
8
+ require 'walletone/recurrent'
9
+ require 'walletone/invoicing'
10
+ require 'walletone/error_response'
8
11
 
9
12
  module Walletone
10
13
  API_URL = 'https://api.w1.ru/OpenApi/'
@@ -0,0 +1,16 @@
1
+ module Walletone
2
+ class ErrorResponse < StandardError
3
+ def initialize(response)
4
+ fail 'Must be a Net::HTTPInternalServerError' unless response.is_a? Net::HTTPInternalServerError
5
+ @response = response
6
+ end
7
+
8
+ def message
9
+ "[#{response.code}] #{response.body}"
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :response
15
+ end
16
+ end
@@ -7,7 +7,7 @@ module Walletone
7
7
  # > payment.WMI_MERCHANT_ID
8
8
  # > payment.WMI_MERCHANT_ID=123
9
9
  #
10
- # > payment.WMI_PTENABLED =
10
+ # > payment.WMI_PTENABLED =
11
11
  fields.each do |k|
12
12
  define_method k do
13
13
  fetch k
@@ -48,6 +48,10 @@ module Walletone
48
48
  end
49
49
  end
50
50
 
51
+ def to_s
52
+ as_list.to_s
53
+ end
54
+
51
55
  private
52
56
 
53
57
  def signer
@@ -11,6 +11,14 @@ module Walletone
11
11
  @payment = payment
12
12
  end
13
13
 
14
+ def to_s
15
+ payment.to_s
16
+ end
17
+
18
+ def as_list
19
+ payment.as_list
20
+ end
21
+
14
22
  def checkout_url
15
23
  Walletone.config.web_checkout_url
16
24
  end
@@ -32,6 +40,5 @@ module Walletone
32
40
  def hidden_field_tag name, value
33
41
  "<input name=\"#{CGI.escapeHTML(name.to_s)}\" type=\"hidden\" value=\"#{CGI.escapeHTML(value.to_s)}\" />"
34
42
  end
35
-
36
43
  end
37
44
  end
@@ -0,0 +1,5 @@
1
+ module Walletone
2
+ module Invoicing
3
+ require 'walletone/invoicing/client'
4
+ end
5
+ end
@@ -0,0 +1,103 @@
1
+ require 'money'
2
+ require 'multi_json'
3
+
4
+ # Invoicing: https://docs.google.com/document/d/18YaYbAwHo5jKCx88ox3okj1RJqcPF_2gSDdzpK2XHDI/pub?embedded=true
5
+ # Recurrent: https://docs.google.com/document/d/1_1HponT9Xv5dJ10Lqh23JyNGhqhNq9myb4xXl-gUOCI/pub?embedded=true
6
+ #
7
+ module Walletone::Invoicing
8
+ class Client
9
+ CABINET_ID = 'checkout' # yessplaycheckout
10
+ OPERATORS = %w(MtsRUB MegafonRUB Tele2RUB BeelineRUB)
11
+
12
+ BASE_URL = "https://wl.walletone.com/#{CABINET_ID}/invoicingapi/"
13
+
14
+ def initialize(user_id:, secret_key:, hash_type: Walletone::Signer::DEFAULT_HASH_TYPE)
15
+ @user_id = user_id or fail 'no user_id'
16
+ @user_id = @user_id.to_s
17
+ @secret_key = secret_key or fail 'no secret_key'
18
+ @hash_type = hash_type or fail 'no hash_type'
19
+ @timestamp = Time.now.utc.strftime('%FT%T')
20
+ end
21
+
22
+ def do_phone_payment(amount:, order_id:, phone: ,additional_params:)
23
+ invoice = make_invoice amount: amount, order_id: order_id, additional_params: additional_params
24
+ make_payments_process_with_phone payment_id: invoice['Invoice']['Payment']['PaymentId'], phone: phone
25
+ end
26
+
27
+ # Для рекурентов
28
+ # {
29
+ # "CustomerId":"123456",
30
+ # "UseSavedAuthData":true,
31
+ # "CreditCardTerminal":Non3Ds,
32
+ # "AuthData": [
33
+ # "RecurrentCreditCardAuthSecurityCode":"123"
34
+ # ]
35
+ # }
36
+
37
+ def make_payments_process(payment_id, params = {})
38
+ fail 'must be payment_id' unless payment_id
39
+ make_request "payments/#{payment_id}/process", params.to_json
40
+ end
41
+
42
+ def make_payments_process_with_phone(payment_id:, customer_id:, phone:)
43
+ make_payments_process payment_id, { 'CustomerId' => customer_id, 'AuthData' => { 'MobileCommercePhoneNumber' => phone } }
44
+ end
45
+
46
+ def make_invoice(invoice)
47
+ fail 'Must be a RecurrentInvoice' unless invoice.is_a? Walletone::Recurrent::Invoice
48
+
49
+ body = {
50
+ 'OrderId' => invoice.OrderId.to_s,
51
+ 'Amount' => invoice.Amount.to_f,
52
+ 'CurrencyId' => invoice.CurrencyId,
53
+ 'PaymentTypeId' => invoice.PaymentTypeId
54
+ }
55
+
56
+ body['InvoiceAdditionalParams'] = invoice.InvoiceAdditionalParams if invoice.InvoiceAdditionalParams.is_a?(Hash) && !invoice.InvoiceAdditionalParams.empty?
57
+
58
+ make_request 'invoices', body.to_json
59
+ end
60
+
61
+ private
62
+
63
+ attr_reader :user_id, :secret_key, :timestamp, :hash_type
64
+
65
+ def make_request(path, body)
66
+ uri = URI.parse BASE_URL + path
67
+
68
+ headers = build_headers(uri.to_s, body)
69
+
70
+ req = Net::HTTP::Post.new uri, headers
71
+ req.body = body
72
+
73
+ log "Request [#{uri}]: #{body}"
74
+ http = build_http uri
75
+ response = http.request req
76
+ log "Response [#{uri}] #{body}: [#{response.code}] #{response.body}"
77
+ fail Walletone::ErrorResponse, response if response.is_a? Net::HTTPInternalServerError
78
+
79
+ MultiJson.load response.body
80
+ end
81
+
82
+ def build_http(uri)
83
+ Net::HTTP.start uri.host, uri.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE # OpenSSL::SSL::VERIFY_PEER
84
+ end
85
+
86
+ def signature url, body
87
+ Walletone::Signer.sign [url, user_id, timestamp, body, secret_key].join, hash_type
88
+ end
89
+
90
+ def log(message)
91
+ Walletone.logger.info "InvoicingAPI: #{message}"
92
+ end
93
+
94
+ def build_headers(url, body)
95
+ {
96
+ 'Content-Type' => 'application/json; charset=utf-8',
97
+ 'X-Wallet-Timestamp' => timestamp,
98
+ 'X-Wallet-UserId' => user_id,
99
+ 'X-Wallet-Signature' => signature(url, body)
100
+ }
101
+ end
102
+ end
103
+ end
@@ -6,19 +6,34 @@ require 'walletone/fields'
6
6
  module Walletone
7
7
  class Notification < Fields
8
8
  FIELDS = %i(
9
- WMI_MERCHANT_ID
10
- WMI_PAYMENT_AMOUNT
11
- WMI_COMMISSION_AMOUNT
12
- WMI_CURRENCY_ID
13
- WMI_TO_USER_ID
14
- WMI_PAYMENT_NO
15
- WMI_ORDER_ID
16
- WMI_DESCRIPTION
17
- WMI_SUCCESS_URL WMI_FAIL_URL
18
- WMI_EXPIRED_DATE
19
- WMI_CREATE_DATE WMI_UPDATE_DATE
20
- WMI_ORDER_STATE
21
- WMI_SIGNATURE
9
+ WMI_AUTO_ACCEPT
10
+
11
+ WMI_NOTIFY_COUNT
12
+ WMI_LAST_NOTIFY_DATE
13
+
14
+ WMI_MERCHANT_ID
15
+
16
+ WMI_RECURRING_PAYMENTS_APPROVED
17
+
18
+ WMI_PAYMENT_NO
19
+ WMI_PAYMENT_AMOUNT
20
+ WMI_PAYMENT_TYPE
21
+
22
+ WMI_COMMISSION_AMOUNT
23
+ WMI_CURRENCY_ID
24
+ WMI_TO_USER_ID
25
+
26
+ WMI_ORDER_ID
27
+ WMI_ORDER_STATE
28
+
29
+ WMI_DESCRIPTION
30
+ WMI_SUCCESS_URL WMI_FAIL_URL
31
+ WMI_EXPIRED_DATE
32
+ WMI_CREATE_DATE WMI_UPDATE_DATE
33
+
34
+ WMI_RECURRENCE_STATE_ID
35
+
36
+ WMI_SIGNATURE
22
37
  )
23
38
 
24
39
  define_fields FIELDS
@@ -28,9 +28,9 @@ module Walletone
28
28
  WMI_CUSTOMER_FIRSTNAME WMI_CUSTOMER_LASTNAME WMI_CUSTOMER_EMAIL
29
29
  WMI_CULTURE_ID
30
30
  WMI_SIGNATURE
31
- WMI_DELIVERY_REQUEST
31
+ WMI_DELIVERY_REQUEST
32
32
  WMI_DELIVERY_COUNTRY WMI_DELIVERY_REGION WMI_DELIVERY_CITY WMI_DELIVERY_ADDRESS
33
- WMI_DELIVERY_CONTACTINFO WMI_DELIVERY_COMMENTS WMI_DELIVERY_ORDERID
33
+ WMI_DELIVERY_CONTACTINFO WMI_DELIVERY_COMMENTS WMI_DELIVERY_ORDERID
34
34
  WMI_DELIVERY_DATEFROM WMI_DELIVERY_DATETILL
35
35
  WMI_PSP_MERCHANT_ID
36
36
  )
@@ -87,6 +87,5 @@ module Walletone
87
87
  value = fetch :WMI_EXPIRED_DATE
88
88
  value ? value.iso8601 : value
89
89
  end
90
-
91
90
  end
92
91
  end
@@ -0,0 +1,8 @@
1
+ module Walletone
2
+ module Recurrent
3
+ require 'walletone/recurrent/client'
4
+ require 'walletone/recurrent/payment'
5
+ require 'walletone/recurrent/invoice'
6
+ require 'walletone/recurrent/result_invoice'
7
+ end
8
+ end
@@ -0,0 +1,76 @@
1
+ require 'faraday'
2
+
3
+ module Walletone::Recurrent
4
+ require 'walletone/recurrent/invoice'
5
+ require 'walletone/recurrent/result_invoice'
6
+
7
+ class Client
8
+ RECURRENT_API = 'https://wl.walletone.com/checkout/invoicingapi/'
9
+ INVOICE_CLASS = Walletone::Recurrent::Invoice
10
+ RESULT_INVOICE_CLASS = Walletone::Recurrent::ResultInvoice
11
+
12
+ # @param [merchant_id]
13
+ #
14
+ def initialize(merchant_id:, customer_id:, secret_key:, hash_type: Walletone::Signer::DEFAULT_HASH_TYPE)
15
+ @merchant_id = merchant_id.to_s
16
+ @customer_id = customer_id.to_s
17
+ @secret_key = secret_key.to_s
18
+ @hash_type = hash_type
19
+ @timestamp = Time.now.utc.strftime('%FT%T')
20
+ end
21
+
22
+ def create_invoice(invoice)
23
+ fail "Must be a #{INVOICE_CLASS} (#{invoice})" unless invoice.is_a? INVOICE_CLASS
24
+
25
+ result = do_request RECURRENT_API + 'invoices', invoice.to_json
26
+
27
+ RESULT_INVOICE_CLASS.new result
28
+ end
29
+
30
+ def make_payment(payment_id: nil, email: nil)
31
+ body = { CustomerId: customer_id, CreditCardTerminal: 'Non3Ds', UseSavedAuthData: 'true', AuthData: { RecurrentCreditCardEmail: email } }.to_json
32
+
33
+ do_request RECURRENT_API + "payments/#{payment_id}/process", body
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :merchant_id, :customer_id, :secret_key, :hash_type, :timestamp, :hash_type
39
+
40
+ def do_request url, body
41
+ uri = URI.parse url
42
+
43
+ req = Net::HTTP::Post.new uri, build_headers(url, body)
44
+ req.body = body
45
+
46
+ log "Request [#{uri}]: #{body}"
47
+ http = build_http uri
48
+ response = http.request req
49
+ log "Response [#{uri}] #{body}:\n [#{response.code}] #{response.body}"
50
+ fail Walletone::ErrorResponse, response if response.is_a? Net::HTTPInternalServerError
51
+
52
+ MultiJson.load response.body
53
+ end
54
+
55
+ def build_http(uri)
56
+ Net::HTTP.start uri.host, uri.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE # OpenSSL::SSL::VERIFY_PEER
57
+ end
58
+
59
+ def build_headers(url, body)
60
+ {
61
+ 'Content-Type' => 'application/json; charset=utf-8',
62
+ 'X-Wallet-UserId' => merchant_id,
63
+ 'X-Wallet-Timestamp' => timestamp,
64
+ 'X-Wallet-Signature' => signature(url, body)
65
+ }
66
+ end
67
+
68
+ def log(message)
69
+ Walletone.logger.info "Recurrent::Client: #{message}"
70
+ end
71
+
72
+ def signature url, body
73
+ Walletone::Signer.sign [url, merchant_id, timestamp, body, secret_key].join, hash_type
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,15 @@
1
+ module Walletone::Recurrent
2
+ class Invoice
3
+ include Virtus.model strict: true, coerce: false
4
+
5
+ attribute :OrderId, String, required: true
6
+ attribute :Amount, Float, required: true
7
+ attribute :CurrencyId, Integer, required: true, default: 643 # rub
8
+ attribute :PaymentTypeId, String, required: true, default: 'CreditCardRUB' # MtsRUB, MegafonRUB, Tele2RUB, BeelineRUB
9
+ attribute :InvoiceAdditionalParams, Hash
10
+
11
+ def to_json
12
+ to_h.to_json
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ class Walletone::Recurrent::Payment < Walletone::Payment
2
+ define_fields %i(WMI_CUSTOMER_ID WMI_RECURRING_AGREEMENT_URL WMI_CUSTOMER_PHONE)
3
+
4
+ def valid?
5
+ super && self.WMI_CUSTOMER_ID && self.WMI_RECURRING_AGREEMENT_URL
6
+ end
7
+ end
@@ -0,0 +1,66 @@
1
+ module Walletone::Recurrent
2
+ class ResultInvoice
3
+ class InvoiceInfo
4
+ RAW_EXAMPLE =
5
+ {"Invoice"=>
6
+ {"InvoiceId"=>345539868062,
7
+ "Amount"=>1.24,
8
+ "CurrencyId"=>643,
9
+ "InvoiceStateId"=>"Created",
10
+ "CreateDate"=>"2015-12-31T08:20:13",
11
+ "UpdateDate"=>"2015-12-31T08:20:13",
12
+ "Payment"=>
13
+ {"PaymentId"=>69904496,
14
+ "PaymentCode"=>"345539868062",
15
+ "PaymentCodeType"=>"InvoiceId",
16
+ "CreateDate"=>"2015-12-31T08:20:14.137",
17
+ "UpdateDate"=>"2015-12-31T08:20:14.137",
18
+ "PaymentStateId"=>"Created",
19
+ "PaymentTypeId"=>"CreditCardRUB"}},
20
+ "CanSaveAsExternalAccount"=>true}
21
+
22
+ class PaymentInfo
23
+ include Virtus.model strict: true
24
+
25
+ attribute :PaymentId, Integer
26
+ attribute :PaymentCode, String
27
+ attribute :PaymentCodeType, String # 'InvoiceId'
28
+ attribute :CreateDate, Time
29
+ attribute :UpdateDate, Time
30
+ attribute :PaymentStateId, String # 'Created'
31
+ # Состояние платежа в ответе на запрос подтверждения списания средств. Может принимать одно из следующих состояний:
32
+ # Paid — списание произошло успешно.
33
+ # Error — произошла ошибка
34
+ # Created — создан, оплата не поступала
35
+ # Processing — в обработке
36
+ attribute :PaymentTypeId, String # 'CreditCardRUB'
37
+ end
38
+
39
+ include Virtus.model strict: true
40
+
41
+ attribute :InvoiceId, Integer
42
+ attribute :Amount, Float
43
+ attribute :InvoiceStateId, String # 'Created'
44
+ # Параметр “InvoiceStateId”
45
+ # Сосотяние выставленного счета в ответе на создание счета. Может принимать одно из следующих значений:
46
+ # Created — счет успешно создан.
47
+ # Canceled — отменен
48
+ # Accepted — оплачен
49
+ # Expired — вышел срок действия
50
+ # Processing — в процессе подтверждения
51
+ # Received — получен, ожидает принятия
52
+ # Rejected — отвергнут
53
+ # PartiallyPaid — частично оплачен
54
+ # OverPaid — переплачен
55
+ attribute :CreateDate, Time
56
+ attribute :UpdateDate, Time
57
+ attribute :Payment, PaymentInfo
58
+ end
59
+
60
+ include Virtus.model strict: true
61
+
62
+ attribute :Invoice, InvoiceInfo, required: true
63
+ attribute :CanSaveAsExternalAccount, Boolean
64
+ end
65
+ end
66
+
@@ -12,17 +12,21 @@ module Walletone
12
12
 
13
13
  attribute :fields, Walletone::Fields, requried: true
14
14
 
15
- def signature secret_key, hash_type=DEFAULT_HASH_TYPE
15
+ def self.sign(content, hash_type)
16
16
  case hash_type
17
17
  when :md5
18
- Digest::MD5.base64digest( fields_as_string( secret_key ) )
18
+ Digest::MD5.base64digest content
19
19
  when :sha1
20
- Digest::SHA1.base64digest( fields_as_string( secret_key ) )
20
+ Digest::SHA1.base64digest content
21
21
  else
22
22
  raise ArgumentError, hash_type
23
23
  end
24
24
  end
25
25
 
26
+ def signature secret_key, hash_type=DEFAULT_HASH_TYPE
27
+ self.class.sign fields_as_string( secret_key ), hash_type
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def fields_as_string secret_key
@@ -34,7 +38,7 @@ module Walletone
34
38
  def sorted_values
35
39
  fields
36
40
  .as_list
37
- .reject { |k, v| k == WMI_SIGNATURE }
41
+ .reject { |f| f.first == WMI_SIGNATURE }
38
42
  .sort { |a, b| [ a[0], a[1] ] <=> [ b[0], b[1] ] }
39
43
  .map(&:last)
40
44
  .map(&:to_s)
@@ -1,3 +1,3 @@
1
1
  module Walletone
2
- VERSION = '0.1.2'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -2,6 +2,10 @@ require 'walletone'
2
2
  require 'fabrication'
3
3
  require 'ffaker'
4
4
  require 'pry'
5
+ require "codeclimate-test-reporter"
6
+ require 'webmock/rspec'
7
+
8
+ CodeClimate::TestReporter.start
5
9
 
6
10
  Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
7
11
 
@@ -0,0 +1,21 @@
1
+ require 'walletone/invoicing'
2
+
3
+ describe Walletone::Invoicing::Client do
4
+ let(:user_id) { 127830694600 }
5
+ let(:secret_key) { 'abc' }
6
+ let(:amount) { Money.new 1000, 'rub' }
7
+ let(:order_id) { '123' }
8
+
9
+ let(:success_response) { '{"Invoice":{"InvoiceId":123,"Amount":10.0000,"CurrencyId":643,"InvoiceStateId":"Created","CreateDate":"2015-11-02T08:11:57","UpdateDate":"2015-11-02T08:11:57","Payment":{"PaymentId":123,"Amount":10.0000,"CurrencyId":643,"PaymentCode":"123","PaymentCodeType":"InvoiceId","CreateDate":"2015-11-02T08:11:57","UpdateDate":"2015-11-02T08:11:57","PaymentStateId":"Created","PaymentTypeId":"MtsRUB","ExternalAccountId":null}},"CanSaveAsExternalAccount":false}' }
10
+
11
+ subject { Walletone::Invoicing::Client.new user_id: user_id, secret_key: secret_key }
12
+
13
+ let(:invoice) { Walletone::Recurrent::Invoice.new Amount: amount, OrderId: order_id }
14
+
15
+ context '#make_invoice' do
16
+ it do
17
+ stub_request(:post, Walletone::Invoicing::Client::BASE_URL + 'invoices').to_return(body: success_response)
18
+ expect(subject.make_invoice(invoice)).to be_a(Hash)
19
+ end
20
+ end
21
+ end
@@ -4,7 +4,7 @@ require 'walletone/middleware/base'
4
4
  describe Walletone::Middleware::Base do
5
5
  let(:middleware) { described_class.new }
6
6
  let!(:params) { { cp1251: 'привет'.encode('windows-1251') } }
7
- subject! { Rack::MockRequest.new(middleware).post('/', params: params ) }
7
+ subject { Rack::MockRequest.new(middleware).post('/', params: params ) }
8
8
 
9
9
  it do
10
10
  expect(subject.status).to eq 200
@@ -5,7 +5,7 @@ describe Walletone::Middleware::Callback do
5
5
  let(:callback) { -> (notify, env) { } }
6
6
  let(:middleware) { described_class.new callback }
7
7
  let!(:params) { { cp1251: 'привет'.encode('windows-1251') } }
8
- subject! { Rack::MockRequest.new(middleware).post('/', params: params ) }
8
+ subject { Rack::MockRequest.new(middleware).post('/', params: params ) }
9
9
 
10
10
  it do
11
11
  expect(subject.body).to eq 'WMI_RESULT=OK'
@@ -39,4 +39,30 @@ describe Walletone::Notification do
39
39
  expect( subject).to be_accepted
40
40
  end
41
41
  end
42
+
43
+ describe 'recurrent' do
44
+ let(:raw_params) do
45
+ {
46
+ "WMI_AUTO_ACCEPT": "1",
47
+ "WMI_COMMISSION_AMOUNT": "0.04",
48
+ "WMI_CREATE_DATE": "2015-11-08 06:04:05",
49
+ "WMI_CURRENCY_ID": "643",
50
+ "WMI_EXPIRED_DATE": "2015-12-08 06:04:05",
51
+ "WMI_EXTERNAL_ACCOUNT_ID": "521324******2146",
52
+ "WMI_FAIL_URL": "http://kiosk.3001.vkontraste.ru/payments/w1/failure",
53
+ "WMI_LAST_NOTIFY_DATE": "2015-11-08 11:17:49",
54
+ "WMI_MERCHANT_ID": "120464954417",
55
+ "WMI_NOTIFY_COUNT": "29",
56
+ "WMI_ORDER_ID": "345825935381",
57
+ "WMI_ORDER_STATE": "Accepted",
58
+ "WMI_PAYMENT_AMOUNT": "1.00",
59
+ "WMI_PAYMENT_NO": "merchant-68-invoice-1",
60
+ "WMI_PAYMENT_TYPE": "CreditCardRUB",
61
+ "WMI_RECURRING_PAYMENTS_APPROVED": "1",
62
+ "WMI_SUCCESS_URL": "http://kiosk.3001.vkontraste.ru/payments/w1/success",
63
+ "WMI_UPDATE_DATE": "2015-11-08 06:18:33",
64
+ "WMI_SIGNATURE": signature
65
+ }
66
+ end
67
+ end
42
68
  end
@@ -0,0 +1,63 @@
1
+ require 'walletone/recurrent'
2
+ require 'walletone/recurrent/invoice'
3
+ require 'walletone/recurrent/client'
4
+
5
+ describe Walletone::Recurrent::Client do
6
+ let(:merchant_id) { 127830694690 }
7
+ let(:secret_key) { '3475706857624f46344e573753316e387c396e5f4b54767b796c4c' }
8
+ let(:customer_id) { 123 }
9
+
10
+ let(:client) { Walletone::Recurrent::Client.new merchant_id: merchant_id, secret_key: secret_key, customer_id: customer_id }
11
+
12
+ let(:fields) do
13
+ Walletone::Fields.new WMI_PAYMENT_AMOUNT: 123, WMI_MERCHANT_ID: merchant_id, WMI_CUSTOMER_ID: 123, WMI_RECURRING_AGREEMENT_URL: 'http://'
14
+ end
15
+
16
+ let(:invoice) { Walletone::Recurrent::Invoice.new Amount: 123, OrderId: 456 }
17
+
18
+ context '#create_invoice' do
19
+ let(:result) {
20
+ {"Invoice"=>
21
+ {"InvoiceId"=>345539868062,
22
+ "Amount"=>1.24,
23
+ "CurrencyId"=>643,
24
+ "InvoiceStateId"=>"Created",
25
+ "CreateDate"=>"2015-12-31T08:20:13",
26
+ "UpdateDate"=>"2015-12-31T08:20:13",
27
+ "Payment"=>
28
+ {"PaymentId"=>69904496,
29
+ "PaymentCode"=>"345539868062",
30
+ "PaymentCodeType"=>"InvoiceId",
31
+ "CreateDate"=>"2015-12-31T08:20:14.137",
32
+ "UpdateDate"=>"2015-12-31T08:20:14.137",
33
+ "PaymentStateId"=>"Created",
34
+ "PaymentTypeId"=>"CreditCardRUB"}},
35
+ "CanSaveAsExternalAccount"=>true}
36
+ }
37
+ before do
38
+ stub_request(:post, "https://wl.walletone.com/checkout/invoicingapi/invoices").
39
+ with(:body => "{\"OrderId\":456,\"Amount\":123,\"CurrencyId\":643,\"PaymentTypeId\":\"CreditCardRUB\",\"InvoiceAdditionalParams\":{}}").
40
+ to_return(:status => 200, :body => result.to_json, :headers => {'Content-Type'=>'application/json; charset=utf-8'})
41
+ end
42
+ it do
43
+ res = client.create_invoice invoice
44
+ expect(res).to be_a Walletone::Recurrent::ResultInvoice
45
+ end
46
+ end
47
+
48
+ context '#make_payment' do
49
+ let(:payment_id) { 123 }
50
+ let(:result) { {} }
51
+ before do
52
+ stub_request(:post, "https://wl.walletone.com/checkout/invoicingapi/payments/123/process").
53
+ with(:body => "{\"CustomerId\":\"123\",\"CreditCardTerminal\":\"Non3Ds\",\"UseSavedAuthData\":\"true\",\"AuthData\":{\"RecurrentCreditCardEmail\":\"some@email.ru\"}}").
54
+ to_return(:status => 200, :body => result.to_json, :headers => {'Content-Type'=>'application/json; charset=utf-8'})
55
+
56
+ end
57
+ pending 'ответ'
58
+ #it do
59
+ #res = client.make_payment payment_id: payment_id, email: 'some@email.ru'
60
+ #expect(res).to eq 'aaa'
61
+ #end
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ require 'walletone/recurrent'
2
+ require 'walletone/recurrent/payment'
3
+
4
+ describe Walletone::Recurrent::Payment do
5
+ let(:merchant_id) { 127830694690 }
6
+ let(:secret_key) { '3475706857624f46344e573753316e387c396e5f4b54767b796c4c' }
7
+
8
+ subject { described_class.new( fields ) }
9
+
10
+ let(:fields) do
11
+ Walletone::Fields.new WMI_PAYMENT_AMOUNT: 123, WMI_MERCHANT_ID: merchant_id, WMI_CUSTOMER_ID: 123, WMI_RECURRING_AGREEMENT_URL: 'http://'
12
+ end
13
+
14
+ it 'works' do
15
+ expect(subject.WMI_MERCHANT_ID).to eq(merchant_id)
16
+ end
17
+
18
+ it 'valid' do
19
+ expect(subject).to be_valid
20
+ end
21
+ end
@@ -5,19 +5,26 @@ describe Walletone do
5
5
  end
6
6
  end
7
7
 
8
+ #let(:notifier) { notifier = Class.new; def notifier.notify *args; end }
9
+ #let(:notifier) { double }
10
+
8
11
  describe 'Использует Bugsnag если он есть' do
9
12
  before do
10
- ::Bugsnag = double
11
13
  # Сбрасываем конфигурацию, чтобы она еще раз создалась
12
14
  Walletone::Configuration.instance_variable_set('@singleton__instance__',nil)
13
15
  end
14
16
 
15
17
  it 'должен найти и применить Bugsnag' do
18
+ module ::Bugsnag
19
+ def self.notify *args
20
+ end
21
+ end
16
22
  expect(Walletone.config.error_notifier).to eq Bugsnag
17
23
  end
18
24
 
19
25
  after do
20
- ::Bugsnag = nil
26
+ Walletone::Configuration.instance_variable_set('@singleton__instance__',nil)
27
+ Object.send(:remove_const, :Bugsnag)
21
28
  end
22
29
  end
23
30
 
@@ -21,15 +21,20 @@ Gem::Specification.new do |s|
21
21
  s.add_dependency 'virtus', '~> 1.0'
22
22
  s.add_dependency 'rack', '~> 1.5'
23
23
 
24
+ s.add_runtime_dependency 'faraday'
25
+ s.add_runtime_dependency 'money'
26
+
27
+ s.add_development_dependency 'multi_json', '>= 1.3.2'
28
+ s.add_development_dependency 'webmock', '>= 1.22'
24
29
  s.add_development_dependency 'rake', '>= 10.4.0'
25
30
  s.add_development_dependency 'rspec', '>= 3.2.0'
26
31
  s.add_development_dependency 'ffaker', '>= 2.0.0'
27
32
  s.add_development_dependency 'fabrication', '>= 2.12'
28
33
  s.add_development_dependency "pry", '~> 0'
29
34
  s.add_development_dependency "pry-nav", '~> 0'
30
- s.add_development_dependency "webmock", '>= 1.21'
31
35
  s.add_development_dependency "guard", '>= 2.12'
32
36
  s.add_development_dependency "guard-rspec", '>= 4.5.0'
33
37
  s.add_development_dependency 'guard-ctags-bundler', '>= 1.4.0'
34
38
  s.add_development_dependency 'yard', '~> 0'
39
+ s.add_development_dependency "codeclimate-test-reporter"
35
40
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: walletone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danil Pismenny
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-04-10 00:00:00.000000000 Z
12
+ date: 2015-12-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: virtus
@@ -39,6 +39,62 @@ dependencies:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: '1.5'
42
+ - !ruby/object:Gem::Dependency
43
+ name: faraday
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: money
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: multi_json
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 1.3.2
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 1.3.2
84
+ - !ruby/object:Gem::Dependency
85
+ name: webmock
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '1.22'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '1.22'
42
98
  - !ruby/object:Gem::Dependency
43
99
  name: rake
44
100
  requirement: !ruby/object:Gem::Requirement
@@ -123,20 +179,6 @@ dependencies:
123
179
  - - "~>"
124
180
  - !ruby/object:Gem::Version
125
181
  version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: webmock
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: '1.21'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- version: '1.21'
140
182
  - !ruby/object:Gem::Dependency
141
183
  name: guard
142
184
  requirement: !ruby/object:Gem::Requirement
@@ -193,6 +235,20 @@ dependencies:
193
235
  - - "~>"
194
236
  - !ruby/object:Gem::Version
195
237
  version: '0'
238
+ - !ruby/object:Gem::Dependency
239
+ name: codeclimate-test-reporter
240
+ requirement: !ruby/object:Gem::Requirement
241
+ requirements:
242
+ - - ">="
243
+ - !ruby/object:Gem::Version
244
+ version: '0'
245
+ type: :development
246
+ prerelease: false
247
+ version_requirements: !ruby/object:Gem::Requirement
248
+ requirements:
249
+ - - ">="
250
+ - !ruby/object:Gem::Version
251
+ version: '0'
196
252
  description: "Клиент для приема оплаты через walletone.com"
197
253
  email:
198
254
  - danil@brandymint.ru
@@ -204,13 +260,21 @@ files:
204
260
  - LICENSE
205
261
  - README.md
206
262
  - lib/walletone.rb
263
+ - lib/walletone/error_response.rb
207
264
  - lib/walletone/fields.rb
208
265
  - lib/walletone/form.rb
266
+ - lib/walletone/invoicing.rb
267
+ - lib/walletone/invoicing/client.rb
209
268
  - lib/walletone/middleware.rb
210
269
  - lib/walletone/middleware/base.rb
211
270
  - lib/walletone/middleware/callback.rb
212
271
  - lib/walletone/notification.rb
213
272
  - lib/walletone/payment.rb
273
+ - lib/walletone/recurrent.rb
274
+ - lib/walletone/recurrent/client.rb
275
+ - lib/walletone/recurrent/invoice.rb
276
+ - lib/walletone/recurrent/payment.rb
277
+ - lib/walletone/recurrent/result_invoice.rb
214
278
  - lib/walletone/signer.rb
215
279
  - lib/walletone/version.rb
216
280
  - spec/fabricators/fields_fabricator.rb
@@ -218,10 +282,13 @@ files:
218
282
  - spec/spec_helper.rb
219
283
  - spec/walletone/fields_spec.rb
220
284
  - spec/walletone/form_spec.rb
285
+ - spec/walletone/invoicing/client_spec.rb
221
286
  - spec/walletone/middleware/base_spec.rb
222
287
  - spec/walletone/middleware/callback_spec.rb
223
288
  - spec/walletone/notification_spec.rb
224
289
  - spec/walletone/payment_spec.rb
290
+ - spec/walletone/recurrent/client_spec.rb
291
+ - spec/walletone/recurrent/payment_spec.rb
225
292
  - spec/walletone/signer_spec.rb
226
293
  - spec/walletone_spec.rb
227
294
  - walletone.gemspec
@@ -245,20 +312,23 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
312
  version: '0'
246
313
  requirements: []
247
314
  rubyforge_project:
248
- rubygems_version: 2.2.2
315
+ rubygems_version: 2.4.5
249
316
  signing_key:
250
317
  specification_version: 4
251
318
  summary: walleton.com Checkout client
252
319
  test_files:
253
- - spec/walletone/payment_spec.rb
320
+ - spec/walletone_spec.rb
321
+ - spec/fabricators/payment_fabricator.rb
322
+ - spec/fabricators/fields_fabricator.rb
323
+ - spec/spec_helper.rb
324
+ - spec/walletone/signer_spec.rb
254
325
  - spec/walletone/fields_spec.rb
326
+ - spec/walletone/payment_spec.rb
327
+ - spec/walletone/invoicing/client_spec.rb
255
328
  - spec/walletone/form_spec.rb
256
- - spec/walletone/notification_spec.rb
257
- - spec/walletone/middleware/callback_spec.rb
258
329
  - spec/walletone/middleware/base_spec.rb
259
- - spec/walletone/signer_spec.rb
260
- - spec/spec_helper.rb
261
- - spec/fabricators/payment_fabricator.rb
262
- - spec/fabricators/fields_fabricator.rb
263
- - spec/walletone_spec.rb
330
+ - spec/walletone/middleware/callback_spec.rb
331
+ - spec/walletone/notification_spec.rb
332
+ - spec/walletone/recurrent/payment_spec.rb
333
+ - spec/walletone/recurrent/client_spec.rb
264
334
  has_rdoc: