Class: PaypalRequest

Inherits:
Object
  • Object
show all
Defined in:
lib/sinatra/paypal/paypal-request.rb

Instance Method Summary collapse

Constructor Details

#initialize(params) ⇒ PaypalRequest

Returns a new instance of PaypalRequest.



4
5
6
7
8
9
10
11
# File 'lib/sinatra/paypal/paypal-request.rb', line 4

def initialize(params)
	if params.is_a? String
		 params = JSON.parse(params, {:symbolize_names => true})
	end

	@fields = params
	@custom_data = nil
end

Instance Method Details

#amountObject



60
61
62
# File 'lib/sinatra/paypal/paypal-request.rb', line 60

def amount
	Float(@fields[:mc_gross] || 0)
end

#complete?Boolean

Returns true if status is Completed

Returns:

  • (Boolean)


136
137
138
# File 'lib/sinatra/paypal/paypal-request.rb', line 136

def complete?
	self.status == 'Completed'
end

#custom_dataObject Also known as: data

Whatever is put in the custom_data field on the payment form will be sent back in the payment notification. This is useful for tracking the username and other information that is required to process the payment.

The sinatra-paypal module expects this to be either a plain string containing the username or a json string that can be parse into a ruby object.

Note that this field can be modified by the user before submitting the form, so you should verify the contents of it before using it.

payment.custom_data # => { :username => 'dave' }


102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/sinatra/paypal/paypal-request.rb', line 102

def custom_data
	if @custom_data.nil? && !@fields[:custom].nil?
		if @fields[:custom].strip.start_with? '{'
			# we could get a json object through, in which case it needs to be parsed...
			@custom_data = JSON.parse(@fields[:custom], {:symbolize_names => true})
		else
			# ...or would just have a string (which we assume is the target username) in that
			# case we need to normalize it into an object
			@custom_data = {:username => @fields[:custom]}
		end
	end

	return @custom_data
end

#custom_data?Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/sinatra/paypal/paypal-request.rb', line 117

def custom_data?
	!custom_data.nil?
end

#fieldsObject

A Hash with the raw data for the paypal transaction, this contains many less useful fields not listed above

Here is a list of the fields for a Completed transaction. These fields differ slightly between the main transaction types.

:business: [email protected] :charset: UTF-8 :cmd: _notify-validate :custom: ! ‘“thread_id”:“3f3fc5”,“username”:“customer_user_name”’ :first_name: Bill :handling_amount: ‘0.00’ :ipn_track_id: a5d596fffd057 :item_name: Describe your item :item_number: I01 :last_name: Davies :mc_currency: USD :mc_fee: ‘0.37’ :mc_gross: ‘2.00’ :notify_version: ‘3.8’ :payer_email: [email protected] :payer_id: 9AFYVBV9TTT5L :payer_status: verified :payment_date: 18:01:26 Jul 29, 2015 PDT :payment_fee: ‘0.37’ :payment_gross: ‘2.00’ :payment_status: Completed :payment_type: instant :protection_eligibility: Ineligible :quantity: ‘1’ :receiver_email: [email protected] :receiver_id: 4SUZXXXXFMC28 :residence_country: US :shipping: ‘0.00’ :tax: ‘0.00’ :transaction_subject: ! ‘“thread_id”:“3f3fc5”,“username”:“customer_user_name”’ :txn_id: 6FH51036BB6776017 :txn_type: web_accept :verify_sign: AmydMwaMHzmxRimnFMnKy3o9n-ElAWWRtiJ9TEixE0iGouC6EaMS0mWI

See developer.paypal.com/docs/classic/ipn/integration-guide/IPNandPDTVariables/ for a full description of the notification fields



198
199
200
# File 'lib/sinatra/paypal/paypal-request.rb', line 198

def fields
	@fields
end

#idObject

a unique id for the transaction (event if the paypal transaction_id is the same)

payment.id # => 661295c9cbf9d6b2f6428414504a8deed3020641



18
19
20
# File 'lib/sinatra/paypal/paypal-request.rb', line 18

def id
	self.transaction_hash
end

#is_accountable?Boolean Also known as: accountable?

Returns true if the transaction results in a change of the merchant account balance. This doesn’t apply to all IPN notifications - some (such as those with status Pending) are simply notifications that do not actually result in money chaning hands

Returns:

  • (Boolean)


143
144
145
146
147
# File 'lib/sinatra/paypal/paypal-request.rb', line 143

def is_accountable?
	# these are payment statues that actually result in the paypal balance changing, so we should set them as
	# accountable in the payment_log
	(self.complete? || self.status == 'Refunded' || self.status == 'Reversed' || self.status == 'Canceled_Reversal')
end

#item_numberObject



56
57
58
# File 'lib/sinatra/paypal/paypal-request.rb', line 56

def item_number
	@fields[:item_number]
end

#item_valid?(item_list, offer_data = nil) ⇒ Boolean

Returns:

  • (Boolean)


37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/sinatra/paypal/paypal-request.rb', line 37

def item_valid?(item_list, offer_data = nil)
	if item_list[self.item_number] != nil
		if item_list[self.item_number][:amount] == self.amount
			# this is a regular purchase at the regular price
			return true
		elsif self.uses_offer?(offer_data)
			# the price comes from a special offer, its valid
			return true
		end
	end

	return false
end

#payment_feeObject



64
65
66
# File 'lib/sinatra/paypal/paypal-request.rb', line 64

def payment_fee
	Float(@fields[:mc_fee] || 0)
end

#profitObject

The payment amount minus any fees, giving the net profit

payment.profit # => 1.63



72
73
74
75
76
77
# File 'lib/sinatra/paypal/paypal-request.rb', line 72

def profit
	# defined as the gross amount, minus transaction fees
	# could also subtract shipping and tax here as well, but we don't have to deal with
	# any of that yet
	self.amount - self.payment_fee
end

#reason_codeObject

returns the reason code for noticiations that have one (usually Pending or Refunded transactions) if a reason code is not applicable, this will return nil



151
152
153
# File 'lib/sinatra/paypal/paypal-request.rb', line 151

def reason_code
	@fields[:reason_code] || @fields[:pending_reason]
end

#statusObject

The payment status. The most common is Completed, but you might also see

- Refunded 
- Pending
- Reversed
- Canceled_Reversal
- Completed

   payment.status # => Pending


131
132
133
# File 'lib/sinatra/paypal/paypal-request.rb', line 131

def status
	@fields[:payment_status]
end

#transaction_hashObject

alias for id



23
24
25
26
27
# File 'lib/sinatra/paypal/paypal-request.rb', line 23

def transaction_hash
	# the same transaction id can come in mulitple times with different statuses
	# so we need to check both of them in order to see if the txn is unquie
	"#{self.transaction_id}-#{@fields[:payment_status]}".sha1
end

#transaction_idObject

the paypal transaction_id

payment.transaction_id # => 6FH51066BB6306017



33
34
35
# File 'lib/sinatra/paypal/paypal-request.rb', line 33

def transaction_id
	@fields[:txn_id]
end

#usernameObject

One of the most common peices of data to send through with the payment is the username that the payment applies to. This method will return the username from the custom_data field, if it contains one

payment.username # => reednj



85
86
87
88
# File 'lib/sinatra/paypal/paypal-request.rb', line 85

def username
	return nil if !custom_data?
	self.custom_data[:username]
end

#uses_offer?(offer_data) ⇒ Boolean

Returns:

  • (Boolean)


51
52
53
54
# File 'lib/sinatra/paypal/paypal-request.rb', line 51

def uses_offer?(offer_data)
	# to check if the offer is valid on this purchase we need to check the item code and the price matches
	return !offer_data.nil? && offer_data[:offer][:item_code] == self.item_number && offer_data[:offer][:amount]  == self.amount
end