activemerchant 1.15.0 → 1.16.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 +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
|
+
|