activemerchant 1.27.0 → 1.28.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.
- data.tar.gz.sig +3 -0
- data/CHANGELOG +13 -0
- data/README.md +4 -1
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -1
- data/lib/active_merchant/billing/gateways/banwire.rb +92 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +35 -35
- data/lib/active_merchant/billing/gateways/elavon.rb +192 -23
- data/lib/active_merchant/billing/gateways/litle.rb +7 -2
- data/lib/active_merchant/billing/gateways/orbital.rb +229 -88
- data/lib/active_merchant/billing/gateways/paypal_express.rb +22 -2
- data/lib/active_merchant/billing/integrations/easy_pay/common.rb +1 -1
- data/lib/active_merchant/billing/integrations/easy_pay/helper.rb +1 -5
- data/lib/active_merchant/billing/integrations/easy_pay/notification.rb +10 -2
- data/lib/active_merchant/billing/integrations/paysbuy.rb +36 -0
- data/lib/active_merchant/billing/integrations/paysbuy/helper.rb +15 -0
- data/lib/active_merchant/billing/integrations/paysbuy/notification.rb +28 -0
- data/lib/active_merchant/billing/integrations/webmoney.rb +43 -0
- data/lib/active_merchant/billing/integrations/webmoney/common.rb +17 -0
- data/lib/active_merchant/billing/integrations/webmoney/helper.rb +39 -0
- data/lib/active_merchant/billing/integrations/webmoney/notification.rb +31 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +60 -25
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
data/CHANGELOG
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
|
+
== Version 1.28.0 (August 10, 2012)
|
4
|
+
|
5
|
+
* PayPal Express: support non standard locale codes [Soleone]
|
6
|
+
* Litle: allow setting test mode per transaction [jduff]
|
7
|
+
* Add Banwire gateway [acolin]
|
8
|
+
* Authorize.Net CIM gateway: Move cardCode after order to comply with the XSD [davetron5000]
|
9
|
+
* Add WebMoney integration [Mehonoshin]
|
10
|
+
* EasyPay: Make symmetric with other integrations [nashby]
|
11
|
+
* Add Paysbuy integration [divineforest]
|
12
|
+
* Bogus gateway: Use last digit for pass/fail [mipearson]
|
13
|
+
* Elavon gateway: Separate from Viaklix, implement refund & void [duff]
|
14
|
+
* Orbital gateway: Update to API version 5.6 and add support for profile requests [rbarazi]
|
15
|
+
|
3
16
|
== Version 1.27.0 (August 10, 2012)
|
4
17
|
|
5
18
|
* Add First Data integration [courtland]
|
data/README.md
CHANGED
@@ -87,6 +87,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
|
|
87
87
|
* [Authorize.Net](http://www.authorize.net/) - US
|
88
88
|
* [Authorize.Net CIM](http://www.authorize.net/) - US
|
89
89
|
* [Balanced](https://www.balancedpayments.com/) - US
|
90
|
+
* [Banwire](https://www.banwire.com/) - MX
|
90
91
|
* [Barclays ePDQ](http://www.barclaycard.co.uk/business/accepting-payments/epdq-mpi/) - UK
|
91
92
|
* [Beanstream.com](http://www.beanstream.com/) - CA
|
92
93
|
* [BluePay](http://www.bluepay.com/) - US
|
@@ -125,7 +126,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
|
|
125
126
|
* [NMI](http://nmi.com/) - US
|
126
127
|
* [Ogone DirectLink](http://www.ogone.com) - BE, DE, FR, NL, AT, CH
|
127
128
|
* [Optimal Payments](http://www.optimalpayments.com/) - CA, US, UK
|
128
|
-
* [Orbital Paymentech](http://chasepaymentech.com/) - CA, US
|
129
|
+
* [Orbital Paymentech](http://chasepaymentech.com/) - CA, US, UK, GB
|
129
130
|
* [PayBox Direct](http://www.paybox.com) - FR
|
130
131
|
* [PayGate PayXML](http://paygate.co.za/) - US, ZA
|
131
132
|
* [PayJunction](http://www.payjunction.com/) - US
|
@@ -181,11 +182,13 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
|
|
181
182
|
* [Nochex](http://www.nochex.com)
|
182
183
|
* [Paxum](https://www.paxum.com/)
|
183
184
|
* [PayPal Website Payments Standard](https://www.paypal.com/cgi-bin/webscr?cmd#_wp-standard-overview-outside)
|
185
|
+
* [Paysbuy](https://www.paysbuy.com/) - TH
|
184
186
|
* [Robokassa](http://robokassa.ru/)
|
185
187
|
* [SagePay Form](http://www.sagepay.com/products_services/sage_pay_go/integration/form)
|
186
188
|
* [Suomen Maksuturva](https://www.maksuturva.fi/services/vendor_services/integration_guidelines.html)
|
187
189
|
* [Valitor](http://www.valitor.is/) - IS
|
188
190
|
* [Verkkomaksut](http://www.verkkomaksut.fi) - FI
|
191
|
+
* [WebMoney](http://www.webmoney.ru) - RU
|
189
192
|
* [WebPay](http://webpay.by/)
|
190
193
|
* [WorldPay](http://www.worldpay.com)
|
191
194
|
|
@@ -673,9 +673,11 @@ module ActiveMerchant #:nodoc:
|
|
673
673
|
xml.tag!('customerProfileId', transaction[:customer_profile_id])
|
674
674
|
xml.tag!('customerPaymentProfileId', transaction[:customer_payment_profile_id])
|
675
675
|
xml.tag!('approvalCode', transaction[:approval_code]) if transaction[:type] == :capture_only
|
676
|
-
tag_unless_blank(xml, 'cardCode', transaction[:card_code])
|
677
676
|
end
|
678
677
|
add_order(xml, transaction[:order]) if transaction[:order].present?
|
678
|
+
unless [:void,:refund,:prior_auth_capture].include?(transaction[:type])
|
679
|
+
tag_unless_blank(xml, 'cardCode', transaction[:card_code])
|
680
|
+
end
|
679
681
|
end
|
680
682
|
end
|
681
683
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class BanwireGateway < Gateway
|
4
|
+
URL = 'https://banwire.com/api.pago_pro'
|
5
|
+
|
6
|
+
self.supported_countries = ['MX']
|
7
|
+
self.supported_cardtypes = [:visa, :master, :american_express]
|
8
|
+
self.homepage_url = 'http://www.banwire.com/'
|
9
|
+
self.display_name = 'Banwire'
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
requires!(options, :login)
|
13
|
+
@options = options
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def purchase(money, creditcard, options = {})
|
18
|
+
post = {}
|
19
|
+
add_response_type(post)
|
20
|
+
add_customer_data(post, options)
|
21
|
+
add_order_data(post, options)
|
22
|
+
add_creditcard(post, creditcard)
|
23
|
+
add_address(post, creditcard, options)
|
24
|
+
add_customer_data(post, options)
|
25
|
+
add_amount(post, money, options)
|
26
|
+
|
27
|
+
commit(money, post)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def add_response_type(post)
|
33
|
+
post[:response_format] = "JSON"
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_customer_data(post, options)
|
37
|
+
post[:user] = @options[:login]
|
38
|
+
post[:phone] = options[:billing_address][:phone]
|
39
|
+
post[:mail] = options[:email]
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_order_data(post, options)
|
43
|
+
post[:reference] = options[:order_id]
|
44
|
+
post[:concept] = options[:description]
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_address(post, creditcard, options)
|
48
|
+
post[:address] = options[:billing_address][:address1]
|
49
|
+
post[:post_code] = options[:billing_address][:zipcode]
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_creditcard(post, creditcard)
|
53
|
+
post[:card_num] = creditcard.number
|
54
|
+
post[:card_name] = creditcard.name
|
55
|
+
post[:card_type] = card_brand(creditcard)
|
56
|
+
post[:card_exp] = "#{sprintf("%02d", creditcard.month)}/#{"#{creditcard.year}"[-2, 2]}"
|
57
|
+
post[:card_ccv2] = creditcard.verification_value
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_amount(post, money, options)
|
61
|
+
post[:ammount] = amount(money)
|
62
|
+
post[:currency] = options[:currency]
|
63
|
+
end
|
64
|
+
|
65
|
+
def card_brand(card)
|
66
|
+
brand = super
|
67
|
+
({"master" => "mastercard", "american_express" => "amex"}[brand] || brand)
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse(body)
|
71
|
+
JSON.parse(body)
|
72
|
+
end
|
73
|
+
|
74
|
+
def commit(money, parameters)
|
75
|
+
response = parse(ssl_post(URL, post_data(parameters)))
|
76
|
+
Response.new(success?(response),
|
77
|
+
response["message"],
|
78
|
+
response,
|
79
|
+
:test => test?,
|
80
|
+
:authorization => response["code_auth"])
|
81
|
+
end
|
82
|
+
|
83
|
+
def success?(response)
|
84
|
+
(response["response"] == "ok")
|
85
|
+
end
|
86
|
+
|
87
|
+
def post_data(parameters = {})
|
88
|
+
parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -3,57 +3,57 @@ module ActiveMerchant #:nodoc:
|
|
3
3
|
# Bogus Gateway
|
4
4
|
class BogusGateway < Gateway
|
5
5
|
AUTHORIZATION = '53433'
|
6
|
-
|
6
|
+
|
7
7
|
SUCCESS_MESSAGE = "Bogus Gateway: Forced success"
|
8
8
|
FAILURE_MESSAGE = "Bogus Gateway: Forced failure"
|
9
|
-
ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error"
|
10
|
-
CREDIT_ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number 1 for success, 2 for exception and anything else for error"
|
11
|
-
UNSTORE_ERROR_MESSAGE = "Bogus Gateway: Use trans_id 1 for success, 2 for exception and anything else for error"
|
12
|
-
CAPTURE_ERROR_MESSAGE = "Bogus Gateway: Use authorization number 1 for exception, 2 for error and anything else for success"
|
13
|
-
VOID_ERROR_MESSAGE = "Bogus Gateway: Use authorization number 1 for exception, 2 for error and anything else for success"
|
14
|
-
REFUND_ERROR_MESSAGE = "Bogus Gateway: Use trans_id number 1 for exception, 2 for error and anything else for success"
|
15
|
-
|
9
|
+
ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error"
|
10
|
+
CREDIT_ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error"
|
11
|
+
UNSTORE_ERROR_MESSAGE = "Bogus Gateway: Use trans_id ending in 1 for success, 2 for exception and anything else for error"
|
12
|
+
CAPTURE_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success"
|
13
|
+
VOID_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success"
|
14
|
+
REFUND_ERROR_MESSAGE = "Bogus Gateway: Use trans_id number ending in 1 for exception, 2 for error and anything else for success"
|
15
|
+
|
16
16
|
self.supported_countries = ['US']
|
17
17
|
self.supported_cardtypes = [:bogus]
|
18
18
|
self.homepage_url = 'http://example.com'
|
19
19
|
self.display_name = 'Bogus'
|
20
|
-
|
20
|
+
|
21
21
|
def authorize(money, credit_card_or_reference, options = {})
|
22
22
|
money = amount(money)
|
23
23
|
case normalize(credit_card_or_reference)
|
24
|
-
when
|
24
|
+
when /1$/
|
25
25
|
Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION )
|
26
|
-
when
|
26
|
+
when /2$/
|
27
27
|
Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
28
28
|
else
|
29
29
|
raise Error, ERROR_MESSAGE
|
30
|
-
end
|
30
|
+
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def purchase(money, credit_card_or_reference, options = {})
|
34
34
|
money = amount(money)
|
35
35
|
case normalize(credit_card_or_reference)
|
36
|
-
when
|
36
|
+
when /1$/, AUTHORIZATION
|
37
37
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
38
|
-
when
|
38
|
+
when /2$/
|
39
39
|
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
|
40
40
|
else
|
41
41
|
raise Error, ERROR_MESSAGE
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def recurring(money, credit_card_or_reference, options = {})
|
46
46
|
money = amount(money)
|
47
47
|
case normalize(credit_card_or_reference)
|
48
|
-
when
|
48
|
+
when /1$/
|
49
49
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
50
|
-
when
|
50
|
+
when /2$/
|
51
51
|
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
|
52
52
|
else
|
53
53
|
raise Error, ERROR_MESSAGE
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def credit(money, credit_card_or_reference, options = {})
|
58
58
|
if credit_card_or_reference.is_a?(String)
|
59
59
|
deprecated CREDIT_DEPRECATION_MESSAGE
|
@@ -62,9 +62,9 @@ module ActiveMerchant #:nodoc:
|
|
62
62
|
|
63
63
|
money = amount(money)
|
64
64
|
case normalize(credit_card_or_reference)
|
65
|
-
when
|
65
|
+
when /1$/
|
66
66
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true )
|
67
|
-
when
|
67
|
+
when /2$/
|
68
68
|
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
69
69
|
else
|
70
70
|
raise Error, CREDIT_ERROR_MESSAGE
|
@@ -74,21 +74,21 @@ module ActiveMerchant #:nodoc:
|
|
74
74
|
def refund(money, reference, options = {})
|
75
75
|
money = amount(money)
|
76
76
|
case reference
|
77
|
-
when
|
77
|
+
when /1$/
|
78
78
|
raise Error, REFUND_ERROR_MESSAGE
|
79
|
-
when
|
79
|
+
when /2$/
|
80
80
|
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
81
81
|
else
|
82
82
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
83
83
|
end
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
def capture(money, reference, options = {})
|
87
87
|
money = amount(money)
|
88
88
|
case reference
|
89
|
-
when
|
89
|
+
when /1$/
|
90
90
|
raise Error, CAPTURE_ERROR_MESSAGE
|
91
|
-
when
|
91
|
+
when /2$/
|
92
92
|
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
93
93
|
else
|
94
94
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
@@ -97,31 +97,31 @@ module ActiveMerchant #:nodoc:
|
|
97
97
|
|
98
98
|
def void(reference, options = {})
|
99
99
|
case reference
|
100
|
-
when
|
100
|
+
when /1$/
|
101
101
|
raise Error, VOID_ERROR_MESSAGE
|
102
|
-
when
|
102
|
+
when /2$/
|
103
103
|
Response.new(false, FAILURE_MESSAGE, {:authorization => reference, :error => FAILURE_MESSAGE }, :test => true)
|
104
104
|
else
|
105
105
|
Response.new(true, SUCCESS_MESSAGE, {:authorization => reference}, :test => true)
|
106
106
|
end
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
def store(credit_card_or_reference, options = {})
|
110
110
|
case normalize(credit_card_or_reference)
|
111
|
-
when
|
111
|
+
when /1$/
|
112
112
|
Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION)
|
113
|
-
when
|
113
|
+
when /2$/
|
114
114
|
Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true)
|
115
115
|
else
|
116
116
|
raise Error, ERROR_MESSAGE
|
117
|
-
end
|
117
|
+
end
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
def unstore(reference, options = {})
|
121
121
|
case reference
|
122
|
-
when
|
122
|
+
when /1$/
|
123
123
|
Response.new(true, SUCCESS_MESSAGE, {}, :test => true)
|
124
|
-
when
|
124
|
+
when /2$/
|
125
125
|
Response.new(false, FAILURE_MESSAGE, {:error => FAILURE_MESSAGE },:test => true)
|
126
126
|
else
|
127
127
|
raise Error, UNSTORE_ERROR_MESSAGE
|
@@ -29,7 +29,9 @@ module ActiveMerchant #:nodoc:
|
|
29
29
|
# puts response.message # Retrieve the message returned by Elavon
|
30
30
|
# puts response.authorization # Retrieve the unique transaction ID returned by Elavon
|
31
31
|
#
|
32
|
-
class ElavonGateway <
|
32
|
+
class ElavonGateway < Gateway
|
33
|
+
class_attribute :test_url, :live_url, :delimiter, :actions
|
34
|
+
|
33
35
|
self.test_url = 'https://demo.myvirtualmerchant.com/VirtualMerchantDemo/process.do'
|
34
36
|
self.live_url = 'https://www.myvirtualmerchant.com/VirtualMerchant/process.do'
|
35
37
|
|
@@ -42,29 +44,59 @@ module ActiveMerchant #:nodoc:
|
|
42
44
|
self.actions = {
|
43
45
|
:purchase => 'CCSALE',
|
44
46
|
:credit => 'CCCREDIT',
|
47
|
+
:refund => 'CCRETURN',
|
45
48
|
:authorize => 'CCAUTHONLY',
|
46
|
-
:capture => 'CCFORCE'
|
49
|
+
:capture => 'CCFORCE',
|
50
|
+
:void => 'CCVOID'
|
47
51
|
}
|
48
|
-
|
52
|
+
|
53
|
+
# Initialize the Gateway
|
54
|
+
#
|
55
|
+
# The gateway requires that a valid login and password be passed
|
56
|
+
# in the +options+ hash.
|
57
|
+
#
|
58
|
+
# ==== Options
|
59
|
+
#
|
60
|
+
# * <tt>:login</tt> -- Merchant ID
|
61
|
+
# * <tt>:password</tt> -- PIN
|
62
|
+
# * <tt>:user</tt> -- Specify a subuser of the account (optional)
|
63
|
+
# * <tt>:test => +true+ or +false+</tt> -- Force test transactions
|
64
|
+
def initialize(options = {})
|
65
|
+
requires!(options, :login, :password)
|
66
|
+
@options = options
|
67
|
+
super
|
68
|
+
end
|
69
|
+
|
70
|
+
# Make a purchase
|
71
|
+
def purchase(money, creditcard, options = {})
|
72
|
+
form = {}
|
73
|
+
add_invoice(form, options)
|
74
|
+
add_creditcard(form, creditcard)
|
75
|
+
add_address(form, options)
|
76
|
+
add_customer_data(form, options)
|
77
|
+
add_test_mode(form, options)
|
78
|
+
commit(:purchase, money, form)
|
79
|
+
end
|
80
|
+
|
49
81
|
# Authorize a credit card for a given amount.
|
50
|
-
#
|
82
|
+
#
|
51
83
|
# ==== Parameters
|
52
84
|
# * <tt>money</tt> - The amount to be authorized as an Integer value in cents.
|
53
85
|
# * <tt>credit_card</tt> - The CreditCard details for the transaction.
|
54
86
|
# * <tt>options</tt>
|
55
|
-
# * <tt>:billing_address</tt> - The billing address for the cardholder.
|
87
|
+
# * <tt>:billing_address</tt> - The billing address for the cardholder.
|
56
88
|
def authorize(money, creditcard, options = {})
|
57
89
|
form = {}
|
58
90
|
add_invoice(form, options)
|
59
|
-
add_creditcard(form, creditcard)
|
60
|
-
add_address(form, options)
|
91
|
+
add_creditcard(form, creditcard)
|
92
|
+
add_address(form, options)
|
61
93
|
add_customer_data(form, options)
|
62
94
|
add_test_mode(form, options)
|
63
95
|
commit(:authorize, money, form)
|
64
96
|
end
|
65
|
-
|
97
|
+
|
66
98
|
# Capture authorized funds from a credit card.
|
67
|
-
#
|
99
|
+
#
|
68
100
|
# ==== Parameters
|
69
101
|
# * <tt>money</tt> - The amount to be captured as an Integer value in cents.
|
70
102
|
# * <tt>authorization</tt> - The approval code returned from the initial authorization.
|
@@ -72,33 +104,116 @@ module ActiveMerchant #:nodoc:
|
|
72
104
|
# * <tt>:credit_card</tt> - The CreditCard details from the initial transaction (required).
|
73
105
|
def capture(money, authorization, options = {})
|
74
106
|
requires!(options, :credit_card)
|
75
|
-
|
107
|
+
|
76
108
|
form = {}
|
77
|
-
|
109
|
+
add_approval_code(form, authorization)
|
78
110
|
add_invoice(form, options)
|
79
111
|
add_creditcard(form, options[:credit_card])
|
80
112
|
add_customer_data(form, options)
|
81
113
|
add_test_mode(form, options)
|
82
114
|
commit(:capture, money, form)
|
83
115
|
end
|
84
|
-
|
116
|
+
|
117
|
+
# Refund a transaction.
|
118
|
+
#
|
119
|
+
# This transaction indicates to the gateway that
|
120
|
+
# money should flow from the merchant to the customer.
|
121
|
+
#
|
122
|
+
# ==== Parameters
|
123
|
+
#
|
124
|
+
# * <tt>money</tt> -- The amount to be credited to the customer as an Integer value in cents.
|
125
|
+
# * <tt>identification</tt> -- The ID of the original transaction against which the refund is being issued.
|
126
|
+
# * <tt>options</tt> -- A hash of parameters.
|
127
|
+
def refund(money, identification, options = {})
|
128
|
+
form = {}
|
129
|
+
add_txn_id(form, identification)
|
130
|
+
add_test_mode(form, options)
|
131
|
+
commit(:refund, money, form)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Void a previous transaction
|
135
|
+
#
|
136
|
+
# ==== Parameters
|
137
|
+
#
|
138
|
+
# * <tt>authorization</tt> - The authorization returned from the previous request.
|
139
|
+
def void(identification, options = {})
|
140
|
+
form = {}
|
141
|
+
add_txn_id(form, identification)
|
142
|
+
add_test_mode(form, options)
|
143
|
+
commit(:void, nil, form)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Make a credit to a card. Use the refund method if you'd like to credit using
|
147
|
+
# previous transaction
|
148
|
+
#
|
149
|
+
# ==== Parameters
|
150
|
+
# * <tt>money</tt> - The amount to be credited as an Integer value in cents.
|
151
|
+
# * <tt>creditcard</tt> - The credit card to be credited.
|
152
|
+
# * <tt>options</tt>
|
153
|
+
def credit(money, creditcard, options = {})
|
154
|
+
if creditcard.is_a?(String)
|
155
|
+
raise ArgumentError, "Reference credits are not supported. Please supply the original credit card or use the #refund method."
|
156
|
+
end
|
157
|
+
|
158
|
+
form = {}
|
159
|
+
add_invoice(form, options)
|
160
|
+
add_creditcard(form, creditcard)
|
161
|
+
add_address(form, options)
|
162
|
+
add_customer_data(form, options)
|
163
|
+
add_test_mode(form, options)
|
164
|
+
commit(:credit, money, form)
|
165
|
+
end
|
166
|
+
|
167
|
+
|
85
168
|
private
|
86
|
-
def
|
87
|
-
form[:
|
169
|
+
def add_invoice(form,options)
|
170
|
+
form[:invoice_number] = (options[:order_id] || options[:invoice]).to_s.slice(0, 10)
|
171
|
+
form[:description] = options[:description].to_s.slice(0, 255)
|
172
|
+
end
|
173
|
+
|
174
|
+
def add_approval_code(form, authorization)
|
175
|
+
form[:approval_code] = authorization.split(';').first
|
176
|
+
end
|
177
|
+
|
178
|
+
def add_txn_id(form, authorization)
|
179
|
+
form[:txn_id] = authorization.split(';').last
|
88
180
|
end
|
89
|
-
|
181
|
+
|
90
182
|
def authorization_from(response)
|
91
|
-
response['approval_code']
|
183
|
+
[response['approval_code'], response['txn_id']].join(';')
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_creditcard(form, creditcard)
|
187
|
+
form[:card_number] = creditcard.number
|
188
|
+
form[:exp_date] = expdate(creditcard)
|
189
|
+
|
190
|
+
if creditcard.verification_value?
|
191
|
+
add_verification_value(form, creditcard)
|
192
|
+
end
|
193
|
+
|
194
|
+
form[:first_name] = creditcard.first_name.to_s.slice(0, 20)
|
195
|
+
form[:last_name] = creditcard.last_name.to_s.slice(0, 30)
|
92
196
|
end
|
93
|
-
|
197
|
+
|
94
198
|
def add_verification_value(form, creditcard)
|
95
|
-
form[:cvv2cvc2] = creditcard.verification_value
|
199
|
+
form[:cvv2cvc2] = creditcard.verification_value
|
96
200
|
form[:cvv2cvc2_indicator] = '1'
|
97
201
|
end
|
98
202
|
|
203
|
+
def add_customer_data(form, options)
|
204
|
+
form[:email] = options[:email].to_s.slice(0, 100) unless options[:email].blank?
|
205
|
+
form[:customer_code] = options[:customer].to_s.slice(0, 10) unless options[:customer].blank?
|
206
|
+
end
|
207
|
+
|
208
|
+
def expdate(creditcard)
|
209
|
+
year = sprintf("%.4i", creditcard.year)
|
210
|
+
month = sprintf("%.2i", creditcard.month)
|
211
|
+
"#{month}#{year[2..3]}"
|
212
|
+
end
|
213
|
+
|
99
214
|
def add_address(form,options)
|
100
|
-
billing_address = options[:billing_address] || options[:address]
|
101
|
-
|
215
|
+
billing_address = options[:billing_address] || options[:address]
|
216
|
+
|
102
217
|
if billing_address
|
103
218
|
form[:avs_address] = billing_address[:address1].to_s.slice(0, 30)
|
104
219
|
form[:address2] = billing_address[:address2].to_s.slice(0, 30)
|
@@ -109,7 +224,7 @@ module ActiveMerchant #:nodoc:
|
|
109
224
|
form[:phone] = billing_address[:phone].to_s.slice(0, 20)
|
110
225
|
form[:country] = billing_address[:country].to_s.slice(0, 50)
|
111
226
|
end
|
112
|
-
|
227
|
+
|
113
228
|
if shipping_address = options[:shipping_address]
|
114
229
|
first_name, last_name = parse_first_and_last_name(shipping_address[:name])
|
115
230
|
form[:ship_to_first_name] = first_name.to_s.slice(0, 20)
|
@@ -123,14 +238,68 @@ module ActiveMerchant #:nodoc:
|
|
123
238
|
form[:ship_to_zip] = shipping_address[:zip].to_s.slice(0, 10)
|
124
239
|
end
|
125
240
|
end
|
126
|
-
|
241
|
+
|
242
|
+
def parse_first_and_last_name(value)
|
243
|
+
name = value.to_s.split(' ')
|
244
|
+
|
245
|
+
last_name = name.pop || ''
|
246
|
+
first_name = name.join(' ')
|
247
|
+
[ first_name, last_name ]
|
248
|
+
end
|
249
|
+
|
250
|
+
def add_test_mode(form, options)
|
251
|
+
form[:test_mode] = 'TRUE' if options[:test_mode]
|
252
|
+
end
|
253
|
+
|
127
254
|
def message_from(response)
|
128
255
|
success?(response) ? response['result_message'] : response['errorMessage']
|
129
256
|
end
|
130
|
-
|
257
|
+
|
131
258
|
def success?(response)
|
132
259
|
!response.has_key?('errorMessage')
|
133
260
|
end
|
261
|
+
|
262
|
+
def commit(action, money, parameters)
|
263
|
+
parameters[:amount] = amount(money)
|
264
|
+
parameters[:transaction_type] = self.actions[action]
|
265
|
+
|
266
|
+
response = parse( ssl_post(test? ? self.test_url : self.live_url, post_data(parameters)) )
|
267
|
+
|
268
|
+
Response.new(response['result'] == '0', message_from(response), response,
|
269
|
+
:test => @options[:test] || test?,
|
270
|
+
:authorization => authorization_from(response),
|
271
|
+
:avs_result => { :code => response['avs_response'] },
|
272
|
+
:cvv_result => response['cvv2_response']
|
273
|
+
)
|
274
|
+
end
|
275
|
+
|
276
|
+
def post_data(parameters)
|
277
|
+
result = preamble
|
278
|
+
result.merge!(parameters)
|
279
|
+
result.collect { |key, value| "ssl_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
280
|
+
end
|
281
|
+
|
282
|
+
def preamble
|
283
|
+
result = {
|
284
|
+
'merchant_id' => @options[:login],
|
285
|
+
'pin' => @options[:password],
|
286
|
+
'show_form' => 'false',
|
287
|
+
'result_format' => 'ASCII'
|
288
|
+
}
|
289
|
+
|
290
|
+
result['user_id'] = @options[:user] unless @options[:user].blank?
|
291
|
+
result
|
292
|
+
end
|
293
|
+
|
294
|
+
def parse(msg)
|
295
|
+
resp = {}
|
296
|
+
msg.split(self.delimiter).collect{|li|
|
297
|
+
key, value = li.split("=")
|
298
|
+
resp[key.strip.gsub(/^ssl_/, '')] = value.to_s.strip
|
299
|
+
}
|
300
|
+
resp
|
301
|
+
end
|
302
|
+
|
134
303
|
end
|
135
304
|
end
|
136
305
|
end
|