Class: ActiveMerchant::Billing::Integrations::Paypal::Notification

Inherits:
Notification
  • Object
show all
Defined in:
lib/active_merchant/billing/integrations/paypal/notification.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 ActiveMerchant::Billing::Integrations

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

    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

Constant Summary collapse

@@paypal_cert =
"""
-----BEGIN CERTIFICATE-----
MIIDoTCCAwqgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBmDELMAkGA1UEBhMCVVMx
EzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcTCFNhbiBKb3NlMRUwEwYDVQQK
EwxQYXlQYWwsIEluYy4xFjAUBgNVBAsUDXNhbmRib3hfY2VydHMxFDASBgNVBAMU
C3NhbmRib3hfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0
MDQxOTA3MDI1NFoXDTM1MDQxOTA3MDI1NFowgZgxCzAJBgNVBAYTAlVTMRMwEQYD
VQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEVMBMGA1UEChMMUGF5
UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQwEgYDVQQDFAtzYW5k
Ym94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG
9w0BAQEFAAOBjQAwgYkCgYEAt5bjv/0N0qN3TiBL+1+L/EjpO1jeqPaJC1fDi+cC
6t6tTbQ55Od4poT8xjSzNH5S48iHdZh0C7EqfE1MPCc2coJqCSpDqxmOrO+9QXsj
HWAnx6sb6foHHpsPm7WgQyUmDsNwTWT3OGR398ERmBzzcoL5owf3zBSpRP0NlTWo
nPMCAwEAAaOB+DCB9TAdBgNVHQ4EFgQUgy4i2asqiC1rp5Ms81Dx8nfVqdIwgcUG
A1UdIwSBvTCBuoAUgy4i2asqiC1rp5Ms81Dx8nfVqdKhgZ6kgZswgZgxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEV
MBMGA1UEChMMUGF5UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQw
EgYDVQQDFAtzYW5kYm94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNv
bYIBADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFc288DYGX+GX2+W
P/dwdXwficf+rlG+0V9GBPJZYKZJQ069W/ZRkUuWFQ+Opd2yhPpneGezmw3aU222
CGrdKhOrBJRRcpoO3FjHHmXWkqgbQqDWdG7S+/l8n1QfDPp+jpULOrcnGEUY41Im
jZJTylbJQ1b5PBBjGiP0PpK48cdF
-----END CERTIFICATE-----
"""

Instance Attribute Summary

Attributes inherited from Notification

#params, #raw

Instance Method Summary collapse

Methods inherited from Notification

#amount, #empty!, #gross_cents, #initialize

Constructor Details

This class inherits a constructor from ActiveMerchant::Billing::Integrations::Notification

Instance Method Details

#acknowledgeObject

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)


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 162

def acknowledge      
  payload =  raw

  uri = URI.parse(Paypal.service_url)
  request_path = "#{uri.path}?cmd=_notify-validate"

  request = Net::HTTP::Post.new(request_path)
  request['Content-Length'] = "#{payload.size}"
  request['User-Agent']     = "Active Merchant -- http://home.leetsoft.com/am"

  http = Net::HTTP.new(uri.host, uri.port)

  http.verify_mode    = OpenSSL::SSL::VERIFY_NONE unless @ssl_strict
  http.use_ssl        = true

  request = http.request(request, payload)

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

  request.body == "VERIFIED"
end

#complete?Boolean

Was the transaction complete?

Returns:

  • (Boolean)


76
77
78
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 76

def complete?
  status == "Completed"
end

#currencyObject

What currency have we been dealing with



127
128
129
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 127

def currency
  params['mc_currency']
end

#feeObject

the markup paypal charges for the transaction



122
123
124
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 122

def fee
  params['mc_fee']
end

#grossObject

the money amount we received in X.2 decimal.



117
118
119
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 117

def gross
  params['mc_gross']
end

#invoiceObject

This is the invoice which you passed to paypal



139
140
141
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 139

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



134
135
136
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 134

def item_id
  params['item_number'] || params['custom']
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



84
85
86
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 84

def received_at
  Time.parse params['payment_date']
end

#statusObject

Status of transaction. List of possible values:

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


101
102
103
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 101

def status
  params['payment_status']
end

#test?Boolean

Was this a test transaction?

Returns:

  • (Boolean)


144
145
146
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 144

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

#transaction_idObject

Id of this transaction (paypal number)



106
107
108
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 106

def transaction_id
  params['txn_id']
end

#typeObject

What type of transaction are we dealing with?

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


112
113
114
# File 'lib/active_merchant/billing/integrations/paypal/notification.rb', line 112

def type
  params['txn_type']
end