activemerchant 1.15.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +21 -0
  3. data/CONTRIBUTORS +13 -1
  4. data/lib/active_merchant.rb +2 -5
  5. data/lib/active_merchant/billing/avs_result.rb +2 -2
  6. data/lib/active_merchant/billing/credit_card.rb +6 -0
  7. data/lib/active_merchant/billing/gateways/authorize_net.rb +1 -1
  8. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +1 -2
  9. data/lib/active_merchant/billing/gateways/bogus.rb +34 -24
  10. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +1 -1
  11. data/lib/active_merchant/billing/gateways/cyber_source.rb +20 -0
  12. data/lib/active_merchant/billing/gateways/moneris.rb +1 -1
  13. data/lib/active_merchant/billing/gateways/orbital.rb +6 -2
  14. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  15. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  16. data/lib/active_merchant/billing/gateways/qbms.rb +1 -3
  17. data/lib/active_merchant/billing/gateways/quickpay.rb +56 -51
  18. data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
  19. data/lib/active_merchant/billing/gateways/worldpay.rb +1 -1
  20. data/lib/active_merchant/billing/integrations/action_view_helper.rb +2 -2
  21. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  22. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  23. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  24. data/lib/active_merchant/billing/integrations/helper.rb +3 -3
  25. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +11 -0
  26. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +16 -7
  27. data/lib/active_merchant/billing/integrations/world_pay.rb +4 -15
  28. data/lib/active_merchant/version.rb +1 -1
  29. metadata +46 -21
  30. metadata.gz.sig +0 -0
  31. 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)
@@ -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 P W Z ),
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, creditcard, options = {})
21
+ def authorize(money, credit_card_or_reference, options = {})
22
22
  money = amount(money)
23
- case creditcard.number
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, creditcard, options = {})
33
+ def purchase(money, credit_card_or_reference, options = {})
34
34
  money = amount(money)
35
- case creditcard.number
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, creditcard, options = {})
45
+ def recurring(money, credit_card_or_reference, options = {})
46
46
  money = amount(money)
47
- case creditcard.number
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, creditcard, options = {})
58
- if creditcard.is_a?(String)
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, creditcard, options)
60
+ return refund(money, credit_card_or_reference, options)
61
61
  end
62
62
 
63
63
  money = amount(money)
64
- case creditcard.number
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, ident, options = {})
74
+ def refund(money, reference, options = {})
75
75
  money = amount(money)
76
- case ident
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, ident, options = {})
86
+ def capture(money, reference, options = {})
87
87
  money = amount(money)
88
- case ident
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(ident, options = {})
99
- case ident
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 => ident, :error => FAILURE_MESSAGE }, :test => true)
103
+ Response.new(false, FAILURE_MESSAGE, {:authorization => reference, :error => FAILURE_MESSAGE }, :test => true)
104
104
  else
105
- Response.new(true, SUCCESS_MESSAGE, {:authorization => ident}, :test => true)
105
+ Response.new(true, SUCCESS_MESSAGE, {:authorization => reference}, :test => true)
106
106
  end
107
107
  end
108
108
 
109
- def store(creditcard, options = {})
110
- case creditcard.number
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(identification, options = {})
121
- case identification
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, creditcard.expiry_date.expiration.strftime("%m%y")
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://www.paymentexpress.com/pxpost.aspx'
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
+