class OffsitePayments::Integrations::Paypal::Notification

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

Public Class Methods

new(post, options = {}) click to toggle source
Calls superclass method OffsitePayments::Notification::new
# File lib/offsite_payments/integrations/paypal.rb, line 185
def initialize(post, options = {})
  super
  extend MassPayNotification if masspay?
end

Public Instance Methods

account() click to toggle source
# File lib/offsite_payments/integrations/paypal.rb, line 276
def account
  params['business'] || params['receiver_email']
end
acknowledge(authcode = nil) click to toggle source

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
# 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?() click to toggle source

Was the transaction complete?

# File lib/offsite_payments/integrations/paypal.rb, line 191
def complete?
  status == "Completed"
end
currency() click to toggle source

What currency have we been dealing with

# File lib/offsite_payments/integrations/paypal.rb, line 255
def currency
  params['mc_currency']
end
fee() click to toggle source

the markup paypal charges for the transaction

# File lib/offsite_payments/integrations/paypal.rb, line 250
def fee
  params['mc_fee']
end
gross() click to toggle source

the money amount we received in X.2 decimal.

# File lib/offsite_payments/integrations/paypal.rb, line 245
def gross
  params['mc_gross']
end
invoice() click to toggle source

This is the invoice which you passed to paypal

# File lib/offsite_payments/integrations/paypal.rb, line 267
def invoice
  params['invoice']
end
item_id() click to toggle source

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

# File lib/offsite_payments/integrations/paypal.rb, line 262
def item_id
  params['item_number'] || params['custom']
end
masspay?() click to toggle source

Is it a masspay notification?

# File lib/offsite_payments/integrations/paypal.rb, line 196
def masspay?
  type == "masspay"
end
received_at() click to toggle source

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

# 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
status() click to toggle source

Status of transaction. List of possible values:

Canceled-Reversal
Completed
Denied
Expired
Failed
In-Progress
Partially-Refunded
Pending
Processed
Refunded
Reversed
Voided
# File lib/offsite_payments/integrations/paypal.rb, line 229
def status
  params['payment_status']
end
test?() click to toggle source

Was this a test transaction?

# File lib/offsite_payments/integrations/paypal.rb, line 272
def test?
  params['test_ipn'] == '1'
end
transaction_id() click to toggle source

Id of this transaction (paypal number)

# File lib/offsite_payments/integrations/paypal.rb, line 234
def transaction_id
  params['txn_id']
end
type() click to toggle source

What type of transaction are we dealing with?

"cart" "send_money" "web_accept" are possible here.
# File lib/offsite_payments/integrations/paypal.rb, line 240
def type
  params['txn_type']
end