activemerchant 1.38.1 → 1.39.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +23 -0
- data/CONTRIBUTORS +8 -0
- data/README.md +65 -59
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +6 -2
- data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +1 -1
- data/lib/active_merchant/billing/gateways/blue_pay.rb +0 -3
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +2 -2
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +70 -67
- data/lib/active_merchant/billing/gateways/cyber_source.rb +2 -4
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +75 -2
- data/lib/active_merchant/billing/gateways/moneris.rb +62 -10
- data/lib/active_merchant/billing/gateways/money_movers.rb +160 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +21 -8
- data/lib/active_merchant/billing/gateways/orbital/avs_result.rb +6 -6
- data/lib/active_merchant/billing/gateways/payflow_uk.rb +2 -2
- data/lib/active_merchant/billing/gateways/paymill.rb +12 -2
- data/lib/active_merchant/billing/gateways/paypal.rb +2 -2
- data/lib/active_merchant/billing/gateways/quickpay.rb +32 -2
- data/lib/active_merchant/billing/gateways/realex.rb +11 -7
- data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
- data/lib/active_merchant/billing/gateways/secure_net.rb +7 -10
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +9 -2
- data/lib/active_merchant/billing/gateways/stripe.rb +1 -1
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +4 -2
- data/lib/active_merchant/billing/gateways/wirecard.rb +1 -1
- data/lib/active_merchant/billing/gateways/worldpay.rb +2 -2
- data/lib/active_merchant/billing/integrations/a1agregator/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +2 -1
- data/lib/active_merchant/billing/integrations/bit_pay/helper.rb +41 -0
- data/lib/active_merchant/billing/integrations/bit_pay/notification.rb +56 -0
- data/lib/active_merchant/billing/integrations/bit_pay.rb +18 -0
- data/lib/active_merchant/billing/integrations/chronopay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/citrus/helper.rb +40 -0
- data/lib/active_merchant/billing/integrations/citrus/notification.rb +133 -0
- data/lib/active_merchant/billing/integrations/citrus/return.rb +40 -0
- data/lib/active_merchant/billing/integrations/citrus.rb +51 -0
- data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/directebanking/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/dotpay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/dwolla/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/easy_pay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/gestpay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/helper.rb +1 -1
- data/lib/active_merchant/billing/integrations/liqpay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/liqpay/return.rb +1 -1
- data/lib/active_merchant/billing/integrations/maksuturva/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/nochex/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/paxum/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/paysbuy/notification.rb +13 -2
- data/lib/active_merchant/billing/integrations/payu_in/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb +19 -0
- data/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb +23 -0
- data/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb +16 -0
- data/lib/active_merchant/billing/integrations/payu_in_paisa.rb +30 -0
- data/lib/active_merchant/billing/integrations/platron/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/pxpay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +28 -6
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/robokassa/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +1 -1
- data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/web_pay/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/webmoney/notification.rb +1 -1
- data/lib/active_merchant/billing/integrations/world_pay/notification.rb +1 -1
- data/lib/active_merchant/version.rb +1 -1
- data/lib/support/gateway_support.rb +16 -10
- data.tar.gz.sig +0 -0
- metadata +23 -3
- metadata.gz.sig +2 -2
@@ -34,7 +34,7 @@ module ActiveMerchant
|
|
34
34
|
self.money_format = :cents
|
35
35
|
self.default_currency = 'EUR'
|
36
36
|
self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :switch, :solo, :laser ]
|
37
|
-
self.supported_countries =
|
37
|
+
self.supported_countries = %w(IE GB FR BE NL LU IT)
|
38
38
|
self.homepage_url = 'http://www.realexpayments.com/'
|
39
39
|
self.display_name = 'Realex'
|
40
40
|
|
@@ -86,8 +86,11 @@ module ActiveMerchant
|
|
86
86
|
def commit(request)
|
87
87
|
response = parse(ssl_post(self.live_url, request))
|
88
88
|
|
89
|
-
Response.new(
|
90
|
-
|
89
|
+
Response.new(
|
90
|
+
(response[:result] == "00"),
|
91
|
+
message_from(response),
|
92
|
+
response,
|
93
|
+
:test => (response[:message] =~ %r{\[ test system \]}),
|
91
94
|
:authorization => authorization_from(response),
|
92
95
|
:cvv_result => response[:cvnresult],
|
93
96
|
:avs_result => {
|
@@ -187,14 +190,14 @@ module ActiveMerchant
|
|
187
190
|
|
188
191
|
if billing_address
|
189
192
|
xml.tag! 'address', 'type' => 'billing' do
|
190
|
-
xml.tag! 'code',
|
193
|
+
xml.tag! 'code', format_address_code(billing_address)
|
191
194
|
xml.tag! 'country', billing_address[:country]
|
192
195
|
end
|
193
196
|
end
|
194
197
|
|
195
198
|
if shipping_address
|
196
199
|
xml.tag! 'address', 'type' => 'shipping' do
|
197
|
-
xml.tag! 'code',
|
200
|
+
xml.tag! 'code', format_address_code(shipping_address)
|
198
201
|
xml.tag! 'country', shipping_address[:country]
|
199
202
|
end
|
200
203
|
end
|
@@ -240,8 +243,9 @@ module ActiveMerchant
|
|
240
243
|
end
|
241
244
|
end
|
242
245
|
|
243
|
-
def
|
244
|
-
zip.to_s.
|
246
|
+
def format_address_code(address)
|
247
|
+
code = [address[:zip].to_s, address[:address1].to_s + address[:address2].to_s]
|
248
|
+
code.collect{|e| e.gsub(/\D/, "")}.reject{|e| e.empty?}.join("|")
|
245
249
|
end
|
246
250
|
|
247
251
|
def new_timestamp
|
@@ -44,7 +44,7 @@ module ActiveMerchant #:nodoc:
|
|
44
44
|
}
|
45
45
|
|
46
46
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :switch, :solo, :maestro, :diners_club]
|
47
|
-
self.supported_countries = ['GB']
|
47
|
+
self.supported_countries = ['GB', 'IE']
|
48
48
|
self.default_currency = 'GBP'
|
49
49
|
|
50
50
|
self.homepage_url = 'http://www.sagepay.com'
|
@@ -93,9 +93,8 @@ module ActiveMerchant #:nodoc:
|
|
93
93
|
|
94
94
|
xml.tag! 'AMOUNT', amount(money)
|
95
95
|
add_credit_card(xml, creditcard)
|
96
|
-
|
96
|
+
add_params_in_required_order(xml, action, options)
|
97
97
|
add_address(xml, creditcard, options)
|
98
|
-
add_invoice(xml, options)
|
99
98
|
add_more_required_params(xml, options)
|
100
99
|
|
101
100
|
xml.target!
|
@@ -111,7 +110,7 @@ module ActiveMerchant #:nodoc:
|
|
111
110
|
xml.tag! 'CARDNUMBER', last_four
|
112
111
|
end
|
113
112
|
|
114
|
-
|
113
|
+
add_params_in_required_order(xml, action, options)
|
115
114
|
xml.tag! 'REF_TRANSID', transaction_id
|
116
115
|
add_more_required_params(xml, options)
|
117
116
|
|
@@ -181,12 +180,6 @@ module ActiveMerchant #:nodoc:
|
|
181
180
|
|
182
181
|
end
|
183
182
|
|
184
|
-
def add_invoice(xml, options)
|
185
|
-
xml.tag! 'NOTE', options[:description] if options[:description]
|
186
|
-
xml.tag! 'INVOICEDESC', options[:invoice_description] if options[:invoice_description]
|
187
|
-
xml.tag! 'INVOICENUM', options[:invoice_number] if options[:invoice_number]
|
188
|
-
end
|
189
|
-
|
190
183
|
def add_merchant_key(xml, options)
|
191
184
|
xml.tag!("MERCHANT_KEY") do
|
192
185
|
xml.tag! 'GROUPID', 0
|
@@ -195,13 +188,17 @@ module ActiveMerchant #:nodoc:
|
|
195
188
|
end
|
196
189
|
end
|
197
190
|
|
198
|
-
|
191
|
+
# SecureNet requires some of the xml params to be in a certain order. http://cl.ly/image/3K260E0p0a0n/content.png
|
192
|
+
def add_params_in_required_order(xml, action, options)
|
199
193
|
xml.tag! 'CODE', TRANSACTIONS[action]
|
200
194
|
add_customer_data(xml, options)
|
201
195
|
xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
|
202
196
|
xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
|
197
|
+
xml.tag! 'INVOICEDESC', options[:invoice_description] if options[:invoice_description]
|
198
|
+
xml.tag! 'INVOICENUM', options[:invoice_number] if options[:invoice_number]
|
203
199
|
add_merchant_key(xml, options)
|
204
200
|
xml.tag! 'METHOD', 'CC'
|
201
|
+
xml.tag! 'NOTE', options[:description] if options[:description]
|
205
202
|
xml.tag! 'ORDERID', options[:order_id]
|
206
203
|
xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
|
207
204
|
end
|
@@ -36,7 +36,9 @@ module ActiveMerchant #:nodoc:
|
|
36
36
|
#
|
37
37
|
# money - The monetary amount of the transaction in cents.
|
38
38
|
# payment_method - The CreditCard or the Spreedly payment method token.
|
39
|
-
# options - A
|
39
|
+
# options - A hash of options:
|
40
|
+
# :store - Retain the payment method if the purchase
|
41
|
+
# succeeds. Defaults to false. (optional)
|
40
42
|
def purchase(money, payment_method, options = {})
|
41
43
|
if payment_method.is_a?(String)
|
42
44
|
purchase_with_token(money, payment_method, options)
|
@@ -52,7 +54,9 @@ module ActiveMerchant #:nodoc:
|
|
52
54
|
#
|
53
55
|
# money - The monetary amount of the transaction in cents.
|
54
56
|
# payment_method - The CreditCard or the Spreedly payment method token.
|
55
|
-
# options - A
|
57
|
+
# options - A hash of options:
|
58
|
+
# :store - Retain the payment method if the authorize
|
59
|
+
# succeeds. Defaults to false. (optional)
|
56
60
|
def authorize(money, payment_method, options = {})
|
57
61
|
if payment_method.is_a?(String)
|
58
62
|
authorize_with_token(money, payment_method, options)
|
@@ -126,6 +130,7 @@ module ActiveMerchant #:nodoc:
|
|
126
130
|
build_xml_request('transaction') do |doc|
|
127
131
|
add_invoice(doc, money, options)
|
128
132
|
doc.payment_method_token(payment_method_token)
|
133
|
+
doc.retain_on_success(true) if options[:store]
|
129
134
|
end
|
130
135
|
end
|
131
136
|
|
@@ -137,6 +142,7 @@ module ActiveMerchant #:nodoc:
|
|
137
142
|
def add_credit_card(doc, credit_card, options)
|
138
143
|
doc.credit_card do
|
139
144
|
doc.number(credit_card.number)
|
145
|
+
doc.verification_value(credit_card.verification_value)
|
140
146
|
doc.first_name(credit_card.first_name)
|
141
147
|
doc.last_name(credit_card.last_name)
|
142
148
|
doc.month(credit_card.month)
|
@@ -147,6 +153,7 @@ module ActiveMerchant #:nodoc:
|
|
147
153
|
doc.city(options[:billing_address].try(:[], :city))
|
148
154
|
doc.state(options[:billing_address].try(:[], :state))
|
149
155
|
doc.zip(options[:billing_address].try(:[], :zip))
|
156
|
+
doc.country(options[:billing_address].try(:[], :country))
|
150
157
|
end
|
151
158
|
end
|
152
159
|
|
@@ -21,7 +21,7 @@ module ActiveMerchant #:nodoc:
|
|
21
21
|
'unchecked' => 'P'
|
22
22
|
}
|
23
23
|
|
24
|
-
self.supported_countries =
|
24
|
+
self.supported_countries = %w(US CA GB AU IE FR NL BE DE ES)
|
25
25
|
self.default_currency = 'USD'
|
26
26
|
self.money_format = :cents
|
27
27
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
|
@@ -2,7 +2,8 @@ module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
3
3
|
|
4
4
|
class UsaEpayTransactionGateway < Gateway
|
5
|
-
self.test_url =
|
5
|
+
self.test_url = 'https://sandbox.usaepay.com/gate.php'
|
6
|
+
self.live_url = 'https://www.usaepay.com/gate.php'
|
6
7
|
|
7
8
|
self.supported_cardtypes = [:visa, :master, :american_express]
|
8
9
|
self.supported_countries = ['US']
|
@@ -168,7 +169,8 @@ module ActiveMerchant #:nodoc:
|
|
168
169
|
end
|
169
170
|
|
170
171
|
def commit(action, parameters)
|
171
|
-
|
172
|
+
url = (self.test? ? self.test_url : self.live_url)
|
173
|
+
response = parse( ssl_post(url, post_data(action, parameters)) )
|
172
174
|
|
173
175
|
Response.new(response[:status] == 'Approved', message_from(response), response,
|
174
176
|
:test => test?,
|
@@ -30,7 +30,7 @@ module ActiveMerchant #:nodoc:
|
|
30
30
|
VALID_PHONE_FORMAT = /\+\d{1,3}(\(?\d{3}\)?)?\d{3}-\d{4}-\d{3}/
|
31
31
|
|
32
32
|
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
33
|
-
self.supported_countries =
|
33
|
+
self.supported_countries = %w(AD CY GI IM MT RO CH AT DK GR IT MC SM TR BE EE HU LV NL SK GB BG FI IS LI NO SI VA FR IL LT PL ES CZ DE IE LU PT SE)
|
34
34
|
|
35
35
|
# Wirecard supports all major credit and debit cards:
|
36
36
|
# Visa, Mastercard, American Express, Diners Club,
|
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
|
7
7
|
self.default_currency = 'GBP'
|
8
8
|
self.money_format = :cents
|
9
|
-
self.supported_countries =
|
9
|
+
self.supported_countries = %w(HK US GB AU AD BE CH CY CZ DE DK ES FI FR GI GR HU IE IL IT LI LU MC MT NL NO NZ PL PT SE SG SI SM TR UM VA)
|
10
10
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :laser]
|
11
11
|
self.homepage_url = 'http://www.worldpay.com/'
|
12
12
|
self.display_name = 'WorldPay'
|
@@ -59,7 +59,7 @@ module ActiveMerchant #:nodoc:
|
|
59
59
|
|
60
60
|
def refund(money, authorization, options = {})
|
61
61
|
MultiResponse.run do |r|
|
62
|
-
r.process{inquire_request(authorization, options, "CAPTURED", "SETTLED")}
|
62
|
+
r.process{inquire_request(authorization, options, "CAPTURED", "SETTLED", "SETTLED_BY_MERCHANT")}
|
63
63
|
r.process{refund_request(money, authorization, options)}
|
64
64
|
end
|
65
65
|
end
|
@@ -49,7 +49,8 @@ module ActiveMerchant #:nodoc:
|
|
49
49
|
service = service_class.new(order, account, options)
|
50
50
|
form_options[:method] = service.form_method
|
51
51
|
result = []
|
52
|
-
|
52
|
+
service_url = integration_module.respond_to?(:credential_based_url) ? integration_module.credential_based_url(options) : integration_module.service_url
|
53
|
+
result << form_tag(service_url, form_options)
|
53
54
|
|
54
55
|
result << capture(service, &proc)
|
55
56
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module BitPay
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper
|
6
|
+
def initialize(order_id, account, options)
|
7
|
+
super
|
8
|
+
add_field('account', account)
|
9
|
+
add_field('orderID', order_id)
|
10
|
+
add_field('posData', options[:authcode])
|
11
|
+
add_field('currency', options[:currency])
|
12
|
+
add_field('fullNotifications', 'true')
|
13
|
+
add_field('transactionSpeed', options[:transactionSpeed] || "high")
|
14
|
+
add_field('address1', options[:address1])
|
15
|
+
end
|
16
|
+
|
17
|
+
# Replace with the real mapping
|
18
|
+
mapping :account, 'key'
|
19
|
+
mapping :amount, 'price'
|
20
|
+
|
21
|
+
mapping :order, 'orderID'
|
22
|
+
mapping :currency, 'currency'
|
23
|
+
|
24
|
+
mapping :customer, :first_name => 'buyerName',
|
25
|
+
:email => 'buyerEmail',
|
26
|
+
:phone => 'buyerPhone'
|
27
|
+
|
28
|
+
mapping :billing_address, :city => 'buyerCity',
|
29
|
+
:address1 => 'buyerAddress1',
|
30
|
+
:address2 => 'buyerAddress2',
|
31
|
+
:state => 'buyerState',
|
32
|
+
:zip => 'buyerZip',
|
33
|
+
:country => 'buyerCountry'
|
34
|
+
|
35
|
+
mapping :notify_url, 'notificationURL'
|
36
|
+
mapping :return_url, 'returnURL'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
module Integrations #:nodoc:
|
6
|
+
module BitPay
|
7
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
8
|
+
def complete?
|
9
|
+
status == "complete"
|
10
|
+
end
|
11
|
+
|
12
|
+
def transaction_id
|
13
|
+
params['id']
|
14
|
+
end
|
15
|
+
|
16
|
+
# When was this payment received by the client.
|
17
|
+
def received_at
|
18
|
+
params['invoiceTime'].to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def currency
|
22
|
+
params['currency']
|
23
|
+
end
|
24
|
+
|
25
|
+
def amount
|
26
|
+
params['price']
|
27
|
+
end
|
28
|
+
|
29
|
+
# the money amount we received in X.2 decimal.
|
30
|
+
def btcPrice
|
31
|
+
params['btcPrice'].to_f
|
32
|
+
end
|
33
|
+
|
34
|
+
def status
|
35
|
+
params['status'].downcase
|
36
|
+
end
|
37
|
+
|
38
|
+
def acknowledge(authcode = nil)
|
39
|
+
authcode == params['posData']
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Take the posted data and move the relevant data into a hash
|
45
|
+
def parse(post)
|
46
|
+
@raw = post.to_s
|
47
|
+
for line in @raw.split('&')
|
48
|
+
key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten
|
49
|
+
params[key] = CGI.unescape(value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/bit_pay/helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/bit_pay/notification.rb'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
module Integrations #:nodoc:
|
7
|
+
module BitPay
|
8
|
+
|
9
|
+
mattr_accessor :service_url
|
10
|
+
self.service_url = 'https://www.bitpay.com/api/invoice'
|
11
|
+
|
12
|
+
def self.notification(post)
|
13
|
+
Notification.new(post)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
module Integrations
|
4
|
+
module Citrus
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper
|
6
|
+
|
7
|
+
mapping :order, 'merchantTxnId'
|
8
|
+
mapping :amount, 'orderAmount'
|
9
|
+
mapping :account, 'merchantAccessKey'
|
10
|
+
mapping :credential2, 'secret_key'
|
11
|
+
mapping :credential3, 'pmt_url'
|
12
|
+
mapping :currency, 'currency'
|
13
|
+
|
14
|
+
mapping :customer, :first_name => 'firstName',:last_name => 'lastName', :email => 'email', :phone => 'mobileNo'
|
15
|
+
|
16
|
+
mapping :billing_address, :city => 'addressCity', :address1 => 'addressStreet1', :address2 => 'addressStreet2',:state => 'addressState',:zip => 'addressZip', :country => 'addressCountry'
|
17
|
+
|
18
|
+
mapping :checksum, 'secSignature'
|
19
|
+
mapping :return_url, 'returnUrl'
|
20
|
+
|
21
|
+
|
22
|
+
def initialize(order, account, options = {})
|
23
|
+
super
|
24
|
+
add_field 'paymentMode', 'NET_BANKING'
|
25
|
+
add_field 'reqtime', (Time.now.to_i * 1000).to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
def form_fields
|
29
|
+
@fields.merge(mappings[:checksum] => generate_checksum)
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_checksum
|
33
|
+
checksum_fields = @fields["pmt_url"] + @fields["orderAmount"].to_s + @fields["merchantTxnId"] + @fields["currency"]
|
34
|
+
Citrus.checksum(@fields["secret_key"], checksum_fields )
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
module Integrations
|
4
|
+
module Citrus
|
5
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
6
|
+
|
7
|
+
def initialize(post, options = {})
|
8
|
+
super(post, options)
|
9
|
+
@secret_key = options[:credential2]
|
10
|
+
end
|
11
|
+
|
12
|
+
def complete?
|
13
|
+
status == "Completed" || status == 'Canceled'
|
14
|
+
end
|
15
|
+
|
16
|
+
def status
|
17
|
+
@status ||= if checksum_ok?
|
18
|
+
if transaction_id.blank?
|
19
|
+
'Invalid'
|
20
|
+
else
|
21
|
+
case transaction_status.downcase
|
22
|
+
when 'success' then 'Completed'
|
23
|
+
when 'canceled' then 'Canceled'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
else
|
27
|
+
'Tampered'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def invoice_ok?( order_id )
|
32
|
+
order_id.to_s == invoice.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def amount_ok?( order_amount )
|
36
|
+
BigDecimal.new( amount ) == order_amount
|
37
|
+
end
|
38
|
+
|
39
|
+
def item_id
|
40
|
+
params['TxId']
|
41
|
+
end
|
42
|
+
|
43
|
+
def invoice
|
44
|
+
item_id
|
45
|
+
end
|
46
|
+
|
47
|
+
# Status of transaction return from the Citrus. List of possible values:
|
48
|
+
# <tt>SUCCESS</tt>::
|
49
|
+
# <tt>CANCELED</tt>::
|
50
|
+
def transaction_status
|
51
|
+
params['TxStatus']
|
52
|
+
end
|
53
|
+
|
54
|
+
def gross
|
55
|
+
params['amount']
|
56
|
+
end
|
57
|
+
|
58
|
+
def amount
|
59
|
+
gross
|
60
|
+
end
|
61
|
+
|
62
|
+
def transaction_id
|
63
|
+
params['pgTxnNo']
|
64
|
+
end
|
65
|
+
|
66
|
+
def issuerrefno
|
67
|
+
params['issuerRefNo']
|
68
|
+
end
|
69
|
+
|
70
|
+
def authidcode
|
71
|
+
params['authIdCode']
|
72
|
+
end
|
73
|
+
|
74
|
+
def pgrespcode
|
75
|
+
params['pgRespCode']
|
76
|
+
end
|
77
|
+
|
78
|
+
def checksum
|
79
|
+
params['signature']
|
80
|
+
end
|
81
|
+
|
82
|
+
def paymentmode
|
83
|
+
params['paymentMode']
|
84
|
+
end
|
85
|
+
|
86
|
+
def currency
|
87
|
+
params['currency']
|
88
|
+
end
|
89
|
+
|
90
|
+
def customer_email
|
91
|
+
params['email']
|
92
|
+
end
|
93
|
+
|
94
|
+
def customer_phone
|
95
|
+
params['mobileNo']
|
96
|
+
end
|
97
|
+
|
98
|
+
def customer_first_name
|
99
|
+
params['firstName']
|
100
|
+
end
|
101
|
+
|
102
|
+
def customer_last_name
|
103
|
+
params['lastName']
|
104
|
+
end
|
105
|
+
|
106
|
+
def customer_address
|
107
|
+
{ :address1 => params['addressStreet1'], :address2 => params['addressStreet2'],
|
108
|
+
:city => params['addressCity'], :state => params['addressState'],
|
109
|
+
:country => params['addressCountry'], :zip => params['addressZip'] }
|
110
|
+
end
|
111
|
+
|
112
|
+
def message
|
113
|
+
@message || params['TxMsg']
|
114
|
+
end
|
115
|
+
|
116
|
+
def acknowledge(authcode = nil)
|
117
|
+
checksum_ok?
|
118
|
+
end
|
119
|
+
|
120
|
+
def checksum_ok?
|
121
|
+
fields = [invoice, transaction_status, amount.to_s, transaction_id, issuerrefno, authidcode, customer_first_name, customer_last_name, pgrespcode, customer_address[:zip]].join
|
122
|
+
|
123
|
+
unless Citrus.checksum(@secret_key, fields ) == checksum
|
124
|
+
@message = 'checksum mismatch...'
|
125
|
+
return false
|
126
|
+
end
|
127
|
+
true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
module Integrations
|
4
|
+
module Citrus
|
5
|
+
class Return < ActiveMerchant::Billing::Integrations::Return
|
6
|
+
|
7
|
+
def initialize(query_string, options = {})
|
8
|
+
super
|
9
|
+
@notification = Notification.new(query_string, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def transaction_id
|
13
|
+
@notification.transaction_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def status( order_id, order_amount )
|
17
|
+
if @notification.invoice_ok?( order_id ) && @notification.amount_ok?( BigDecimal.new(order_amount) )
|
18
|
+
@notification.status
|
19
|
+
else
|
20
|
+
'Mismatch'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def success?
|
25
|
+
status( @params['TxId'], @params['amount'] ) == 'Completed'
|
26
|
+
end
|
27
|
+
|
28
|
+
def message
|
29
|
+
@notification.message
|
30
|
+
end
|
31
|
+
|
32
|
+
def cancelled?
|
33
|
+
@notification.status == 'Cancelled'
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
module Integrations
|
4
|
+
module Citrus
|
5
|
+
autoload :Helper, File.dirname(__FILE__) + '/citrus/helper.rb'
|
6
|
+
autoload :Notification, File.dirname(__FILE__) + '/citrus/notification.rb'
|
7
|
+
autoload :Return, File.dirname(__FILE__) + '/citrus/return.rb'
|
8
|
+
|
9
|
+
mattr_accessor :sandbox_url
|
10
|
+
mattr_accessor :staging_url
|
11
|
+
mattr_accessor :production_url
|
12
|
+
|
13
|
+
self.sandbox_url = 'https://sandbox.citruspay.com/'
|
14
|
+
self.staging_url = 'https://stg.citruspay.com/'
|
15
|
+
self.production_url = 'https://www.citruspay.com/'
|
16
|
+
|
17
|
+
def self.credential_based_url(options)
|
18
|
+
pmt_url = options[:credential3]
|
19
|
+
|
20
|
+
case ActiveMerchant::Billing::Base.integration_mode
|
21
|
+
when :production
|
22
|
+
self.production_url + pmt_url
|
23
|
+
when :test
|
24
|
+
self.sandbox_url + pmt_url
|
25
|
+
when :staging
|
26
|
+
self.staging_url + pmt_url
|
27
|
+
else
|
28
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.helper(order, account, options = {})
|
33
|
+
Helper.new(order, account, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.notification(post, options = {})
|
37
|
+
Notification.new(post, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.return(query_string, options = {})
|
41
|
+
Return.new(query_string, options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.checksum(secret_key, payload_items )
|
45
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
46
|
+
OpenSSL::HMAC.hexdigest(digest, secret_key, payload_items)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -7,7 +7,7 @@ module ActiveMerchant #:nodoc:
|
|
7
7
|
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
8
8
|
RESPONSE_PARAMS = ['DirecPay Reference ID', 'Flag', 'Country', 'Currency', 'Other Details', 'Merchant Order No', 'Amount']
|
9
9
|
|
10
|
-
def acknowledge
|
10
|
+
def acknowledge(authcode = nil)
|
11
11
|
true
|
12
12
|
end
|
13
13
|
|