walletone 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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: