activemerchant 1.15.0 → 1.16.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +21 -0
- data/CONTRIBUTORS +13 -1
- data/lib/active_merchant.rb +2 -5
- data/lib/active_merchant/billing/avs_result.rb +2 -2
- data/lib/active_merchant/billing/credit_card.rb +6 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +1 -1
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +1 -2
- data/lib/active_merchant/billing/gateways/bogus.rb +34 -24
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +1 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +20 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +1 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +6 -2
- data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
- data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +1 -3
- data/lib/active_merchant/billing/gateways/quickpay.rb +56 -51
- data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +1 -1
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +2 -2
- data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
- data/lib/active_merchant/billing/integrations/helper.rb +3 -3
- data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +11 -0
- data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +16 -7
- data/lib/active_merchant/billing/integrations/world_pay.rb +4 -15
- data/lib/active_merchant/version.rb +1 -1
- metadata +46 -21
- metadata.gz.sig +0 -0
- data/README.rdoc +0 -164
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG
CHANGED
@@ -1,6 +1,27 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
|
+
== Version 1.16.0 (May 12, 2011)
|
4
|
+
|
5
|
+
* Bogus: Support referenced transactions for #authorize, #purchase, #recurring and
|
6
|
+
#credit [dasch/jduff]
|
7
|
+
* Payment Express: Update gateway url [bayan/titanous]
|
8
|
+
* Moneybookers: Send country and account_name if provided [Soleone]
|
9
|
+
* Moneris: Add Diners Club and Discover [Soleone]
|
10
|
+
* Cybersource: add auth_reversal support [jeberly/titanous]
|
11
|
+
* WorldPay: Update endpoint URLs for offsite gateway [Soleone]
|
12
|
+
* Worldpay: Add JCB and add Maestro [Soleone]
|
13
|
+
* Authorize.net: Add Diners Club and JCB [Soleone]
|
14
|
+
* Quickpay: Add testmode for subscribe and authorize [dasch/jduff]
|
15
|
+
* Orbital: fix handling of phone numbers. [ntalbott]
|
16
|
+
* Braintree: Add Diners Club [cody]
|
17
|
+
* Add ePaymentPlans offsite payment [robertomiranda/Soleone]
|
18
|
+
* Add Stripe gateway [boucher/titanous]
|
19
|
+
* Add Paystation gateway [nikz/jduff]
|
20
|
+
* Bump minimum ActiveSupport version to 2.3.11 [titanous]
|
21
|
+
* Use securerandom from stdlib not active_support [phlipper/jduff]
|
22
|
+
|
3
23
|
== Version 1.15.0 (May 12, 2011)
|
24
|
+
|
4
25
|
* DirecPay: Fix address to not include address2 twice in some cases [Soleone]
|
5
26
|
* DirecPay: Send company if available [Soleone]
|
6
27
|
* Realex: Fix hash signature [ntalbott/Soleone]
|
data/CONTRIBUTORS
CHANGED
@@ -230,4 +230,16 @@ Orbital Paymentech Gateway (July, 2009)
|
|
230
230
|
|
231
231
|
DIRECTebanking - Payment Network AG (May, 2011)
|
232
232
|
|
233
|
-
* Gerwin Brunner (Vilango)
|
233
|
+
* Gerwin Brunner (Vilango)
|
234
|
+
|
235
|
+
Stripe
|
236
|
+
|
237
|
+
* Ross Boucher (boucher)
|
238
|
+
|
239
|
+
Paystation (July, 2011)
|
240
|
+
|
241
|
+
* Nik Wakelin (nikz)
|
242
|
+
|
243
|
+
ePaymentPlans offsite gatway (June, 2011)
|
244
|
+
|
245
|
+
* Roberto Miranda (robertomiranda)
|
data/lib/active_merchant.rb
CHANGED
@@ -20,8 +20,6 @@
|
|
20
20
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
|
-
|
24
|
-
$:.unshift File.dirname(__FILE__)
|
25
23
|
|
26
24
|
require 'active_support'
|
27
25
|
require 'active_support/core_ext/string/inflections'
|
@@ -31,10 +29,9 @@ require 'active_support/core_ext/class/attribute'
|
|
31
29
|
require 'active_support/core_ext/class/attribute_accessors'
|
32
30
|
require 'active_support/core_ext/class/delegating_attributes'
|
33
31
|
require 'active_support/core_ext/module/attribute_accessors'
|
34
|
-
require 'active_support/core_ext/kernel/requires'
|
35
32
|
require 'active_support/base64'
|
36
|
-
require 'active_support/secure_random'
|
37
33
|
|
34
|
+
require 'securerandom'
|
38
35
|
require 'builder'
|
39
36
|
require 'cgi'
|
40
37
|
require 'rexml/document'
|
@@ -44,7 +41,7 @@ require 'active_merchant/billing'
|
|
44
41
|
require 'active_merchant/version'
|
45
42
|
|
46
43
|
module ActiveMerchant #:nodoc:
|
47
|
-
module Billing #:nodoc:
|
44
|
+
module Billing #:nodoc:
|
48
45
|
autoload :Integrations, 'active_merchant/billing/integrations'
|
49
46
|
end
|
50
47
|
end
|
@@ -53,9 +53,9 @@ module ActiveMerchant
|
|
53
53
|
# Map vendor's AVS result code to a street match code
|
54
54
|
STREET_MATCH_CODE = {
|
55
55
|
'Y' => %w( A B D H J M O Q T V X Y ),
|
56
|
-
'N' => %w( C K L N
|
56
|
+
'N' => %w( C K L N W Z ),
|
57
57
|
'X' => %w( G S ),
|
58
|
-
nil => %w( E F I R U )
|
58
|
+
nil => %w( E F I P R U )
|
59
59
|
}.inject({}) do |map, (type, codes)|
|
60
60
|
codes.each { |code| map[code] = type }
|
61
61
|
map
|
@@ -80,6 +80,12 @@ module ActiveMerchant #:nodoc:
|
|
80
80
|
[@first_name, @last_name].compact.join(' ')
|
81
81
|
end
|
82
82
|
|
83
|
+
def name=(full_name)
|
84
|
+
names = full_name.split
|
85
|
+
self.last_name = names.pop
|
86
|
+
self.first_name = names.join(" ")
|
87
|
+
end
|
88
|
+
|
83
89
|
def verification_value?
|
84
90
|
!@verification_value.blank?
|
85
91
|
end
|
@@ -42,7 +42,7 @@ module ActiveMerchant #:nodoc:
|
|
42
42
|
AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE = 5, 6, 38
|
43
43
|
|
44
44
|
self.supported_countries = ['US']
|
45
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
45
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
46
46
|
self.homepage_url = 'http://www.authorize.net/'
|
47
47
|
self.display_name = 'Authorize.Net'
|
48
48
|
|
@@ -153,8 +153,7 @@ module ActiveMerchant #:nodoc:
|
|
153
153
|
{
|
154
154
|
:success => success,
|
155
155
|
:message => message,
|
156
|
-
:authorization =>
|
157
|
-
[find(doc, "//OrderFormDoc/Id"), find(doc, "//Transaction/Id")].join(":"),
|
156
|
+
:authorization => find(doc, "//Transaction/Id"),
|
158
157
|
:avs_result => find(doc, "//Transaction/AvsRespCode"),
|
159
158
|
:cvv_result => find(doc, "//Transaction/Cvv2Resp"),
|
160
159
|
:order_id => find(doc, "//OrderFormDoc/Transaction/Id"),
|
@@ -18,9 +18,9 @@ module ActiveMerchant #:nodoc:
|
|
18
18
|
self.homepage_url = 'http://example.com'
|
19
19
|
self.display_name = 'Bogus'
|
20
20
|
|
21
|
-
def authorize(money,
|
21
|
+
def authorize(money, credit_card_or_reference, options = {})
|
22
22
|
money = amount(money)
|
23
|
-
case
|
23
|
+
case normalize(credit_card_or_reference)
|
24
24
|
when '1'
|
25
25
|
Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION )
|
26
26
|
when '2'
|
@@ -30,10 +30,10 @@ module ActiveMerchant #:nodoc:
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def purchase(money,
|
33
|
+
def purchase(money, credit_card_or_reference, options = {})
|
34
34
|
money = amount(money)
|
35
|
-
case
|
36
|
-
when '1'
|
35
|
+
case normalize(credit_card_or_reference)
|
36
|
+
when '1', AUTHORIZATION
|
37
37
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
38
38
|
when '2'
|
39
39
|
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
|
@@ -42,9 +42,9 @@ module ActiveMerchant #:nodoc:
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
def recurring(money,
|
45
|
+
def recurring(money, credit_card_or_reference, options = {})
|
46
46
|
money = amount(money)
|
47
|
-
case
|
47
|
+
case normalize(credit_card_or_reference)
|
48
48
|
when '1'
|
49
49
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
50
50
|
when '2'
|
@@ -54,14 +54,14 @@ module ActiveMerchant #:nodoc:
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
def credit(money,
|
58
|
-
if
|
57
|
+
def credit(money, credit_card_or_reference, options = {})
|
58
|
+
if credit_card_or_reference.is_a?(String)
|
59
59
|
deprecated CREDIT_DEPRECATION_MESSAGE
|
60
|
-
return refund(money,
|
60
|
+
return refund(money, credit_card_or_reference, options)
|
61
61
|
end
|
62
62
|
|
63
63
|
money = amount(money)
|
64
|
-
case
|
64
|
+
case normalize(credit_card_or_reference)
|
65
65
|
when '1'
|
66
66
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true )
|
67
67
|
when '2'
|
@@ -71,9 +71,9 @@ module ActiveMerchant #:nodoc:
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
def refund(money,
|
74
|
+
def refund(money, reference, options = {})
|
75
75
|
money = amount(money)
|
76
|
-
case
|
76
|
+
case reference
|
77
77
|
when '1'
|
78
78
|
raise Error, REFUND_ERROR_MESSAGE
|
79
79
|
when '2'
|
@@ -83,9 +83,9 @@ module ActiveMerchant #:nodoc:
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
def capture(money,
|
86
|
+
def capture(money, reference, options = {})
|
87
87
|
money = amount(money)
|
88
|
-
case
|
88
|
+
case reference
|
89
89
|
when '1'
|
90
90
|
raise Error, CAPTURE_ERROR_MESSAGE
|
91
91
|
when '2'
|
@@ -95,21 +95,21 @@ module ActiveMerchant #:nodoc:
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
def void(
|
99
|
-
case
|
98
|
+
def void(reference, options = {})
|
99
|
+
case reference
|
100
100
|
when '1'
|
101
101
|
raise Error, VOID_ERROR_MESSAGE
|
102
102
|
when '2'
|
103
|
-
Response.new(false, FAILURE_MESSAGE, {:authorization =>
|
103
|
+
Response.new(false, FAILURE_MESSAGE, {:authorization => reference, :error => FAILURE_MESSAGE }, :test => true)
|
104
104
|
else
|
105
|
-
Response.new(true, SUCCESS_MESSAGE, {:authorization =>
|
105
|
+
Response.new(true, SUCCESS_MESSAGE, {:authorization => reference}, :test => true)
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
def store(
|
110
|
-
case
|
109
|
+
def store(credit_card_or_reference, options = {})
|
110
|
+
case normalize(credit_card_or_reference)
|
111
111
|
when '1'
|
112
|
-
Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION
|
112
|
+
Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION)
|
113
113
|
when '2'
|
114
114
|
Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true)
|
115
115
|
else
|
@@ -117,8 +117,8 @@ module ActiveMerchant #:nodoc:
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
def unstore(
|
121
|
-
case
|
120
|
+
def unstore(reference, options = {})
|
121
|
+
case reference
|
122
122
|
when '1'
|
123
123
|
Response.new(true, SUCCESS_MESSAGE, {}, :test => true)
|
124
124
|
when '2'
|
@@ -127,6 +127,16 @@ module ActiveMerchant #:nodoc:
|
|
127
127
|
raise Error, UNSTORE_ERROR_MESSAGE
|
128
128
|
end
|
129
129
|
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def normalize(credit_card_or_reference)
|
134
|
+
if credit_card_or_reference.respond_to?(:number)
|
135
|
+
credit_card_or_reference.number
|
136
|
+
else
|
137
|
+
credit_card_or_reference.to_s
|
138
|
+
end
|
139
|
+
end
|
130
140
|
end
|
131
141
|
end
|
132
142
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module BraintreeCommon
|
2
2
|
def self.included(base)
|
3
3
|
base.supported_countries = ['US']
|
4
|
-
base.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb]
|
4
|
+
base.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
|
5
5
|
base.homepage_url = 'http://www.braintreepaymentsolutions.com'
|
6
6
|
base.display_name = 'Braintree'
|
7
7
|
base.default_currency = 'USD'
|
@@ -109,6 +109,10 @@ module ActiveMerchant #:nodoc:
|
|
109
109
|
setup_address_hash(options)
|
110
110
|
commit(build_auth_request(money, creditcard, options), options )
|
111
111
|
end
|
112
|
+
|
113
|
+
def auth_reversal(money, identification, options = {})
|
114
|
+
commit(build_auth_reversal_request(money, identification, options), options)
|
115
|
+
end
|
112
116
|
|
113
117
|
# Capture an authorization that has previously been requested
|
114
118
|
def capture(money, authorization, options = {})
|
@@ -225,6 +229,15 @@ module ActiveMerchant #:nodoc:
|
|
225
229
|
xml.target!
|
226
230
|
end
|
227
231
|
|
232
|
+
def build_auth_reversal_request(money, identification, options)
|
233
|
+
order_id, request_id, request_token = identification.split(";")
|
234
|
+
options[:order_id] = order_id
|
235
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
236
|
+
add_purchase_data(xml, money, true, options)
|
237
|
+
add_auth_reversal_service(xml, request_id, request_token)
|
238
|
+
xml.target!
|
239
|
+
end
|
240
|
+
|
228
241
|
def build_credit_request(money, identification, options)
|
229
242
|
order_id, request_id, request_token = identification.split(";")
|
230
243
|
options[:order_id] = order_id
|
@@ -324,6 +337,13 @@ module ActiveMerchant #:nodoc:
|
|
324
337
|
end
|
325
338
|
end
|
326
339
|
|
340
|
+
def add_auth_reversal_service(xml, request_id, request_token)
|
341
|
+
xml.tag! 'ccAuthReversalService', {'run' => 'true'} do
|
342
|
+
xml.tag! 'authRequestID', request_id
|
343
|
+
xml.tag! 'authRequestToken', request_token
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
327
347
|
def add_credit_service(xml, request_id, request_token)
|
328
348
|
xml.tag! 'ccCreditService', {'run' => 'true'} do
|
329
349
|
xml.tag! 'captureRequestID', request_id
|
@@ -14,7 +14,7 @@ module ActiveMerchant #:nodoc:
|
|
14
14
|
LIVE_URL = 'https://www3.moneris.com/gateway2/servlet/MpgRequest'
|
15
15
|
|
16
16
|
self.supported_countries = ['CA']
|
17
|
-
self.supported_cardtypes = [:visa, :master, :american_express]
|
17
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover]
|
18
18
|
self.homepage_url = 'http://www.moneris.com/'
|
19
19
|
self.display_name = 'Moneris'
|
20
20
|
|
@@ -154,7 +154,7 @@ module ActiveMerchant #:nodoc:
|
|
154
154
|
xml.tag! :AVSaddress2, address[:address2]
|
155
155
|
xml.tag! :AVScity, address[:city]
|
156
156
|
xml.tag! :AVSstate, address[:state]
|
157
|
-
xml.tag! :AVSphoneNum, address[:phone] ? address[:phone].scan(/\d/).to_s : nil
|
157
|
+
xml.tag! :AVSphoneNum, address[:phone] ? address[:phone].scan(/\d/).join.to_s : nil
|
158
158
|
xml.tag! :AVSname, creditcard.name
|
159
159
|
xml.tag! :AVScountryCode, address[:country]
|
160
160
|
end
|
@@ -162,7 +162,7 @@ module ActiveMerchant #:nodoc:
|
|
162
162
|
|
163
163
|
def add_creditcard(xml, creditcard, currency=nil)
|
164
164
|
xml.tag! :AccountNum, creditcard.number
|
165
|
-
xml.tag! :Exp,
|
165
|
+
xml.tag! :Exp, expiry_date(creditcard)
|
166
166
|
|
167
167
|
xml.tag! :CurrencyCode, currency_code(currency)
|
168
168
|
xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen.
|
@@ -312,6 +312,10 @@ module ActiveMerchant #:nodoc:
|
|
312
312
|
def currency_code(currency)
|
313
313
|
CURRENCY_CODES[(currency || self.default_currency)].to_s
|
314
314
|
end
|
315
|
+
|
316
|
+
def expiry_date(credit_card)
|
317
|
+
"#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
|
318
|
+
end
|
315
319
|
end
|
316
320
|
end
|
317
321
|
end
|
@@ -21,7 +21,7 @@ module ActiveMerchant #:nodoc:
|
|
21
21
|
self.homepage_url = 'http://www.paymentexpress.com/'
|
22
22
|
self.display_name = 'PaymentExpress'
|
23
23
|
|
24
|
-
URL = 'https://
|
24
|
+
URL = 'https://sec.paymentexpress.com/pxpost.aspx'
|
25
25
|
|
26
26
|
APPROVED = '1'
|
27
27
|
|
@@ -0,0 +1,201 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class PaystationGateway < Gateway
|
4
|
+
|
5
|
+
URL = "https://www.paystation.co.nz/direct/paystation.dll"
|
6
|
+
|
7
|
+
# an "error code" of "0" means "No error - transaction successful"
|
8
|
+
SUCCESSFUL_RESPONSE_CODE = '0'
|
9
|
+
|
10
|
+
# an "error code" of "34" means "Future Payment Stored OK"
|
11
|
+
SUCCESSFUL_FUTURE_PAYMENT = '34'
|
12
|
+
|
13
|
+
# TODO: check this with paystation
|
14
|
+
self.supported_countries = ['NZ']
|
15
|
+
|
16
|
+
# TODO: check this with paystation (amex and diners need to be enabled)
|
17
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club ]
|
18
|
+
|
19
|
+
self.homepage_url = 'http://paystation.co.nz'
|
20
|
+
self.display_name = 'Paystation'
|
21
|
+
|
22
|
+
self.default_currency = 'NZD'
|
23
|
+
self.money_format = :cents
|
24
|
+
|
25
|
+
def initialize(options = {})
|
26
|
+
# You need to pass your Paystation ID and Gateway ID
|
27
|
+
requires!(options, :paystation_id, :gateway_id)
|
28
|
+
@options = options
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def authorize(money, credit_card, options = {})
|
33
|
+
post = new_request
|
34
|
+
|
35
|
+
add_invoice(post, options)
|
36
|
+
add_amount(post, money, options)
|
37
|
+
|
38
|
+
add_credit_card(post, credit_card)
|
39
|
+
|
40
|
+
add_authorize_flag(post, options)
|
41
|
+
|
42
|
+
commit(post)
|
43
|
+
end
|
44
|
+
|
45
|
+
def capture(money, authorization_token, options = {})
|
46
|
+
post = new_request
|
47
|
+
|
48
|
+
add_invoice(post, options)
|
49
|
+
add_amount(post, money, options)
|
50
|
+
|
51
|
+
add_authorization_token(post, authorization_token, options[:credit_card_verification])
|
52
|
+
|
53
|
+
commit(post)
|
54
|
+
end
|
55
|
+
|
56
|
+
def purchase(money, payment_source, options = {})
|
57
|
+
post = new_request
|
58
|
+
|
59
|
+
add_invoice(post, options)
|
60
|
+
add_amount(post, money, options)
|
61
|
+
|
62
|
+
if payment_source.is_a?(String)
|
63
|
+
add_token(post, payment_source)
|
64
|
+
else
|
65
|
+
add_credit_card(post, payment_source)
|
66
|
+
end
|
67
|
+
|
68
|
+
add_customer_data(post, options) if options.has_key?(:customer)
|
69
|
+
|
70
|
+
commit(post)
|
71
|
+
end
|
72
|
+
|
73
|
+
def store(credit_card, options = {})
|
74
|
+
post = new_request
|
75
|
+
|
76
|
+
add_invoice(post, options)
|
77
|
+
add_credit_card(post, credit_card)
|
78
|
+
store_credit_card(post, options)
|
79
|
+
|
80
|
+
commit(post)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def new_request
|
86
|
+
{
|
87
|
+
:pi => @options[:paystation_id], # paystation account id
|
88
|
+
:gi => @options[:gateway_id], # paystation gateway id
|
89
|
+
"2p" => "t", # two-party transaction type
|
90
|
+
:nr => "t", # -- redirect??
|
91
|
+
:df => "yymm" # date format: optional sometimes, required others
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def add_customer_data(post, options)
|
96
|
+
post[:mc] = options[:customer]
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_invoice(post, options)
|
100
|
+
requires!(options, :order_id)
|
101
|
+
|
102
|
+
post[:ms] = options[:order_id] # "Merchant Session", must be unique per request
|
103
|
+
post[:mo] = options[:invoice] # "Order Details", displayed in Paystation Admin
|
104
|
+
post[:mr] = options[:description] # "Merchant Reference Code", seen from Paystation Admin
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_credit_card(post, credit_card)
|
108
|
+
|
109
|
+
post[:cn] = credit_card.number
|
110
|
+
post[:ct] = credit_card.type
|
111
|
+
post[:ex] = format_date(credit_card.month, credit_card.year)
|
112
|
+
post[:cc] = credit_card.verification_value if credit_card.verification_value?
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
# bill a token (stored via "store") rather than a Credit Card
|
117
|
+
def add_token(post, token)
|
118
|
+
post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
|
119
|
+
post[:ft] = token
|
120
|
+
end
|
121
|
+
|
122
|
+
def store_credit_card(post, options)
|
123
|
+
|
124
|
+
post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
|
125
|
+
post[:fs] = "t" # tells paystation to store right now, not bill
|
126
|
+
post[:ft] = options[:token] if options[:token] # specify a token to use that, or let Paystation generate one
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
def add_authorize_flag(post, options)
|
131
|
+
post[:pa] = "t" # tells Paystation that this is a pre-auth authorisation payment (account must be in pre-auth mode)
|
132
|
+
end
|
133
|
+
|
134
|
+
def add_authorization_token(post, auth_token, verification_value = nil)
|
135
|
+
post[:cp] = "t" # Capture Payment flag – tells Paystation this transaction should be treated as a capture payment
|
136
|
+
post[:cx] = auth_token
|
137
|
+
post[:cc] = verification_value
|
138
|
+
end
|
139
|
+
|
140
|
+
def add_amount(post, money, options)
|
141
|
+
|
142
|
+
post[:am] = amount(money)
|
143
|
+
post[:cu] = options[:currency] || currency(money)
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
def parse(xml_response)
|
148
|
+
response = {}
|
149
|
+
|
150
|
+
xml = REXML::Document.new(xml_response)
|
151
|
+
|
152
|
+
# for normal payments, the root node is <Response>
|
153
|
+
# for "future payments", it's <PaystationFuturePaymentResponse>
|
154
|
+
xml.elements.each("#{xml.root.name}/*") do |element|
|
155
|
+
response[element.name.underscore.to_sym] = element.text
|
156
|
+
end
|
157
|
+
|
158
|
+
response
|
159
|
+
end
|
160
|
+
|
161
|
+
def commit(post)
|
162
|
+
|
163
|
+
post[:tm] = "T" if test? # test mode
|
164
|
+
|
165
|
+
pstn_prefix_params = post.collect { |key, value| "pstn_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
166
|
+
|
167
|
+
# need include paystation param as "initiator flag for payment engine"
|
168
|
+
data = ssl_post(URL, "#{pstn_prefix_params}&paystation=_empty")
|
169
|
+
response = parse(data)
|
170
|
+
message = message_from(response)
|
171
|
+
|
172
|
+
PaystationResponse.new(success?(response), message, response,
|
173
|
+
:test => (response[:tm] && response[:tm].downcase == "t"),
|
174
|
+
:authorization => response[:paystation_transaction_id]
|
175
|
+
)
|
176
|
+
end
|
177
|
+
|
178
|
+
def success?(response)
|
179
|
+
(response[:ec] == SUCCESSFUL_RESPONSE_CODE) || (response[:ec] == SUCCESSFUL_FUTURE_PAYMENT)
|
180
|
+
end
|
181
|
+
|
182
|
+
def message_from(response)
|
183
|
+
response[:em]
|
184
|
+
end
|
185
|
+
|
186
|
+
def format_date(month, year)
|
187
|
+
"#{format(year, :two_digits)}#{format(month, :two_digits)}"
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
class PaystationResponse < Response
|
193
|
+
# add a method to response so we can easily get the token
|
194
|
+
# for Validate transactions
|
195
|
+
def token
|
196
|
+
@params["future_payment_token"]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|