Make Paypal PDF invoices with Payday

Posted: April 7th, 2011 | Author: | Filed under: General | 1 Comment »

A lot of small web applications use Paypal as their primary gateway for accepting payments. Paypal takes care of the payment transactions for your application and sends the customer back to your site once the payment done. The only thing Paypal doesn’t do is proper invoicing. It sends confirmation emails with the transaction details but many corporate customers require a well-formatted PDF invoice as a proof or purchase.

Payday is a Ruby gem that will help you create simple invoices. It’s a generic PDF invoicing library and as I will show you in this tutorial, it can be easily used to help you create invoices from Paypal transactions.

First thing to do, add the gem to your Gemfile :

gem "payday"

Next, you can create a rails initializer file with your company infos :

# /config/initializers/payday.rb
Payday::Config.default.invoice_logo = "#{Rails.root}/public/images/logo.png"
Payday::Config.default.company_name = "My Company inc."
Payday::Config.default.company_details = "100 Sunset Blvd\nHollywood\nUnited States\ninfo@mycompany.com"

When a client makes a purchase on Paypal, you can configure your account to receive Instant Payment Notifications (IPN). I save each transaction in a Payment model and dump the paypal IPN request params in a serialized hash called paypal_params. This is the method from my model class I use to generate the invoice :

# app/models/payment.rb
serialize :paypal_params

def generate_pdf_invoice
  invoice = Payday::Invoice.new(
    :invoice_number => paypal_params['invoice'],
    :currency => paypal_params['mc_currency'])
  invoice.paid_at = invoice.due_at = created_at.to_date
  invoice.bill_to = invoice.ship_to = paypal_params.slice(
    'address_name', 'address_street', 'address_city',
    'address_zip', 'address_country').values.join("\n")
  invoice.line_items << Payday::LineItem.new(
    :price => paypal_params['mc_gross'],
    :quantity => 1,
    :description => paypal_params['item_name'])
  invoice.notes = "Thank you for your purchase!"
  invoice.render_pdf
end

Obviously, you will want to adjust this code to fit what you are selling. In my case, there is always only one line item in my transactions.

Finally, I make the invoice downloadable from the user account page. The controller method works like this :

# app/controllers/payments_controller.rb
def pdf_invoice
  payment = Payment.find_by_tx_id! params[:id]
  respond_to do |format|
    format.pdf do
      send_data payment.generate_pdf_invoice,
        :filename => payment.invoice_filename,
        :type => "application/pdf"  , :disposition => "inline"
    end
  end
end

Again, you will probably have to adjust this method for your own needs. Don’t forget to add the pdf mime type to the mime_types.rb initializer :

# /config/initializers/mime_types.rb
Mime::Type.register 'application/pdf', :pdf

There’s a lot more you can do with Payday. It supports I18n and it integrates well with ActiveRecord. I encourage you to take a look at the readme on github.


Cookies and Facebook canvas apps

Posted: March 8th, 2011 | Author: | Filed under: Facebook, Rails | 5 Comments »

With the new Facebook way of loading iframes apps with POST requests, the safari third-party cookie problem is now partly fixed. It has always been a big headache dealing with cookies on the Facebook platform since Safari rejects them by default. With POST requests however, it is now possible to set cookies from the server. It seems Safari will still reject cookies set from the client.

So if you are using the Facebook Javascript SDK and set the cookies option to true, Safari won’t accept the FBS_XXXX cookie planted by the SDK. I struggled a whole week-end before figuring it out.

The work-around I use is to set a cookie from the server with the signed_request in it if there is one present. This solves most of the problems since I can just use the cookie when I don’t have a fresh signed_request (this happens when I do a request inside the canvas).

Here is the code inside a before_filter in the application_controller. I use Rails with the Facebooker2 gem :

The P3P header is used to make IE6 and IE7 accept the cookie as well.

If you’re building a Facebook canvas application with Rails, take the time to also read my post about keeping your REST architecture with the POST requests.


Restful Facebook canvas app with Rails and POST For Canvas

Posted: March 7th, 2011 | Author: | Filed under: Facebook | 12 Comments »

Update: The rack middleware is now included in Facebooker2. If you’re using Facebooker2, see the readme for details.

Starting March 10th, The POST for canvas option will become mandatory for all Facebook canvas apps. This means all requests to your iframe originating from the Facebook frame will be POST requests. If you use restful controllers in your app, this is not a good news. Fortunately, there is a very easy way to convert those POST back to GET with a Rack middleware :

Since all request coming from Facebook will include a signed_request parameter, you can assume that these requests are coming from the top frame. Other requests made directly from your iframe won’t be altered. You can safely now safely use Post for canvas and continue to assume all requests coming from the top frame will be get requests.