Module: Paypal::Helpers::Common

Defined in:
lib/paypal/helpers/common.rb

Instance Method Summary collapse

Instance Method Details

#paypal_address(options = {}) ⇒ Object

Pass an address to paypal so that all signup forms can be prefilled

  • email – Customer’s email address

  • first_name – Customer’s first name. Must be alpha-numeric, with a 32 character limit

  • last_name – Customer’s last name. Must be alpha-numeric, with a 64 character limit

  • address1 – First line of customer’s address. Must be alpha-numeric, with a 100 character limit

  • address2 – Second line of customer’s address. Must be alpha-numeric, with a 100 character limit

  • city – City of customer’s address. Must be alpha-numeric, with a 100 character limit

  • state – State of customer’s address. Must be official 2 letter abbreviation

  • zip – Zip code of customer’s address

  • night_phone_a – Area code of customer’s night telephone number

  • night_phone_b – First three digits of customer’s night telephone number

  • day_phone_a – Area code of customer’s daytime telephone number

  • day_phone_b – First three digits of customer’s daytime telephon



188
189
190
191
192
# File 'lib/paypal/helpers/common.rb', line 188

def paypal_address(options = {})
  options.collect do |key, value|
    %Q{<input type="hidden" name="#{key}" value="#{value}" />}
  end.join("\n")
end

#paypal_setup(item_number, amount, business, options = {}) ⇒ Object

This helper creates the hidden form data which is needed for a paypal purchase.

  • item_number – The first parameter is the item number. This is for your personal organization and can be arbitrary. Paypal will sent the item number back with the IPN so its a great place to store a user ID or a order ID or something like this.

  • amount – should be a parameter of type Money ( see leetsoft.com/api/money ) but can also be a string of type “50.00” for 50$. If you use the string syntax make sure you set the current currency as part of the options hash. The default is USD

  • business – This is your paypal account name ( an email ). This needs to be a valid paypal business account.

The last parameter is a options hash. You can set or override any Paypal-recognized parameter, including:

  • :cmd – default is ‘_xclick’ or ‘_xclick-subscriptions’ when you use :subscription.

  • :quantity – default is ‘1’.

  • :no_note – default is ‘1’.

  • :item_name – default is ‘Store purchase’. This is the name of the purchase which will be displayed on the paypal page.

  • :no_shipping – default is ‘1’. By default we tell paypal that no shipping is required. Usually the shipping address should be collected in our application, not by paypal.

  • :currency – default is ‘USD’. If you provide a Money object, that will automatically override the value.

  • :charset – default is ‘utf-8’.

  • :notify_url – If provided paypal will send its IPN notification once a purchase is made, canceled or any other status changes occur.

  • :return – If provided paypal will redirect a user back to this url after a successful purchase. Useful for a kind of thankyou page.

  • :cancel_return – If provided paypal will redirect a user back to this url when the user cancels the purchase.

  • :tax – the tax for the store purchase. Same format as the amount parameter but optional

  • :invoice – Unique invoice number. User will never see this. optional

  • :custom – Custom field. User will never see this. optional

Dealing with subscriptions

  • :subscription – Hash containing the subscription options. optional

    • :period – One of :monthly, :yearly, :weekly or :daily

    • :length – How often, based on :period. E.g. 6 :monthly?

    • :retry – Default is false. Boolean for if paypal should retry failed payments.

    • :recurring – Default is false. Boolean for if paypal should recur payment and end of period.

Generating encrypted form data

The helper also supports the generation of encrypted button data. Please see the README for more information on the setup and prerequisite steps for using encrypted forms.

The following options must all be provided (as strings) to encrypt the data:

  • :business_key – The private key you have generated

  • :business_cert – The public certificate you have also uploaded to Paypal

  • :business_certid – The certificate ID that Paypal has assigned to your certificate.

Examples:

<%= paypal_setup @order.id, Money.us_dollar(50000), "[email protected]" %>
<%= paypal_setup @order.id, '50.00', "[email protected]", :currency => 'USD' %>
<%= paypal_setup @order.id, '50.00', "[email protected]", :currency => 'USD', :notify_url => url_for(:only_path => false, :action => 'paypal_ipn') %>
<%= paypal_setup @order.id, Money.ca_dollar(50000), "[email protected]", :item_name => 'Snowdevil shop purchase', :return_url => paypal_return_url, :cancel_url => paypal_cancel_url, :notify_url => paypal_ipn_url  %>
<%= paypal_setup @order.id, Money.ca_dollar(50000), "[email protected]", :item_name => 'Snowdevil shop purchase', :return_url => paypal_return_url, :cancel_url => paypal_cancel_url, :business_key => @business_key, :business_cert => @business_cert, :business_certid => @business_certid  %>

Raises:

  • (ArgumentError)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/paypal/helpers/common.rb', line 79

def paypal_setup(item_number, amount, business, options = {})

  subscription = options.delete(:subscription)

  misses = (options.keys - valid_setup_options)
  raise ArgumentError, "Unknown option #{misses.inspect}" unless misses.empty?

  params = {
    :cmd => subscription ? '_ext-enter' : '_xclick',
    :redirect_cmd => subscription ? '_xclick-subscriptions' : nil,
    :quantity => 1,
    :business => business,
    :item_number => item_number,
    :item_name => 'Store purchase',
    :no_shipping => '1',
    :no_note => '1',
    :charset => 'utf-8',
    :page_style => 'PayPal'
  }.reject{|k,v| v.nil?}.merge(options)

  params[:currency_code] = amount.currency if amount.respond_to?(:currency)
  params[:currency_code] = params.delete(:currency) if params[:currency]
  params[:currency_code] ||= 'USD'

  # We accept both strings and money objects as amount
  amount = amount.cents.to_f / 100.0 if amount.respond_to?(:cents)
  amount = sprintf('%.2f', amount)

  if subscription.nil?
    params[:amount] = amount
  else
    params[:a3]  = amount
    params[:p3]  = subscription[:length]
    params[:sra] = subscription[:retry] == true ? 1 : 0
    params[:src] = subscription[:recurring] == true ? 1 : 0
    params[:t3]  = case subscription[:period]
      when :monthly; 'M'
      when :yearly;  'Y'
      when :weekly;  'W'
      when :daily;   'D'
    end
  end

  # same for tax
  tax = params[:tax]
  unless tax.nil?
    tax = tax.cents.to_f / 100.0 if tax.respond_to?(:cents)
    params[:tax] = sprintf("%.2f", tax)
  end

  # look for encryption parameters, save them outsite the parameter hash.
  if params.delete(:enable_encryption)
    business_key = Paypal::Config.business_key
    business_cert = Paypal::Config.business_cert
    business_certid = Paypal::Config.business_cert_id
    unless business_key && business_cert && business_certid
      raise ArgumentError, "Paypal::Config.business_key, Paypal::Config.business_cert and Paypal::Config.business_cert_id should be set if you use :enable_encryption"
    end
  end

  # Build the form
  buttons = []
  # Only attempt an encrypted form if we have all the required fields.
  if business_key and business_cert and business_certid
    require 'openssl'

    # Convert the key and certificates into OpenSSL-friendly objects.
    paypal_cert = OpenSSL::X509::Certificate.new(Paypal::Config.paypal_cert)
    business_key = OpenSSL::PKey::RSA.new(business_key)
    business_cert = OpenSSL::X509::Certificate.new(business_cert)
    # Put the certificate ID back into the parameter hash the way Paypal wants it.
    params[:cert_id] = business_certid

    # Prepare a string of data for encryption
    data = ""
    params.each_pair {|k,v| data << "#{k}=#{v}\n"}

    # Sign the data with our key/certificate pair
    signed = OpenSSL::PKCS7::sign(business_cert, business_key, data, [], OpenSSL::PKCS7::BINARY)
    # Encrypt the signed data with Paypal's public certificate.
    encrypted = OpenSSL::PKCS7::encrypt([paypal_cert], signed.to_der, OpenSSL::Cipher::Cipher::new("DES3"), OpenSSL::PKCS7::BINARY).to_s.gsub("\n", "")

    # The command for encrypted forms is always '_s-xclick'; the real command is in the encrypted data.
    buttons << %Q{<input type="hidden" name="cmd" value="_s-xclick" />}
    buttons << %Q{<input type="hidden" name="encrypted" value="#{encrypted}" />}
  else
    # Just emit all the parameters that we have as hidden fields.
    # Note that the sorting isn't really needed, but it makes testing a lot easier for now.
    params.each do |key, value|
      buttons << %Q{<input type="hidden" name="#{key}" value="#{value}" />} unless value.nil?
    end
  end
  buttons.join("\n")
end