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.
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
+