koffsite_payments 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +13 -0
  4. data/lib/offsite_payments.rb +48 -0
  5. data/lib/offsite_payments/action_view_helper.rb +72 -0
  6. data/lib/offsite_payments/helper.rb +119 -0
  7. data/lib/offsite_payments/integrations.rb +14 -0
  8. data/lib/offsite_payments/integrations/a1agregator.rb +245 -0
  9. data/lib/offsite_payments/integrations/authorize_net_sim.rb +580 -0
  10. data/lib/offsite_payments/integrations/bit_pay.rb +150 -0
  11. data/lib/offsite_payments/integrations/bogus.rb +32 -0
  12. data/lib/offsite_payments/integrations/chronopay.rb +283 -0
  13. data/lib/offsite_payments/integrations/citrus.rb +227 -0
  14. data/lib/offsite_payments/integrations/coinbase.rb +166 -0
  15. data/lib/offsite_payments/integrations/direc_pay.rb +339 -0
  16. data/lib/offsite_payments/integrations/directebanking.rb +237 -0
  17. data/lib/offsite_payments/integrations/doku.rb +171 -0
  18. data/lib/offsite_payments/integrations/dotpay.rb +166 -0
  19. data/lib/offsite_payments/integrations/dwolla.rb +160 -0
  20. data/lib/offsite_payments/integrations/e_payment_plans.rb +146 -0
  21. data/lib/offsite_payments/integrations/easy_pay.rb +137 -0
  22. data/lib/offsite_payments/integrations/epay.rb +161 -0
  23. data/lib/offsite_payments/integrations/first_data.rb +133 -0
  24. data/lib/offsite_payments/integrations/gestpay.rb +203 -0
  25. data/lib/offsite_payments/integrations/hi_trust.rb +179 -0
  26. data/lib/offsite_payments/integrations/ipay88.rb +251 -0
  27. data/lib/offsite_payments/integrations/klarna.rb +291 -0
  28. data/lib/offsite_payments/integrations/liqpay.rb +216 -0
  29. data/lib/offsite_payments/integrations/maksuturva.rb +231 -0
  30. data/lib/offsite_payments/integrations/mollie_ideal.rb +216 -0
  31. data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
  32. data/lib/offsite_payments/integrations/nochex.rb +228 -0
  33. data/lib/offsite_payments/integrations/pag_seguro.rb +268 -0
  34. data/lib/offsite_payments/integrations/paxum.rb +114 -0
  35. data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
  36. data/lib/offsite_payments/integrations/pay_u_latam.rb +246 -0
  37. data/lib/offsite_payments/integrations/paydollar.rb +142 -0
  38. data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
  39. data/lib/offsite_payments/integrations/paypal.rb +362 -0
  40. data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
  41. data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
  42. data/lib/offsite_payments/integrations/payu_in.rb +266 -0
  43. data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
  44. data/lib/offsite_payments/integrations/platron.rb +153 -0
  45. data/lib/offsite_payments/integrations/pxpay.rb +273 -0
  46. data/lib/offsite_payments/integrations/quickpay.rb +232 -0
  47. data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
  48. data/lib/offsite_payments/integrations/robokassa.rb +154 -0
  49. data/lib/offsite_payments/integrations/sage_pay_form.rb +425 -0
  50. data/lib/offsite_payments/integrations/two_checkout.rb +329 -0
  51. data/lib/offsite_payments/integrations/universal.rb +181 -0
  52. data/lib/offsite_payments/integrations/valitor.rb +200 -0
  53. data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
  54. data/lib/offsite_payments/integrations/web_pay.rb +186 -0
  55. data/lib/offsite_payments/integrations/webmoney.rb +119 -0
  56. data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
  57. data/lib/offsite_payments/integrations/world_pay.rb +273 -0
  58. data/lib/offsite_payments/notification.rb +71 -0
  59. data/lib/offsite_payments/return.rb +37 -0
  60. data/lib/offsite_payments/version.rb +3 -0
  61. metadata +268 -0
@@ -0,0 +1,199 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module Moneybookers
4
+ mattr_accessor :production_url
5
+ self.production_url = 'https://www.moneybookers.com/app/payment.pl'
6
+
7
+ def self.service_url
8
+ self.production_url
9
+ end
10
+
11
+ def self.notification(post, options)
12
+ Notification.new(post, options)
13
+ end
14
+
15
+ def self.return(post, options = {})
16
+ Return.new(post, options)
17
+ end
18
+
19
+ class Helper < OffsitePayments::Helper
20
+ mapping :account, 'pay_to_email'
21
+ mapping :order, 'transaction_id'
22
+ mapping :amount, 'amount'
23
+ mapping :currency, 'currency'
24
+
25
+ mapping :customer,
26
+ :first_name => 'firstname',
27
+ :last_name => 'lastname',
28
+ :email => 'pay_from_email',
29
+ :phone => 'phone_number'
30
+
31
+ mapping :billing_address,
32
+ :city => 'city',
33
+ :address1 => 'address',
34
+ :address2 => 'address2',
35
+ :state => 'state',
36
+ :zip => 'postal_code',
37
+ :country => 'country'
38
+
39
+ mapping :notify_url, 'status_url'
40
+ mapping :return_url, 'return_url'
41
+ mapping :cancel_return_url, 'cancel_url'
42
+ mapping :description, 'detail1_text'
43
+
44
+ MAPPED_COUNTRY_CODES = {
45
+ 'SE' => 'SV',
46
+ 'DK' => 'DA'
47
+ }
48
+
49
+ SUPPORTED_COUNTRY_CODES = [
50
+ 'FI', 'DE', 'ES', 'FR',
51
+ 'IT','PL', 'GR', 'RO',
52
+ 'RU', 'TR', 'CN', 'CZ', 'NL'
53
+ ]
54
+
55
+ def initialize(order, account, options = {})
56
+ super
57
+ add_tracking_token
58
+ add_default_parameters
59
+ add_seller_details(options)
60
+ end
61
+
62
+ private
63
+
64
+ def add_tracking_token
65
+ return if application_id.blank? || application_id == 'ActiveMerchant'
66
+
67
+ add_field('merchant_fields', 'platform')
68
+ add_field('platform', application_id)
69
+ end
70
+
71
+ def add_default_parameters
72
+ add_field('hide_login', 1)
73
+ end
74
+
75
+ def add_seller_details(options)
76
+ add_field('recipient_description', options[:account_name]) if options[:account_name]
77
+ add_field('country', lookup_country_code(options[:country], :alpha3)) if options[:country]
78
+ add_field('language', locale_code(options[:country])) if options[:country]
79
+ end
80
+
81
+ def locale_code(country_code)
82
+ return country_code if SUPPORTED_COUNTRY_CODES.include?(country_code)
83
+ MAPPED_COUNTRY_CODES[country_code] || 'EN'
84
+ end
85
+ end
86
+
87
+ class Notification < OffsitePayments::Notification
88
+ def complete?
89
+ status == 'Completed'
90
+ end
91
+
92
+ # ‘2’ Processed – This status is sent when the transaction is processed and the funds have been received on your Moneybookers account.
93
+ # ‘0’ Pending – This status is sent when the customers pays via the pending bank transfer option. Such transactions will auto-process IF the bank transfer is received by Moneybookers. We strongly recommend that you do NOT process the order/transaction in your system upon receipt of a pending status from Moneybookers.
94
+ # ‘-1’ Cancelled – Pending transactions can either be cancelled manually by the sender in their online account history or they will auto-cancel after 14 days if still pending.
95
+ # ‘-2’ Failed – This status is sent when the customer tries to pay via Credit Card or Direct Debit but our provider declines the transaction. If you do not accept Credit Card or Direct Debit payments via Moneybookers (see page 17) then you will never receive the failed status.
96
+ # ‘-3’ Chargeback – This status could be received only if your account is configured to receive chargebacks. If this is the case, whenever a chargeback is received by Moneybookers, a -3 status will be posted on the status_url for the reversed transaction.
97
+ def status
98
+ case status_code
99
+ when '2'
100
+ 'Completed'
101
+ when '0'
102
+ 'Pending'
103
+ when '-1'
104
+ 'Cancelled'
105
+ when '-2'
106
+ 'Failed'
107
+ when '-3'
108
+ 'Reversed'
109
+ else
110
+ 'Error'
111
+ end
112
+ end
113
+
114
+ def status_code
115
+ params['status']
116
+ end
117
+
118
+ def item_id
119
+ params['transaction_id']
120
+ end
121
+
122
+ def transaction_id
123
+ params['mb_transaction_id']
124
+ end
125
+
126
+ # When was this payment received by the client.
127
+ def received_at
128
+ nil
129
+ end
130
+
131
+ def payer_email
132
+ params['pay_from_email']
133
+ end
134
+
135
+ def receiver_email
136
+ params['pay_to_email']
137
+ end
138
+
139
+ def md5sig
140
+ params['md5sig']
141
+ end
142
+
143
+ #Unique ID from the merchant's Moneybookers.com account, needed for calculatinon of md5 sig
144
+ def merchant_id
145
+ params['merchant_id']
146
+ end
147
+
148
+ # currency of the payment as posted by the merchant on the entry form
149
+ def currency
150
+ params['currency']
151
+ end
152
+
153
+ # amount of the payment as posted by the merchant on the entry form (ex. 39.60/39.6/39)
154
+ def gross
155
+ params['amount']
156
+ end
157
+
158
+ # currency of mb_amount, will always be the same as the currency of the beneficiary's account at Moneybookers.com
159
+ def merchant_currency
160
+ params['mb_currency']
161
+ end
162
+
163
+ # total amount of the payment in Merchants currency (ex 25.46/25.4/25)
164
+ def merchant_amount
165
+ params['mb_amount']
166
+ end
167
+
168
+ # Was this a test transaction?
169
+ def test?
170
+ false
171
+ end
172
+
173
+ def secret
174
+ @options[:credential2]
175
+ end
176
+
177
+ # Acknowledge the transaction to MoneyBooker. This method has to be called after a new
178
+ # apc arrives. It will verify that all the information we received is correct and will return a
179
+ # ok or a fail. The secret (second credential) has to be provided in the parameter :credential2
180
+ # when instantiating the Notification object.
181
+ #
182
+ # Example:
183
+ #
184
+ # def ipn
185
+ # notify = Moneybookers.notification(request.raw_post, :credential2 => 'secret')
186
+ #
187
+ # if notify.acknowledge
188
+ # ... process order ... if notify.complete?
189
+ # else
190
+ # ... log possible hacking attempt ...
191
+ # end
192
+ def acknowledge(authcode = nil)
193
+ fields = [merchant_id, item_id, Digest::MD5.hexdigest(secret.to_s).upcase, merchant_amount, merchant_currency, status_code].join
194
+ md5sig == Digest::MD5.hexdigest(fields).upcase
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,228 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ # To start with Nochex, follow the instructions for installing
4
+ # ActiveMerchant as a plugin, as described on
5
+ # http://www.activemerchant.org/.
6
+ #
7
+ # The plugin will automatically add the ActionView helper for
8
+ # ActiveMerchant, which will allow you to make the Nochex payments.
9
+ # The idea behind the helper is that it generates an invisible
10
+ # forwarding screen that will automatically redirect the user.
11
+ # So you would collect all the information about the order and then
12
+ # simply render the hidden form, which redirects the user to Nochex.
13
+ #
14
+ # The syntax of the helper is as follows:
15
+ #
16
+ # <% payment_service_for 'order id', 'nochex_user_id',
17
+ # :amount => 50.00,
18
+ # :service => :nochex,
19
+ # :html => { :id => 'nochex-form' } do |service| %>
20
+ #
21
+ # <% service.customer :first_name => 'Cody',
22
+ # :last_name => 'Fauser',
23
+ # :phone => '(555)555-5555',
24
+ # :email => 'cody@example.com' %>
25
+ #
26
+ # <% service.billing_address :city => 'Ottawa',
27
+ # :address1 => '21 Snowy Brook Lane',
28
+ # :address2 => 'Apt. 36',
29
+ # :state => 'ON',
30
+ # :country => 'CA',
31
+ # :zip => 'K1J1E5' %>
32
+ #
33
+ # <% service.invoice '#1000' %>
34
+ # <% service.shipping '0.00' %>
35
+ # <% service.tax '0.00' %>
36
+ #
37
+ # <% service.notify_url url_for(:action => 'notify', :only_path => false) %>
38
+ # <% service.return_url url_for(:action => 'done', :only_path => false) %>
39
+ # <% service.cancel_return_url 'http://mystore.com' %>
40
+ # <% end %>
41
+ #
42
+ # The notify_url is the URL that the Nochex IPN will be sent. You can
43
+ # handle the notification in your controller action as follows:
44
+ #
45
+ # class NotificationController < ApplicationController
46
+ # include OffsitePayments::Integrations
47
+ #
48
+ # def notify
49
+ # notification = Nochex::Notification.new(request.raw_post)
50
+ #
51
+ # begin
52
+ # # Acknowledge notification with Nochex
53
+ # raise StandardError, 'Illegal Notification' unless notification.acknowledge
54
+ # # Process the payment
55
+ # rescue => e
56
+ # logger.warn("Illegal notification received: #{e.message}")
57
+ # ensure
58
+ # head(:ok)
59
+ # end
60
+ # end
61
+ # end
62
+ module Nochex
63
+ mattr_accessor :service_url
64
+ self.service_url = 'https://secure.nochex.com'
65
+
66
+ mattr_accessor :notification_confirmation_url
67
+ self.notification_confirmation_url = 'https://www.nochex.com/nochex.dll/apc/apc'
68
+
69
+ # Simply a convenience method that returns a new
70
+ # OffsitePayments::Integrations::Nochex::Notification
71
+ def self.notification(post, options = {})
72
+ Notification.new(post)
73
+ end
74
+
75
+ def self.return(query_string, options = {})
76
+ Return.new(query_string)
77
+ end
78
+
79
+ class Helper < OffsitePayments::Helper
80
+ # Required Parameters
81
+ # email
82
+ # amount
83
+ mapping :account, 'email'
84
+ mapping :amount, 'amount'
85
+
86
+ # Set the field status = test for testing with accounts:
87
+ # Account Password
88
+ # test1@nochex.com 123456
89
+ # test2@nochex.com 123456
90
+ # def initialize(order, account, options = {})
91
+ # super
92
+ # add_field('status', 'test')
93
+ # end
94
+
95
+ # Need to format the amount to have 2 decimal places
96
+ def amount=(money)
97
+ cents = money.respond_to?(:cents) ? money.cents : money
98
+ raise ArgumentError, "amount must be a Money object or an integer" if money.is_a?(String)
99
+ raise ActionViewHelperError, "amount must be greater than $0.00" if cents.to_i <= 0
100
+
101
+ add_field mappings[:amount], sprintf("%.2f", cents.to_f/100)
102
+ end
103
+
104
+ # Optional Parameters
105
+ # ordernumber
106
+ mapping :order, 'ordernumber'
107
+
108
+ # firstname
109
+ # lastname
110
+ # email_address_sender
111
+ mapping :customer, :first_name => 'firstname',
112
+ :last_name => 'lastname',
113
+ :email => 'email_address_sender'
114
+
115
+ # town
116
+ # firstline
117
+ # county
118
+ # postcode
119
+ mapping :billing_address, :city => 'town',
120
+ :address1 => 'firstline',
121
+ :state => 'county',
122
+ :zip => 'postcode'
123
+
124
+ # responderurl
125
+ mapping :notify_url, 'responderurl'
126
+
127
+ # returnurl
128
+ mapping :return_url, 'returnurl'
129
+
130
+ # cancelurl
131
+ mapping :cancel_return_url, 'cancelurl'
132
+
133
+ # description
134
+ mapping :description, 'description'
135
+
136
+ # Currently unmapped
137
+ # logo
138
+ end
139
+
140
+ # Parser and handler for incoming Automatic Payment Confirmations from Nochex.
141
+ class Notification < OffsitePayments::Notification
142
+ include ActiveMerchant::PostsData
143
+
144
+ def complete?
145
+ status == 'Completed'
146
+ end
147
+
148
+ # Id of the order we passed to Nochex
149
+ def item_id
150
+ params['order_id']
151
+ end
152
+
153
+ def transaction_id
154
+ params['transaction_id']
155
+ end
156
+
157
+ def currency
158
+ 'GBP'
159
+ end
160
+
161
+ # When was this payment received by the client.
162
+ def received_at
163
+ # U.K. Format: 27/09/2006 22:30:54
164
+ return if params['transaction_date'].blank?
165
+ time = params['transaction_date'].scan(/\d+/)
166
+ Time.utc(time[2], time[1], time[0], time[3], time[4], time[5])
167
+ end
168
+
169
+ def payer_email
170
+ params['from_email']
171
+ end
172
+
173
+ def receiver_email
174
+ params['to_email']
175
+ end
176
+
177
+ def security_key
178
+ params['security_key']
179
+ end
180
+
181
+ # the money amount we received in X.2 decimal.
182
+ def gross
183
+ sprintf("%.2f", params['amount'].to_f)
184
+ end
185
+
186
+ # Was this a test transaction?
187
+ def test?
188
+ params['status'] == 'test'
189
+ end
190
+
191
+ def status
192
+ 'Completed'
193
+ end
194
+
195
+ # Acknowledge the transaction to Nochex. This method has to be called after a new
196
+ # apc arrives. Nochex will verify that all the information we received are correct and will return a
197
+ # ok or a fail. This is very similar to the PayPal IPN scheme.
198
+ #
199
+ # Example:
200
+ #
201
+ # def nochex_ipn
202
+ # notify = NochexNotification.new(request.raw_post)
203
+ #
204
+ # if notify.acknowledge
205
+ # ... process order ... if notify.complete?
206
+ # else
207
+ # ... log possible hacking attempt ...
208
+ # end
209
+ def acknowledge(authcode = nil)
210
+ payload = raw
211
+
212
+ response = ssl_post(Nochex.notification_confirmation_url, payload,
213
+ 'Content-Length' => "#{payload.size}",
214
+ 'User-Agent' => "Active Merchant -- http://activemerchant.org",
215
+ 'Content-Type' => "application/x-www-form-urlencoded"
216
+ )
217
+
218
+ raise StandardError.new("Faulty Nochex result: #{response}") unless ["AUTHORISED", "DECLINED"].include?(response)
219
+
220
+ response == "AUTHORISED"
221
+ end
222
+ end
223
+
224
+ class Return < OffsitePayments::Return
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,268 @@
1
+ # encoding: utf-8
2
+
3
+ module OffsitePayments #:nodoc:
4
+ module Integrations #:nodoc:
5
+ module PagSeguro
6
+ mattr_accessor :service_production_url
7
+ self.service_production_url = 'https://pagseguro.uol.com.br/v2/checkout/payment.html'
8
+
9
+ mattr_accessor :service_test_url
10
+ self.service_test_url = 'https://sandbox.pagseguro.uol.com.br/v2/checkout/payment.html'
11
+
12
+ mattr_accessor :invoicing_production_url
13
+ self.invoicing_production_url = 'https://ws.pagseguro.uol.com.br/v2/checkout/'
14
+
15
+ mattr_accessor :invoicing_test_url
16
+ self.invoicing_test_url = 'https://ws.sandbox.pagseguro.uol.com.br/v2/checkout/'
17
+
18
+ mattr_accessor :notification_production_url
19
+ self.notification_production_url = 'https://ws.pagseguro.uol.com.br/v2/transactions/notifications/'
20
+
21
+ mattr_accessor :notification_test_url
22
+ self.notification_test_url = 'https://ws.sandbox.pagseguro.uol.com.br/v2/transactions/notifications/'
23
+
24
+ def self.service_url
25
+ test? ? service_test_url : service_production_url
26
+ end
27
+
28
+ def self.invoicing_url
29
+ test? ? invoicing_test_url : invoicing_production_url
30
+ end
31
+
32
+ def self.notification_url
33
+ test? ? notification_test_url : notification_production_url
34
+ end
35
+
36
+ def self.notification(query_string, options = {})
37
+ Notification.new(query_string, options)
38
+ end
39
+
40
+ def self.return(query_string, options = {})
41
+ Return.new(query_string, options)
42
+ end
43
+
44
+ def self.test?
45
+ OffsitePayments.mode == :test
46
+ end
47
+
48
+ class Helper < OffsitePayments::Helper
49
+ def initialize(order_id, account, options)
50
+ super
51
+ @account = account
52
+
53
+ add_field('itemAmount1', sprintf("%0.02f", options[:amount]))
54
+ add_field('itemId1', '1')
55
+ add_field('itemQuantity1', '1')
56
+ add_field('shippingType', '3')
57
+ add_field('currency', 'BRL')
58
+ end
59
+
60
+ mapping :account, 'email'
61
+ mapping :credential2, 'token'
62
+
63
+ mapping :order, 'reference'
64
+
65
+ mapping :notify_url, 'notificationURL'
66
+ mapping :return_url, 'redirectURL'
67
+ mapping :description, 'itemDescription1'
68
+
69
+ def shipping_address(params = {})
70
+ add_field('shippingAddressCity', params[:city].slice(0, 60)) if params[:city]
71
+ add_field('shippingAddressStreet', params[:address1].slice(0, 80)) if params[:address1]
72
+ add_field('shippingAddressComplement', params[:address2].slice(0, 40)) if params[:address2]
73
+ add_field('shippingAddressState', params[:state])
74
+ add_field('shippingAddressPostalCode', params[:zip].delete("^0-9").slice(0, 8)) if params[:zip]
75
+ end
76
+
77
+ def form_fields
78
+ invoice_id = fetch_token
79
+
80
+ {"code" => invoice_id}
81
+ end
82
+
83
+ def shipping(value)
84
+ add_field("shippingCost", sprintf("%0.02f", value))
85
+ end
86
+
87
+ def customer(params = {})
88
+ full_name = remove_excessive_whitespace("#{params[:first_name]} #{params[:last_name]}")
89
+
90
+ if phone = area_code_and_number(params[:phone])
91
+ add_field("senderAreaCode", phone[0])
92
+ add_field("senderPhone", phone[1])
93
+ end
94
+
95
+ add_field("senderEmail", params[:email])
96
+ add_field('senderName', full_name)
97
+ end
98
+
99
+ def fetch_token
100
+ uri = URI.parse(PagSeguro.invoicing_url)
101
+ http = Net::HTTP.new(uri.host, uri.port)
102
+ http.use_ssl = true
103
+
104
+ request = Net::HTTP::Post.new(uri.request_uri)
105
+ request.content_type = "application/x-www-form-urlencoded"
106
+ request.set_form_data @fields
107
+
108
+ response = http.request(request)
109
+ xml = Nokogiri::XML.parse(response.body)
110
+
111
+ check_for_errors(response, xml)
112
+
113
+ extract_token(xml)
114
+ rescue Timeout::Error, Errno::ECONNRESET, Errno::ETIMEDOUT => e
115
+ raise ActionViewHelperError, "Erro ao conectar-se ao PagSeguro. Por favor, tente novamente."
116
+ end
117
+
118
+ def area_code_and_number(phone)
119
+ return if phone.nil?
120
+ phone.gsub!(/[^\d]/, '')
121
+
122
+ ddd = phone.slice(0..1)
123
+ number = phone.slice(2..12)
124
+
125
+ [ddd, number]
126
+ end
127
+
128
+ def check_for_errors(response, xml)
129
+ return if response.code == "200"
130
+
131
+ case response.code
132
+ when "400"
133
+ raise ActionViewHelperError, humanize_errors(xml)
134
+ when "401"
135
+ raise ActionViewHelperError, "Token do PagSeguro inválido."
136
+ else
137
+ raise ActiveMerchant::ResponseError, response
138
+ end
139
+ end
140
+
141
+ def extract_token(xml)
142
+ xml.css("code").text
143
+ end
144
+
145
+ def humanize_errors(xml)
146
+ # reference: https://pagseguro.uol.com.br/v2/guia-de-integracao/codigos-de-erro.html
147
+
148
+ xml.css("errors").children.map do |error|
149
+ case error.css('code').text
150
+ when "11013"
151
+ "Código de área inválido"
152
+ when "11014"
153
+ "Número de telefone inválido. Formato esperado: (DD) XXXX-XXXX"
154
+ when "11017"
155
+ "Código postal (CEP) inválido."
156
+ else
157
+ error.css('message').text
158
+ end
159
+ end.join(", ")
160
+ end
161
+
162
+ def remove_excessive_whitespace(text)
163
+ text.gsub(/\s{2,}/, ' ').strip
164
+ end
165
+ end
166
+
167
+ class Notification < OffsitePayments::Notification
168
+ class NotificationError < StandardError; end
169
+
170
+ def initialize(post, options = {})
171
+ @acknowledge = true
172
+ notify_code = parse_http_query(post)["notificationCode"]
173
+ email = options[:credential1]
174
+ token = options[:credential2]
175
+
176
+ uri = URI.join(PagSeguro.notification_url, notify_code)
177
+ parse_xml(web_get(uri, email: email, token: token))
178
+
179
+ rescue NotificationError
180
+ @acknowledge = false
181
+ end
182
+
183
+ def complete?
184
+ status == "Completed"
185
+ end
186
+
187
+ def item_id
188
+ params["transaction"]["reference"]
189
+ end
190
+
191
+ def transaction_id
192
+ params["transaction"]["code"]
193
+ end
194
+
195
+ def received_at
196
+ params["transaction"]["date"]
197
+ end
198
+
199
+ def payer_email
200
+ params["sender"]["email"]
201
+ end
202
+
203
+ def gross
204
+ params["transaction"]["grossAmount"]
205
+ end
206
+
207
+ def currency
208
+ "BRL"
209
+ end
210
+
211
+ def payment_method_type
212
+ params["transaction"]["paymentMethod"]["type"]
213
+ end
214
+
215
+ def payment_method_code
216
+ params["transaction"]["paymentMethod"]["code"]
217
+ end
218
+
219
+ def status
220
+ case params["transaction"]["status"]
221
+ when "1", "2"
222
+ "Pending"
223
+ when "3"
224
+ "Completed"
225
+ when "4"
226
+ "Available"
227
+ when "5"
228
+ "Dispute"
229
+ when "6"
230
+ "Reversed"
231
+ when "7"
232
+ "Failed"
233
+ end
234
+ end
235
+
236
+ def acknowledge
237
+ @acknowledge
238
+ end
239
+
240
+ private
241
+
242
+ def web_get(uri, params)
243
+ uri.query = URI.encode_www_form(params)
244
+
245
+ response = Net::HTTP.get_response(uri)
246
+ raise NotificationError if response.code.to_i > 200
247
+
248
+ response.body
249
+ end
250
+
251
+ # Take the posted data and move the relevant data into a hash
252
+ def parse_xml(post)
253
+ @params = Hash.from_xml(post)
254
+ end
255
+
256
+ def parse_http_query(post)
257
+ @raw = post
258
+ params = {}
259
+ for line in post.split('&')
260
+ key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
261
+ params[key] = value
262
+ end
263
+ params
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end