51
Under the Hood of a Salesforce.com Business Application Developers Emin Gerba: Salesforce.com Samarpan Jain: Salesforce.com

Under the Hood of a Salesforce.com Business Application

Embed Size (px)

DESCRIPTION

Salesforce.com uses the Force.com cloud platform to develop internal applications as well as customer-facing applications. In this session, we'll take a close look at how salesforce.com built its App Store application. Learn how to build complex, mission-critical applications that can scale, integrate with other systems, and provide the best user experience possible using Force.com pages (Visualforce), Force.com code (Apex), and the full platform stack.

Citation preview

Page 1: Under the Hood of a Salesforce.com Business Application

Under the Hood of a Salesforce.com Business Application

Developers

Emin Gerba: Salesforce.comSamarpan Jain: Salesforce.com

Page 2: Under the Hood of a Salesforce.com Business Application

Safe HarborSafe harbor statement under the Private Securities Litigation Reform Act of 1995: This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services.

The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of intellectual property and other litigation, risks associated with possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-K for the most recent fiscal year ended January 31, 2010. This documents and others are available on the SEC Filings section of the Investor Information section of our Web site.

Any unreleased services or features referenced in this or other press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.

Page 3: Under the Hood of a Salesforce.com Business Application

Agenda

• Salesforce.com application landscape – a quick overview

• Major functional areas running on Force.com

• Deep-dive on Checkout & Quote-to-Cash

• Q&A

Page 4: Under the Hood of a Salesforce.com Business Application

Salesforce.com application landscape

Page 5: Under the Hood of a Salesforce.com Business Application

Human Capital Management

Customer Service

Sales & Marketing DevelopmentFinance Enterprise

InfrastructureCompliance

and Risk

• Performance Management

• Time-off Manager• Volunteer Tracking• Recruiting

Management• Callidus Comp Plan

Communicator• Kelly Contingent

Worker Outsourcing• Workday HCM• ADP payroll

• Coupa Procure to Pay

• Concur T&E Manager

• Manhattan Space & Lease Management

• Ruesch Payment Services

• Oracle eBusiness Suite Financials

• Sabrix for Tax• Hyperion Financial

Management and Planning

• Salesforce Automation (“Org 62”)

• Opportunity to Quote• Quote to Cash• Checkout (e-

commerce & account management)

• Event Management• Access Hoovers• Clicktools Survey Tool• Conga Mail Merge• D&B• Sales Genius• Mindjet Org Charting • Ribbit Voice to Text • Inside View Account

News • Click to Dial (CTI

Integrations)• Instant Service Live

Chat• Xactly Sales

Compensation• Comergent

Configurator• CyberSource

payment gateway• DocuSign e-signature

portal• Aptus agreements

management

• Salesforce Customer Service & Support Portal

• Salesforce Knowledge Base

• Salesforce Ideas• Appirio Services

Management• Plateau Learning

Management

• IT Help Desk• Asset Management

Object • iLinc Web Meetings• Live Ops Global

Contact Center Infrastructure

• Google Docs• Omniture Web

Analytics• Business

Objects/SPSS BI• OpenCms Web CMS• Ping Identity

Management• Microsoft Exchange• Perforce Software

Config Mgmt• Oracle BPEL Process

Manager• Cisco Call Manager

• Agile Scrum and Bug Management

• Program and Resource Management

• Test Repository

• Audit Controls Management

• Business Impact Analysis

• Change Management

Legend• Salesforce.com products• Built on force.com• SAAS/PAAS Products• On Premise Applications

Page 6: Under the Hood of a Salesforce.com Business Application

Major Business Applications on Force.com

•Sales force Automation (campaign, lead, opportunity management)

•Checkout (eCommerce & account management)•Quote to Cash•Customer Service & Support Portal•Event Management•Agile Scrum & Bug Management•Program & Resource Management•Performance Management•Time-off Manager•Volunteer Tracking•Recruiting Management• IT Help Desk•Change Management

A View from the salesforce.com IT Cloud

Page 7: Under the Hood of a Salesforce.com Business Application

Checkout & Quote-to-Cash

Page 8: Under the Hood of a Salesforce.com Business Application

It covers a lot of ground

e-commerce portal

quoting & approvals

configuratorservicerenewal

forecasting

contract & order

management

CyberSourcepayment processor

DocuSign e-signature

portal

CyberSourcepayment processor

opportunity management

billing & credit memo

engine

customer notifications

paymentmanagement

service renewal &

suspension

usage entitlements & tracking

financials

force.com cloud on-premise

sales commissions

XactlyIncent

Page 9: Under the Hood of a Salesforce.com Business Application

Customer self-service account management and purchase of SFDC and partner services & products.

Streamlined electronic interaction between customers and sales: publish quotes, e-signature, place orders, etc.

Advanced quoting & approval flows for sales; craft custom deals, including custom pricing, product terms, contract terms, etc.

Sophisticated approval flows defined by sales ops, finance, and legal, with rule based and human approvals.

Renewals forecasting layer that tracks current vs. projected service levels across our customer base by product category.

Page 10: Under the Hood of a Salesforce.com Business Application

Order management application that enforces data integrity, stamps data required by finance for revenue recognition and even stages data for sales commission payouts.

Service enablement & suspension based on activated orders, received payments, etc.

Billing & credit memo engine that creates invoices and credit memos based on orders

Usage entitlement creation based on orders, actual usage tracking.

Back-end integrations that pushes invoices & credit memos from Salesforce to Oracle Financials for creation of accounting entries, brings back tax calc

Page 11: Under the Hood of a Salesforce.com Business Application

Technologies

Customer Portal for e-commerce, utilizing High Volume portal user

Apex triggers, classes, and web services to implement core business logic

Batch Apex to implement bulk functionality. Employs software development best practices, like object orientation, design patterns, etc.

Visualforce to implement streamlined, scalable, tailored look & feel.

Salesforce.com sharing (private), user profiles to enforce granular data access security.

3rd party configurator engine and Force.com to provide comprehensive quoting capabilities. Bi-directional communication between Salesforce.com and configurator implemented using Apex call-outs and Apex web services.

Page 12: Under the Hood of a Salesforce.com Business Application

Technologies

Integration to CyberSource payment gateway, using hosted CC/DD page using silent https post.

Multiple approval flows leveraging standard Salesforce.com approvals engine, additional custom control logic in Apex driven by metadata

Approval requests, including quote details and cumulative approval comments, sent out via email. Executives able to approve quotes via email on their mobile devices. Utilizes Apex, Visualforce e-mail templates.

Integrates to DocuSign platform for electronic signature, using AppExchange package, Wsdl2Apex functionality, Apex.

A caching layer in Apex that caches information across request event handlers – e.g. before insert to after insert; allows for significantly more data to be processed with flat memory consumption

Page 13: Under the Hood of a Salesforce.com Business Application

The back-end

e-commerce portal

quoting

configuratorservicerenewal

forecasting

contract & order

management

CyberSourcepayment processor

DocuSign e-signature

portal

CyberSourcepayment processor

opportunity management

billing & credit memo

engine

customer notifications

force.com cloud on-premise

sales commissions

XactlyIncent

focus

paymentmanagement

service renewal &

suspension

financials

usage entitlements & tracking

Page 14: Under the Hood of a Salesforce.com Business Application

You will see examples of:

• How we used Design Patterns to implement a scalable, flexible

billing engine

• Use of SOQL to implement complex filtering criteria

Page 15: Under the Hood of a Salesforce.com Business Application

Flyweight Pattern

Your design requires a whole lot of objects that would be too expensive to create separately.

The objects can be made shareable; they can be designed so they do not contain contextual state. Perfect for stateless business logic!

Sharing objects would significantly decrease the number of needed objects and memory requirements.

Factory Pattern

You wish to make your client independent of the actual subclasses of the product.

You wish to centralize the creation logic in one place.

Page 16: Under the Hood of a Salesforce.com Business Application

Using Design Patterns in Apex - Flyweight

public class GroupAlgorithm implements BaseBill.TrxAlg{

public boolean Execute(List<BaseBill.TransactionClass> trx_list){...BObj.OrderClass lhOrder = (BObj.OrderClass)trx_list[0];BObj.OrderClass rhOrder = (BObj.OrderClass)trx_list[1];/* 1. Forced separation flag */if(lhOrder.GetSObject().BillSep__c || rhOrder.GetSObject().BillSep__c){

return false;}

/* 2. Contract */if(lhOrder.GetSObject().Ctr!=rhOrder.GetSObject().Ctr){

return false;}..../* 4. Shipping Address */String lhCountry, lhState, lhCity, lhZIP, rhCountry, rhState, rhCity, rhZIP;

lhCountry=lhOrder.GetSObject().ShippingCountry!=null?lhOrder.GetSObject().ShippingCountry : lhOrder.GetSObject().Contract.ShippingCountry;

....

if(lhCity.equalsIgnoreCase(rhCity) && lhState.equalsIgnoreCase(rhState) && lhZIP.equalsIgnoreCase(rhZIP)){….

}else{if(lhCity.equalsIgnoreCase(rhCity)) return true;

}return false;

} }

Page 17: Under the Hood of a Salesforce.com Business Application

Using Design Patterns in Apex – Flyweight

public class …{

/* Provide functionality for the object to compare itself to the supplied object using the provided TrxAlgorithm */ public boolean DoCompare(TrxAlgFactory trxAlgFact, TrxClass trx){ List<TrxClass > trxList = new TrxClass []{this, trx}; TrxAlg trxAlg = trxAlgFact.getAlgorithm(trxList); return trxAlg.Execute(trxList); } /* Invokes the Execute method on the provided algorithm object and passes itself to it. It also must invoke the same method on all its children */ public virtual void DoCreate(TrxAlgFactory trxAlgFact){ List<TrxClass > trx = new TrxClass []{this}; TrxAlg trxAlg = trxAlgFact.getAlgorithm(trx); trxAlg.Execute(trx); if(this.children!=null){ for(TrxClass child:this.children){ child.DoCreate(trxAlgFact); } } }}

Page 18: Under the Hood of a Salesforce.com Business Application

Using Design Patterns in Apex - Factory

// This method decides the algorithm to be returned based on the nature of the object public ...TrxAlg getAlgorithm(List<...TrxClass> trxList){

...if(containsHdr(trxList)){

return new InvoiceHeaderCreationAlgorithm();}else if(containOdr(trxList)){

return new GroupAlgorithm();}else if(containsItemBFZero(trxList)){

return new BFZeroAlgorithm();}else if(containsItemBFNotZero(trxList)){

....}else{

throw new ...InvalidDataException(...);}return null;}

}

Page 19: Under the Hood of a Salesforce.com Business Application

Making SOQL do complex filtering

private OrdItem[] getBilOrds(String revOwn, Integer maxRows , String ctr, ...){

OrdItem[] billRows; String baseQuery = 'SELECT Id, ListPrice, …’ + 'FROM OrdItem '+ 'WHERE Ord.ActDate!=null AND Ord.Status != \'Canceled\' AND '+

'(Ord.Cont.EndDate > '+String.valueOf(System.Today())+' OR (PE.BillFreq=0 AND ’+

‘Ord.Cont.EndDate = '+String.valueOf(System.Today())+')) AND '+

‘(OriItemId!=null OR (BillThrDate__c = null AND '+

‘(OIEffectiveDate__c - Ord.Cont.OrdPrebillDays <= '+String.valueOf(System.Today())+')) OR '+

'(BillThrDate__c != null AND (OIEndDate__c - BillTrhDate__c > 0) AND '+

'PE.BillFreq !=0 AND (BillThrDate__c - Ord.Cont.OrdPrebillDays < ‘+String.valueOf(System.Today())+'))) AND

Ord.Cont.Id=\''+ctr+'\'';

Page 20: Under the Hood of a Salesforce.com Business Application

Order Management

e-commerce portal

quoting & approvals

configuratorservicerenewal

forecasting

contract & order

management

CyberSourcepayment processor

DocuSign e-signature

portal

opportunity management

billing & credit memo

engine

paymentmanagement

service renewal &

suspension

usage entitlements & tracking

financials

force.com cloud on-premise

XactlyIncent

focus

XactlyIncent

CyberSourcepayment processor

customer notifications

sales commissions

Page 21: Under the Hood of a Salesforce.com Business Application

You will see examples of:

• How we cache data in Apex to reduce resource usage

Page 22: Under the Hood of a Salesforce.com Business Application

Transactional caching in Apex

Page 23: Under the Hood of a Salesforce.com Business Application

Cache implementationpublic class OrderCache extends BaseCache

public override Map<Id, SObject> getCache(Set<Id> sObjectIdList, String soqlQuery, boolean reQuery, boolean lockRecords) {

//If the records need to be locked,we add to the list if(lockRecords) {

lockedIds.addAll(sObjectIdList); } //Doing the search first because if the map already contains the required orders, then we do not do any soql and work with the existing map Map<Id, Order> selectedOrders = searchCache(sObjectIdList); if(reQuery || selectedOrders == null) { //If we are requerying either due to forced requery or the selected ids are not there in the cache, see if the cache size is beyond threshold ….

selectedOrders = getOrderInfo(sObjectIdList, soqlQuery); orderMap.putAll(selectedOrders); } return selectedOrders;}

public override Map<Id, SObject> addToCache(List<SObject> sObjectList) { if(orderMap == null) { orderMap = new Map<Id, Order>(); } for(sObject glSObject : sObjectList) { if(glSObject instanceOf Order) {

Order order = (Order) glSObject; orderMap.put(order.Id, order);

} } return orderMap; }

public override void persist() { if(orderMap != null && orderMap.size() > 0) { update orderMap.values(); …

Page 24: Under the Hood of a Salesforce.com Business Application

Using the cache

public class OrderInfo { //Caching all of the order/order item related info

public static EntityCache orderCache = new OrderCache(); …. public static Map<Id, List<OrderItem>> getOrdersWithOrderItems(List<Order> orders, Boolean lockRecords) {

Set<Id> orderIds = new Set<Id>(); orderIds.addAll(eimUtils.getIds(orders)); Map<Id,Order> orderMap = (Map<Id, Order>)orderCache.getCache(orderIds, '', false, lockRecords); Map<Id, List<OrderItem>> orderToOrderItemsMap = new Map<Id, List<OrderItem>>(); for(Order sOrder:orderMap.values()) {

if(sOrder.OrderItems != null) orderToOrderItemsMap.put(sOrder.Id, sOrder.OrderItems); } return orderToOrderItemsMap;

}

//Adds any order/order item to the cache. If the object already exists, the new object will replace it.

public static void addToOrderCache(Order sOrder) {

orderCache.addToCache(sOrder); }}

Page 25: Under the Hood of a Salesforce.com Business Application

You will see examples of:

• Use of language override and transactional data to set locale

without relying on the browser locale

Page 26: Under the Hood of a Salesforce.com Business Application
Page 27: Under the Hood of a Salesforce.com Business Application
Page 28: Under the Hood of a Salesforce.com Business Application

Using language override

<apex:page controller="InvoiceController" title="Salesforce" language="{!language}" showHeader="false"> <div id="sfdcheader"> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td valign="top" align="left">{!FromName}<br/> <apex:outputtext escape="false" value="{!FORMAT_ADDRESS(divInfo.oldFromStreet1, divInfo.oldFromStreet2__c, divInfo.oldFromCity,

divInfo.oldFromState__c, divInfo.oldFromZip,divInfo.FromCountry, '<br/>')}"/></td>

</apex:outputText> … <tbody> <tr> <th width="160" align="left">{!$Label.tableService}</th> … <th width="93" class=“num">{!$Label.tableQty} … <th width="90" class="currency">{!$Label.tableTotal}</th> </tr> <apex:repeat value="{!orderData.lineWrappers}" var="tranLine"> <tr> <td>{!tranLine.lineNo}</td> <td class="num">{!FORMAT(tranLine.line.Quantity)}</td> <td class="currency">{!tranLine.formatTotalPrice}</td> </tr> </apex:repeat></apex:page>

Page 29: Under the Hood of a Salesforce.com Business Application

Using transactional data to determine locale

public with sharing class InvoiceController extends TransactionController { ….

public String getCoverSheetName() { String firstName = getname(getContract().MailingFirstName__c); String lastName = getName(getContract().MailingLastName__c); String salutation = getname(getContract().MailingSalutation__c); String result = ''; …. if ('ja' == getContract().BillingLanguage || 'ko' == getContract().BillingLanguage ||

getContract().BillingLanguage.contains('zh')) { return result + lastName + ' ' + firstName + ' '+salutation;

} else { return result + salutation +' '+ firstName + ' ' + lastName;

} return result; } public String getLanguage() { Contract c = getContract(); if (c == null) return 'en_US'; if (getContract().BillingLanguage == 'en_US') { if (c.RevenueOwner__c == 'ROWH' || c.RevenueOwner__c == 'US') {

return 'en_US'; } else if(c.RevenueOwner__c == 'EU' || c.RevenueOwner__c == 'ASIA PAC') {

return 'en_GB'; } } return c.BillingLanguage; }}

Page 30: Under the Hood of a Salesforce.com Business Application

Checkout

e-commerce portal

quoting & approvals

configuratorservicerenewal

forecasting

contract & order

management

CyberSourcepayment processor

DocuSign e-signature

portal

CyberSourcepayment processor

opportunity management

billing & credit memo

engine

customer notifications

paymentmanagement

service renewal &

suspension

usage entitlements & tracking

financials

force.com cloud on-premise

sales commissions

XactlyIncent

focus

Page 31: Under the Hood of a Salesforce.com Business Application

You will see examples of:

• Use of Visualforce components to achieve flexible look & feel

• Use of metadata to control display of content blocks

• Use of iFrames in Visualforce to display external content and

integrate with an e-signature portal

• Use of Visualforce to perform silent post and integrate with a

payment processing gateway

Page 32: Under the Hood of a Salesforce.com Business Application
Page 33: Under the Hood of a Salesforce.com Business Application

Building a header component

<apex:component controller="StoreNavBarController" >

<apex:stylesheet value="{!URLFOR($Resource.styleszip, '/common/css/styles.css')}"/><apex:includeScript value="{!URLFOR($Resource.styleszip, '/common/js/sf.js')}"/><apex:attribute ... />

<div id="pagewrap" style="width:980px;text-align:left;overflow: visible;"><div class="sfLogo">

<apex:image styleClass="logo" ...sf_logo_onblue.png')}" width="159" height="124" ... /></div><div id="header">

<div class="links">

<span class="welcome"> {!$Label.store_welcome},&nbsp; <em>{!userName}</em> ...

</div><!-- .links --><span class='endofcontainer'><!-- .endofcontainer --></span>

</div><!-- header --> ...<div id="bodycontent">

<apex:outputText rendered="{!FromPage != '062'}"><apex:form >

<ul id="nav" style="padding-left:0px"> ...<!-- trial org --><apex:outputText rendered="{!stat}"> ...

<apex:outputText rendered="{!FromPage == 'quoteDoor'}"><li...>{!$Label.store_editions}</li>

</apex:outputText> ...</apex:outputText>

</ul></apex:form>

</apex:outputText> </apex:component>

Page 34: Under the Hood of a Salesforce.com Business Application

Components in action

<apex:page id="thePage" showHeader="false" standardStylesheets="false" controller="FastBuyPageController"> <c:storeOmniture pgName="Fast Buy Quote Edit Form"/> <c:storeMenu FromPage="fastbuyedit"/> <apex:outputPanel id="mainpage" rendered="{!!showErr}"> <div id='bodycontent'> <apex:form id="editForm"> <!-- form --> <div id="subscriptionSection">

<apex:outputPanel rendered="{!showErrorBubble}"><div id="licenseSelection"><div id="totalPrice"><b>{!$Label.store_total}:&nbsp;&nbsp; <apex:outputText value="{!format_currency(quote.CurrIsoCode,licPrd.Total_Price__c)}"/></b></div> ….<apex:inputText value="{!ordQty}" id="licText" rendered="{!!isLmtSeats}" /><apex:commandLink action="{!save}">{!$Label.store_update}</apex:commandLink></div><p class="ccMessage">* {!$Label.store_creditcardcharged}</p>

</div> <!-- licenseSelection --> ……… </apex:form> <!-- form --> </div><!-- #bodycontent --> </apex:outputPanel> <c:storefooter /></apex:page>

Page 35: Under the Hood of a Salesforce.com Business Application

The brains of the page controller

public class StoreNavBarController{

private List<StoreConfig__c> storeConfigs;public StoreNavBarController(){

getAccountExecInfo();// get all store config objects for this edition

storeConfigs = StoreUtil.getStoreConfigs();}public boolean getStat(){

return StoreUtil.getStat(); }

public String getUserName(){return UserInfo.getName();

}

private void getAccountExecInfo() {Exception err = null;try {

StoreUtil.AccountExecInfo aeInfo = StoreUtil.getAccountExec(UserInfo.getUserId()); aeName = aeInfo.name; … return;} catch(Exception e) { err = e; …}// return defaults if cannot get real AE infoaeName = Label.store_ae_name_default;aePhone = Label.store_ae_phone_default;

}

Page 36: Under the Hood of a Salesforce.com Business Application

Metadata Configuration

public static List<StoreConfig__c> getStoreConfigs() {try {

String orgEdition = StoreControllerUtil.getOrgEdition();return [select Id, HideRequestSalesAssistance__c, MaximumSeats__c, …..

HideAccountContact__c, HideAdditionalProduct__c,HideLowerEditions__c, EditionName__cfrom StoreConfig__c where EditionName__c =: orgEdition];

} catch (Exception e) {return null;

}}

}

Page 37: Under the Hood of a Salesforce.com Business Application

E-signature Portal Integration

Page 38: Under the Hood of a Salesforce.com Business Application
Page 39: Under the Hood of a Salesforce.com Business Application

Staging a document for e-signature

public void docusignSetup() {…// launch docusign with new envelope// 1. Create documentPageReference page = new PageReference(…);

Blob myblob = page.getContentAsPDF();SFDCToDocusignAPI.DocuSignDocument mydoc = new SFDCToDocusignAPI.DocuSignDocument('Quote Legal View','pdf',myblob);

// 2. Create recipient

SFDCToDocusignAPI.DocusignRecipient toReceip = new SFDCToDocusignAPI.DocusignRecipient(this.portalUserInfo.Contact.Email,…);

// 3. Create connection (contains envelope)

SFDCToDocusignAPI env = new SFDCToDocusignAPI('Embedded Signing',‘Store Flow',…);

// 4. Add document to envelopeenvelope.addDocuments(mydoc);

// 5. Add recipient to envelopeenvelope.addRecipients(toReceip);

// 6. Create the Portal configuration (Request the token) // change the URL based on whether this is inline or

SFDCToDocusignAPI.DocusignPortalInfo portInfo = new SFDCToDocusignAPI.DocusignPortalInfo(email,

'https://...salesforce.com/apex/storeorderlanding?il=...);

String retUrl = env.RequestDSToken(portInfo);this.docusignPage = new PageReference(retUrl);this.docusignPage.setRedirect(true);...

Page 40: Under the Hood of a Salesforce.com Business Application

Using iFrame to serve external content

<apex:page title="Docusign Entry" controller="DocusignInitController" action="{!docusignSetup}" showHeader="false" standardStylesheets="true">

<c:storeOmniture pgName="Docusign Initialization"/><c:storeMenu FromPage="docusign" rendered="{!!isCancel}"/>

<apex:iframe src="{!docusignUrl}" rendered="{!!isCancel && !hasError}"/>

<apex:outputText rendered="{!hasError}" value="This quote is already processed"/>

<apex:outputText rendered="{!isCancel}"><script type="text/javascript">

parent.goBackToQuote();</script>

</apex:outputText>

<c:storefooter rendered="{!!isCancel}"/></apex:page>

Page 41: Under the Hood of a Salesforce.com Business Application

Payment Processing Gateway Integration

Page 42: Under the Hood of a Salesforce.com Business Application
Page 43: Under the Hood of a Salesforce.com Business Application

Credit Card processing using silent post in Visualforce

<apex:page id="superRoot" controller="StoreCreditCardController" title="{!$Label.store_enterCCDetails}" showHeader="false" standardStylesheets="true"> <apex:includeScript value="{!$Resource.cardvalidation}"/> …

<apex:form action=“{!CreditCardSystemUrl}"> … <input type="text" name="lastName"> <select name="card_cardType" id="ccTypes"><br />

<option value="">{!$Label.store_select}</option><option value="001">Visa</option> …

</select> <input type="text" name="cardNumber"/> <select name="card_expirationMonth" id="cardExpMnth">

<option value="01">01</option> ... </select> <select name="card_expirationYear" id="cardExpYr">

<option value="2010">2010</option> … </select>

<input type="hidden" name="orderPage_receiptResponseURL" value="https://.../apex/ReceiptPage" /><input type="hidden" name="orderPage_signaturePublic" value="{!InsertSignature}"/><input type="hidden" name="merchantID" value=…/> …

</apex:form></apex:page>

Page 44: Under the Hood of a Salesforce.com Business Application

The controller behind silent post

public class StoreCreditCardController { … // This method gathers the data and calls a Crypto class method to generate signature

public String InsertSignature(String amt, …){ String data = getMerchantID() + amt + …; return EncodingUtil.base64Encode(Crypto.generateMac('HmacSHA1',Blob.valueOf(data),

Blob.valueOf(getPublicKey()))); }  public boolean VerifySignature(String data){ return (tranField == EncodingUtil.base64Encode(Crypto.generateMac('HmacSHA1',Blob.valueOf(data),

Blob.valueOf(getPublicKey())))); }

Page 45: Under the Hood of a Salesforce.com Business Application

Landing for silent post

<apex:form > <apex:actionFunction name="callReceipt" action="{!initi}" /> … <div id="waitingBlock" > </apex:outputText> <div id="imgBlock" style="padding-left:100px"> <img src="{!URLFOR($Resource.styleszip,'/images/waiting_spin.gif')}"></img></div> </div> <!-- waitingBlock --></apex:form>

… and the controller

public class StoreReceiptController{ public PageReference initPage(){ reason = ApexPages.currentPage().getParameters().get('reason');

  if(VerifySignature()){if(reason == '100'){ receiptFwd = new PageReference('/‘…&reason='+status );}else{ //Read the reason code and redirect the user to credit card page

receiptFwd = new PageReference('/apex/creditcardform?...&reason='+status );}

Page 46: Under the Hood of a Salesforce.com Business Application

Key Take Aways

You can run a very complex, mission-critical application on Force.com.

Taking advantage of force.com features can help you achieve your goals.

Use AppExchange applications, SAAS solutions to extend you business functionality.

Use Apex and Visualforce to extend stock Salesforce.com functionality and tailor user experience.

Page 47: Under the Hood of a Salesforce.com Business Application

Emin Gerba

Director, Software Engineering

Samarpan Jain

Principal Architect

Question & Answer

Salesforce.com

Salesforce.com

Page 48: Under the Hood of a Salesforce.com Business Application

Under the Hood of a Salesforce.com Business

Application

Page 49: Under the Hood of a Salesforce.com Business Application

D I S C O V E R

Visit the Developer Training and Support Booth in Force.com Zone

Discover

Developer

Learning Paths

Developer training, certification and support resources

S U C C E S SFind us in the Partner Demo Area of

Force.com Zone 2nd Floor Moscone West

that help you achieve

Learn about Developer

Certifications

Page 50: Under the Hood of a Salesforce.com Business Application

Remember. . .

Check Chatter for additional session information

Get your developer Workbooks and Cheat Sheets in

the Force.com Zone

Visit for more information related

to this topicDon’t forget the survey!

Page 51: Under the Hood of a Salesforce.com Business Application

How Could Dreamforce Be Better? Tell Us!

Log in to the Dreamforce app to submitsurveys for the sessions you attended

Use the Dreamforce Mobile

app to submit surveys

Every session survey you submit is a chance to win an iPod nano!

OR