How Do I Integrate Quik! with Salesforce?

You can add Quik! integration to your Salesforce account by using just the Quik! web services (to generate forms and to display a list of forms to users). The integration will generally take a salesforce.com developer 5 to 15 days to complete depending on the complexity of your user experience. The implementation uses Apex, JavaScript and XML.

Concepts

It's important to understand the framework in which Quik! forms can be displayed and controlled within SalesForce. Since SalesForce has strong control over it's user experience and security, you can't just simply display a Quik! Form Viewer (HTML) in an iFrame.

In addition, you should not use set "HostFormsOnQuik = TRUE" to return a URL to the form as that is not a secure method for display forms within SalesForce. Instead, you need display the entire HTML returned by the Quik! Forms Engine Execute HTML method. 

SalesForce won't allow external references or javascripts to run in an iFrame that is displayed within a typical Lightning or other SalesForce component. Instead, you must display a Visual Force in the iFrame for the Quik! Form to display within. Set the iFrame to the Visual Force page URL and set the Visual Force page with the HTML content. 

Be aware that the styles within the Quik! Form Viewer (HTML) use absolute references to display items. Be sure to allow sufficient size to display the entire Quik! Form.

Program Flow

The basic program flow is as follows:

  1. Build SOAP XML Request – Create a SOAP envelope using an Apex string object.

String requestXML = FormXmlBuilder.buildXml();

  1. Send the SOAP Request to the Quik Forms Engine Web Service.

String xmlResponse=QuikFormHttpUtility.SendSOAPRequest(requestXML);

  1. Decode the response and parse out the HTML form.

String outputHTML=QuikFormController.decodeHtml( QuikFormController.parseResponseXmlForHtml(xmlResponse);

  1. Display the HTML form in a Visual Apex Page

<apex:page standardController="YOUR_CONTROLLER_c" extensions="QuikFormController" sidebar="false" showHeader="false" standardStylesheets="true" >
<style type="text/css">
ul,li {margin-left:0 !important;}
</style>
<apex:pageBlock rendered="{!{*}{_}outputHTML{_}{*}!=null}">
<apex:outputPanel >
<apex:outputText value="{!outputHTML}" escape="false"/>
</apex:outputPanel>
</apex:pageBlock>
</apex:page>

Sample Code

The sample code below is available to you for your own development purposes but is not to be shared outside your implementation, as protected by Copyright.

QuikFormHttpUtility

The following class is used to create and post an XML SOAP request and to process the response.
public with sharing class QuikFormHttpUtility {
public static String SendSOAPRequest(string strXML )

System.debug(strXML);
string xml='';
http soap = new http();
Httprequest soap_request = new Httprequest();
Httpresponse soap_response = new Httpresponse();
//soap_request.setEndpoint('https://websvcs.quikforms.com/quikformsenginews/5300/QuikFormsEngine.asmx');
soap_request.setEndpoint('https://websvcs.quikforms.com/quikformsenginews/5300/quikformsengine.asmx');
soap_request.setHeader('SOAPAction','https://websvcs.quikforms.com/quikformsenginews/Execute'); 

soap_request.setMethod('POST');
soap_request.setHeader('Host''websvcs.quikforms.com');
soap_request.setHeader('Content-type''text/xml; charset=utf-8');
soap_request.setHeader('Content-Length''' + strXML.length()); 
soap_request.setTimeout(30000);
soap_request.setBody(strXML); 
try
{
// Send the SOAP request
soap_response = soap.send(soap_request); 
// Process the response
System.Debug(soap_response.getBody());
System.Debug(soap_response.getStatusCode());
System.Debug(soap_response.getStatus());
xml=soap_response.getBody();
return xml;
}
catch(System.CalloutException ex)
{
System.Debug('Exception thrown: ' + ex.getMessage());
throw ex;
}
catch (Exception e)
{
System.Debug('Exception thrown: ' + e.getMessage());
throw e;
}
return xml;
}
}

Sample SOAP XML

<?xml version="1.0" encoding="utf-8"?>
<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">
<soap:Header>
<AuthenticationHeader xmlns="https://websvcs.quikforms.com/quikformsenginews/">
<CustomerID>CUSTOMER_ID</CustomerID>
<UserName>USER_NAME</UserName>
<Password>PASSWORD</Password>
</AuthenticationHeader>
</soap:Header>
<soap:Body>
<Execute xmlns="https://websvcs.quikforms.com/quikformsenginews/">
<CustomJavaFileIncludePath />
<CustomJavaScript />
<FormIDs>1,2,3</FormIDs>
<TestDataMode>false</TestDataMode>
<TestFinalFormsMode>false</TestFinalFormsMode>
<FormExpiryDate />
<HTMLBodyOnloadFunction />
<HTMLFieldFontColor />
<HTMLFooter />
<HTMLFooterStyle />
<HTMLLoadingImage />
<HTMLLogoAltText />
<HTMLLogoPath />
<HTMLMainInstruction />
<HTMLMetaNames />
<HTMLMinorInstruction />
<HTMLReportFormError />
<HTMLRequiredBorderColor />
<HTMLShowButtonClear>true</HTMLShowButtonClear>
<HTMLShowButtonPrint>true</HTMLShowButtonPrint>
<HTMLShowButtonReset>true</HTMLShowButtonReset>
<HTMLShowButtonSave>true</HTMLShowButtonSave>
<HTMLShowButtonSign>true</HTMLShowButtonSign>
<HTMLShowButtonSubmit>true</HTMLShowButtonSubmit>
<HTMLStyles />
<HTMLTitle />
<iScrollFilePath />
<iScrollOff>false</iScrollOff>
<jQueryBlockUIFilePath />
<jQueryFilePath />
<jQueryUIFilePath />
<LoadXML><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ParentField><Field><FieldName>1own.SSN</FieldName><FieldValue>333224444</FieldValue><FieldReadOnly>false</FieldReadOnly><FieldVisibility>1</FieldVisibility><FieldRequired>false</FieldRequired><FieldFormat></FieldFormat><FieldMask>false</FieldMask><FieldCalcOverride>false</FieldCalcOverride><HiddenField>false</HiddenField></Field></ParentField>]]></LoadXML>
<SaveURL />
<SignAllDocsCombined>true</SignAllDocsCombined>
<SignJavascript />
<SignMessage />
<SignShowSignNow>false</SignShowSignNow>
<SignShowVerifyCode>false</SignShowVerifyCode>
<SignShowVerifyIDCheck>false</SignShowVerifyIDCheck>
<SignSubject />
<SignURL>https://websvcs.quikforms.com/Docusign/QuikESignTransportVersion/5300/QuikSignTransport.aspx</SignURL>
<SubmitJavascript />
<SubmitURL>https://websvcs.quikforms.com/HTMLFormViewTrans/v5300/FormViewHTML/QFVGetPDF.aspx?Edit=FALSE</SubmitURL>
<HostFormOnQuik>true</HostFormOnQuik>
<PreviewMode>false</PreviewMode>
</Execute>
</soap:Body>
</soap:Envelope>


Additional Code Snippets That May Help

Your Visualforce Page should contains an iFrame:

Here is where the callout is made and the result is pushed into the iFrame

    • Visualforce.remoting.Manager.invokeAction(

      '{!$RemoteAction.QuikConnectorController.makePostCalloutForHTMLRemoteAction}',

                paramValue,accountId,

                function (result, event) {

                    if (event.status) {

                        var iframe = document.getElementById("myiframeid");

                        if(iframe){

                            var frameDoc = iframe.document;

                            if (iframe.contentWindow) {

                                frameDoc = iframe.contentWindow.document;

                            }

                           

                            frameDoc.open();

                            frameDoc.writeln(result);

                            frameDoc.close();


                            refreshIFrameElements(frameDoc);
                     }
                 },  { escape: false, timeout: 30000, buffer: false }
)


Elsewhere in the Script tag where the event listener for the iFrame message is created

  • window.addEventListener('message', function(event) {

            var accountId = {!$CurrentPage.parameters.accountId};

            var selectionType = {!$CurrentPage.parameters.selectionType};

            if(event.data.startsWith('EditablePDF', 2)){   //The browser will post message events occassionally, only grab messages with the payload

                Visualforce.remoting.Manager.invokeAction(

                    '{!$RemoteAction.QuikConnectorController.fetchPDFsFromQuik}',

                    event.data, accountId, selectionType,

                    function (result, event) {

                        if (event.status) {

                            console.log('Result: ', result);                          

                            window.setTimeout(displayDSButton, 2000);

                            document.getElementById("spinner").style.display = "none";

                            alert('Upload to CLM Complete');

                        }else {

                            document.getElementById("spinner").style.display = "none";

                            j$('#errorText').text(event.message);

                            j$('#errorDialog').modal();

                        }

                    }, { escape: false, timeout: 30000, buffer: false }

                );

            }

        });

And in the VF Controller or Controller Helper class here is how to setup the custom button 

    • FormButton HTMLButtonSubmit = new FormButton(dummyRedirectURL, customJS, 'Send', 'Send');form.HTMLButtonSubmit = HTMLButtonSubmit;

Timeout Configuration

There are 2 necessary entries to add the timeout configuration:
  • In the class, before sending the request to the http service      
1	HttpRequest req = new HttpRequest();


2	req.setTimeout(120000); // timeout in milliseconds


  • In the Visualforce page, on the call to the remote action
  • We recommend increasing to the max of 120000 milliseconds



For help regarding Quik! Forms and the Quik! API
Email: support@quikforms.com | Phone: (877) 456-QUIK