rails-gp-webpay 0.1.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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +41 -0
  3. data/Rakefile +6 -0
  4. data/app/controllers/gp_webpay/cards_controller.rb +11 -0
  5. data/app/controllers/gp_webpay/orders_controller.rb +11 -0
  6. data/app/controllers/gp_webpay_controller.rb +18 -0
  7. data/changelog.md +4 -0
  8. data/config/keys/cert.pem +8 -0
  9. data/config/keys/pkey.pem +13 -0
  10. data/config/routes.rb +4 -0
  11. data/config/wsdl/GPwebpayAdditionalInfoResponse_v1.xsd +194 -0
  12. data/config/wsdl/cws_v1.wsdl +2355 -0
  13. data/config/wsdl/swaref.xsd +59 -0
  14. data/lib/gp_webpay.rb +55 -0
  15. data/lib/gp_webpay/configuration.rb +65 -0
  16. data/lib/gp_webpay/engine.rb +7 -0
  17. data/lib/gp_webpay/error.rb +4 -0
  18. data/lib/gp_webpay/http/base_signed_request.rb +72 -0
  19. data/lib/gp_webpay/http/create_order.rb +24 -0
  20. data/lib/gp_webpay/http/external_url.rb +13 -0
  21. data/lib/gp_webpay/http/http_request.rb +63 -0
  22. data/lib/gp_webpay/http/http_response.rb +40 -0
  23. data/lib/gp_webpay/http/validate_result.rb +63 -0
  24. data/lib/gp_webpay/http/verify_card.rb +18 -0
  25. data/lib/gp_webpay/openssl_security.rb +16 -0
  26. data/lib/gp_webpay/response.rb +34 -0
  27. data/lib/gp_webpay/service.rb +15 -0
  28. data/lib/gp_webpay/version.rb +3 -0
  29. data/lib/gp_webpay/ws/base_signed_request.rb +69 -0
  30. data/lib/gp_webpay/ws/echo.rb +35 -0
  31. data/lib/gp_webpay/ws/services/get_master_payment_status.rb +32 -0
  32. data/lib/gp_webpay/ws/services/get_payment_status.rb +19 -0
  33. data/lib/gp_webpay/ws/services/get_token_status.rb +21 -0
  34. data/lib/gp_webpay/ws/services/process_cancel_capture.rb +20 -0
  35. data/lib/gp_webpay/ws/services/process_capture_reverse.rb +20 -0
  36. data/lib/gp_webpay/ws/services/process_card_on_file_payment.rb +40 -0
  37. data/lib/gp_webpay/ws/services/process_master_payment_revoke.rb +20 -0
  38. data/lib/gp_webpay/ws/services/process_recurring_payment.rb +20 -0
  39. data/lib/gp_webpay/ws/services/process_refund_payment.rb +20 -0
  40. data/lib/gp_webpay/ws/services/process_token_payment.rb +26 -0
  41. data/lib/gp_webpay/ws/services/process_token_revoke.rb +20 -0
  42. data/lib/gp_webpay/ws/services/process_usage_based_payment.rb +21 -0
  43. data/lib/gp_webpay/ws/validate_result.rb +48 -0
  44. data/lib/gp_webpay/ws/ws_request.rb +39 -0
  45. data/lib/gp_webpay/ws/ws_response.rb +54 -0
  46. metadata +135 -0
@@ -0,0 +1,18 @@
1
+ ##
2
+ # Service object creates request data for GP Webpay CARD_VERIFICATION operation.
3
+
4
+ module GpWebpay
5
+ module Http
6
+ class VerifyCard < BaseSignedRequest
7
+ def initialize(attributes, locale, merchant_number: nil, url_attributes: {})
8
+ super(attributes, locale, 'CARD_VERIFICATION', merchant_number: merchant_number, url_attributes: url_attributes)
9
+ end
10
+
11
+ protected
12
+
13
+ def callback_url
14
+ GpWebpay::Engine.routes.url_helpers.gp_webpay_cards_path({ merchant_number: config.merchant_number, locale: locale }.merge(url_attributes))
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module GpWebpay
2
+ module OpensslSecurity
3
+ def self.generate_digest(configuration, digest_text)
4
+ private_pem = OpenSSL::PKey::RSA.new(configuration.merchant_pem, configuration.merchant_password)
5
+ sign = private_pem.sign(OpenSSL::Digest.new('SHA1'), digest_text)
6
+ Base64.encode64(sign).gsub("\n", '')
7
+ end
8
+
9
+ def self.validate_digests(configuration, data)
10
+ public_pem = OpenSSL::X509::Certificate.new(configuration.gpe_pem).public_key
11
+ data.all? do |received, expected|
12
+ public_pem.verify(OpenSSL::Digest.new('SHA1'), Base64.decode64(received), expected)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ module GpWebpay
2
+ class Response
3
+ attr_accessor :original_response,
4
+ :result_text,
5
+ :token,
6
+ :status,
7
+ :pr_code,
8
+ :sr_code,
9
+ :config,
10
+ :params
11
+
12
+ # rubocop:disable Metrics/ParameterLists
13
+ def initialize(original_response:, result_text:, status:, pr_code:, sr_code:, params:, token: nil, merchant_number: nil)
14
+ @original_response = original_response
15
+ @result_text = result_text
16
+ @token = token
17
+ @status = status
18
+ @pr_code = pr_code
19
+ @sr_code = sr_code
20
+ @params = params
21
+ @merchant_number = merchant_number
22
+ @config = GpWebpay.config[merchant_number] || GpWebpay.config.default
23
+ end
24
+
25
+ # rubocop:enable Metrics/ParameterLists
26
+
27
+ def valid?
28
+ end
29
+
30
+ def success?
31
+ pr_code == '0' && sr_code == '0'
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ module GpWebpay
2
+ class Service
3
+ def initialize(*)
4
+ end
5
+
6
+ class << self
7
+ ruby2_keywords def call(*args)
8
+ new(*args).call
9
+ end
10
+ end
11
+
12
+ def call
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module GpWebpay
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,69 @@
1
+ ##
2
+ # Service object signs request which can be send to GP Webpay payment gateway.
3
+ #
4
+ # 1. Use request value object to translate attributes to correct GP Webpay format and order.
5
+ # 2. Append generated signature to attributes. We expect that XML types are prefixed with 'ins0:' by default.
6
+ # 3. send XML WS SOAP API request.
7
+ # 4. generate response object:
8
+ # - success containing response.
9
+ # - http error when client-side request fails.
10
+ # - fail error when external server returns fault.
11
+ #
12
+ # @param [Hash] attributes for GP Webpay
13
+ #
14
+ # @return [GpwebpayWsResponse] response value object
15
+
16
+ module GpWebpay
17
+ module Ws
18
+ class BaseSignedRequest < Service
19
+ attr_reader :attributes, :config
20
+
21
+ OPERATION_NAME = 'override_me'.freeze
22
+ REQUEST_NAME = 'override_me'.freeze
23
+ RESPONSE_NAME = 'override_me'.freeze
24
+ RESPONSE_ENTITY_NAME = 'override_me'.freeze
25
+ SERVICE_EXCEPTION = :service_exception
26
+
27
+ def initialize(attributes, merchant_number: :default)
28
+ @attributes = attributes
29
+ @merchant_number = merchant_number
30
+ @config = GpWebpay.config[@merchant_number] || GpWebpay.config.default
31
+ super()
32
+ end
33
+
34
+ def call
35
+ attrs = WsRequest.new(attributes.merge(provider: config.provider, merchant_number: config.merchant_number)).to_gpwebpay
36
+
37
+ res = client.call(self.class::OPERATION_NAME, message: { self.class::REQUEST_NAME => attributes_with_signature(attrs) })
38
+ WsResponse.from_success(res.body, self.class::RESPONSE_NAME, self.class::RESPONSE_ENTITY_NAME, config.merchant_number)
39
+ rescue Savon::HTTPError => e
40
+ rescue_from_http(e)
41
+ rescue Savon::SOAPFault => e
42
+ rescue_from_soap(e)
43
+ end
44
+
45
+ protected
46
+
47
+ def digest_text(attrs)
48
+ attrs.values.join('|')
49
+ end
50
+
51
+ def attributes_with_signature(attrs)
52
+ digest = OpensslSecurity.generate_digest(config, digest_text(attrs))
53
+ attrs.merge('ins0:signature' => digest)
54
+ end
55
+
56
+ def client
57
+ @client ||= Savon.client(wsdl: config.wsdl_file, endpoint: config.ws_url, pretty_print_xml: true)
58
+ end
59
+
60
+ def rescue_from_http(error)
61
+ WsResponse.from_http_error(error.to_hash, config.merchant_number)
62
+ end
63
+
64
+ def rescue_from_soap(error)
65
+ WsResponse.from_fault_error(error.to_hash, self.class::SERVICE_EXCEPTION, config.merchant_number)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ ##
2
+ # Service object checks if GP Webpay WS service is available.
3
+ #
4
+ # 1. Send request :echo operation to SOUP API.
5
+ # 2. Receive answer, return true if response is present in desired format.
6
+ # 3. Return false if
7
+ # - response is not in valid format.
8
+ # - request fails client-side.
9
+ # - request returns failure from server.
10
+ #
11
+ # @return [Boolean] GP Webpay is available
12
+
13
+ module GpWebpay
14
+ module Ws
15
+ class Echo < Service
16
+ attr_reader :config
17
+
18
+ def initialize
19
+ super
20
+ @config = GpWebpay.config.default
21
+ end
22
+
23
+ def call
24
+ res = client.call(:echo)
25
+ res.body && res.body[:echo_response].present?
26
+ rescue Savon::HTTPError, Savon::SOAPFault
27
+ false
28
+ end
29
+
30
+ def client
31
+ @client ||= Savon.client(wsdl: config.wsdl_file, endpoint: config.ws_url, pretty_print_xml: true)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ ##
2
+ # Service object returns current status of credit card token.
3
+ # Should be used to keep credit card status up-to date,
4
+ # should be called before process_token_payment to ensure card is still VERIFIED.
5
+ #
6
+ # @param [Hash] attributes for GP Webpay
7
+ #
8
+ # @return [GpwebpayWsResponse] response value object
9
+
10
+ module GpWebpay
11
+ module Ws
12
+ module Services
13
+ class GetMasterPaymentStatus < BaseSignedRequest
14
+ OPERATION_NAME = :get_master_payment_status
15
+ REQUEST_NAME = :master_payment_status_request
16
+ RESPONSE_NAME = :get_master_payment_status_response
17
+ RESPONSE_ENTITY_NAME = :master_payment_status_response
18
+
19
+ SHORTCUT_TRANSFORMATION = {
20
+ CR: 'CREATED',
21
+ PS: 'ISSUED',
22
+ OK: 'VERIFIED',
23
+ CM: 'REVOKED',
24
+ CI: 'DECLINED',
25
+ CC: 'DECLINED',
26
+ EC: 'EXPIRED',
27
+ EP: 'EXPIRED'
28
+ }.freeze
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ ##
2
+ # Service object returns current status of payment.
3
+ #
4
+ # @param [Hash] attributes for GP Webpay
5
+ #
6
+ # @return [GpwebpayWsResponse] response value object
7
+
8
+ module GpWebpay
9
+ module Ws
10
+ module Services
11
+ class GetPaymentStatus < BaseSignedRequest
12
+ OPERATION_NAME = :get_payment_status
13
+ REQUEST_NAME = :payment_status_request
14
+ RESPONSE_NAME = :get_payment_status_response
15
+ RESPONSE_ENTITY_NAME = :payment_status_response
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ ##
2
+ # Service object returns current status of credit card token.
3
+ # Should be used to keep credit card status up-to date,
4
+ # should be called before process_token_payment to ensure card is still VERIFIED.
5
+ #
6
+ # @param [Hash] attributes for GP Webpay
7
+ #
8
+ # @return [GpwebpayWsResponse] response value object
9
+
10
+ module GpWebpay
11
+ module Ws
12
+ module Services
13
+ class GetTokenStatus < BaseSignedRequest
14
+ OPERATION_NAME = :get_token_status
15
+ REQUEST_NAME = :token_status_request
16
+ RESPONSE_NAME = :get_token_status_response
17
+ RESPONSE_ENTITY_NAME = :token_status_response
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ ##
2
+ # Service object creates fast payment without need of leaving user from Wilio web / app.
3
+ # It uses VERIFIED credit card token to skip filling card again and 3D secure step.
4
+ #
5
+ # @param [Hash] attributes for GP Webpay
6
+ #
7
+ # @return [GpwebpayWsResponse] response value object
8
+
9
+ module GpWebpay
10
+ module Ws
11
+ module Services
12
+ class ProcessCancelCapture < BaseSignedRequest
13
+ OPERATION_NAME = :process_authorization_reverse
14
+ REQUEST_NAME = :authorization_reverse_request
15
+ RESPONSE_NAME = :process_authorization_reverse_response
16
+ RESPONSE_ENTITY_NAME = :authorization_reverse_response
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ ##
2
+ # Service object creates fast payment without need of leaving user from Wilio web / app.
3
+ # It uses VERIFIED credit card token to skip filling card again and 3D secure step.
4
+ #
5
+ # @param [Hash] attributes for GP Webpay
6
+ #
7
+ # @return [GpwebpayWsResponse] response value object
8
+
9
+ module GpWebpay
10
+ module Ws
11
+ module Services
12
+ class ProcessCaptureReverse < BaseSignedRequest
13
+ OPERATION_NAME = :process_capture_reverse
14
+ REQUEST_NAME = :capture_reverse_request
15
+ RESPONSE_NAME = :process_capture_reverse_response
16
+ RESPONSE_ENTITY_NAME = :capture_reverse_response
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ ##
2
+ # Service object creates fast payment without need of leaving user from Wilio web / app.
3
+ # It uses VERIFIED credit card token to skip filling card again and 3D secure step.
4
+ #
5
+ # @param [Hash] attributes for GP Webpay
6
+ #
7
+ # @return [GpwebpayWsResponse] response value object
8
+
9
+ module GpWebpay
10
+ module Ws
11
+ module Services
12
+ class ProcessCardOnFilePayment < BaseSignedRequest
13
+ OPERATION_NAME = :process_card_on_file_payment
14
+ REQUEST_NAME = :card_on_file_payment_request
15
+ RESPONSE_NAME = :process_card_on_file_payment_response
16
+ RESPONSE_ENTITY_NAME = :card_on_file_payment_response
17
+ SERVICE_EXCEPTION = :card_on_file_payment_service_exception
18
+
19
+ def rescue_from_soap(exception)
20
+ response = WsResponse.from_fault_error(exception.to_hash, self.class::SERVICE_EXCEPTION, config.merchant_number)
21
+
22
+ if response.valid? && response.params[:authentication_link].present?
23
+ raise GpWebpayConfirmationRequired.new('GP Webpay requires authentication', response.params[:authentication_link])
24
+ else
25
+ response
26
+ end
27
+ end
28
+
29
+ class GpWebpayConfirmationRequired < GpWebpay::Error
30
+ attr_reader :authentication_link
31
+
32
+ def initialize(msg = nil, authentication_link = nil)
33
+ super(msg)
34
+ @authentication_link = authentication_link
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ ##
2
+ # Service object changes credit card token status to "REVOKED".
3
+ # Should be used when user decides to remove card from system.
4
+ #
5
+ # @param [Hash] attributes for GP Webpay
6
+ #
7
+ # @return [GpwebpayWsResponse] response value object
8
+
9
+ module GpWebpay
10
+ module Ws
11
+ module Services
12
+ class ProcessMasterPaymentRevoke < BaseSignedRequest
13
+ OPERATION_NAME = :process_master_payment_revoke
14
+ REQUEST_NAME = :master_payment_revoke_request
15
+ RESPONSE_NAME = :process_master_payment_revoke_response
16
+ RESPONSE_ENTITY_NAME = :master_payment_status_response
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ ##
2
+ # Service object creates fast payment without need of leaving user from Wilio web / app.
3
+ # It uses VERIFIED credit card token to skip filling card again and 3D secure step.
4
+ #
5
+ # @param [Hash] attributes for GP Webpay
6
+ #
7
+ # @return [GpwebpayWsResponse] response value object
8
+
9
+ module GpWebpay
10
+ module Ws
11
+ module Services
12
+ class ProcessRecurringPayment < BaseSignedRequest
13
+ OPERATION_NAME = :process_recurring_payment
14
+ REQUEST_NAME = :recurring_payment_request
15
+ RESPONSE_NAME = :process_recurring_payment_response
16
+ RESPONSE_ENTITY_NAME = :recurring_payment_response
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ ##
2
+ # Service object creates fast payment without need of leaving user from Wilio web / app.
3
+ # It uses VERIFIED credit card token to skip filling card again and 3D secure step.
4
+ #
5
+ # @param [Hash] attributes for GP Webpay
6
+ #
7
+ # @return [GpwebpayWsResponse] response value object
8
+
9
+ module GpWebpay
10
+ module Ws
11
+ module Services
12
+ class ProcessRefundPayment < BaseSignedRequest
13
+ OPERATION_NAME = :process_refund
14
+ REQUEST_NAME = :refund_request
15
+ RESPONSE_NAME = :process_refund_response
16
+ RESPONSE_ENTITY_NAME = :refund_request_response
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ ##
2
+ # Service object creates fast payment without need of leaving user from Wilio web / app.
3
+ # It uses VERIFIED credit card token to skip filling card again and 3D secure step.
4
+ #
5
+ # @param [Hash] attributes for GP Webpay
6
+ #
7
+ # @return [GpwebpayWsResponse] response value object
8
+
9
+ module GpWebpay
10
+ module Ws
11
+ module Services
12
+ class ProcessTokenPayment < BaseSignedRequest
13
+ OPERATION_NAME = :process_token_payment
14
+ REQUEST_NAME = :token_payment_request
15
+ RESPONSE_NAME = :process_token_payment_response
16
+ RESPONSE_ENTITY_NAME = :token_payment_response
17
+ SERVICE_EXCEPTION = :payment_service_exception
18
+
19
+ def initialize(attributes)
20
+ super
21
+ @attributes = attributes.except(:return_url)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end