activemerchant 1.20.4 → 1.21.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 (36) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +29 -0
  3. data/CONTRIBUTORS +13 -0
  4. data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
  5. data/lib/active_merchant/billing/gateway.rb +1 -1
  6. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +104 -18
  7. data/lib/active_merchant/billing/gateways/beanstream.rb +29 -1
  8. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +105 -3
  9. data/lib/active_merchant/billing/gateways/braintree_orange.rb +4 -0
  10. data/lib/active_merchant/billing/gateways/certo_direct.rb +279 -0
  11. data/lib/active_merchant/billing/gateways/epay.rb +2 -2
  12. data/lib/active_merchant/billing/gateways/eway_managed.rb +1 -0
  13. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +1 -0
  14. data/lib/active_merchant/billing/gateways/nab_transact.rb +244 -0
  15. data/lib/active_merchant/billing/gateways/payflow.rb +10 -2
  16. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
  17. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  18. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
  19. data/lib/active_merchant/billing/gateways/paypal_express.rb +36 -1
  20. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
  21. data/lib/active_merchant/billing/gateways/quickpay.rb +1 -0
  22. data/lib/active_merchant/billing/gateways/samurai.rb +1 -0
  23. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +136 -49
  24. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +1 -1
  25. data/lib/active_merchant/billing/gateways/stripe.rb +23 -11
  26. data/lib/active_merchant/billing/gateways/verifi.rb +2 -2
  27. data/lib/active_merchant/billing/gateways/viaklix.rb +1 -1
  28. data/lib/active_merchant/billing/integrations/action_view_helper.rb +5 -1
  29. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
  30. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
  31. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
  32. data/lib/active_merchant/billing/integrations/helper.rb +13 -1
  33. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +1 -1
  34. data/lib/active_merchant/version.rb +1 -1
  35. metadata +37 -31
  36. metadata.gz.sig +0 -0
@@ -11,6 +11,10 @@ module ActiveMerchant #:nodoc:
11
11
  def api_url
12
12
  'https://secure.braintreepaymentgateway.com/api/transact.php'
13
13
  end
14
+
15
+ def add_processor(post, options)
16
+ post[:processor_id] = options[:processor] unless options[:processor].nil?
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -0,0 +1,279 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class CertoDirectGateway < Gateway
4
+ class_attribute :gateway_url
5
+ self.gateway_url = "https://secure.certodirect.com/gateway/process/v2"
6
+
7
+ self.supported_countries = [
8
+ "BE", "BG", "CZ", "DK", "DE", "EE", "IE", "EL", "ES", "FR",
9
+ "IT", "CY", "LV", "LT", "LU", "HU", "MT", "NL", "AT", "PL",
10
+ "PT", "RO", "SI", "SK", "FI", "SE", "UK"
11
+ ]
12
+
13
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
14
+ self.homepage_url = 'http://www.certodirect.com/'
15
+ self.display_name = 'CertoDirect'
16
+
17
+ # Creates a new CertoDirectGateway
18
+ #
19
+ # The gateway requires that a valid login and password be passed
20
+ # in the +options+ hash.
21
+ #
22
+ # ==== Options
23
+ #
24
+ # * <tt>:login</tt> -- The CertoDirect Shop ID (REQUIRED)
25
+ # * <tt>:password</tt> -- The CertoDirect Shop Password. (REQUIRED)
26
+ # * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
27
+ # Otherwise, perform transactions against the production server.
28
+ def initialize(options = {})
29
+ requires!(options, :login, :password)
30
+ @options = options
31
+ super
32
+ end
33
+
34
+ # Perform a purchase, which is essentially an authorization and capture in a single operation.
35
+ #
36
+ # ==== Parameters
37
+ #
38
+ # * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
39
+ # * <tt>credit_card</tt> -- The CreditCard details for the transaction.
40
+ # * <tt>options</tt> -- A hash of optional parameters.
41
+ def purchase(money, credit_card, options = {})
42
+ requires!(options, :email, :currency, :ip, :description)
43
+
44
+ commit(build_sale_request(money, credit_card, options))
45
+ end
46
+
47
+ # Refund a transaction.
48
+ #
49
+ # This transaction indicates to the gateway that
50
+ # money should flow from the merchant to the customer.
51
+ #
52
+ # ==== Parameters
53
+ #
54
+ # * <tt>money</tt> -- The amount to be credited to the customer as an Integer value in cents.
55
+ # * <tt>identification</tt> -- The ID of the original order against which the refund is being issued.
56
+ # * <tt>options</tt> -- A hash of parameters.
57
+ def refund(money, identification, options = {})
58
+ requires!(options, :reason)
59
+
60
+ commit(build_refund_request(money, identification, options))
61
+ end
62
+
63
+ # Performs an authorization, which reserves the funds on the customer's credit card, but does not
64
+ # charge the card.
65
+ #
66
+ # ==== Parameters
67
+ #
68
+ # * <tt>money</tt> -- The amount to be authorized as an Integer value in cents.
69
+ # * <tt>credit_card</tt> -- The CreditCard details for the transaction.
70
+ # * <tt>options</tt> -- A hash of optional parameters.
71
+ def authorize(money, credit_card, options = {})
72
+ requires!(options, :email, :currency, :ip, :description)
73
+
74
+ commit(build_authorize_request(money, credit_card, options))
75
+ end
76
+
77
+ # Captures the funds from an authorized transaction.
78
+ #
79
+ # ==== Parameters
80
+ #
81
+ # * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
82
+ # * <tt>identification</tt> -- The authorization returned from the previous authorize request.
83
+ def capture(money, identification, options = {})
84
+ commit(build_capture_request(money, identification))
85
+ end
86
+
87
+ # Void a previous transaction
88
+ #
89
+ # ==== Parameters
90
+ #
91
+ # * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
92
+ # * <tt>identification</tt> - The authorization returned from the previous authorize request.
93
+ def void(money, identification, options = {})
94
+ commit(build_void_request(money, identification))
95
+ end
96
+
97
+ # Create a recurring payment.
98
+ #
99
+ # ==== Parameters
100
+ #
101
+ # * <tt>options</tt> -- A hash of parameters.
102
+ #
103
+ # ==== Options
104
+ #
105
+ def recurring(identification, options={})
106
+ commit(build_recurring_request(identification, options))
107
+ end
108
+
109
+
110
+ private
111
+
112
+ def commit(request_xml)
113
+ begin
114
+ response = Hash.from_xml(ssl_post(gateway_url, request_xml, headers))
115
+ Response.new(success?(response),
116
+ message(response),
117
+ response,
118
+ :test => test?,
119
+ :authorization => authorization(response))
120
+ rescue ResponseError => e
121
+ raise e unless e.response.code == '403'
122
+ response = Hash.from_xml(e.response.body)['response']
123
+ Response.new(false, message(response), {}, :test => test?)
124
+ end
125
+ end
126
+
127
+ def build_sale_request(money, credit_card, options)
128
+ build_request_xml('Sale') do |xml|
129
+ add_order(xml, money, credit_card, options)
130
+ end
131
+ end
132
+
133
+ def build_authorize_request(money, credit_card, options)
134
+ build_request_xml('Authorize') do |xml|
135
+ add_order(xml, money, credit_card, options)
136
+ end
137
+ end
138
+
139
+ def build_refund_request(money, identification, options)
140
+ build_request_xml('Refund') do |xml|
141
+ add_reference_info(xml, money, identification, options)
142
+ xml.tag! 'reason', options[:reason]
143
+ end
144
+ end
145
+
146
+ def build_capture_request(money, identification)
147
+ build_request_xml('Capture') do |xml|
148
+ add_reference_info(xml, money, identification, options)
149
+ end
150
+ end
151
+
152
+ def build_void_request(money, identification)
153
+ build_request_xml('Void') do |xml|
154
+ add_reference_info(xml, money, identification, options)
155
+ end
156
+ end
157
+
158
+ def build_recurring_request(identification, options)
159
+ build_request_xml('Sale') do |xml|
160
+ xml.tag! 'order' do |xml|
161
+ xml.tag!('test', 'true') if test?
162
+ xml.tag! 'initial_order_id', identification, :type => 'integer'
163
+
164
+ add_order_details(xml, options[:amount], options) if has_any_order_details_key?(options)
165
+ add_address(xml, 'billing_address', options[:billing_address]) if options[:billing_address]
166
+ add_address(xml, 'shipping_address', options[:shipping_address]) if options[:shipping_address]
167
+ end
168
+ end
169
+ end
170
+
171
+ def build_request_xml(type, &block)
172
+ xml = Builder::XmlMarkup.new(:indent => 2)
173
+ xml.tag! 'transaction' do
174
+ xml.tag! 'type', type
175
+ yield(xml)
176
+ end
177
+ xml.target!
178
+ end
179
+
180
+ def add_order(xml, money, credit_card, options)
181
+ xml.tag! 'order' do
182
+ xml.tag!('test', 'true') if test?
183
+
184
+ xml.tag!('return_url', options[:return_url]) if options[:return_url]
185
+ xml.tag!('cancel_url', options[:cancel_url]) if options[:cancel_url]
186
+
187
+ xml.tag! 'payment_method_type', 'CreditCard'
188
+ xml.tag! 'payment_method' do
189
+ xml.tag! 'number', credit_card.number
190
+ xml.tag! 'exp_month', "%02i" % credit_card.month
191
+ xml.tag! 'exp_year', credit_card.year
192
+ xml.tag! 'holder', credit_card.name
193
+ xml.tag! 'verification_value', credit_card.verification_value
194
+ end
195
+
196
+ add_order_details(xml, money, options)
197
+ add_address(xml, 'billing_address', options[:billing_address]) if options[:billing_address]
198
+ add_address(xml, 'shipping_address', options[:shipping_address]) if options[:shipping_address]
199
+ end
200
+ end
201
+
202
+ def add_order_details(xml, money, options)
203
+ xml.tag! 'details' do
204
+ xml.tag!('amount', localized_amount(money, options[:currency]), :type => 'decimal') if money
205
+ xml.tag!('currency', options[:currency]) if options[:currency]
206
+ xml.tag!('email', options[:email]) if options[:email]
207
+ xml.tag!('ip', options[:ip]) if options[:ip]
208
+ xml.tag!('shipping', options[:shipping], :type => 'decimal') if options[:shipping]
209
+ xml.tag!('description', options[:description]) if options[:description]
210
+ end
211
+ end
212
+
213
+ def add_reference_info(xml, money, identification, options)
214
+ xml.tag! 'order_id', identification, :type => 'integer'
215
+ xml.tag! 'amount', localized_amount(money, options[:currency]), :type => 'decimal'
216
+ end
217
+
218
+ def add_address(xml, address_type, address)
219
+ xml.tag! address_type do
220
+ xml.tag! 'address', address[:address1]
221
+ xml.tag! 'city', address[:city]
222
+ xml.tag! 'country', address[:country]
223
+ xml.tag! 'first_name', address[:first_name]
224
+ xml.tag! 'last_name', address[:last_name]
225
+ xml.tag! 'state', address[:state]
226
+ xml.tag! 'phone', address[:phone]
227
+ xml.tag! 'zip', address[:zip]
228
+ end
229
+ end
230
+
231
+ def has_any_order_details_key?(options)
232
+ [ :currency, :amount, :email, :ip, :shipping, :description ].any? do |key|
233
+ options.has_key?(key)
234
+ end
235
+ end
236
+
237
+ def success?(response)
238
+ %w(completed forwarding).include?(state(response)) and
239
+ status(response) == 'success'
240
+ end
241
+
242
+ def error?(response)
243
+ response['errors']
244
+ end
245
+
246
+ def state(response)
247
+ response["transaction"].try(:[], "state")
248
+ end
249
+
250
+ def status(response)
251
+ response['transaction'].try(:[], 'response').try(:[], 'status')
252
+ end
253
+
254
+ def authorization(response)
255
+ error?(response) ? nil : response["transaction"]["order"]['id'].to_s
256
+ end
257
+
258
+ def message(response)
259
+ return response['errors'].join('; ') if error?(response)
260
+
261
+ if state(response) == 'completed'
262
+ response["transaction"]["response"]["message"]
263
+ else
264
+ response['transaction']['message']
265
+ end
266
+ end
267
+
268
+ def headers
269
+ { 'authorization' => basic_auth,
270
+ 'Accept' => 'application/xml',
271
+ 'Content-Type' => 'application/xml' }
272
+ end
273
+
274
+ def basic_auth
275
+ 'Basic ' + ["#{@options[:login]}:#{@options[:password]}"].pack('m').delete("\r\n")
276
+ end
277
+ end
278
+ end
279
+ end
@@ -53,7 +53,7 @@ module ActiveMerchant #:nodoc:
53
53
  # login: merchant number
54
54
  # password: referrer url (for authorize authentication)
55
55
  def initialize(options = {})
56
- requires!(options, :login, :password)
56
+ requires!(options, :login)
57
57
  @options = options
58
58
  super
59
59
  end
@@ -181,7 +181,7 @@ module ActiveMerchant #:nodoc:
181
181
 
182
182
  def do_authorize(params)
183
183
  headers = {}
184
- headers['Referer'] = options[:password] if options[:password]
184
+ headers['Referer'] = (options[:password] || "activemerchant.org")
185
185
 
186
186
  response = raw_ssl_request(:post, 'https://' + API_HOST + '/auth/default.aspx', authorize_post_data(params), headers)
187
187
 
@@ -188,6 +188,7 @@ private
188
188
  reply[:message]=REXML::XPath.first(node, '//ewayTrxnError').text
189
189
  reply[:success]=(REXML::XPath.first(node, '//ewayTrxnStatus').text == 'True')
190
190
  reply[:auth_code]=REXML::XPath.first(node, '//ewayAuthCode').text
191
+ reply[:transaction_number]=REXML::XPath.first(node, '//ewayTrxnNumber').text
191
192
  reply
192
193
  end
193
194
 
@@ -90,6 +90,7 @@ module ActiveMerchant #:nodoc:
90
90
  if creditcard_or_card_id.is_a?(String)
91
91
  # using stored card
92
92
  post[:card_id] = creditcard_or_card_id
93
+ post[:card_exp_date] = options[:expiration_date] if options[:expiration_date]
93
94
  else
94
95
  # card info is provided
95
96
  add_creditcard(post, creditcard_or_card_id, options)
@@ -0,0 +1,244 @@
1
+ require 'rexml/document'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # The National Australia Bank provide a payment gateway that seems to
6
+ # be a rebadged Securepay Australia service, though some differences exist.
7
+ class NabTransactGateway < Gateway
8
+ API_VERSION = 'xml-4.2'
9
+ PERIODIC_API_VERSION = "spxml-4.2"
10
+
11
+ TEST_URL = 'https://transact.nab.com.au/test/xmlapi/payment'
12
+ LIVE_URL = 'https://transact.nab.com.au/live/xmlapi/payment'
13
+ TEST_PERIODIC_URL = "https://transact.nab.com.au/xmlapidemo/periodic"
14
+ LIVE_PERIODIC_URL = "https://transact.nab.com.au/xmlapi/periodic"
15
+
16
+ self.supported_countries = ['AU']
17
+
18
+ # The card types supported by the payment gateway
19
+ # Note that support for Diners, Amex, and JCB require extra
20
+ # steps in setting up your account, as detailed in the NAB Transact API
21
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
22
+
23
+ self.homepage_url = 'http://transact.nab.com.au'
24
+ self.display_name = 'NAB Transact'
25
+
26
+ cattr_accessor :request_timeout
27
+ self.request_timeout = 60
28
+
29
+ self.money_format = :cents
30
+ self.default_currency = 'AUD'
31
+
32
+ #Transactions currently accepted by NAB Transact XML API
33
+ TRANSACTIONS = {
34
+ :purchase => 0, #Standard Payment
35
+ :credit => 4, #Refund
36
+ :void => 6, #Client Reversal (Void)
37
+ :authorization => 10, #Preauthorise
38
+ :capture => 11 #Preauthorise Complete (Advice)
39
+ }
40
+
41
+ PERIODIC_TYPES = {
42
+ :addcrn => 5,
43
+ :editcrn => 5,
44
+ :deletecrn => 5,
45
+ :trigger => 8
46
+ }
47
+
48
+ SUCCESS_CODES = [ '00', '08', '11', '16', '77' ]
49
+
50
+
51
+ def initialize(options = {})
52
+ requires!(options, :login, :password)
53
+ @options = options
54
+ super
55
+ end
56
+
57
+ def test?
58
+ @options[:test] || super
59
+ end
60
+
61
+ def purchase(money, credit_card_or_stored_id, options = {})
62
+ if credit_card_or_stored_id.is_a?(ActiveMerchant::Billing::CreditCard)
63
+ #Credit card for instant payment
64
+ commit :purchase, build_purchase_request(money, credit_card_or_stored_id, options)
65
+ else
66
+ #Triggered payment for an existing stored credit card
67
+ options[:billing_id] = credit_card_or_stored_id.to_s
68
+ commit_periodic build_periodic_item(:trigger, money, nil, options)
69
+ end
70
+ end
71
+
72
+ def store(creditcard, options = {})
73
+ requires!(options, :billing_id, :amount)
74
+ commit_periodic(build_periodic_item(:addcrn, options[:amount], creditcard, options))
75
+ end
76
+
77
+ def unstore(identification, options = {})
78
+ options[:billing_id] = identification
79
+ commit_periodic(build_periodic_item(:deletecrn, options[:amount], nil, options))
80
+ end
81
+
82
+ private
83
+
84
+ def build_purchase_request(money, credit_card, options)
85
+ xml = Builder::XmlMarkup.new
86
+ xml.tag! 'amount', amount(money)
87
+ xml.tag! 'currency', options[:currency] || currency(money)
88
+ xml.tag! 'purchaseOrderNo', options[:order_id].to_s.gsub(/[ ']/, '')
89
+
90
+ xml.tag! 'CreditCardInfo' do
91
+ xml.tag! 'cardNumber', credit_card.number
92
+ xml.tag! 'expiryDate', expdate(credit_card)
93
+ xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value?
94
+ end
95
+
96
+ xml.target!
97
+ end
98
+
99
+ #Generate payment request XML
100
+ # - API is set to allow multiple Txn's but currentlu only allows one
101
+ # - txnSource = 23 - (XML)
102
+
103
+ def build_request(action, body)
104
+ xml = Builder::XmlMarkup.new
105
+ xml.instruct!
106
+ xml.tag! 'NABTransactMessage' do
107
+ xml.tag! 'MessageInfo' do
108
+ xml.tag! 'messageID', Utils.generate_unique_id.slice(0, 30)
109
+ xml.tag! 'messageTimestamp', generate_timestamp
110
+ xml.tag! 'timeoutValue', request_timeout
111
+ xml.tag! 'apiVersion', API_VERSION
112
+ end
113
+
114
+ xml.tag! 'MerchantInfo' do
115
+ xml.tag! 'merchantID', @options[:login]
116
+ xml.tag! 'password', @options[:password]
117
+ end
118
+
119
+ xml.tag! 'RequestType', 'Payment'
120
+ xml.tag! 'Payment' do
121
+ xml.tag! 'TxnList', "count" => 1 do
122
+ xml.tag! 'Txn', "ID" => 1 do
123
+ xml.tag! 'txnType', TRANSACTIONS[action]
124
+ xml.tag! 'txnSource', 23
125
+ xml << body
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ xml.target!
132
+ end
133
+
134
+ def build_periodic_item(action, money, credit_card, options)
135
+ xml = Builder::XmlMarkup.new
136
+
137
+ xml.tag! 'actionType', action.to_s
138
+ xml.tag! 'periodicType', PERIODIC_TYPES[action] if PERIODIC_TYPES[action]
139
+ xml.tag! 'currency', options[:currency] || currency(money)
140
+ xml.tag! 'crn', options[:billing_id]
141
+
142
+ if credit_card
143
+ xml.tag! 'CreditCardInfo' do
144
+ xml.tag! 'cardNumber', credit_card.number
145
+ xml.tag! 'expiryDate', expdate(credit_card)
146
+ xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value?
147
+ end
148
+ end
149
+ xml.tag! 'amount', amount(money)
150
+
151
+ xml.target!
152
+ end
153
+
154
+ def build_periodic_request(body)
155
+ xml = Builder::XmlMarkup.new
156
+ xml.instruct!
157
+ xml.tag! 'NABTransactMessage' do
158
+ xml.tag! 'MessageInfo' do
159
+ xml.tag! 'messageID', ActiveMerchant::Utils.generate_unique_id.slice(0, 30)
160
+ xml.tag! 'messageTimestamp', generate_timestamp
161
+ xml.tag! 'timeoutValue', request_timeout
162
+ xml.tag! 'apiVersion', PERIODIC_API_VERSION
163
+ end
164
+
165
+ xml.tag! 'MerchantInfo' do
166
+ xml.tag! 'merchantID', @options[:login]
167
+ xml.tag! 'password', @options[:password]
168
+ end
169
+
170
+ xml.tag! 'RequestType', 'Periodic'
171
+ xml.tag! 'Periodic' do
172
+ xml.tag! 'PeriodicList', "count" => 1 do
173
+ xml.tag! 'PeriodicItem', "ID" => 1 do
174
+ xml << body
175
+ end
176
+ end
177
+ end
178
+ end
179
+
180
+ xml.target!
181
+ end
182
+
183
+ def commit(action, request)
184
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, build_request(action, request)))
185
+
186
+ Response.new(success?(response), message_from(response), response,
187
+ :test => test?,
188
+ :authorization => authorization_from(response)
189
+ )
190
+ end
191
+
192
+ def commit_periodic(request)
193
+ response = parse(ssl_post(test? ? TEST_PERIODIC_URL : LIVE_PERIODIC_URL, build_periodic_request(request)))
194
+ Response.new(success?(response), message_from(response), response,
195
+ :test => test?,
196
+ :authorization => authorization_from(response)
197
+ )
198
+ end
199
+
200
+ def success?(response)
201
+ SUCCESS_CODES.include?(response[:response_code])
202
+ end
203
+
204
+ def authorization_from(response)
205
+ response[:txn_id]
206
+ end
207
+
208
+ def message_from(response)
209
+ response[:response_text] || response[:status_description]
210
+ end
211
+
212
+ def expdate(credit_card)
213
+ "#{format(credit_card.month, :two_digits)}/#{format(credit_card.year, :two_digits)}"
214
+ end
215
+
216
+ def parse(body)
217
+ xml = REXML::Document.new(body)
218
+
219
+ response = {}
220
+
221
+ xml.root.elements.to_a.each do |node|
222
+ parse_element(response, node)
223
+ end
224
+
225
+ response
226
+ end
227
+
228
+ def parse_element(response, node)
229
+ if node.has_elements?
230
+ node.elements.each{|element| parse_element(response, element) }
231
+ else
232
+ response[node.name.underscore.to_sym] = node.text
233
+ end
234
+ end
235
+
236
+ # YYYYDDMMHHNNSSKKK000sOOO
237
+ def generate_timestamp
238
+ time = Time.now.utc
239
+ time.strftime("%Y%d%m%H%M%S#{time.usec}+000")
240
+ end
241
+
242
+ end
243
+ end
244
+ end