Class: OffsitePayments::Integrations::Paypal::Notification

Inherits:
Notification
  • Object
show all
Includes:
ActiveUtils::PostsData
Defined in:
lib/offsite_payments/integrations/paypal.rb

Overview

Parser and handler for incoming Instant payment notifications from paypal. The Example shows a typical handler in a rails application. Note that this is an example, please read the Paypal API documentation for all the details on creating a safe payment controller.

Example

class BackendController < ApplicationController
  include OffsitePayments::Integrations

  def paypal_ipn
    notify = Paypal::Notification.new(request.raw_post)

    if notify.masspay?
      masspay_items = notify.items
    end

    order = Order.find(notify.item_id)

    if notify.acknowledge
      begin

        if notify.complete? and order.total == notify.amount
          order.status = 'success'

          shop.ship(order)
        else
          logger.error("Failed to verify Paypal's notification, please investigate")
        end

      rescue => e
        order.status        = 'failed'
        raise
      ensure
        order.save
      end
    end

    render :nothing
  end
end

Instance Attribute Summary

Attributes inherited from Notification

#params, #raw

Instance Method Summary collapse

Methods inherited from Notification

#amount, #empty!, #gross_cents, #iso_currency, #valid_sender?

Constructor Details

#initialize(post, options = {}) ⇒ Notification

Returns a new instance of Notification.



185
186
187
188
# File 'lib/offsite_payments/integrations/paypal.rb', line 185

def initialize(post, options = {})
  super
  extend MassPayNotification if masspay?
end

Instance Method Details

#accountObject



276
277
278
# File 'lib/offsite_payments/integrations/paypal.rb', line 276

def 
  params['business'] || params['receiver_email']
end

#acknowledge(authcode = nil) ⇒ Object

Acknowledge the transaction to paypal. This method has to be called after a new ipn arrives. Paypal will verify that all the information we received are correct and will return a ok or a fail.

Example:

def paypal_ipn
  notify = PaypalNotification.new(request.raw_post)

  if notify.acknowledge
    ... process order ... if notify.complete?
  else
    ... log possible hacking attempt ...
  end

Raises:

  • (StandardError)


294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/offsite_payments/integrations/paypal.rb', line 294

def acknowledge(authcode = nil)
  payload =  raw

  response = ssl_post(Paypal.service_url + '?cmd=_notify-validate', payload,
    'Content-Length' => "#{payload.size}",
    'User-Agent'     => "Active Merchant -- http://activemerchant.org"
  )

  raise StandardError.new("Faulty paypal result: #{response}") unless ["VERIFIED", "INVALID"].include?(response)

  response == "VERIFIED"
end

#complete?Boolean

Was the transaction complete?

Returns:

  • (Boolean)


191
192
193
# File 'lib/offsite_payments/integrations/paypal.rb', line 191

def complete?
  status == "Completed"
end

#currencyObject

What currency have we been dealing with



255
256
257
# File 'lib/offsite_payments/integrations/paypal.rb', line 255

def currency
  params['mc_currency']
end

#feeObject

the markup paypal charges for the transaction



250
251
252
# File 'lib/offsite_payments/integrations/paypal.rb', line 250

def fee
  params['mc_fee']
end

#grossObject

the money amount we received in X.2 decimal.



245
246
247
# File 'lib/offsite_payments/integrations/paypal.rb', line 245

def gross
  params['mc_gross']
end

#invoiceObject

This is the invoice which you passed to paypal



267
268
269
# File 'lib/offsite_payments/integrations/paypal.rb', line 267

def invoice
  params['invoice']
end

#item_idObject

This is the item number which we submitted to paypal The custom field is also mapped to item_id because PayPal doesn’t return item_number in dispute notifications



262
263
264
# File 'lib/offsite_payments/integrations/paypal.rb', line 262

def item_id
  params['item_number'] || params['custom']
end

#masspay?Boolean

Is it a masspay notification?

Returns:

  • (Boolean)


196
197
198
# File 'lib/offsite_payments/integrations/paypal.rb', line 196

def masspay?
  type == "masspay"
end

#received_atObject

When was this payment received by the client. sometimes it can happen that we get the notification much later. One possible scenario is that our web application was down. In this case paypal tries several times an hour to inform us about the notification



204
205
206
207
208
209
210
211
212
213
214
# File 'lib/offsite_payments/integrations/paypal.rb', line 204

def received_at
  parsed_time_fields = DateTime._strptime(params['payment_date'], "%H:%M:%S %b %d, %Y %Z")
  Time.gm(
    parsed_time_fields[:year],
    parsed_time_fields[:mon],
    parsed_time_fields[:mday],
    parsed_time_fields[:hour],
    parsed_time_fields[:min],
    parsed_time_fields[:sec]
  ) - Time.zone_offset(parsed_time_fields[:zone])
end

#statusObject

Status of transaction. List of possible values:

Canceled-Reversal
Completed
Denied
Expired
Failed
In-Progress
Partially-Refunded
Pending
Processed
Refunded
Reversed
Voided


229
230
231
# File 'lib/offsite_payments/integrations/paypal.rb', line 229

def status
  params['payment_status']
end

#test?Boolean

Was this a test transaction?

Returns:

  • (Boolean)


272
273
274
# File 'lib/offsite_payments/integrations/paypal.rb', line 272

def test?
  params['test_ipn'] == '1'
end

#transaction_idObject

Id of this transaction (paypal number)



234
235
236
# File 'lib/offsite_payments/integrations/paypal.rb', line 234

def transaction_id
  params['txn_id']
end

#typeObject

What type of transaction are we dealing with?

"cart" "send_money" "web_accept" are possible here.


240
241
242
# File 'lib/offsite_payments/integrations/paypal.rb', line 240

def type
  params['txn_type']
end