activemerchant 1.28.0 → 1.29.1
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.
- data/CHANGELOG +41 -0
- data/CONTRIBUTORS +12 -0
- data/README.md +6 -0
- data/lib/active_merchant/billing/gateway.rb +2 -1
- data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +77 -78
- data/lib/active_merchant/billing/gateways/balanced.rb +0 -1
- data/lib/active_merchant/billing/gateways/banwire.rb +1 -2
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +19 -20
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +35 -36
- data/lib/active_merchant/billing/gateways/blue_pay.rb +135 -140
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +12 -4
- data/lib/active_merchant/billing/gateways/card_stream.rb +54 -59
- data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +19 -14
- data/lib/active_merchant/billing/gateways/data_cash.rb +106 -112
- data/lib/active_merchant/billing/gateways/efsnet.rb +29 -34
- data/lib/active_merchant/billing/gateways/elavon.rb +7 -1
- data/lib/active_merchant/billing/gateways/epay.rb +0 -1
- data/lib/active_merchant/billing/gateways/eway.rb +88 -93
- data/lib/active_merchant/billing/gateways/eway_managed.rb +47 -51
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +300 -0
- data/lib/active_merchant/billing/gateways/exact.rb +45 -54
- data/lib/active_merchant/billing/gateways/federated_canada.rb +3 -4
- data/lib/active_merchant/billing/gateways/first_pay.rb +37 -38
- data/lib/active_merchant/billing/gateways/garanti.rb +1 -2
- data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +5 -8
- data/lib/active_merchant/billing/gateways/inspire.rb +52 -52
- data/lib/active_merchant/billing/gateways/instapay.rb +10 -11
- data/lib/active_merchant/billing/gateways/iridium.rb +38 -39
- data/lib/active_merchant/billing/gateways/itransact.rb +7 -9
- data/lib/active_merchant/billing/gateways/jetpay.rb +45 -46
- data/lib/active_merchant/billing/gateways/linkpoint.rb +104 -108
- data/lib/active_merchant/billing/gateways/litle.rb +1 -5
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +153 -155
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +49 -50
- data/lib/active_merchant/billing/gateways/mercury.rb +272 -0
- data/lib/active_merchant/billing/gateways/metrics_global.rb +9 -10
- data/lib/active_merchant/billing/gateways/migs.rb +5 -3
- data/lib/active_merchant/billing/gateways/modern_payments.rb +6 -7
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +40 -41
- data/lib/active_merchant/billing/gateways/moneris.rb +46 -50
- data/lib/active_merchant/billing/gateways/moneris_us.rb +52 -55
- data/lib/active_merchant/billing/gateways/nab_transact.rb +0 -5
- data/lib/active_merchant/billing/gateways/net_registry.rb +20 -21
- data/lib/active_merchant/billing/gateways/netaxept.rb +30 -36
- data/lib/active_merchant/billing/gateways/netbilling.rb +2 -2
- data/lib/active_merchant/billing/gateways/ogone.rb +0 -5
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +1 -6
- data/lib/active_merchant/billing/gateways/orbital/avs_result.rb +93 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +25 -21
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +1 -6
- data/lib/active_merchant/billing/gateways/pay_junction.rb +62 -63
- data/lib/active_merchant/billing/gateways/pay_secure.rb +29 -30
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +0 -5
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +33 -38
- data/lib/active_merchant/billing/gateways/payment_express.rb +48 -51
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +7 -11
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +7 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +3 -0
- data/lib/active_merchant/billing/gateways/paystation.rb +62 -64
- data/lib/active_merchant/billing/gateways/payway.rb +2 -9
- data/lib/active_merchant/billing/gateways/plugnpay.rb +0 -1
- data/lib/active_merchant/billing/gateways/psigate.rb +102 -94
- data/lib/active_merchant/billing/gateways/psl_card.rb +66 -67
- data/lib/active_merchant/billing/gateways/qbms.rb +0 -6
- data/lib/active_merchant/billing/gateways/quantum.rb +2 -8
- data/lib/active_merchant/billing/gateways/quickpay.rb +2 -3
- data/lib/active_merchant/billing/gateways/realex.rb +6 -16
- data/lib/active_merchant/billing/gateways/redsys.rb +394 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +25 -26
- data/lib/active_merchant/billing/gateways/sage.rb +15 -16
- data/lib/active_merchant/billing/gateways/sage_pay.rb +51 -56
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +1 -2
- data/lib/active_merchant/billing/gateways/samurai.rb +1 -4
- data/lib/active_merchant/billing/gateways/secure_net.rb +0 -1
- data/lib/active_merchant/billing/gateways/secure_pay.rb +5 -8
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +0 -5
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +17 -18
- data/lib/active_merchant/billing/gateways/skip_jack.rb +29 -34
- data/lib/active_merchant/billing/gateways/smart_ps.rb +55 -56
- data/lib/active_merchant/billing/gateways/stripe.rb +8 -3
- data/lib/active_merchant/billing/gateways/trans_first.rb +28 -29
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +85 -87
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +27 -28
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +0 -5
- data/lib/active_merchant/billing/gateways/verifi.rb +86 -87
- data/lib/active_merchant/billing/gateways/viaklix.rb +42 -47
- data/lib/active_merchant/billing/gateways/vindicia.rb +30 -28
- data/lib/active_merchant/billing/gateways/webpay.rb +45 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +0 -6
- data/lib/active_merchant/billing/gateways/worldpay.rb +4 -9
- data/lib/active_merchant/billing/gateways.rb +6 -7
- data/lib/active_merchant/billing/integrations/a1agregator/helper.rb +31 -0
- data/lib/active_merchant/billing/integrations/a1agregator/notification.rb +186 -0
- data/lib/active_merchant/billing/integrations/a1agregator/status.rb +38 -0
- data/lib/active_merchant/billing/integrations/a1agregator.rb +26 -0
- data/lib/active_merchant/billing/integrations/liqpay/helper.rb +43 -0
- data/lib/active_merchant/billing/integrations/liqpay/notification.rb +89 -0
- data/lib/active_merchant/billing/integrations/liqpay/return.rb +83 -0
- data/lib/active_merchant/billing/integrations/liqpay.rb +30 -0
- data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +17 -1
- data/lib/active_merchant/billing/integrations/notification.rb +4 -0
- data/lib/active_merchant/billing/integrations/pay_fast/common.rb +42 -0
- data/lib/active_merchant/billing/integrations/pay_fast/helper.rb +50 -0
- data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +134 -0
- data/lib/active_merchant/billing/integrations/pay_fast/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/pay_fast.rb +70 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +64 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +10 -7
- data/lib/active_merchant/billing/integrations/webmoney/notification.rb +12 -0
- data/lib/active_merchant/billing/response.rb +17 -4
- data/lib/active_merchant/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +46 -27
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
|
|
3
|
+
module ActiveMerchant #:nodoc:
|
|
4
|
+
module Billing #:nodoc:
|
|
5
|
+
module Integrations #:nodoc:
|
|
6
|
+
module Liqpay
|
|
7
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
|
8
|
+
def self.recognizes?(params)
|
|
9
|
+
params.has_key?('amount') && params.has_key?('order_id')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(post, options = {})
|
|
13
|
+
raise ArgumentError if post.blank?
|
|
14
|
+
super
|
|
15
|
+
@params.merge!(Hash.from_xml(Base64.decode64(xml))["response"])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def xml
|
|
19
|
+
@params["operation_xml"]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def complete?
|
|
23
|
+
status == 'success'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def account
|
|
27
|
+
params['merchant_id']
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def amount
|
|
31
|
+
BigDecimal.new(gross)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def item_id
|
|
35
|
+
params['order_id']
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def transaction_id
|
|
39
|
+
params['transaction_id']
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def action_name
|
|
43
|
+
params['action_name'] # either 'result_url' or 'server_url'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def version
|
|
47
|
+
params['version']
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def sender_phone
|
|
51
|
+
params['sender_phone']
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def security_key
|
|
55
|
+
params[ActiveMerchant::Billing::Integrations::Liqpay.signature_parameter_name]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def gross
|
|
59
|
+
params['amount']
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def currency
|
|
63
|
+
params['currency']
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def status
|
|
67
|
+
params['status'] # 'success', 'failure' or 'wait_secure'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def code
|
|
71
|
+
params['code']
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def generate_signature_string
|
|
75
|
+
"#{@options[:secret]}#{Base64.decode64(xml)}#{@options[:secret]}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def generate_signature
|
|
79
|
+
Base64.encode64(Digest::SHA1.digest(generate_signature_string)).strip
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def acknowledge
|
|
83
|
+
security_key == generate_signature
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
module Integrations #:nodoc:
|
|
4
|
+
module Liqpay
|
|
5
|
+
class Return < ActiveMerchant::Billing::Integrations::Return
|
|
6
|
+
def self.recognizes?(params)
|
|
7
|
+
params.has_key?('amount') && params.has_key?('order_id')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(post)
|
|
11
|
+
super
|
|
12
|
+
xml = Base64.decode64(@params["operation_xml"])
|
|
13
|
+
@params.merge!(Hash.from_xml(xml)["response"])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def complete?
|
|
17
|
+
status == 'success'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def account
|
|
21
|
+
params['merchant_id']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def amount
|
|
25
|
+
BigDecimal.new(gross)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def item_id
|
|
29
|
+
params['order_id']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def transaction_id
|
|
33
|
+
params['transaction_id']
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def action_name
|
|
37
|
+
params['action_name'] # either 'result_url' or 'server_url'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def version
|
|
41
|
+
params['version']
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def sender_phone
|
|
45
|
+
params['sender_phone']
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def security_key
|
|
49
|
+
params[ActiveMerchant::Billing::Integrations::Liqpay.signature_parameter_name]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def gross
|
|
53
|
+
params['amount']
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def currency
|
|
57
|
+
params['currency']
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def status
|
|
61
|
+
params['status'] # 'success', 'failure' or 'wait_secure'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def code
|
|
65
|
+
params['code']
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def generate_signature_string
|
|
69
|
+
['', version, @options[:secret], action_name, sender_phone, account, gross, currency, item_id, transaction_id, status, code, ''].flatten.compact.join('|')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def generate_signature
|
|
73
|
+
Base64.encode64(Digest::SHA1.digest(generate_signature_string)).gsub(/\n/, '')
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def acknowledge
|
|
77
|
+
security_key == generate_signature
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
module Integrations #:nodoc:
|
|
4
|
+
# Documentation: https://www.liqpay.com/?do=pages&p=cnb10
|
|
5
|
+
module Liqpay
|
|
6
|
+
autoload :Helper, File.dirname(__FILE__) + '/liqpay/helper.rb'
|
|
7
|
+
autoload :Notification, File.dirname(__FILE__) + '/liqpay/notification.rb'
|
|
8
|
+
autoload :Return, File.dirname(__FILE__) + '/liqpay/return.rb'
|
|
9
|
+
|
|
10
|
+
mattr_accessor :service_url
|
|
11
|
+
self.service_url = 'https://liqpay.com/?do=clickNbuy'
|
|
12
|
+
|
|
13
|
+
mattr_accessor :signature_parameter_name
|
|
14
|
+
self.signature_parameter_name = 'signature'
|
|
15
|
+
|
|
16
|
+
def self.helper(order, account, options = {})
|
|
17
|
+
Helper.new(order, account, options)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.notification(query_string, options = {})
|
|
21
|
+
Notification.new(query_string, options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.return(query_string)
|
|
25
|
+
Return.new(query_string)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -26,6 +26,17 @@ module ActiveMerchant #:nodoc:
|
|
|
26
26
|
mapping :return_url, 'return_url'
|
|
27
27
|
mapping :cancel_return_url, 'cancel_url'
|
|
28
28
|
mapping :description, 'detail1_text'
|
|
29
|
+
|
|
30
|
+
MAPPED_COUNTRY_CODES = {
|
|
31
|
+
'SE' => 'SV',
|
|
32
|
+
'DK' => 'DA'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
SUPPORTED_COUNTRY_CODES = [
|
|
36
|
+
'FI', 'DE', 'ES', 'FR',
|
|
37
|
+
'IT','PL', 'GR', 'RO',
|
|
38
|
+
'RU', 'TR', 'CN', 'CZ', 'NL'
|
|
39
|
+
]
|
|
29
40
|
|
|
30
41
|
def initialize(order, account, options = {})
|
|
31
42
|
super
|
|
@@ -34,7 +45,6 @@ module ActiveMerchant #:nodoc:
|
|
|
34
45
|
add_seller_details(options)
|
|
35
46
|
end
|
|
36
47
|
|
|
37
|
-
|
|
38
48
|
private
|
|
39
49
|
|
|
40
50
|
def add_tracking_token
|
|
@@ -51,6 +61,12 @@ module ActiveMerchant #:nodoc:
|
|
|
51
61
|
def add_seller_details(options)
|
|
52
62
|
add_field('recipient_description', options[:account_name]) if options[:account_name]
|
|
53
63
|
add_field('country', lookup_country_code(options[:country], :alpha3)) if options[:country]
|
|
64
|
+
add_field('language', locale_code(options[:country])) if options[:country]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def locale_code(country_code)
|
|
68
|
+
return country_code if SUPPORTED_COUNTRY_CODES.include?(country_code)
|
|
69
|
+
MAPPED_COUNTRY_CODES[country_code] || 'EN'
|
|
54
70
|
end
|
|
55
71
|
end
|
|
56
72
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
module Integrations #:nodoc:
|
|
4
|
+
module PayFast
|
|
5
|
+
module Common
|
|
6
|
+
def generate_signature(type)
|
|
7
|
+
string = case type
|
|
8
|
+
when :request
|
|
9
|
+
request_signature_string
|
|
10
|
+
when :notify
|
|
11
|
+
notify_signature_string
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Digest::MD5.hexdigest(string)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def request_attributes
|
|
18
|
+
[:merchant_id, :merchant_key, :return_url, :cancel_url,
|
|
19
|
+
:notify_url, :name_first, :name_last, :email_address,
|
|
20
|
+
:payment_id, :amount, :item_name, :item_description,
|
|
21
|
+
:custom_str1, :custom_str2, :custom_str3, :custom_str4,
|
|
22
|
+
:custom_str5, :custom_int1, :custom_int2, :custom_int3,
|
|
23
|
+
:custom_int4, :custom_int5, :email_confirmation,
|
|
24
|
+
:confirmation_address]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def request_signature_string
|
|
28
|
+
request_attributes.map do |attr|
|
|
29
|
+
"#{mappings[attr]}=#{CGI.escape(@fields[mappings[attr]])}" if @fields[mappings[attr]].present?
|
|
30
|
+
end.compact.join('&')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def notify_signature_string
|
|
34
|
+
params.map do |key, value|
|
|
35
|
+
"#{key}=#{CGI.escape(value)}" unless key == PayFast.signature_parameter_name
|
|
36
|
+
end.compact.join('&')
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
module Integrations #:nodoc:
|
|
4
|
+
module PayFast
|
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper
|
|
6
|
+
include Common
|
|
7
|
+
|
|
8
|
+
def initialize(order, account, options = {})
|
|
9
|
+
super
|
|
10
|
+
add_field('merchant_id', account)
|
|
11
|
+
add_field('merchant_key', options.delete(:credential2))
|
|
12
|
+
add_field('m_payment_id', order)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def form_fields
|
|
16
|
+
@fields
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def params
|
|
20
|
+
@fields
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
mapping :merchant_id, 'merchant_id'
|
|
24
|
+
mapping :merchant_key, 'merchant_key'
|
|
25
|
+
mapping :return_url, 'return_url'
|
|
26
|
+
mapping :cancel_return_url, 'cancel_url'
|
|
27
|
+
mapping :notify_url, 'notify_url'
|
|
28
|
+
mapping :name_first, 'name_first'
|
|
29
|
+
mapping :name_last, 'name_last'
|
|
30
|
+
mapping :email_address, 'email_address'
|
|
31
|
+
mapping :payment_id, 'm_payment_id'
|
|
32
|
+
mapping :amount, 'amount'
|
|
33
|
+
mapping :item_name, 'item_name'
|
|
34
|
+
mapping :description, 'item_name'
|
|
35
|
+
|
|
36
|
+
mapping :customer, :first_name => 'name_first',
|
|
37
|
+
:last_name => 'name_last',
|
|
38
|
+
:email => 'email_address',
|
|
39
|
+
:phone => 'phone'
|
|
40
|
+
|
|
41
|
+
5.times { |i| mapping :"custom_str#{i}", "custom_str#{i}" }
|
|
42
|
+
5.times { |i| mapping :"custom_int#{i}", "custom_int#{i}" }
|
|
43
|
+
|
|
44
|
+
mapping :email_confirmation, 'email_confirmation'
|
|
45
|
+
mapping :confirmation_address, 'confirmation_address'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
|
|
3
|
+
module ActiveMerchant #:nodoc:
|
|
4
|
+
module Billing #:nodoc:
|
|
5
|
+
module Integrations #:nodoc:
|
|
6
|
+
module PayFast
|
|
7
|
+
# Parser and handler for incoming ITN from PayFast.
|
|
8
|
+
# The Example shows a typical handler in a rails application.
|
|
9
|
+
#
|
|
10
|
+
# Example
|
|
11
|
+
#
|
|
12
|
+
# class BackendController < ApplicationController
|
|
13
|
+
# include ActiveMerchant::Billing::Integrations
|
|
14
|
+
#
|
|
15
|
+
# def pay_fast_itn
|
|
16
|
+
# notify = PayFast::Notification.new(request.raw_post)
|
|
17
|
+
#
|
|
18
|
+
# order = Order.find(notify.item_id)
|
|
19
|
+
#
|
|
20
|
+
# if notify.acknowledge
|
|
21
|
+
# begin
|
|
22
|
+
#
|
|
23
|
+
# if notify.complete? and order.total == notify.amount
|
|
24
|
+
# order.status = 'success'
|
|
25
|
+
#
|
|
26
|
+
# shop.ship(order)
|
|
27
|
+
# else
|
|
28
|
+
# logger.error("Failed to verify Paypal's notification, please investigate")
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# rescue => e
|
|
32
|
+
# order.status = 'failed'
|
|
33
|
+
# raise
|
|
34
|
+
# ensure
|
|
35
|
+
# order.save
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
#
|
|
39
|
+
# render :nothing
|
|
40
|
+
# end
|
|
41
|
+
# end
|
|
42
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
|
43
|
+
include PostsData
|
|
44
|
+
include Common
|
|
45
|
+
|
|
46
|
+
# Was the transaction complete?
|
|
47
|
+
def complete?
|
|
48
|
+
status == "Completed"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Status of transaction. List of possible values:
|
|
52
|
+
# <tt>COMPLETE</tt>::
|
|
53
|
+
def status
|
|
54
|
+
if params['payment_status'] == "COMPLETE"
|
|
55
|
+
"Completed"
|
|
56
|
+
else
|
|
57
|
+
"Failed"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Id of this transaction (uniq PayFast transaction id)
|
|
62
|
+
def transaction_id
|
|
63
|
+
params['pf_payment_id']
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Id of this transaction (uniq Shopify transaction id)
|
|
67
|
+
def item_id
|
|
68
|
+
params['m_payment_id']
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# The total amount which the payer paid.
|
|
72
|
+
def gross
|
|
73
|
+
params['amount_gross']
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# The total in fees which was deducated from the amount.
|
|
77
|
+
def fee
|
|
78
|
+
params['amount_fee']
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The net amount credited to the receiver's account.
|
|
82
|
+
def amount
|
|
83
|
+
params['amount_net']
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# The name of the item being charged for.
|
|
87
|
+
def item_name
|
|
88
|
+
params['item_name']
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# The Merchant ID as given by the PayFast system. Used to uniquely identify the receiver's account.
|
|
92
|
+
def merchant_id
|
|
93
|
+
params['merchant_id']
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def currency
|
|
97
|
+
nil
|
|
98
|
+
end
|
|
99
|
+
# Generated hash depends on params order so use OrderedHash instead of Hash
|
|
100
|
+
def empty!
|
|
101
|
+
super
|
|
102
|
+
@params = ActiveSupport::OrderedHash.new
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Acknowledge the transaction to PayFast. This method has to be called after a new
|
|
106
|
+
# ITN arrives. PayFast will verify that all the information we received are correct and will return a
|
|
107
|
+
# VERIFIED or INVALID status.
|
|
108
|
+
#
|
|
109
|
+
# Example:
|
|
110
|
+
#
|
|
111
|
+
# def pay_fast_itn
|
|
112
|
+
# notify = PayFastNotification.new(request.raw_post)
|
|
113
|
+
#
|
|
114
|
+
# if notify.acknowledge
|
|
115
|
+
# ... process order ... if notify.complete?
|
|
116
|
+
# else
|
|
117
|
+
# ... log possible hacking attempt ...
|
|
118
|
+
# end
|
|
119
|
+
def acknowledge
|
|
120
|
+
if params[PayFast.signature_parameter_name] == generate_signature(:notify)
|
|
121
|
+
response = ssl_post(PayFast.validate_service_url, notify_signature_string,
|
|
122
|
+
'Content-Type' => "application/x-www-form-urlencoded",
|
|
123
|
+
'Content-Length' => "#{notify_signature_string.size}"
|
|
124
|
+
)
|
|
125
|
+
raise StandardError.new("Faulty PayFast result: #{response}") unless ['VALID', 'INVALID'].include?(response)
|
|
126
|
+
|
|
127
|
+
response == "VALID"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
module Integrations #:nodoc:
|
|
4
|
+
|
|
5
|
+
# Documentation:
|
|
6
|
+
# https://www.payfast.co.za/s/std/integration-guide
|
|
7
|
+
module PayFast
|
|
8
|
+
autoload :Return, File.dirname(__FILE__) + '/pay_fast/return.rb'
|
|
9
|
+
autoload :Helper, File.dirname(__FILE__) + '/pay_fast/helper.rb'
|
|
10
|
+
autoload :Notification, File.dirname(__FILE__) + '/pay_fast/notification.rb'
|
|
11
|
+
autoload :Common, File.dirname(__FILE__) + '/pay_fast/common.rb'
|
|
12
|
+
|
|
13
|
+
# Overwrite this if you want to change the PayFast sandbox url
|
|
14
|
+
mattr_accessor :process_test_url
|
|
15
|
+
self.process_test_url = 'https://sandbox.payfast.co.za/eng/process'
|
|
16
|
+
|
|
17
|
+
# Overwrite this if you want to change the PayFast production url
|
|
18
|
+
mattr_accessor :process_production_url
|
|
19
|
+
self.process_production_url = 'https://www.payfast.co.za/eng/process'
|
|
20
|
+
|
|
21
|
+
# Overwrite this if you want to change the PayFast sandbox url
|
|
22
|
+
mattr_accessor :validate_test_url
|
|
23
|
+
self.validate_test_url = 'https://sandbox.payfast.co.za/eng/query/validate'
|
|
24
|
+
|
|
25
|
+
# Overwrite this if you want to change the PayFast production url
|
|
26
|
+
mattr_accessor :validate_production_url
|
|
27
|
+
self.validate_production_url = 'https://www.payfast.co.za/eng/query/validate'
|
|
28
|
+
|
|
29
|
+
mattr_accessor :signature_parameter_name
|
|
30
|
+
self.signature_parameter_name = 'signature'
|
|
31
|
+
|
|
32
|
+
def self.service_url
|
|
33
|
+
mode = ActiveMerchant::Billing::Base.integration_mode
|
|
34
|
+
case mode
|
|
35
|
+
when :production
|
|
36
|
+
self.process_production_url
|
|
37
|
+
when :test
|
|
38
|
+
self.process_test_url
|
|
39
|
+
else
|
|
40
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.validate_service_url
|
|
45
|
+
mode = ActiveMerchant::Billing::Base.integration_mode
|
|
46
|
+
case mode
|
|
47
|
+
when :production
|
|
48
|
+
self.validate_production_url
|
|
49
|
+
when :test
|
|
50
|
+
self.validate_test_url
|
|
51
|
+
else
|
|
52
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.helper(order, account, options = {})
|
|
57
|
+
Helper.new(order, account, options)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.notification(query_string, options = {})
|
|
61
|
+
Notification.new(query_string, options)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.return(post, options = {})
|
|
65
|
+
Return.new(post, options)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -16,6 +16,10 @@ module ActiveMerchant #:nodoc:
|
|
|
16
16
|
#
|
|
17
17
|
# def paypal_ipn
|
|
18
18
|
# notify = Paypal::Notification.new(request.raw_post)
|
|
19
|
+
#
|
|
20
|
+
# if notify.masspay?
|
|
21
|
+
# masspay_items = notify.items
|
|
22
|
+
# end
|
|
19
23
|
#
|
|
20
24
|
# order = Order.find(notify.item_id)
|
|
21
25
|
#
|
|
@@ -43,12 +47,22 @@ module ActiveMerchant #:nodoc:
|
|
|
43
47
|
# end
|
|
44
48
|
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
|
45
49
|
include PostsData
|
|
50
|
+
|
|
51
|
+
def initialize(post, options = {})
|
|
52
|
+
super
|
|
53
|
+
extend MassPayNotification if masspay?
|
|
54
|
+
end
|
|
46
55
|
|
|
47
56
|
# Was the transaction complete?
|
|
48
57
|
def complete?
|
|
49
58
|
status == "Completed"
|
|
50
59
|
end
|
|
51
60
|
|
|
61
|
+
# Is it a masspay notification?
|
|
62
|
+
def masspay?
|
|
63
|
+
type == "masspay"
|
|
64
|
+
end
|
|
65
|
+
|
|
52
66
|
# When was this payment received by the client.
|
|
53
67
|
# sometimes it can happen that we get the notification much later.
|
|
54
68
|
# One possible scenario is that our web application was down. In this case paypal tries several
|
|
@@ -149,6 +163,56 @@ module ActiveMerchant #:nodoc:
|
|
|
149
163
|
response == "VERIFIED"
|
|
150
164
|
end
|
|
151
165
|
end
|
|
166
|
+
|
|
167
|
+
module MassPayNotification
|
|
168
|
+
# Mass pay returns a collection of MassPay Items, so inspect items to get the values
|
|
169
|
+
def transaction_id
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Mass pay returns a collection of MassPay Items, so inspect items to get the values
|
|
173
|
+
def gross
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Mass pay returns a collection of MassPay Items, so inspect items to get the values
|
|
177
|
+
def fee
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Mass pay returns a collection of MassPay Items, so inspect items to get the values
|
|
181
|
+
def currency
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Mass pay returns a collection of MassPay Items, so inspect items to get the values
|
|
185
|
+
def item_id
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Mass pay returns a collection of MassPay Items, so inspect items to get the values
|
|
189
|
+
def account
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Collection of notification items returned for MassPay transactions
|
|
193
|
+
def items
|
|
194
|
+
@items ||= (1..number_of_mass_pay_items).map do |item_number|
|
|
195
|
+
MassPayItem.new(
|
|
196
|
+
params["masspay_txn_id_#{item_number}"],
|
|
197
|
+
params["mc_gross_#{item_number}"],
|
|
198
|
+
params["mc_fee_#{item_number}"],
|
|
199
|
+
params["mc_currency_#{item_number}"],
|
|
200
|
+
params["unique_id_#{item_number}"],
|
|
201
|
+
params["receiver_email_#{item_number}"],
|
|
202
|
+
params["status_#{item_number}"]
|
|
203
|
+
)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
|
|
209
|
+
def number_of_mass_pay_items
|
|
210
|
+
@number_of_mass_pay_items ||= params.keys.select { |k| k.start_with? 'masspay_txn_id' }.size
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
class MassPayItem < Struct.new(:transaction_id, :gross, :fee, :currency, :item_id, :account, :status)
|
|
215
|
+
end
|
|
152
216
|
end
|
|
153
217
|
end
|
|
154
218
|
end
|