rails-gp-webpay 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/app/controllers/gp_webpay/cards_controller.rb +11 -0
- data/app/controllers/gp_webpay/orders_controller.rb +11 -0
- data/app/controllers/gp_webpay_controller.rb +18 -0
- data/changelog.md +4 -0
- data/config/keys/cert.pem +8 -0
- data/config/keys/pkey.pem +13 -0
- data/config/routes.rb +4 -0
- data/config/wsdl/GPwebpayAdditionalInfoResponse_v1.xsd +194 -0
- data/config/wsdl/cws_v1.wsdl +2355 -0
- data/config/wsdl/swaref.xsd +59 -0
- data/lib/gp_webpay.rb +55 -0
- data/lib/gp_webpay/configuration.rb +65 -0
- data/lib/gp_webpay/engine.rb +7 -0
- data/lib/gp_webpay/error.rb +4 -0
- data/lib/gp_webpay/http/base_signed_request.rb +72 -0
- data/lib/gp_webpay/http/create_order.rb +24 -0
- data/lib/gp_webpay/http/external_url.rb +13 -0
- data/lib/gp_webpay/http/http_request.rb +63 -0
- data/lib/gp_webpay/http/http_response.rb +40 -0
- data/lib/gp_webpay/http/validate_result.rb +63 -0
- data/lib/gp_webpay/http/verify_card.rb +18 -0
- data/lib/gp_webpay/openssl_security.rb +16 -0
- data/lib/gp_webpay/response.rb +34 -0
- data/lib/gp_webpay/service.rb +15 -0
- data/lib/gp_webpay/version.rb +3 -0
- data/lib/gp_webpay/ws/base_signed_request.rb +69 -0
- data/lib/gp_webpay/ws/echo.rb +35 -0
- data/lib/gp_webpay/ws/services/get_master_payment_status.rb +32 -0
- data/lib/gp_webpay/ws/services/get_payment_status.rb +19 -0
- data/lib/gp_webpay/ws/services/get_token_status.rb +21 -0
- data/lib/gp_webpay/ws/services/process_cancel_capture.rb +20 -0
- data/lib/gp_webpay/ws/services/process_capture_reverse.rb +20 -0
- data/lib/gp_webpay/ws/services/process_card_on_file_payment.rb +40 -0
- data/lib/gp_webpay/ws/services/process_master_payment_revoke.rb +20 -0
- data/lib/gp_webpay/ws/services/process_recurring_payment.rb +20 -0
- data/lib/gp_webpay/ws/services/process_refund_payment.rb +20 -0
- data/lib/gp_webpay/ws/services/process_token_payment.rb +26 -0
- data/lib/gp_webpay/ws/services/process_token_revoke.rb +20 -0
- data/lib/gp_webpay/ws/services/process_usage_based_payment.rb +21 -0
- data/lib/gp_webpay/ws/validate_result.rb +48 -0
- data/lib/gp_webpay/ws/ws_request.rb +39 -0
- data/lib/gp_webpay/ws/ws_response.rb +54 -0
- 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,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
|