Showing posts with label soap. Show all posts
Showing posts with label soap. Show all posts

OAuth Token as Salesforce SessionId in SOAP API (PHP)

Sunday, October 7, 2012 by Aslam - The Alexendra
Hi All,
Most of the time developers who write applications in php/java or any other language, using salesforce soap APIs (partner wsdl or enterprise wsdl), they hard-code the username/password and security token in their code or in a property file. But there is one issue in this approach, anytime, if your org password or security token get change, your application may down. You have to update the credentials in your code or property file on server to get your application work.

One alternate solution for this issue is to use OAuth token in your code and write one automated code which will refresh your oauth token whenever it gets expired. The approach which i am going to tell in few moments has a benefit that you don't have to modify your code much. The place where you setting your sessionid, you just need to change that place, instead of getting sessionid from login method, you simply need to change with oauth token way.

Here is a complete process to achieve this:


1) Go to your org, Setup->Remote Access, make New remote access entry there for your application. Give return url for the file which will get oauth code returned. In my example, i used this url
http://localhost/oauthsample/tokenprint.php




You will notice that you will get Consumer key and Consumer secret.

2) Make one php file at this location oauthsample/tokenprint.php with below code. The purpose of this code is simply print the oauth code.
<?php var_dump($_REQUEST); ?>


3) Now use your browser, prepare this url and invoke from address bar of browser
https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=<your_consumer_key>&redirect_uri=http://localhost/oauthsample/tokenprint.php
 

As soon you invoke this url, you will see the generated oauth code on screen, copy the "GENERATED CODE" from the browser window.

4) Now use following html code, run it in your browser, by simply double click, fill the values in each field.


<form method="post" action="https://login.salesforce.com/services/oauth2/token"> <input type="hidden" name="grant_type" value="authorization_code"/> <table> <tr> <td> GENERATED CODE </td> <td> <input type="text" name="code" /> </td> </tr> <tr> <td> CONSUMER KEY </td> <td> <input type="text" name="client_id" value=""/> </td> </tr> <td> CONSUMER SECRET </Td> <td> <input type="text" name="client_secret" value=""/> </td> </tr> <tr> <td> REDIRECT URL </td> <td> <input type="text" name="redirect_uri" value="http://localhost/oauthsample/tokenprint.php"/> </td> </tr> </table> <input type="submit" /> </form>











5) After you execute this, you will get xml output on screen something like this:





Here you will get two important things, one Refresh Token and second "access token".

6) Now, in your PHP/Java code you need to replace your session id with this access token. There is another thing in your code "server url", this you need to hard code something like below (make sure to use instance url of your org) :

$mySoapClient = $sfConnection->createConnection('partner.wsdl'); $serverUrl = "https://ap1.salesforce.com/services/Soap/u/25.0/00D90000000Abcd"; $sessionId = "<<ACCESS TOKEN>>"; $mylogin = $sfConnection->attach($serverUrl, $sessionId);



7) Now, how to deal with expired token? For that you need to either make a separate method for it, or simply you need enclosed you code in try, catch block and look for INVALID SESSION exception. That exception will come whenever you try to access server contents and your token is expired. So the idea is, whenever that happen , simply catch that exception and use below code to get new access token. In below code, simply replace the different fields with your org info like consumer key, secret and important "REFRESH TOKEN" which we got in step #5.


<?php function getNewToken(){ try{ $url = 'https://login.salesforce.com/services/oauth2/token'; $fields = array( 'grant_type' => "refresh_token", 'client_id' => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 'client_secret' => "xxxxxxxxxxx", 'refresh_token' => "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" ); foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; } $ch = curl_init($url); //set the url, number of POST vars, POST data curl_setopt($ch,CURLOPT_POST, true); curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //execute post $result = curl_exec($ch); //close connection curl_close($ch); $json_a=json_decode($result,true); return $json_a; }catch(Exception $e){ var_dump($e); } } ?>

You can simply call this method getNewToken() to make new token whenever needed.

You are now all set, now you don't have to worry about user credentials updation or revealing it.

Let me know if you face issue in any step.

Thanks
Aslam Bari

Ruby and Salesforce Integration with SOAP

Saturday, January 15, 2011 by Aslam - The Alexendra
Hi All,
I am not a Ruby guy, but last few days i had to look into this language, moreover in the context of calling apex web service method using Ruby. I love doing this using java and php, even i did in python also, but this time its a challenge for me to achieve this. Its a challenge because lack of documentation and sample codes on net and as a newbie in Ruby world. As every new developer i also searched many times on net but was struggling sometimes setting up Ruby, sometimes rubygems, sometimes things were not working. I left many times work in middle long before also. But searching and searching and i found this blogpost by Andrew very helpful. http://hideoustriumph.wordpress.com/2008/05/05/ws-deathstar-for-the-rest-of-us/.

So most of the things i took from that blog only and here i am describing some sample code how i achieve my task.

1) You first need to install ruby. I had InstantRails 2.0. That fits my need.
2) Now first go to your developer account, Setup->Develop->API, choose "enterprise.wsdl" and save it somewhere on your disk , for example in my case i am saving it as below location.
D:\RubyRails\rails_apps\sfdc\enterprise.xml
3) Open the ruby console
4) Then you need to install "SOAP4R" by this command.
gem install soap4r

When i ran this command, i got errors like "Errno::EADDRNOTAVAIL". Its because my gems were outdated, if this is the same case with you then you need to install first updated gems. so...
5) go to this site http://rubygems.org/pages/download
6) Download the gems and unpack to a directory and go to that directory from the command line
7) Install with:
ruby setup.rb

8) Now issue the command to install soap4r
gem install soap4r

Hopefully this time it will get installed.
9) Now go to that directory where you saved the "enterprise.xml" from command line and issue following command.

ruby wsdl2ruby.rb --wsdl D:\RubyRails\rails_apps\sfdc\enterprise.xml --type client --force

You will see 4 files created into your current directory ('sfdc' in above case)

10) Now here is the code for one extra file which i copied from the above blogpost for easy login
client_auth_header_handler.rb
--------------------------------

require 'soap/header/simplehandler'

class ClientAuthHeaderHandler < SOAP::Header::SimpleHandler
SessionHeader
= XSD::QName.new("rn:enterprise.soap.sforce.com", "SessionHeader")

attr_accessor :sessionid
def initialize
super(SessionHeader)
@sessionid
= nil
end

def on_simple_outbound
if @sessionid
{
"sessionId" => @sessionid}
end
end

def on_simple_inbound(my_header, mustunderstand)
@sessionid
= my_header["sessionid"]
end
end


11) And now here is the final code for doing Login, fetching records from Account object and Printing raw output on screen. Change the username, password and security token as needed.
test.rb
--------------------------------

require 'rubygems'
gem
'soap4r'
require
'soap/soap'
require
'defaultDriver'
require
'client_auth_header_handler'
require
'soap/wsdlDriver'


d
= Soap.new
d.wiredump_dev
= STDOUT

h
= ClientAuthHeaderHandler.new # Create a new handler

l
= d.login(:username => "USERNAME", :password => "PASSWORD" + "SECURITY_TOKEN")

d.endpoint_url
= l.result.serverUrl # Change the endpoint to what login tells us it should be
h.sessionid = l.result.sessionId # Tell the header handler what the session id is
d.headerhandler << h # Add the header handler to the Array of headerhandlers

d.getUserInfo(
"")
d.query(:queryString
=> "select id,name from account")



12) For test the above code, go to ruby console, go to "sfdc" folder and issue following command.
ruby test.rb

13) Now, the main task for which i struggled and not found any easy code on net. Calling apex method from ruby. I tried different things and thought it might be of few lines but may be complex. But finally after so many hit and trial i found that, the code is really very small and easy enough.

14) For example, lets say i want to make one webservice method in Apex to just print one greeting message on screen to passed one Name param. Create one apex class like this.
MyService.cls
--------------------------------
global class MyService{
webservice
static string printMe(string name){
return "Hello " + name;
}
}
15) Save the above class and click on WSDL link/button for this class. You will get one xml file regarding this class. Save it to your disk. For example i am saving this to "service" folder with name "myservice.xml":-
D:\RubyRails\rails_apps\sfdc\service\myservice.xml

16) Now here is the complete code to invoke the "printMe" method, for calling this you also need login first, so the complete example is as below.
test.rb
------------------------------------------------
require 'rubygems'
gem
'soap4r'
require
'soap/soap'
require
'defaultDriver'
require
'client_auth_header_handler'
require
'soap/wsdlDriver'


d
= Soap.new
d.wiredump_dev
= STDOUT

h
= ClientAuthHeaderHandler.new # Create a new handler

l
= d.login(:username => "USERNAME", :password => "PASSWORD" + "SECURITY_TOKEN")

d.endpoint_url
= l.result.serverUrl # Change the endpoint to what login tells us it should be
h.sessionid = l.result.sessionId # Tell the header handler what the session id is
d.headerhandler << h # Add the header handler to the Array of headerhandlers

client
= SOAP::WSDLDriverFactory.new( 'service/myservice.xml' ).create_rpc_driver
client.wiredump_dev
= STDOUT
client.headerhandler
<< h
result
= client.printMe(:name => "Aslam Bari");


17) If all goes well, you will see raw xml output on console printed.
18) Now its time to explore more in your Ruby skills with SFDC :)


Thanks
Aslam Bari