Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm having a real nightmare trying to get the PesaPal API to work for me using Ruby...

I appreciate that it's probably not the most commonly used API but if there's anybody online here who has more experience using OAuth, and/or PHP experience who could offer a fresh pair of eyes I'd appreciate it.

So the PesaPal developer site is here: http://developer.pesapal.com Their API docs don't give away too many clues about how to use OAuth with their site and I don't understand PHP well enough to be sure I've read their PHP sample correctly.

Here's my attempt at implementing this in Ruby:

require 'oauth'
require 'uri'

key = '<my sandbox key>'
sec = '<my sandbox secret>' 

API_DOMAIN = 'https://demo.pesapal.com'

# An XML string of param data to include with our request
RAW_XML  = %{<?xml version=\"1.0\" encoding=\"utf-8\"?><PesapalDirectOrderInfo xmlns:xsi=\"http://www.w3.org/2001/XMLSchemainstance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" Amount=\"12.34\" Description=\"Bob Test 1\" Type=\"MERCHANT\" Reference=\"808\" FirstName=\"Bo\" LastName=\"Tester\" Email=\"[email protected]\" xmlns=\"http://www.pesapal.com\" />}

# Escape the XML
@post_xml = URI.escape(RAW_XML)

# Create a new OAuth Consumer
@consumer = OAuth::Consumer.new(key, sec, {
  site: API_DOMAIN, 
  scheme: :query_string
})

# The signed request object
@signed_request  = @consumer.create_signed_request('get', "#{API_DOMAIN}/API/PostPesapalDirectOrderV4")

# Join the pesapal_request_data and oauth_callback with '&' for valid URL params
@params = { 
  oauth_callback: URI.escape('http://localhost:3000'),
  pesapal_request_data: @post_xml,
}.map { |k,v| "#{k}=#{v}" }.join('&')

# This is the URL we should redirect to
puts redirect_url = "#{@signed_request.path}&#{@params}"

When I try to visit the URL returned by this code, I get: Problem: signature_invalid | Advice: > | back from the API.

Can anyone think of what I'm doing wrong here?

Thanks

share|improve this question
add comment

2 Answers

Check out the pesapal RubyGem here ... https://rubygems.org/gems/pesapal ... it handles all that stuff for you.

share|improve this answer
 
Thanks :) A shame that wasn't around when we were working on this project –  bodacious Sep 30 '13 at 17:36
add comment

I had the same problem and I solved it by creating a method to manually sign the url. create your own method to get the oauth_nonce like this.

def nonce
Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
end

The signature method looks like this:

def signature
key = percent_encode( @consumer_secret ) + '&' + percent_encode( @token_secret )

digest = OpenSSL::Digest::Digest.new( 'sha1' )
hmac = OpenSSL::HMAC.digest( digest, key, @base_str )

Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
end

This is the @base_str instance variable:

@base_str = [@req_method,
percent_encode( req_url ),
percent_encode( query_string )
].join( '&' )

This is the query_string method:

def query_string
pairs = []
@params.sort.each { | key, val |
pairs.push( "#{ percent_encode( key ) }=#{ percent_encode( val.to_s ) }" )
}
pairs.join '&'
end

You can then use the signature method above to get the oauth_signature param to use in the resulting url

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.