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

Simple Paypal Integration with Salesforce (Step by Step)

Tuesday, January 11, 2011 by Aslam - The Alexendra
Hi All,
Recently I got a need to implement Paypal integration with Salesforce for a basic payment for Merchant Type account, the payments would be from Customers using Credit Cards like Visa etc. I started looking into Paypal methods to find out which is best to implement using Apex, then i found one old blog post very helpful (Unfortunately that blog post is removed recently so not able to paste url here). The method which i preferred is DoDirectPayment. I did some modification in that code and provided in this blog.
The main problem i faced, was not the code, the testing. Like me, many new developers face this problem, thats why i came with this blog to describe step by step procedure to do a simple test with your paypal payment process using salesforce code. This might be useful for the developers who dealing with Paypal first time as well as want to integrate it with Salesforce.




1) Setup one sandbox account.

Go to http://developer.paypal.com and create one account there. After creating, login there only. In the left menu you will find "Test Accounts" link. Click on that.
From the right side screen, you can create multiple test accounts.
For testing purpose generally you need two type of accounts. One is "Seller" and one is "Buyer". Its always better to create preconfigured accounts.
Click on "PreConfigured" link to create one 'Buyer' account, set some amount there.
Click on "PreConfigured" link to create one 'Seller' account, set some amount there.
Click on "PreConfigured" link to create one 'Website Payments Pro' account, used for Merchant (Seller), set some amount there. Dont choose seller account this time because we going to use "DoDirectPayment" API method which need this type of account.

We dont need "Seller" account but i found after some struggle that if you not create any Seller account first then if you create any 'Website Payments Pro', then it will always be "unverified". I am not sure why it is like this. But this is "My Best Practice" that you should first create one Seller account, then create this ''Website Payments Pro' account. And verify, that one is marked as "Verified" as shown in the below screenshot.




2) Test Merchant Account API Setup

Now, select your 'website payments pro' account using radio button there and click 'Enter Sandbox Test Site'.
Login with your password.
Click on Profile link after you login. It will be on top right side.
Click on 'Request API Credentials' link in bottom left side.
Click on 'Set up PayPal API credentials and permissions' link.
Click on 'View API Signature' link and note down your API Username, API Password, API Signature
Click on 'Grant API Access' link on previous screen. Here give your API username and Check all checkboxes and Save
Now you ok with configuration.

2) Salesforce Code setup
Now copy paste following Apex Class code in your org.
Add "https://api-3t.sandbox.paypal.com/2.0/" url into "Remote Site Setting".

In the below code change your API Username, API Password and Signature.
public class PaypalProccessor{
public string amount;
public String result {set;get;}
public string FirstName{get; set; }
public string LastName{get; set; }
public string Addy1{get; set; }
public string Addy2{get; set; }
public string Country{get; set; }
public string CardType{get; set; }
public string CardNo{get; set; }
public string expMo{get; set; }
public string expYe{get; set; }
public string CVV{get; set; }
public string city{get; set; }
public string state{get; set; }
public string zip{get; set; }
public string payer{ get; set; }
public string transid {get; set;}
public string message {get; set; }
public string err {get; set; }
public string rawResponse {get; set; }

public PaypalProccessor(){
city
= '';
state
= '';
zip
= '';
CVV
= '';
expYe
= '';
expMo
= '';
CardNo
= '';
CardType
= 'Visa';
FirstName
= '';
LastName
= '';
Country
= 'US';
Addy1
= '';
Addy2
= '';
payer
= '';
err
= '';
message
= '';
}


public String doDirectPayment()
{

Http h
= new Http();
HttpRequest req
= new HttpRequest();
String url
= 'https://api-3t.sandbox.paypal.com/2.0/';
string un
= 'sel2_1294222298_biz_api1.gmail.com';
string pw
= 'xxxxxxxxxx';
string sig
= 'AwG6Yp1inPr4tudjFvxxxxxxxtAVuo9M5cH1nAqpxK2Biv1RrZa4gX';


String doDirectRequest;
doDirectRequest
= '<soap:Envelope xmlns:soap=' + '\'' + 'http://schemas.xmlsoap.org/soap/envelope/' + '\'' + ' xmlns:xsi=' + '\''+ 'http://www.w3.org/2001/XMLSchema-instance' + '\'' + ' xmlns:xsd=' + '\''+ 'http://www.w3.org/2001/XMLSchema' + '\'' + '>';
doDirectRequest
+= '<soap:Header><RequesterCredentials xmlns="urn:ebay:api:PayPalAPI"><Credentials xmlns="urn:ebay:apis:eBLBaseComponents">';
doDirectRequest
+= '<Username>' + un + '</Username><ebl:Password xmlns:ebl="urn:ebay:apis:eBLBaseComponents">' + pw;
doDirectRequest
+= '</ebl:Password><Signature>' + sig + '</Signature>';
doDirectRequest
+= '</Credentials></RequesterCredentials></soap:Header><soap:Body><DoDirectPaymentReq xmlns="urn:ebay:api:PayPalAPI">';
doDirectRequest
+= '<DoDirectPaymentRequest><Version xmlns="urn:ebay:apis:eBLBaseComponents">1.00</Version>';
doDirectRequest
+= '<DoDirectPaymentRequestDetails xmlns="urn:ebay:apis:eBLBaseComponents">';
doDirectRequest
+= '<PaymentAction>Sale</PaymentAction><PaymentDetails><OrderTotal currencyID="USD">' + amount + '</OrderTotal>';
doDirectRequest
+= '<ShipToAddress><Name>' + FirstName + ' ' + LastName + '</Name><Street1>' + Addy1 + '</Street1><Street2>' +Addy2 + '</Street2>';
doDirectRequest
+= '<CityName>' + city + '</CityName><StateOrProvince>' + state + '</StateOrProvince><PostalCode>' + zip + '</PostalCode>';
doDirectRequest
+= '<Country>' + country + '</Country></ShipToAddress>';
doDirectRequest
+= '</PaymentDetails><CreditCard><CreditCardType>' + CardType + '</CreditCardType><CreditCardNumber>' + CardNo + '</CreditCardNumber>';
doDirectRequest
+= '<ExpMonth>' + expMo + '</ExpMonth><ExpYear>' + expYe + '</ExpYear><CardOwner><PayerStatus>verified</PayerStatus>';
doDirectRequest
+= '<PayerName><FirstName>' + FirstName+ '</FirstName><LastName>' + LastName + '</LastName></PayerName><PayerCountry>' + country + '</PayerCountry>';
doDirectRequest
+= '<Address><Street1>' + Addy1 + '</Street1><Street2>' + Addy2 + '</Street2><CityName>' + city + '</CityName>';
doDirectRequest
+= '<StateOrProvince>' + state + '</StateOrProvince><Country>' + country + '</Country><PostalCode>' + zip + '</PostalCode></Address>';
doDirectRequest
+= '</CardOwner><CVV2>' + CVV + '</CVV2></CreditCard></DoDirectPaymentRequestDetails>';
doDirectRequest
+= '</DoDirectPaymentRequest></DoDirectPaymentReq></soap:Body></soap:Envelope>';

req.setBody(doDirectRequest);

req.setEndpoint(url);
req.setMethod(
'POST');
req.setHeader(
'Content-length', '1753' );
req.setHeader(
'Content-Type', 'text/xml;charset=UTF-8');
req.setHeader(
'SOAPAction','');
req.setHeader(
'Host','api-aa.sandbox.paypal.com');
HttpResponse res
= h.send(req);
String xml
= res.getBody();
rawResponse
= xml;
system.debug(
'::' + rawResponse);
XmlStreamReader reader
= res.getXmlStreamReader();
result
= readXMLResponse(reader,'Ack');
reader
= res.getXmlStreamReader();
err
= readXMLResponse(reader, 'LongMessage');

if (result == 'Success')
{
reader
= res.getXmlStreamReader();
transid
= readXMLResponse(reader, 'TransactionID');
system.debug(
'::' + transid );
}
else
{
result
= err;
}
return result;
}

public String readXMLResponse(XmlStreamReader reader, String sxmltag)
{
string retValue;
// Read through the XML
while(reader.hasNext())
{
if (reader.getEventType() == XmlTag.START_ELEMENT)
{
if (reader.getLocalName() == sxmltag) {
reader.next();
if (reader.getEventType() == XmlTag.characters)
{
retValue
= reader.getText();
}
}
}
reader.next();
}
return retValue;
}

public String pay(){

err
= '';
if (FirstName == '')
err
= err + 'You must enter a First Name.\n';
if (LastName == '')
err
= err + 'You must enter a Last Name.\n';
if (Addy1 == '')
err
= err + 'You must enter an Address.\n';
if (city == '')
err
= err + 'You must enter a City.\n';
if (state == '')
err
= err + 'You must enter a State.\n';
if (zip == '')
err
= err + 'You must enter a Zip.\n';
if (CardNo == '')
err
= err + 'You must enter a Credit Card Number.\n';
if (expMo.length() != 2)
err
= err + 'Expiration month must be in the format MM.\n';
if (expYe.length() != 4)
err
= err + 'Expiration year must be in the format YYYY.\n';

if (amount == '0')
{
err
+= 'Amount 0 can not process.\n';
message
= err;
}
message
= err;
if (err == '')
{
message
= doDirectPayment();
}

if (message == 'Success')
{

}
else
{
//pr = null;
}
return message;
}

}


3) Run and Test
Now you can use below code to do a sample payment. Run this code either on your VF screen or from System Log screen.
PaypalProccessor p = new PaypalProccessor();
p.city
= 'ajm';
p.state
= 'CA';
p.zip
= '4534';
p.CVV
= '';
p.expYe
= '2016';
p.expMo
= '01';
p.CardNo
= '4028398122647025';
p.CardType
= 'Visa';
p.FName
= 'aslam';
p.LName
= 'bari';
p.Country
= 'US';
p.Addy1
= '44';
p.Addy2
= '433';
p.payer
= 'abuy_1294681533_per@gmail.com';
p.amount
= '100';
string message
= p.pay();
string transactionid
= p.transid;
system.debug(
'#### Message::' + message);
system.debug(
'#### Transaction Id::' + transactionid);

You will see that you got one Transaction Id and 'Success' message. If you dont find success message, then print "err" property to check whats wrong.
Log into your test pro account and check your balance, it might be increased. If so, its all fine :)


Thanks
Aslam Bari

JQuery 'Sticky Notes' integration with 'Salesforce Tasks'

Saturday, December 4, 2010 by Aslam - The Alexendra
Hi All,
Here i came up again with something interesting stuffs. I found recently one cool JQuery Sticky Notes plugin here Tutorialzine [http://tutorialzine.com/2010/01/sticky-notes-ajax-php-jquery/]. Then i came up with an idea to integration this cool feature with Salesforce Tasks.



Sorry, this time i can't share a Force.com sites link to show you a demo because this project inloves with Tasks and Users objects, that has Public Site access limitation, thats why, Here is a simple Screencast demo i created, check it out.

Click and View:
Sticky_notes_salesforce

Sticky Dashboard:


Add Note Screen:

I created this complete stuff in couple of hours so it may have many flaws. I am thinking to improve this on following points:

1) Need to push more fields (Status, Priority etc on Add note and dashboard screen for Sticky Tasks Page)
2) Reassign a task to other
3) Also, thinking to integrate this with my previous stuff (VFTalkie), which is voice enabled.
4) Thinking to integrate this with Twilio voice system also, so you no need to write your task, just call and your task will be created on Sticky home :) (Isn't it cool).
5) And many more....

If you need the code just mail me, and As always, provide me your valuable suggestions.

Thanks
Aslam Bari
Posted in | 17 Comments »

Easy SF Portlets With jQuery (Project)

Tuesday, October 12, 2010 by Aslam - The Alexendra
Hi All,
With my previous experience with many projects it seems "one special" kind of requirement comes always and that always needs me and my team to build every time from scratch and takes time to complete. Yes, this is "Portlets Home" page for clients with a drag and drop boxes on a single page, each box contains different information section bla bla. Yes, requirements for different clients always differ from each other, but the BASIC building blocks are same for all. All needed a Home page with 3 or 4 column boxes with title and information. All boxes must be draggable etc. These building blocks every time needs attest 30-50 hours to complete. Some people uses ExtJs to build it, some uses jQuery and other JS Framework.



So, here i have come up with a "SF Portlets" project. The beauty of this project is , it is configurable , easy to install/setup, and you don't need to think about BASIC BUILDING BLOCKS, all is created and ready to use for you, you just need to concentrate on client extra requirement From that point where this project Ends.


I have shared this project on Code Share here:-
http://developer.force.com/codeshare/project/sf-portlets

You can also directly install the App from the below link:-
https://login.salesforce.com/?startURL=%2Fpackaging%2FinstallPackage.apexp%3Fp0%3D04t90000000Pl0v


Portlet Configuration Screen:-

You need to create at least one Portlet Config record with all given flags and fields. Also create your portlets and one Attachment for your portlet logo as shown below in this screen.


You can choose multiple themes from the Portlet Config picklist as below:



Default Theme



Redmond Theme



Black-Tie Theme



Create Different Types of Portlets as per your need
HTML
Will render whatever html you provided here as it is.



Text
Will show your text simply on screen.



URL
Will load the external data from given url (It must be Public accessible url). If you give WAP url then it must be good because that is perfect for a small porlet screen.



Query
Will run your SOQL query and show your data in tabular format (Please provide optimized and limit in your query for better load data). Query example:-

SELECT Name, Email, Phone FROM Contact ORDER BY LastModifiedDate DESC LIMIT 10



Activate/Deactivate Portlets
You can also set Activate or De-Activate any portlet which is you want or not to show on the Portlet Home using "Active" field flag(checkbox)



Here is the working demo for your view, it is hosted on Salesforce Public Sites.
http://labsprojects-developer-edition.ap1.force.com/

Future of the Project

Save Portlets State
Right now I am not storing user's drag and drop of the portlet on particular position. Right now all portlets comes as per last modified date desc order. I am planning to store their states also.


More Portlet Types
In my view, it must be very useful for basic portlets implementation with given options. I am thinking to extend it in terms of many aspects like support for more Portlet Types like:

Report
Will accept Report link and will show report details in portlet

Chart
Will accept Report link and will show its chart in portlet

Dashboard
Will accept Dashboard name and its component, and it will show that component in Portlet

Image
Will accept one Resource, Document name or link and will show that image

Attachment
Will accept one link of the attachment and will show in Portlet

Detail
Will accept a Id of the Record (Account, contact or opportunity), and will show that detail in this area

YouTube
Will accept a YouTube url and show that video in this portlet.

Feeds
Will accept any RSS Feed and show the details here.

And Much Much More…

View/Download complete documentation here:-

SF Portlets

So, give it a try, install and test it. Let me know for any feedback so that i can enhance it.



Thanks
Aslam Bari
Posted in | 19 Comments »

Cool Dock Menu for your Salesforce Site

Monday, August 16, 2010 by Aslam - The Alexendra
Hi All,
Yesterday i was exploring some jQuery menus and found some cool jqDock top menu which can be used in your Salesforce Site.
Here is the link for jqDock Menu.



Here is the link for working demo which uses this jqDock menu.

jqDockDemo link

Mail me if you need its code :)

Thanks
Aslam Bari

VFTalkie : Enable your Visual Force pages to speak !!!

Monday, August 2, 2010 by Aslam - The Alexendra
Hi All,
Yesterday i was searching for some jQuery related plugins and found two very useful web services / plugins on net. Then i decided to integrate both of this services to Salesforce to get something useful.

jTalk :- Speech-enable your website!. It provides you much useful API to convert your text to speech on the fly. Go for more info here http://www.jtalkplugin.com/.

Dewplayer :- Dewplayer lecteur mp3 en flash! It provides a very cool flash mp3 player . Go for more info here http://www.alsacreations.fr/dewplayer.html.



The idea is simple. Whatever output data you have on your vf screen (Output Fields). Convert that into MP3 on run time using jTalk API and Pass it to a supporting player like Dewplayer.

Isn't it cool :)

Here is the simple demo for this integration:-

VF Talkie Account Detail

Here is the more interactive demo for this integration:-
VF Talkie Contact List

For integrating this into your VF page you just need to add VFTalkie component on your page with text as below:-

<c:vftalkie val="{!accRecord.Description}">

For getting complete project code click here.

So, make sure your speaker is on then give it a try :)

If any questions, mail me at aslam.bari@gmail.com

Hope you enjoyed.

Thanks
Aslam Bari

Salesforce Solutions Browsing in Interactive JQuery Way

Wednesday, July 28, 2010 by Aslam - The Alexendra
Hi All,
Hope you all aware of Saleforce Solutions Feature. Each solution is associated with one or more Categories which is called 'Solution Category'. Salesforce provide some basic solution browsing feature. I was thinking to implement something more Interactive UI perspective.

Then i found one jQuery solution for this here by filamentgroup.
I found it is very useful for Hierarchical Data representation. It actually an iPod style browsing categories. So i used this idea and implemented Solutions Browsing in Salesforce using this jQuery menu way But i think this can be used to implement any object records hierarchical data like Account and parent accounts, Users and their managers etc.


Here is the working demo for this:-
http://labsprojects-developer-edition.ap1.force.com/solutions_menu_demo

Try to browse AllCategory->Entertainment->Movies OR
All Category -> Breaking News -> Politics

You will see on demand filter results. For rest of the menu items i just provided all records for demo purpose.

If you need the complete code for this demo then mail me at: aslam.bari@gmail.com

Thanks
Aslam Bari
Posted in | 2 Comments »