wirecard_checkout_page 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +2 -1
  4. data/Gemfile +2 -0
  5. data/README.md +4 -0
  6. data/Rakefile +1 -2
  7. data/VERSION +1 -1
  8. data/lib/wirecard_checkout_page.rb +6 -2
  9. data/lib/wirecard_checkout_page/errors.rb +2 -0
  10. data/lib/wirecard_checkout_page/fingerprint.rb +0 -0
  11. data/lib/wirecard_checkout_page/gateway.rb +26 -12
  12. data/lib/wirecard_checkout_page/init_request.rb +71 -0
  13. data/lib/wirecard_checkout_page/init_response.rb +12 -2
  14. data/lib/wirecard_checkout_page/request.rb +85 -0
  15. data/lib/wirecard_checkout_page/response_checksum.rb +15 -45
  16. data/lib/wirecard_checkout_page/toolkit/recur_payment.rb +66 -0
  17. data/lib/wirecard_checkout_page/toolkit/request.rb +55 -0
  18. data/lib/wirecard_checkout_page/toolkit/response.rb +50 -0
  19. data/lib/wirecard_checkout_page/version.rb +1 -1
  20. data/spec/spec_helper.rb +12 -8
  21. data/spec/wirecard_checkout_page/gateway_spec.rb +86 -28
  22. data/spec/wirecard_checkout_page/init_request_spec.rb +62 -0
  23. data/spec/wirecard_checkout_page/request_spec.rb +88 -0
  24. data/spec/wirecard_checkout_page/response_checksum_spec.rb +70 -116
  25. data/spec/wirecard_checkout_page/toolkit/recur_payment_spec.rb +125 -0
  26. data/spec/wirecard_checkout_page/toolkit/request_spec.rb +79 -0
  27. data/spec/wirecard_checkout_page/toolkit/response_spec.rb +36 -0
  28. data/wirecard_checkout_page.gemspec +9 -12
  29. metadata +40 -45
  30. data/lib/wirecard_checkout_page/request_checksum.rb +0 -88
  31. data/lib/wirecard_checkout_page/value_handling.rb +0 -19
  32. data/lib/wirecard_checkout_page/value_missing.rb +0 -1
  33. data/spec/wirecard_checkout_page/request_checksum_spec.rb +0 -96
  34. data/spec/wirecard_checkout_page/response_spec.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dc51edcaa21801adf0d37957f3990226d9184b66
4
- data.tar.gz: 2a97377d4cee7c220213c2b46f16f0929082b3bf
3
+ metadata.gz: e9938c8656716ad478ae1decf6e699af89c27a21
4
+ data.tar.gz: 234cfd69101fb4cd77c68113ff76506b9828a0a4
5
5
  SHA512:
6
- metadata.gz: 17df65f469ef1335cd5d70617d5922a138a4c860d439774de221b59c57a53fa329292ef74580374258b84239d11340c6581cf933fa0157a3c20d3ca27f10c0c7
7
- data.tar.gz: edfea03e52cbb6efd033c0699ca99b8c24802fb31cd24fbc86f6433352d93cd98799d9f7520b85e7e7b4d7804390178e64858fc1a87225309b07411f8fb1ab2a
6
+ metadata.gz: 46bb266f885eaf7b2b4e02fc158cb4c4c228ee07adce3a6340c3c6d27eca484b7ec83c3c0f8075b6c01cd7c1b6bee1e9aa3a76603b4f8718ddc284ea0e8f78ff
7
+ data.tar.gz: c707323a6264a864130258e842108c39df9f04084d4495be6ccd9f4dc24e9eb84e40a1eb0b883bf57f3c4a40d2a7818c864fad8111667b96853886d75db0c333
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  .*.sw[pon]
2
2
  .AppleDouble
3
3
  .DS_Store
4
+ .envrc
4
5
  .rvmrc
5
6
  Gemfile.lock
6
7
  coverage
@@ -1,6 +1,7 @@
1
1
  rvm:
2
- - 2.0.0
2
+ - 2.0
3
3
  - 2.1
4
+ - 2.2
4
5
  - ruby-head
5
6
  - jruby-head
6
7
  matrix:
data/Gemfile CHANGED
@@ -5,3 +5,5 @@ source 'https://rubygems.org'
5
5
  gemspec
6
6
 
7
7
  gem "codeclimate-test-reporter", group: :test, require: nil
8
+
9
+ gem 'byebug', group: :test, platforms: :mri
data/README.md CHANGED
@@ -41,3 +41,7 @@ puts response.params
41
41
  [![Code Climate](https://codeclimate.com/github/flori/wirecard_checkout_page/badges/gpa.svg)](https://codeclimate.com/github/flori/wirecard_checkout_page)
42
42
 
43
43
  [![Test Coverage](https://codeclimate.com/github/flori/wirecard_checkout_page/badges/coverage.svg)](https://codeclimate.com/github/flori/wirecard_checkout_page)
44
+
45
+
46
+ ## TODOS
47
+ [] Document the toolkit features
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ GemHadar do
10
10
  summary 'Library for using Wirecard Checkout Page'
11
11
  description 'This library allows you to use the Wirecard Checkout Page service.'
12
12
  test_dir 'tests'
13
- ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', 'coverage', '.rvmrc', '.AppleDouble', '.DS_Store'
13
+ ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', 'coverage', '.rvmrc', '.AppleDouble', '.DS_Store', '.envrc'
14
14
  readme 'README.md'
15
15
  title "#{name.camelize} -- Wirecard Checkout Page implementation"
16
16
  licenses << 'Apache-2.0'
@@ -19,7 +19,6 @@ GemHadar do
19
19
  development_dependency 'rake'
20
20
  development_dependency 'simplecov'
21
21
  development_dependency 'rspec'
22
- development_dependency 'byebug'
23
22
  end
24
23
 
25
24
  task :default => :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
@@ -1,13 +1,17 @@
1
1
  require 'digest/md5'
2
- require 'uri'
3
2
  require 'typhoeus'
4
3
  require 'wirecard_checkout_page/errors'
5
4
  require 'wirecard_checkout_page/gateway'
6
5
  require 'wirecard_checkout_page/utils'
7
- require 'wirecard_checkout_page/request_checksum'
8
6
  require 'wirecard_checkout_page/response_checksum'
7
+ require 'wirecard_checkout_page/request'
8
+ require 'wirecard_checkout_page/init_request'
9
9
  require 'wirecard_checkout_page/init_response'
10
10
  require 'wirecard_checkout_page/checked_response'
11
+ require 'wirecard_checkout_page/fingerprint'
12
+ require 'wirecard_checkout_page/toolkit/request'
13
+ require 'wirecard_checkout_page/toolkit/response'
14
+ require 'wirecard_checkout_page/toolkit/recur_payment'
11
15
 
12
16
  module WirecardCheckoutPage
13
17
  end
@@ -2,4 +2,6 @@ module WirecardCheckoutPage
2
2
  class WirecardCheckoutPageError < StandardError; end
3
3
 
4
4
  class ValueMissing < WirecardCheckoutPageError; end
5
+ class NotImplementedError < WirecardCheckoutPageError; end
6
+ class InvalidResponseFingerPrintOrder < WirecardCheckoutPageError; end
5
7
  end
@@ -1,30 +1,44 @@
1
1
  module WirecardCheckoutPage
2
2
  class Gateway
3
- DEFAULT_INIT_URL = 'https://checkout.wirecard.com/page/init.php'
4
3
 
5
- attr_accessor :customerId, :secret, :init_url
4
+ attr_accessor :customer_id, :secret, :toolkit_password, :shop_id
6
5
 
7
- def initialize(customerId: nil, secret: nil, init_url: nil)
8
- @customerId = customerId
9
- @secret = secret
10
- @init_url = init_url || DEFAULT_INIT_URL
6
+ def initialize(customer_id: nil, secret: nil, toolkit_password: nil, shop_id: nil)
7
+ @customer_id = customer_id
8
+ @secret = secret
9
+ @toolkit_password = toolkit_password
10
+ @shop_id = shop_id
11
11
  end
12
12
 
13
13
  def init(params = {})
14
- checksum = WirecardCheckoutPage::RequestChecksum.new(params.merge(authentication_params))
15
- InitResponse.new Typhoeus.post(init_url, body: checksum.request_parameters)
14
+ params = params.merge(authentication_params).merge( transactionIdentifier: 'SINGLE' )
15
+ InitRequest.new(params: params).call
16
+ end
17
+
18
+ def recurring_init(params = {})
19
+ params = params.merge(authentication_params).merge( transactionIdentifier: 'INITIAL' )
20
+ InitRequest.new(params: params).call
21
+ end
22
+
23
+ def recurring_process(params = {})
24
+ params = params.merge(toolkit_authentication_params)
25
+ Toolkit::RecurPayment.new(params: params).call
16
26
  end
17
27
 
18
28
  def check_response(params = {})
19
- WirecardCheckoutPage::CheckedResponse.new(
20
- params.merge(authentication_params)
21
- )
29
+ CheckedResponse.new params.merge(authentication_params)
22
30
  end
23
31
 
24
32
  private
25
33
 
26
34
  def authentication_params
27
- { secret: secret, customerId: customerId }
35
+ params = { secret: secret, customerId: customer_id }
36
+ params[:shopId] = shop_id if shop_id
37
+ params
38
+ end
39
+
40
+ def toolkit_authentication_params
41
+ authentication_params.merge( toolkitPassword: toolkit_password )
28
42
  end
29
43
 
30
44
  end
@@ -0,0 +1,71 @@
1
+ module WirecardCheckoutPage
2
+ class InitRequest < Request
3
+
4
+ DEFAULT_URL = 'https://checkout.wirecard.com/page/init.php'
5
+
6
+ def initialize(url: nil, params: {})
7
+ super url: url || DEFAULT_URL, params: params
8
+ self.transactionIdentifier ||= 'SINGLE'
9
+ end
10
+
11
+ # Parameter Within fingerprint Data type Short description
12
+ # customerId Required Alphanumeric with a fixed length of 7. Unique ID of merchant.
13
+ # language Required Alphabetic with a fixed length of 2. Language for displayed texts on payment page.
14
+ # paymentType Optional Enumeration Selected payment method of your consumer.
15
+ # amount Required Amount Amount of payment.
16
+ # currency required Alphabetic with a fixed length of 3 or numeric with a fixed length of 3. Currency code of amount.
17
+ # orderDescription Required Alphanumeric with a variable length of up to 255. Unique description of the consumer's order in a human readable form.
18
+ # successUrl Required Alphanumeric with special characters. URL of your online shop when payment process was successful.
19
+ # cancelUrl Optional Alphanumeric with special characters. URL of your online shop when payment process has been canceled.
20
+ # failureUrl Optional Alphanumeric with special characters. URL of your online shop when an error occured within payment process.
21
+ # serviceUrl Optional Alphanumeric with special characters and a variable length of up to 255. URL of your service page containing contact information.
22
+
23
+ param :secret, required: true
24
+ param :customerId, required: true
25
+ param :language, required: true
26
+ param :paymentType, required: true
27
+ param :amount, required: true
28
+ param :currency, required: true
29
+ param :orderDescription, required: true
30
+ param :successUrl, required: true
31
+ param :cancelUrl, required: true # Seems to be required even if the docs say otherwise
32
+ param :failureUrl, required: true # Seems to be required even if the docs say otherwise
33
+ param :serviceUrl, required: true # Seems to be required even if the docs say otherwise
34
+
35
+ # Parameter Within fingerprint Data type Short description
36
+ # pendingUrl Optional Alphanumeric with special characters. URL of your online shop when result of payment process could not be determined yet.
37
+ # confirmUrl Required if used. Alphanumeric with special characters. URL of your online shop where Wirecard sends a server-to-server confirmation.
38
+ # noScriptInfoUrl Optional Alphanumeric with special characters. URL of your online shop where your information page regarding de-activated JavaScript resides.
39
+ # orderNumber Required if used. Numeric with a variable length of up to 9. Order number of payment.
40
+ # windowName Optional Alphanumeric Window name of browser window where payment page is opened.
41
+ # duplicateRequestCheck Required if used. Boolean (“yes” or “no”). Check for duplicate requests done by your consumer.
42
+ # customerStatement Required if used. Alphanumeric with a variable length of up to 254 characters, but may differ for specific payment methods. Text displayed on invoice of financial institution of your consumer.
43
+ # orderReference Required if used. Alphanumeric with a variable length up to 128 characters, but may differ for specific payment methods. Unique order reference ID sent from merchant to financial institution.
44
+ # transactionIdentifier Required if used. Enumeration Possible values are SINGLE (for one-off transactions) or INITIAL (for the first transaction of a series of recurring transactions).
45
+
46
+ param :pendingUrl
47
+ param :confirmUrl, required: true # Seems to be required even if the docs say otherwise
48
+ param :noScriptInfoUrl
49
+ param :orderNumber
50
+ param :windowName
51
+ param :duplicateRequestCheck
52
+ param :customerStatement
53
+ param :orderReference
54
+ param :transactionIdentifier
55
+ param :shopId
56
+
57
+ def fingerprint_order
58
+ super + [:requestFingerprintOrder]
59
+ end
60
+
61
+ def requestFingerprintOrder
62
+ fingerprint_order * ','
63
+ end
64
+
65
+ def call
66
+ raise WirecardCheckoutPage::ValueMissing, errors.join(', ') unless valid?
67
+ InitResponse.from_typhoeus_response Typhoeus.post(DEFAULT_URL, body: body)
68
+ end
69
+
70
+ end
71
+ end
@@ -3,10 +3,20 @@
3
3
 
4
4
  module WirecardCheckoutPage
5
5
  class InitResponse
6
- def initialize(response)
7
- @original_response = response
6
+
7
+ def self.from_typhoeus_response(response)
8
+ new(response.body, original_response: response)
9
+ end
10
+
11
+ def initialize(body, original_response: nil)
12
+ @body = body
13
+ @original_response = original_response
8
14
  end
9
15
 
16
+ attr_reader :original_response
17
+
18
+ attr_reader :body
19
+
10
20
  def params
11
21
  {
12
22
  payment_url: @original_response.headers['Location']
@@ -0,0 +1,85 @@
1
+ module WirecardCheckoutPage
2
+ class Request
3
+ def self.param(name, options = {})
4
+ name = name.to_sym
5
+ params_order << name
6
+ params[name] = options
7
+ attr_accessor name
8
+ end
9
+
10
+ def self.params
11
+ @params ||= {}
12
+ end
13
+
14
+ def self.params_order
15
+ @params_order ||= []
16
+ end
17
+
18
+ def initialize(url: nil, params: {})
19
+ @url = url
20
+ params.each { |param, value| send "#{param}=", value }
21
+ end
22
+
23
+ attr_reader :url
24
+
25
+ attr_reader :params
26
+
27
+ attr_reader :errors
28
+
29
+ def valid?
30
+ @errors = []
31
+ attributes.each do |param, options|
32
+ next unless options[:required] == true
33
+ val = send param
34
+ @errors << "#{param} is required" if val.nil? || val == ''
35
+ end
36
+ @errors.empty?
37
+ end
38
+
39
+ def body
40
+ fingerprinted_request_params
41
+ end
42
+
43
+ def call
44
+ raise NotImplementedError, '#call not implemented'
45
+ end
46
+
47
+ def fingerprint_string
48
+ fingerprint_order.each_with_object('') { |param, str| str << send(param).to_s }
49
+ end
50
+
51
+ def fingerprint
52
+ Digest::MD5.hexdigest fingerprint_string
53
+ end
54
+
55
+ def fingerprint_order
56
+ self.class.params_order.select do |param|
57
+ attributes[param][:required] || send(param).to_s != ''
58
+ end
59
+ end
60
+
61
+ def request_params
62
+ rp = {}
63
+ attributes.keys.each do |param|
64
+ next if param == :secret
65
+ val = send(param).to_s
66
+ next if val == ''
67
+ rp[param.to_s] = val
68
+ end
69
+ rp
70
+ end
71
+
72
+ def fingerprinted_request_params
73
+ request_params.merge(
74
+ 'requestFingerprint' => fingerprint,
75
+ 'requestFingerprintOrder' => fingerprint_order.join(',')
76
+ )
77
+ end
78
+
79
+ private
80
+
81
+ def attributes
82
+ self.class.params
83
+ end
84
+ end
85
+ end
@@ -1,64 +1,34 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'wirecard_checkout_page/value_handling'
4
-
5
3
  module WirecardCheckoutPage
6
4
  class ResponseChecksum
7
5
  include WirecardCheckoutPage::Utils
8
- include WirecardCheckoutPage::ValueHandling
9
-
10
- def initialize(values = {})
11
- @values = stringify_keys(values)
12
- @secret = @values.delete('secret') or
13
- raise WirecardCheckoutPage::ValueMissing, 'value "secret" is missing'
14
- # This rails form value is escaped as an html entity by
15
- # WirecardCheckoutPage, so set it back to the original UTF-8 here if it
16
- # exists:
17
- @values['utf8'] and @values['utf8'] = '✓'
18
- @values.freeze
19
- reset_missing_keys
20
- end
21
-
22
- attr_reader :values
23
-
24
- attr_reader :expected_fingerprint
25
-
26
- attr_reader :computed_fingerprint
27
6
 
28
- def fingerprint
29
- values = @values.dup
30
- values['secret'] ||= @secret
31
- if seed = responseFingerprintSeed(responseFingerprintOrder(values), values)
32
- Digest::MD5.hexdigest seed
7
+ def initialize(params)
8
+ @params = stringify_keys(params)
9
+ unless response_fingerprint_order_parts.include? 'secret'
10
+ raise InvalidResponseFingerPrintOrder, 'Missing :secret as a part of the responseFingerprintOrder'
33
11
  end
34
12
  end
35
13
 
14
+ attr_reader :params
15
+
36
16
  def valid?
37
- reset_missing_keys
38
- @expected_fingerprint = values.fetch('responseFingerprint') do |k|
39
- add_missing_key k
40
- end
41
- @computed_fingerprint = fingerprint
42
- !missing_keys? && computed_fingerprint == @expected_fingerprint
17
+ params['responseFingerprint'] == computed_fingerprint
43
18
  end
44
19
 
45
20
  private
46
21
 
47
- def responseFingerprintOrder(values)
48
- order = values.fetch('responseFingerprintOrder') do |k|
49
- add_missing_key k
50
- return []
51
- end
52
- order.split(',')
22
+ def response_fingerprint_order_parts
23
+ params['responseFingerprintOrder'].to_s.split(',')
24
+ end
25
+
26
+ def fingerprint_string
27
+ response_fingerprint_order_parts.map {|key| params[key.to_s] }.join
53
28
  end
54
29
 
55
- def responseFingerprintSeed(keys, values)
56
- fingerprint = keys.map do |k|
57
- values.fetch(k) do
58
- add_missing_key k
59
- end
60
- end * ''
61
- fingerprint unless missing_keys?
30
+ def computed_fingerprint
31
+ Digest::MD5.hexdigest fingerprint_string
62
32
  end
63
33
  end
64
34
  end
@@ -0,0 +1,66 @@
1
+ module WirecardCheckoutPage
2
+ module Toolkit
3
+ class RecurPayment < Request
4
+
5
+ def initialize(params: {})
6
+ super
7
+ self.command = 'recurPayment'
8
+ end
9
+
10
+ # Which request parameters are required for all operations?
11
+ # To start an operation you have to set all required parameters to their corresponding values.
12
+ # If one or more of these required parameters are missing you will get an error message.
13
+
14
+ # Parameter Data type Short description
15
+ # customerId Alphanumeric with a fixed length of 7. Unique ID of merchant.
16
+ # shopId Alphanumeric with a variable length of 16. Unique ID of your online shop if several
17
+ # toolkitPassword Alphanumeric with special characters. Your password for Toolkit light operations.
18
+ # command Enumeration Operation to be executed.
19
+ # language Alphabetic with a fixed length of 2. Language for returned texts and error messages,
20
+ # currently only “en” is supported; we are able
21
+ # to integrate other languages upon request.
22
+ # requestFingerprint Alphanumeric with a fixed length of 32. Computed fingerprint of the parameter
23
+ # values and the secret.
24
+ param :customerId, required: true
25
+ param :shopId
26
+ param :toolkitPassword, required: true
27
+ param :secret, required: true
28
+ param :command, required: true
29
+ param :language, required: true
30
+
31
+ # Additional required request parameters
32
+ #
33
+ # Parameter Data type Short description
34
+ # amount Amount Debit amount.
35
+ # currency Alphabetic with a fixed length of 3 Currency code of amount.
36
+ # or numeric with a fixed length of 3.
37
+ # orderDescription Alphanumeric with a variable length Textual description of order.
38
+ # of up to 255 characters.
39
+ # sourceOrderNumber Numeric with a variable length of Original order number used for new payment.
40
+ # up to 9 digits.
41
+
42
+ # Additional optional request parameters
43
+ #
44
+ # Parameter Data type Short description
45
+ # autoDeposit Enumeration Possible values are Yes and No.
46
+ # Yes is used for enabling and No for
47
+ # disabling automated deposit and
48
+ # day-end closing of payments.
49
+ # customerStatement Alphanumeric with a variable length Text displayed on invoice of
50
+ # of up to 254 characters. financial institution of your consumer.
51
+ # orderNumber Numeric with a variable length Order number of payment.
52
+ # of up to 9 digits.
53
+ # orderReference Alphanumeric with a variable length Unique order reference ID sent from
54
+ # of up to 128 characters. merchant to financial institution.
55
+ param :orderNumber
56
+ param :sourceOrderNumber, required: true
57
+ param :autoDeposit
58
+ param :orderDescription, required: true
59
+ param :amount, required: true
60
+ param :currency, required: true
61
+ param :orderReference
62
+ param :customerStatement
63
+
64
+ end
65
+ end
66
+ end