Ruby on Rails
PayPalWebServices (Version #28)

Here i compile my attempts to use the PayPal webservices with ruby, and eventually ruby on rails.

generating client stuff

Download and install a development build of soap4r from
http://dev.ctor.org/download/. (The latest stable build as of 1.5.5 has a couple of bugs that are critical). Install also the dependent libs.

Now you can use wsdl4r to generate the client stuff you will need like so (assuming your in the root dir where you downloaded soap4r):

./bin/wsdl2ruby.rb --wsdl <a href="http://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl">http://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl</a> --type client --force

getting certificates

Create a developer account on http://www.sandbox.paypal.com, and download the client digital certificate: cert_key_pem.txt (im sure you can work out this bit)

I split this manually into client key and client certificate… putting rsa key part of cert_key_pem.txt into a file called client.key and the rest into client.cert. Dont know if this is necessary, but it works.

Now we need to grab the server certificate from somewhere for the sandbox server, i stole this from the PHP SDK you can download… after unpacking it you can find it at : Services_PayPal/PayPal/cert/api_cert_chain.crt

test with the express payment API

For my test i used the following little script:

#!/usr/bin/env ruby
require 'defaultDriver.rb'
class RequesterCredentialsHandler < SOAP::Header::SimpleHandler
   HeaderName = XSD::QName.new('urn:ebay:api:PayPalAPI',
'RequesterCredentials')
   CredentialsName =
     XSD::QName.new('urn:ebay:apis:eBLBaseComponents', 'Credentials')
   UsernameName = XSD::QName.new(nil, 'Username')
   PasswordName = XSD::QName.new(nil, 'Password')
   SubjectName = XSD::QName.new(nil, 'Subject')

   def initialize(username, password, subject)
     super(HeaderName)
     @username, @password, @subject = username, password, subject
   end

   def on_simple_outbound
     {CredentialsName => {UsernameName => @username, PasswordName =>
@password,
       SubjectName => @subject}}
   end
 end 
client = PayPalAPIAAInterface.new(endpoint_url)
client.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_PEER
client.options['protocol.http.ssl_config.ca_file'] = 'api_cert_chain.crt'
client.options['protocol.http.ssl_config.client_cert'] = 'client.cert'
client.options['protocol.http.ssl_config.client_key'] = 'client.key'

client.headerhandler << RequesterCredentialsHandler.new('username', 'password','

# run ruby with -d to see SOAP wiredumps.
obj.wiredump_dev = STDERR if $DEBUG

req =SetExpressCheckoutReq.new
type = SetExpressCheckoutRequestType.new
type.Version = "2.0" 
details = SetExpressCheckoutRequestDetailsType.new
type.SetExpressCheckoutRequestDetails = details

#we have to use a workaround to set the OrderTotal
#due to a current limitation in soap4r
ns = "urn:ebay:apis:eBLBaseComponents" 
otqname = XSD::QName.new(ns, "OrderTotal")
otele = SOAPElement.new(otqname, "500")
otele.extraattr["currencyID"] = "EUR" 

details.OrderTotal = otele
details.ReturnURL = "http://foo.net" 
details.CancelURL = "http://foo.net" 

req.SetExpressCheckoutRequest=type
res =  client.setExpressCheckout(req)
puts res.token

(This script assumes the certificates and keys are in the same directory).

Success!

Well this works for me now, now im gonna try and implement it for real in my rails app…

Remember to use the -d option with ruby to see the soap request/response.

Many thanks to Hiroshi Nakamura for his invaluable tips and advice!

Note:

When I ran this program, I saw that several methods were spelt wrong. details.OrderTotal should be details.orderTotal and so on. I was finally able to run the test script successfully though and I documented my experience on my blog.

Here i compile my attempts to use the PayPal webservices with ruby, and eventually ruby on rails.

generating client stuff

Download and install a development build of soap4r from
http://dev.ctor.org/download/. (The latest stable build as of 1.5.5 has a couple of bugs that are critical). Install also the dependent libs.

Now you can use wsdl4r to generate the client stuff you will need like so (assuming your in the root dir where you downloaded soap4r):

./bin/wsdl2ruby.rb --wsdl <a href="http://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl">http://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl</a> --type client --force

getting certificates

Create a developer account on http://www.sandbox.paypal.com, and download the client digital certificate: cert_key_pem.txt (im sure you can work out this bit)

I split this manually into client key and client certificate… putting rsa key part of cert_key_pem.txt into a file called client.key and the rest into client.cert. Dont know if this is necessary, but it works.

Now we need to grab the server certificate from somewhere for the sandbox server, i stole this from the PHP SDK you can download… after unpacking it you can find it at : Services_PayPal/PayPal/cert/api_cert_chain.crt

test with the express payment API

For my test i used the following little script:

#!/usr/bin/env ruby
require 'defaultDriver.rb'
class RequesterCredentialsHandler < SOAP::Header::SimpleHandler
   HeaderName = XSD::QName.new('urn:ebay:api:PayPalAPI',
'RequesterCredentials')
   CredentialsName =
     XSD::QName.new('urn:ebay:apis:eBLBaseComponents', 'Credentials')
   UsernameName = XSD::QName.new(nil, 'Username')
   PasswordName = XSD::QName.new(nil, 'Password')
   SubjectName = XSD::QName.new(nil, 'Subject')

   def initialize(username, password, subject)
     super(HeaderName)
     @username, @password, @subject = username, password, subject
   end

   def on_simple_outbound
     {CredentialsName => {UsernameName => @username, PasswordName =>
@password,
       SubjectName => @subject}}
   end
 end 
client = PayPalAPIAAInterface.new(endpoint_url)
client.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_PEER
client.options['protocol.http.ssl_config.ca_file'] = 'api_cert_chain.crt'
client.options['protocol.http.ssl_config.client_cert'] = 'client.cert'
client.options['protocol.http.ssl_config.client_key'] = 'client.key'

client.headerhandler << RequesterCredentialsHandler.new('username', 'password','

# run ruby with -d to see SOAP wiredumps.
obj.wiredump_dev = STDERR if $DEBUG

req =SetExpressCheckoutReq.new
type = SetExpressCheckoutRequestType.new
type.Version = "2.0" 
details = SetExpressCheckoutRequestDetailsType.new
type.SetExpressCheckoutRequestDetails = details

#we have to use a workaround to set the OrderTotal
#due to a current limitation in soap4r
ns = "urn:ebay:apis:eBLBaseComponents" 
otqname = XSD::QName.new(ns, "OrderTotal")
otele = SOAPElement.new(otqname, "500")
otele.extraattr["currencyID"] = "EUR" 

details.OrderTotal = otele
details.ReturnURL = "http://foo.net" 
details.CancelURL = "http://foo.net" 

req.SetExpressCheckoutRequest=type
res =  client.setExpressCheckout(req)
puts res.token

(This script assumes the certificates and keys are in the same directory).

Success!

Well this works for me now, now im gonna try and implement it for real in my rails app…

Remember to use the -d option with ruby to see the soap request/response.

Many thanks to Hiroshi Nakamura for his invaluable tips and advice!

Note:

When I ran this program, I saw that several methods were spelt wrong. details.OrderTotal should be details.orderTotal and so on. I was finally able to run the test script successfully though and I documented my experience on my blog.