This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.
Processing Sales in Zoho CRM
The second use case in the Zoho CRM business scenario is processing sales. This page describes the related tasks and the operations you use in the Zoho CRM connector and the other ESB connectors.
Overview
The flow for processing sales is illustrated in the following diagram. The ESB connectors for Zoho CRM and QuickBooks will be used to connect to each service.
- In this use case, you initiate the sales process by creating quotes in Zoho CRM using the insertRecords operation. You then use the getRecordsById operation to retrieve these quotes, and then create them as estimates in QuickBooks using the createEstimate operation.
- Retrieve the quotes in "confirmed" status using getRecordsById and create sales orders using insertRecords in Zoho CRM. Retrieve corresponding estimates from Quickbooks using query and create sales receipts using createSalesReceipt.
- Update the status of sales orders as "Closed won" using updateRecords in Zoho CRM.
- For these "Closed won" sales orders, create invoices in Zoho CRM using insertRecords , and also create invoices for them in QuickBooks using createInvoice. (Using QuickBooks as an accounting API helps to record book-keeping functionalities by mapping relevant financial details such as customers, invoices, and sales orders in Zoho CRM.)
Zoho CRM operations
QuickBooks operations
Notes
When publishing a Zoho CRM quote in QuickBooks as an estimate, or publishing a Zoho CRM sales order in Quickbooks as a sales receipt, note the following:
- The corresponding request contains an additional parameter called "productItemMap". This parameter refers to the "id" mapping between the products in Zoho CRM and items in QuickBooks.
- The parameter value takes the form of {<zohocrm-productId>:<quickbooks-itemId>}.
When creating invoices in Zoho CRM and QuickBooks:
- The parameter "zohoSalesOrderId" is taken from Zoho CRM and the parameter "qbSalesReceiptId" is taken from QuickBooks to create invoices.
- The parameter value takes the form of {<zohocrm-quoteId>:<quickbooks-estimateId>}.
Samples
Sample Template for Creating and Retrieving Quote Details
<!-- createAndRetrieveQuoteDetails template is used to create a quote in ZohoCRM and retrieve details --> <template name="zohocrm-createAndRetrieveQuoteDetails" xmlns="http://ws.apache.org/ns/synapse"> <parameter name="zohoScope" description="Specify the value as crmapi" /> <parameter name="zohoAccessToken" description="Encrypted alphanumeric string to authenticate the Zoho credentials" /> <parameter name="zohoApiUrl" description="The api url" /> <parameter name="zohoIsApproval" description="To keep the records in approval mode" /> <parameter name="zohoWfTrigger" description="The wfTrigger parameter is used to trigger the workflow rule while inserting record into CRM account" /> <parameter name="zohoNewFormat" description="The newFormat, an integer determine weather null valus should be excluded(1) or included(2)" /> <parameter name="zohoVersion" description="The API version" /> <parameter name="zohoDuplicateCheck" description="Checking the duplicate records and throw an error response" /> <parameter name="zohoXmlData" description="The xml string containing the data to be inserted" /> <sequence> <property name="uri.var.zohoScope" expression="$func:zohoScope" /> <property name="uri.var.zohoAccessToken" expression="$func:zohoAccessToken" /> <property name="uri.var.zohoApiUrl" expression="$func:zohoApiUrl" /> <property name="uri.var.zohoIsApproval" expression="$func:zohoIsApproval" /> <property name="uri.var.zohoWfTrigger" expression="$func:zohoWfTrigger" /> <property name="uri.var.zohoNewFormat" expression="$func:zohoNewFormat" /> <property name="uri.var.zohoVersion" expression="$func:zohoVersion" /> <property name="uri.var.zohoDuplicateCheck" expression="$func:zohoDuplicateCheck" /> <property name="uri.var.zohoXmlData" expression="$func:zohoXmlData" /> <property name="uri.var.zohoModuleType" value="Quotes" /> <zohocrm.init> <scope>{$ctx:uri.var.zohoScope}</scope> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> </zohocrm.init> <zohocrm.insertRecords> <moduleType>{$ctx:uri.var.zohoModuleType}</moduleType> <duplicateCheck>{$ctx:uri.var.zohoDuplicateCheck}</duplicateCheck> <xmlData>{$ctx:uri.var.zohoXmlData}</xmlData> <isApproval>{$ctx:uri.var.zohoIsApproval}</isApproval> <wfTrigger>{$ctx:uri.var.zohoWfTrigger}</wfTrigger> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> </zohocrm.insertRecords> <!-- Retrieving the id of the new quote--> <property name="uri.var.zohoQuoteId" expression="json-eval($.response.result.recorddetail.FL[0].content)"/> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_createQuote" /> | ) * </call-template> <filter source="boolean(get-property('uri.var.zohoQuoteId'))" regex="false"> <then> <loopback/> </then> </filter> <!-- Retrieving information about the quote--> <zohocrm.init> <scope>{$ctx:uri.var.zohoScope}</scope> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> </zohocrm.init> <zohocrm.getRecordsById> <id>{$ctx:uri.var.zohoQuoteId}</id> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> <moduleType>{$ctx:uri.var.zohoModuleType}</moduleType> </zohocrm.getRecordsById> <property name="uri.var.errorOutput" expression="json-eval($.response.error)"/> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getQuoteById" /> | ) * </call-template> <filter source="boolean(get-property('uri.var.errorOutput'))" regex="true"> <then> <loopback/> </then> </filter> </sequence> </template>
Sample Proxy for Publishing the ZohoCRM Quote in QuickBooks as an Estimate
<proxy xmlns="http://ws.apache.org/ns/synapse" name="zohocrm_qbCreateEstimate" transports="https,http" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence onError="faultHandlerSeq"> <!-- ZohoCRM insertRecords parameters --> <property name="zohoApiUrl" expression="json-eval($.zohoApiUrl)"/> <property name="zohoAccessToken" expression="json-eval($.zohoAccessToken)"/> <property name="zohoScope" expression="json-eval($.zohoScope)"/> <property name="zohoNewFormat" expression="json-eval($.zohoNewFormat)"/> <property name="zohoVersion" expression="json-eval($.zohoVersion)"/> <property name="zohoXmlData" expression="json-eval($.zohoXmlData)"/> <property name="zohoWfTrigger" expression="json-eval($.zohoWfTrigger)"/> <property name="zohoDuplicateCheck" expression="json-eval($.zohoDuplicateCheck)"/> <property name="zohoIsApproval" expression="json-eval($.zohoIsApproval)"/> <property name="zohoModuleType" expression="json-eval($.zohoModuleType)"/> <!-- QuickBooks createQuote parameters--> <property name="qbConsumerKey" expression="json-eval($.qbConsumerKey)"/> <property name="qbAccessToken" expression="json-eval($.qbAccessToken)"/> <property name="qbAccessTokenSecret" expression="json-eval($.qbAccessTokenSecret)"/> <property name="qbResponseType" expression="json-eval($.qbResponseType)"/> <property name="qbApiUrl" expression="json-eval($.qbApiUrl)"/> <property name="qbCompanyId" expression="json-eval($.qbCompanyId)"/> <property name="qbConsumerSecret" expression="json-eval($.qbConsumerSecret)"/> <property name="qbDepartmentRef" expression="json-eval($.qbDepartmentRef)"/> <property name="qbCustomField" expression="json-eval($.qbCustomField)"/> <property name="qbExchangeRate" expression="json-eval($.qbExchangeRate)"/> <property name="qbPrintStatus" expression="json-eval($.qbPrintStatus)"/> <property name="qbGlobalTaxCalculation" expression="json-eval($.qbGlobalTaxCalculation)"/> <property name="qbShipDate" expression="json-eval($.qbShipDate)"/> <property name="qbTotalAmt" expression="json-eval($.qbTotalAmt)"/> <property name="qbClassRef" expression="json-eval($.qbClassRef)"/> <property name="qbTxnDate" expression="json-eval($.qbTxnDate)"/> <property name="qbSalesTermRef" expression="json-eval($.qbSalesTermRef)"/> <property name="qbApplyTaxAfterDiscount" expression="json-eval($.qbApplyTaxAfterDiscount)"/> <property name="qbCustomerMemo" expression="json-eval($.qbCustomerMemo)"/> <property name="qbBillEmail" expression="json-eval($.qbBillEmail)"/> <property name="qbAcceptedDate" expression="json-eval($.qbAcceptedDate)"/> <property name="qbExpirationDate" expression="json-eval($.qbExpirationDate)"/> <property name="qbShipMethodRef" expression="json-eval($.qbShipMethodRef)"/> <property name="qbLinkedTxn" expression="json-eval($.qbLinkedTxn)"/> <property name="qbCurrencyRef" expression="json-eval($.qbCurrencyRef)"/> <property name="qbTxnStatus" expression="json-eval($.qbTxnStatus)"/> <property name="qbDocNumber" expression="json-eval($.qbDocNumber)"/> <property name="qbAcceptedBy" expression="json-eval($.qbAcceptedBy)"/> <property name="qbEmailStatus" expression="json-eval($.qbEmailStatus)"/> <property name="qbCustomerRef" expression="json-eval($.qbCustomerRef)"/> <property name="qbTxnTaxDetail" expression="json-eval($.qbTxnTaxDetail)"/> <property name="qbBillAddr" expression="json-eval($.qbBillAddr)"/> <property name="qbShipAddr" expression="json-eval($.qbShipAddr)"/> <property name="productItemMap" expression="json-eval($.productItemMap)"/> <call-template target="zohocrm-createAndRetrieveQuoteDetails"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="zohoScope" value="{$ctx:zohoScope}" /> | <with-param name="zohoAccessToken" value="{$ctx:zohoAccessToken}" /> | <with-param name="zohoApiUrl" value="{$ctx:zohoApiUrl}" /> | <with-param name="zohoModuleType" value="{$ctx:zohoModuleType}" /> | <with-param name="zohoDuplicateCheck" value="{$ctx:zohoDuplicateCheck}" /> | <with-param name="zohoXmlData" value="{$ctx:zohoXmlData}" /> | <with-param name="zohoIsApproval" value="{$ctx:zohoIsApproval}" /> | <with-param name="zohoWfTrigger" value="{$ctx:zohoWfTrigger}" /> | <with-param name="zohoNewFormat" value="{$ctx:zohoNewFormat}" /> | <with-param name="zohoVersion" value="{$ctx:zohoVersion}" /> | ) * </call-template> <!-- Retrieving relevant attributes of ZohoCRm quote --> <property name="quoteAttributes" expression="json-eval($.response.result.Quotes.row.FL)"/> <script language="js"> var products; var productAttributes; var lineObject; var productName; var listPrice; var quantity; var productId; var jsn = eval("(" + mc.getProperty("quoteAttributes") + ")"); var lineArray=eval("([])"); var productItemMap = eval("("+mc.getProperty('productItemMap')+")"); for (var i = 0; i < jsn.length ; i++) { if(jsn[i].val == "Subject"){ mc.setProperty('qbQuoteSubject', jsn[i].content) } if(jsn[i].val == "Product Details"){ products = jsn[i].product; } } if (typeof(products) == "object" && (products.join == undefined)) { productAttributes = products.FL; lineObject=eval("({})"); for (var i = 0; i < productAttributes.length ; i++) { if(productAttributes[i].val == "Product Name"){ productName = productAttributes[i].content; } if(productAttributes[i].val == "List Price"){ listPrice = productAttributes[i].content; } if(productAttributes[i].val == "Quantity"){ quantity = productAttributes[i].content; } if(productAttributes[i].val == "Product Id"){ productId = productAttributes[i].content; } } lineObject.Id = "1"; lineObject.DetailType = "SalesItemLineDetail"; lineObject.SalesItemLineDetail = eval("({})"); lineObject.SalesItemLineDetail.UnitPrice = eval(listPrice); lineObject.SalesItemLineDetail.Qty = eval(quantity); lineObject.SalesItemLineDetail.ItemRef = eval("({})"); lineObject.SalesItemLineDetail.ItemRef.name = productName; lineObject.SalesItemLineDetail.ItemRef.value = productItemMap[productId]; lineObject.Amount = eval(listPrice + '*' + quantity); lineArray[0] = lineObject; mc.setPayloadJSON(lineArray); }else{ for (var j = 0; j < products.length ; j++) { productAttributes = products[j].FL; lineObject=eval("({})"); for (var i = 0; i < productAttributes.length ; i++) { if(productAttributes[i].val == "Product Name"){ productName = productAttributes[i].content; } if(productAttributes[i].val == "List Price"){ listPrice = productAttributes[i].content; } if(productAttributes[i].val == "Quantity"){ quantity = productAttributes[i].content; } if(productAttributes[i].val == "Product Id"){ productId = productAttributes[i].content; } } lineObject.Id = eval('"'+(j+1)+'"'); lineObject.DetailType = "SalesItemLineDetail"; lineObject.SalesItemLineDetail = eval("({})"); lineObject.SalesItemLineDetail.UnitPrice = eval(listPrice); lineObject.SalesItemLineDetail.Qty = eval(quantity); lineObject.SalesItemLineDetail.ItemRef = eval("({})"); lineObject.SalesItemLineDetail.ItemRef.name = productName; lineObject.SalesItemLineDetail.ItemRef.value = productItemMap[productId]; lineObject.Amount = eval(listPrice + '*' + quantity); lineArray[j] = lineObject; mc.setPayloadJSON(lineArray); } } </script> <property name="qbLine" expression="json-eval($)"/> <quickbooks.init> <consumerKey>{$ctx:qbConsumerKey}</consumerKey> <accessToken>{$ctx:qbAccessToken}</accessToken> <accessTokenSecret>{$ctx:qbAccessTokenSecret}</accessTokenSecret> <responseType>{$ctx:qbResponseType}</responseType> <apiUrl>{$ctx:qbApiUrl}</apiUrl> <companyId>{$ctx:qbCompanyId}</companyId> <consumerSecret>{$ctx:qbConsumerSecret}</consumerSecret> </quickbooks.init> <quickbooks.createEstimate> <departmentRef>{$ctx:qbDepartmentRef}</departmentRef> <customField>{$ctx:qbCustomField}</customField> <exchangeRate>{$ctx:qbExchangeRate}</exchangeRate> <printStatus>{$ctx:qbPrintStatus}</printStatus> <line>{$ctx:qbLine}</line> <globalTaxCalculation>{$ctx:qbGlobalTaxCalculation}</globalTaxCalculation> <shipDate>{$ctx:qbShipDate}</shipDate> <totalAmt>{$ctx:qbTotalAmt}</totalAmt> <classRef>{$ctx:qbClassRef}</classRef> <txnDate>{$ctx:qbTxnDate}</txnDate> <salesTermRef>{$ctx:qbSalesTermRef}</salesTermRef> <applyTaxAfterDiscount>{$ctx:qbApplyTaxAfterDiscount}</applyTaxAfterDiscount> <customerMemo>{$ctx:qbCustomerMemo}</customerMemo> <billEmail>{$ctx:qbBillEmail}</billEmail> <acceptedDate>{$ctx:qbAcceptedDate}</acceptedDate> <expirationDate>{$ctx:qbExpirationDate}</expirationDate> <shipMethodRef>{$ctx:qbShipMethodRef}</shipMethodRef> <linkedTxn>{$ctx:qbLinkedTxn}</linkedTxn> <currencyRef>{$ctx:qbCurrencyRef}</currencyRef> <txnStatus>{$ctx:qbTxnStatus}</txnStatus> <docNumber>{$ctx:qbDocNumber}</docNumber> <acceptedBy>{$ctx:qbAcceptedBy}</acceptedBy> <emailStatus>{$ctx:qbEmailStatus}</emailStatus> <customerRef>{$ctx:qbCustomerRef}</customerRef> <txnTaxDetail>{$ctx:qbTxnTaxDetail}</txnTaxDetail> <privateNote>{$ctx:qbQuoteSubject}</privateNote> <shipAddr>{$ctx:qbShipAddr}</shipAddr> <billAddr>{$ctx:qbBillAddr}</billAddr> </quickbooks.createEstimate> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="quickbooks_createEstimate" /> | ) * </call-template> <loopback/> </inSequence> <outSequence> <property name="messageType" value="application/json" scope="axis2"></property> <payloadFactory media-type="json"> <format> { "Response":[$1] } </format> <args> <arg expression="get-property('uri.var.responseString')" /> </args> </payloadFactory> <send/> </outSequence> </target> <description/> </proxy>
Sample Request for Publishing the ZohoCRM Quote in QuickBooks as an Estimate
{ "zohoApiUrl":"https://crm.zoho.com", "zohoAccessToken":"1784c3e25c7dd0ae1bc639122c948a88", "zohoScope":"crmapi", "zohoXmlData":"<Quotes><row no=\"1\"><FL val=\"Subject\">Zillium - Quote</FL><FL val=\"Subject\">TEST</FL><FL val=\"Quote Stage\">Draft</FL><FL val=\"Carrier\">FedEX</FL><FL val=\"ACCOUNTID\">1243444000000095001</FL><FL val=\"Account Name\">Virtusa</FL><FL val=\"Billing Street\">test</FL><FL val=\"Shipping Street\">test</FL><FL val=\"Billing City\">test</FL><FL val=\"Shipping City\">test</FL><FL val=\"Billing State\">test</FL><FL val=\"Shipping State\">test</FL><FL val=\"Billing Code\">223</FL><FL val=\"Shipping Code\">223</FL><FL val=\"Billing Country\">test</FL><FL val=\"Shipping Country\">test</FL><FL val=\"Product Details\"><product no=\"1\"><FL val=\"Product Id\">1243444000000097003</FL><FL val=\"Product Name\">prd1</FL><FL val=\"Unit Price\">20.0</FL><FL val=\"Quantity\">1.0</FL><FL val=\"Quantity in Stock\">0.0</FL><FL val=\"Total\">23.0</FL><FL val=\"Discount\">0.0</FL><FL val=\"Total After Discount\">23.0</FL><FL val=\"List Price\">23.0</FL><FL val=\"Net Total\">23.0</FL><FL val=\"Tax\">0.0</FL></product><product no=\"2\"><FL val=\"Product Id\">1243444000000071042</FL><FL val=\"Product Name\">prd2</FL><FL val=\"Unit Price\">10.0</FL><FL val=\"Quantity\">1.0</FL><FL val=\"Quantity in Stock\">0.0</FL><FL val=\"Total\">23.0</FL><FL val=\"Discount\">0.0</FL><FL val=\"Total After Discount\">23.0</FL><FL val=\"List Price\">23.0</FL><FL val=\"Net Total\">23.0</FL><FL val=\"Tax\">0.0</FL></product></FL><FL val=\"Terms and Conditions\">Test by Zoho</FL><FL val=\"Description\">Test By Zoho</FL></row></Quotes>", "zohoNewFormat":1, "zohoVersion":1, "qbConsumerKey": "qyprd1Qy5c9wyCPR47L6Dz9axlWxlX", "qbConsumerSecret": "OKGhR9prSSFyqVNt43lQUu7m6jkyUehPEyTEdHGd", "qbAccessToken": "qyprdGIcJnUXiAGtWPWoMZuIZ9N96HIo6IPc9Sm58buaAe3t", "qbAccessTokenSecret": "1kLzyitnhP9h45Paxuc7YSMNEk1EwNVEc1z2ry5F", "qbResponseType": "application/json", "qbApiUrl": "https://qb.sbfinance.intuit.com:443", "qbCompanyId": "1263450945", "qbCustomerRef":{ "value": "12", "name": "Sarindu" }, "productItemMap":{"1243444000000097003":"31","1243444000000071042":"32"} }
Sample Template for Creating a Sales Order
<template name="zohocrm-createSalesOrder" xmlns="http://ws.apache.org/ns/synapse"> <parameter name="zohoApiUrl" description="The api url." /> <parameter name="zohoAccessToken" description="Encrypted alphanumeric string to authenticate the Zoho credentials." /> <parameter name="zohoNewFormat" description="The newFormat, an integer determine weather null valus should be excluded(1) or included(2)." /> <parameter name="zohoVersion" description="The API version." /> <parameter name="zohoXmlDataSalesOrder" description="The xml string containing the data to be inserted." /> <parameter name="zohoScope" description="Specify the value as crmapi." /> <parameter name="zohowfTrigger" description="The wfTrigger parameter is used to trigger the work flow rule while inserting record into CRM account."/> <parameter name="zohoduplicateCheck" description="Checking the duplicate records and throw an error response."/> <parameter name="zohoisApproval" description="To keep the records in approval mode."/> <parameter name="zohoQuoteId" description="The respective quote ID."/> <sequence> <property name="uri.var.zohoApiUrl" expression="$func:zohoApiUrl" /> <property name="uri.var.zohoAccessToken" expression="$func:zohoAccessToken" /> <property name="uri.var.zohoNewFormat" expression="$func:zohoNewFormat" /> <property name="uri.var.zohoVersion" expression="$func:zohoVersion" /> <property name="uri.var.zohoXmlDataSalesOrder" expression="$func:zohoXmlDataSalesOrder" /> <property name="uri.var.zohoScope" expression="$func:zohoScope" /> <property name="uri.var.zohoModuleTypeSalesOrder" value="SalesOrders" /> <property name="uri.var.zohoWfTrigger" expression="$func:zohoWfTrigger" /> <property name="uri.var.zohoDuplicateCheck" expression="$func:zohoDuplicateCheck" /> <property name="uri.var.zohoIsApproval" expression="$func:zohoIsApproval" /> <property name="uri.var.zohoQuoteId" expression="$func:zohoQuoteId" /> <property name="uri.var.zohoModuleTypeQuote" value="Quotes" /> <property name="uri.var.zohoXmlDataQuote" value="<Quotes><row no="1"><FL val="Quote Stage">Closed Won</FL></row></Quotes>" /> <zohocrm.init> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <scope>{$ctx:uri.var.zohoScope}</scope> </zohocrm.init> <zohocrm.insertRecords> <moduleType>{$ctx:uri.var.zohoModuleTypeSalesOrder}</moduleType> <duplicateCheck>{$ctx:uri.var.zohoDuplicateCheck}</duplicateCheck> <xmlData>{$ctx:uri.var.zohoXmlDataSalesOrder}</xmlData> <isApproval>{$ctx:uri.var.zohoIsApproval}</isApproval> <wfTrigger>{$ctx:uri.var.zohoWfTrigger}</wfTrigger> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> </zohocrm.insertRecords> <!-- Retrieving the sales order ID of the created Sales order --> <property name="uri.var.zohoSalesOrderId" expression="json-eval($.response.result.recorddetail.FL[0].content)"/> <header name="Set-Cookie" action="remove" scope="transport"/> <header name="Content-Type" action="remove" scope="transport"/> <header name="Date" action="remove" scope="transport"/> <header name="Server" action="remove" scope="transport"/> <header name="Transfer-Encoding" action="remove" scope="transport"/> <header name="Connection" action="remove" scope="transport"/> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_createSalesOrder" />| ) * </call-template> <!-- Check the availability of zohoSalesOrderId to proceed with other API calls --> <filter source="boolean(get-property('uri.var.zohoSalesOrderId'))" regex="true"> <then> <!--Updating Quote status--> <zohocrm.init> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <scope>{$ctx:uri.var.zohoScope}</scope> </zohocrm.init> <zohocrm.updateRecords> <id>{$ctx:uri.var.zohoQuoteId}</id> <moduleType>{$ctx:uri.var.zohoModuleTypeQuote}</moduleType> <xmlData>{$ctx:uri.var.zohoXmlDataQuote}</xmlData> <wfTrigger>{$ctx:uri.var.zohoWfTrigger}</wfTrigger> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> </zohocrm.updateRecords> <!-- Retrieving the quote ID of the updated quote --> <property name="uri.var.zohoUpdatedQuoteID" expression="json-eval($.response.result.recorddetail.FL[0].content)"/> <!--Removing headers--> <header name="Set-Cookie" action="remove" scope="transport"/> <header name="Content-Type" action="remove" scope="transport"/> <header name="Date" action="remove" scope="transport"/> <header name="Server" action="remove" scope="transport"/> <header name="Transfer-Encoding" action="remove" scope="transport"/> <header name="Connection" action="remove" scope="transport"/> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_updateQuote" />| ) * </call-template> </then> <else> <!-- If the sales order is not successfully created --> <payloadFactory media-type="json"> <format> { "response":"Sales order is not successfully created." } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_createSalesOrderFailure" />| ) * </call-template> </else> </filter> </sequence> </template>
Sample Template for Creating a Sales Receipt in QuickBooks
<template xmlns="http://ws.apache.org/ns/synapse" name="zohocrm_createQbSalesReceipt"> <parameter name="zohoApiUrl" description="The api url" /> <parameter name="zohoAccessToken" description="Encrypted alphanumeric string to authenticate the Zoho credentials" /> <parameter name="zohoScope" description="Specify the value as crmapi" /> <parameter name="zohoQuoteId" description="The id of the quote which is in the confirmed state" /> <parameter name="zohoNewFormat" description="The newFormat, an integer determine weather null valus should be excluded(1) or included(2)" /> <parameter name="zohoVersion" description="The API version" /> <parameter name="zohowfTrigger" description="The wfTrigger parameter is used to trigger the workflow rule while inserting record into CRM account"/> <parameter name="zohoduplicateCheck" description="Checking the duplicate records and throw an error response"/> <parameter name="qbApiUrl" description="The apiUrl of quickbooks." /> <parameter name="qbConsumerKey" description="The consumer key of the created application." /> <parameter name="qbConsumerSecret" description="The consumer secret of the created application." /> <parameter name="qbAccessToken" description="The generated access token." /> <parameter name="qbAccessTokenSecret" description="The generated access token secret." /> <parameter name="qbCompanyId" description="The ID of the company." /> <parameter name="qbDepartmentRef" description="Location of the transaction, as defined using location tracking in QuickBooks Online." /> <parameter name="qbCustomField" description="Custom field or data extension." /> <parameter name="qbExchangeRate" description="Currency exchange rate." /> <parameter name="qbPrintStatus" description="Printing status of the invoice." /> <parameter name="qbGlobalTaxCalculation" description="Method in which tax is applied." /> <parameter name="qbShipDate" description="Date for delivery of goods or services." /> <parameter name="qbClassRef" description="Reference to the Class associated with the transaction." /> <parameter name="qbTxnDate" description="The date entered by the user when this transaction occurred." /> <parameter name="qbAutoIncrementDocNumber" description="A boolean flag to auto increment the doc number." /> <parameter name="qbApplyTaxAfterDiscount" description="If false or null, calculate the sales tax first, and then apply the discount. If true, subtract the discount first and then calculate the sales tax." /> <parameter name="qbTrackingNum" description="Shipping provider's tracking number for the delivery of the goods associated with the transaction." /> <parameter name="qbPaymentRefNum" description="Reference number for the payment." /> <parameter name="qbPaymentMethodRef" description="Reference to the PaymentMethod." /> <parameter name="qbCustomerMemo" description="The user-entered message to the customer that appears in the printed invoice or the memo of the transaction to provide more detail, and does not appear in the printed message of the bill or the message appears in the printed record if it is an invoice or Bill or Credit Card respectively. " /> <parameter name="qbBillEmail" description="Identifies the e-mail address where the SalesReceipt is sent." /> <parameter name="qbBillAddr" description="Bill-to address of the receipt." /> <parameter name="qbDepositToAccountRef" description="Asset account where the payment money is deposited." /> <parameter name="qbShipMethodRef" description="Reference to the ShipMethod associated with the transaction." /> <parameter name="qbLinkedTxn" description="Zero or more linked transactions." /> <parameter name="qbShipAddr" description="Shipping address of the receipt." /> <parameter name="qbCurrencyRef" description="Reference to the Currency in which all amounts on the associated transaction are expressed." /> <parameter name="qbTxnStatus" description="The status of the transaction." /> <parameter name="qbDocNumber" description="Reference number for the transaction." /> <parameter name="qbEmailStatus" description="Email status of the invoice." /> <parameter name="qbCustomerRef" description="Reference to a Customer or job." /> <parameter name="qbTxnTaxDetail" description="Details of taxes charged on the transaction as a whole." /> <parameter name="qbPrivateNote" description="User entered, organization-private note about the transaction." /> <parameter name="quoteEstimateMap" description="The mapping between the quotes in Zoho and estimate in QuickBooks." /> <sequence> <property name="zohoApiUrl" expression="$func:zohoApiUrl" /> <property name="zohoAccessToken" expression="$func:zohoAccessToken" /> <property name="zohoScope" expression="$func:zohoScope" /> <property name="zohoQuoteId" expression="$func:zohoQuoteId" /> <property name="zohoNewFormat" expression="$func:zohoNewFormat" /> <property name="zohoVersion" expression="$func:zohoVersion" /> <property name="zohoWfTrigger" expression="$func:zohoWfTrigger" /> <property name="zohoduplicateCheck" expression="$func:zohoduplicateCheck" /> <property name="zohoisApproval" value="true" /> <!-- QuickBooks createQuote parameters--> <property name="qbApiUrl" expression="$func:qbApiUrl"/> <property name="qbConsumerKey" expression="$func:qbConsumerKey"/> <property name="qbConsumerSecret" expression="$func:qbConsumerSecret"/> <property name="qbAccessToken" expression="$func:qbAccessToken"/> <property name="qbAccessTokenSecret" expression="$func:qbAccessTokenSecret"/> <property name="qbResponseType" value="application/json"/> <property name="qbCompanyId" expression="$func:qbCompanyId"/> <property name="qbDepartmentRef" expression="$func:qbDepartmentRef"/> <property name="qbCustomField" expression="$func:qbCustomField"/> <property name="qbExchangeRate" expression="$func:qbExchangeRate"/> <property name="qbPrintStatus" expression="$func:qbPrintStatus"/> <property name="qbGlobalTaxCalculation" expression="$func:qbGlobalTaxCalculation"/> <property name="qbShipDate" expression="$func:qbShipDate"/> <property name="qbClassRef" expression="$func:qbClassRef"/> <property name="qbTxnDate" expression="$func:qbTxnDate"/> <property name="qbAutoIncrementDocNumber" expression="$func:qbAutoIncrementDocNumber"/> <property name="qbApplyTaxAfterDiscount" expression="$func:qbApplyTaxAfterDiscount"/> <property name="qbTrackingNum" expression="$func:qbTrackingNum"/> <property name="qbPaymentRefNum" expression="$func:qbPaymentRefNum"/> <property name="qbPaymentMethodRef" expression="$func:qbPaymentMethodRef"/> <property name="qbCustomerMemo" expression="$func:qbCustomerMemo"/> <property name="qbBillEmail" expression="$func:qbBillEmail"/> <property name="qbBillAddr" expression="$func:qbBillAddr"/> <property name="qbDepositToAccountRef" expression="$func:qbDepositToAccountRef"/> <property name="qbShipMethodRef" expression="$func:qbShipMethodRef"/> <property name="qbLinkedTxn" expression="$func:qbLinkedTxn"/> <property name="qbShipAddr" expression="$func:qbShipAddr"/> <property name="qbCurrencyRef" expression="$func:qbCurrencyRef"/> <property name="qbTxnStatus" expression="$func:qbTxnStatus"/> <property name="qbDocNumber" expression="$func:qbDocNumber"/> <property name="qbEmailStatus" expression="$func:qbEmailStatus"/> <property name="qbCustomerRef" expression="$func:qbCustomerRef"/> <property name="qbTxnTaxDetail" expression="$func:qbTxnTaxDetail"/> <property name="qbPrivateNote" expression="$func:qbPrivateNote"/> <property name="quoteEstimateMap" expression="$func:quoteEstimateMap"/> <script language="js"> <![CDATA[ var quoteEstimateMapping = eval("(" + mc.getProperty('quoteEstimateMap') + ")"); var quoteId = mc.getProperty('zohoQuoteId'); var estimateId = quoteEstimateMapping[quoteId]; if(estimateId == undefined){ mc.setProperty('isEstimateExist', 'false'); }else{ mc.setProperty('qbEstimateId', "'" + estimateId + "'"); mc.setProperty('isEstimateExist', 'true'); } ]]> </script> <!-- Check the availability of corresponding estimate id for a given quote id --> <filter source="get-property('isEstimateExist')" regex="false"> <then> <!-- If quote attributes are not fetched successfully --> <payloadFactory media-type="json"> <format> { "response":"The quote id is not available in the given mapping." } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_fetchCorrespondingEstimateFailure" />| ) * </call-template> </then> <else> <!--Query Quote details--> <zohocrm.init> <apiUrl>{$ctx:zohoApiUrl}</apiUrl> <accessToken>{$ctx:zohoAccessToken}</accessToken> <scope>{$ctx:zohoScope}</scope> </zohocrm.init> <zohocrm.getRecordsById> <id>{$ctx:zohoQuoteId}</id> <moduleType>Quotes</moduleType> </zohocrm.getRecordsById> <!--Removing headers--> <header name="Set-Cookie" action="remove" scope="transport"/> <header name="Content-Type" action="remove" scope="transport"/> <header name="Date" action="remove" scope="transport"/> <header name="Server" action="remove" scope="transport"/> <header name="Transfer-Encoding" action="remove" scope="transport"/> <header name="Connection" action="remove" scope="transport"/> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getRecordsByIdQuote" />| ) * </call-template> <!-- Retrieving Quote information --> <property name="uri.var.quoteAttributes" expression="json-eval($.response.result.Quotes.row.FL)"/> <!-- Check the availability of quoteAttributes to proceed with other API calls --> <filter source="boolean(get-property('uri.var.quoteAttributes'))" regex="true"> <then> <script language="js"> <![CDATA[ var quoteAttributesString = mc.getProperty("uri.var.quoteAttributes"); var quoteAttributes = eval("(" + quoteAttributesString + ")"); //attribute variables var subject=''; var accountName=''; var productDetails=''; var productAttributes=''; var productXmlData=''; var productId=''; var productName=''; var quantity=''; var unitPrice=''; var listPrice=''; var xmlData=''; for (var i = 0; i < quoteAttributes.length ; i++) { if(quoteAttributes[i].val == "Quote Stage"){ mc.setProperty('zohoQuoteStage', quoteAttributes[i].content); } if(quoteAttributes[i].val == "Subject"){ subject = quoteAttributes[i].content; } if(quoteAttributes[i].val == "Account Name"){ accountName = quoteAttributes[i].content; } if(quoteAttributes[i].val == "Product Details"){ productDetails = quoteAttributes[i].product; if (typeof(productDetails) == "object" && (productDetails.join == undefined)) { //Checking for single product productAttributes = productDetails.FL; //iterating through the product details for (var j = 0; j < productAttributes.length ; j++) { if(productAttributes[j].val == "Product Id"){ productId = productAttributes[j].content; } if(productAttributes[j].val == "Product Name"){ productName = productAttributes[j].content; } if(productAttributes[j].val == "List Price"){ listPrice = productAttributes[j].content; } if(productAttributes[j].val == "Quantity"){ quantity = productAttributes[j].content; } if(productAttributes[j].val == "Unit Price"){ unitPrice = productAttributes[j].content; } } productXmlData += '<product no="1"><FL val="Product Id">' + productId + '</FL><FL val="Quantity">' + quantity + '</FL><FL val="Unit Price">'+ unitPrice + '</FL><FL val="List Price">'+ listPrice +'</FL></product>' }else{ //Checking for multiple products //iterating through the products for (var k = 0; k < productDetails.length ; k++) { productAttributes = productDetails[k].FL; //iterating through the product details for (var j = 0; j < productAttributes.length ; j++) { if(productAttributes[j].val == "Product Id"){ productId = productAttributes[j].content; } if(productAttributes[j].val == "Product Name"){ productName = productAttributes[j].content; } if(productAttributes[j].val == "List Price"){ listPrice = productAttributes[j].content; } if(productAttributes[j].val == "Quantity"){ quantity = productAttributes[j].content; } if(productAttributes[j].val == "Unit Price"){ unitPrice = productAttributes[j].content; } } productXmlData += '<product no="' + eval((k+1)) + '"><FL val="Product Id">' + productId + '</FL><FL val="Quantity">' + quantity + '</FL><FL val="Unit Price">'+ unitPrice + '</FL><FL val="List Price">'+ listPrice +'</FL></product>' } } } } xmlData += '<row no="1"><FL val="Subject">' + subject + '</FL><FL val="Account Name">' + accountName + '</FL><FL val="Product Details">' + productXmlData +'</FL></row>'; xmlData = '<SalesOrders>' + xmlData + '</SalesOrders>'; mc.setProperty('zohoXmlDataSalesOrder', xmlData); ]]> </script> <call-template target="zohocrm-createSalesOrder"> <with-param name="zohoApiUrl" value="{$ctx:zohoApiUrl}"/> <with-param name="zohoAccessToken" value="{$ctx:zohoAccessToken}"/> <with-param name="zohoScope" value="{$ctx:zohoScope}"/> <with-param name="zohoIsApproval" value="{$ctx:zohoIsApproval}"/> <with-param name="zohoXmlDataSalesOrder" value="{$ctx:zohoXmlDataSalesOrder}"/> <with-param name="zohoNewFormat" value="{$ctx:zohoNewFormat}"/> <with-param name="zohoVersion" value="{$ctx:zohoVersion}"/> <with-param name="zohoWfTrigger" value="{$ctx:zohoWfTrigger}"/> <with-param name="zohoDuplicateCheck" value="{$ctx:zohoDuplicateCheck}"/> <with-param name="zohoQuoteId" value="{$ctx:zohoQuoteId}"/> </call-template> <!-- Check whether the zohocrm quote is successfully updated --> <filter source="boolean(get-property('uri.var.zohoUpdatedQuoteID'))" regex="true"> <then> <property name="qbQueryString" expression="fn:concat('select * from Estimate where Id =', get-property('qbEstimateId'))"/> <quickbooks.init> <consumerKey>{$ctx:qbConsumerKey}</consumerKey> <accessToken>{$ctx:qbAccessToken}</accessToken> <accessTokenSecret>{$ctx:qbAccessTokenSecret}</accessTokenSecret> <responseType>{$ctx:qbResponseType}</responseType> <apiUrl>{$ctx:qbApiUrl}</apiUrl> <companyId>{$ctx:qbCompanyId}</companyId> <consumerSecret>{$ctx:qbConsumerSecret}</consumerSecret> </quickbooks.init> <quickbooks.query> <queryString>{$ctx:qbQueryString}</queryString> </quickbooks.query> <!-- Obtaining the estimate details--> <property name="uri.var.qbEstimateDetails" expression="json-eval($.QueryResponse.Estimate)"/> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="quickbooks_fetchEstimateData" />| ) * </call-template> <!-- Check whether the estimate details are successfully derived --> <filter source="boolean(get-property('uri.var.qbEstimateDetails'))" regex="true"> <then> <property name="qbLine" expression="json-eval($.QueryResponse.Estimate[0].Line)"/> <property name="qbCustomerRef" expression="json-eval($.QueryResponse.Estimate[0].CustomerRef)"/> <property name="qbPrivateNote" expression="json-eval($.QueryResponse.Estimate[0].PrivateNote)"/> <!--Creating Sales Receipt in Quickbooks--> <quickbooks.init> <apiUrl>{$ctx:qbApiUrl}</apiUrl> <consumerKey>{$ctx:qbConsumerKey}</consumerKey> <accessToken>{$ctx:qbAccessToken}</accessToken> <accessTokenSecret>{$ctx:qbAccessTokenSecret}</accessTokenSecret> <responseType>{$ctx:qbResponseType}</responseType> <companyId>{$ctx:qbCompanyId}</companyId> <consumerSecret>{$ctx:qbConsumerSecret}</consumerSecret> <notes>{$ctx:qbDescription}</notes> </quickbooks.init> <quickbooks.createSalesReceipt> <departmentRef>{$ctx:qbDepartmentRef}</departmentRef> <homeTotalAmt>{$ctx:qbHomeTotalAmt}</homeTotalAmt> <customField>{$ctx:qbCustomField}</customField> <exchangeRate>{$ctx:qbExchangeRate}</exchangeRate> <printStatus>{$ctx:qbPrintStatus}</printStatus> <line>{$ctx:qbLine}</line> <globalTaxCalculation>{$ctx:qbGlobalTaxCalculation}</globalTaxCalculation> <shipDate>{$ctx:qbShipDate}</shipDate> <totalAmt>{$ctx:qbTotalAmt}</totalAmt> <classRef>{$ctx:qbClassRef}</classRef> <txnDate>{$ctx:qbTxnDate}</txnDate> <balance>{$ctx:qbBalance}</balance> <autoIncrementDocNumber>{$ctx:qbAutoIncrementDocNumber}</autoIncrementDocNumber> <applyTaxAfterDiscount>{$ctx:qbApplyTaxAfterDiscount}</applyTaxAfterDiscount> <trackingNum>{$ctx:qbTrackingNum}</trackingNum> <paymentRefNum>{$ctx:qbPaymentRefNum}</paymentRefNum> <paymentMethodRef>{$ctx:qbPaymentMethodRef}</paymentMethodRef> <customerMemo>{$ctx:qbCustomerMemo}</customerMemo> <billEmail>{$ctx:qbBillEmail}</billEmail> <billAddr>{$ctx:qbBillAddr}</billAddr> <depositToAccountRef>{$ctx:qbDepositToAccountRef}</depositToAccountRef> <shipMethodRef>{$ctx:qbShipMethodRef}</shipMethodRef> <linkedTxn>{$ctx:qbLinkedTxn}</linkedTxn> <shipAddr>{$ctx:qbShipAddr}</shipAddr> <currencyRef>{$ctx:qbCurrencyRef}</currencyRef> <txnStatus>{$ctx:qbTxnStatus}</txnStatus> <docNumber>{$ctx:qbDocNumber}</docNumber> <emailStatus>{$ctx:qbEmailStatus}</emailStatus> <customerRef>{$ctx:qbCustomerRef}</customerRef> <txnTaxDetail>{$ctx:qbTxnTaxDetail}</txnTaxDetail> <privateNote>{$ctx:qbPrivateNote}</privateNote> </quickbooks.createSalesReceipt> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="quickbooks_createSalesReciept" />| ) * </call-template> </then> <else> <!-- If the estimate details are not successfully derived --> <payloadFactory media-type="json"> <format> { "response":"Estimate details are not successfully fetched." } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="quickbooks_createSalesReceipt" />| ) * </call-template> </else> </filter> </then> <else> <!-- If the quote is not successfully updated --> <payloadFactory media-type="json"> <format> { "response":"Quote is not successfully updated." } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_updateQuoteFailure" />| ) * </call-template> </else> </filter> </then> <else> <!-- If quote attributes are not fetched successfully --> <payloadFactory media-type="json"> <format> { "response":"Unable to fetch quote data due to invalid id." } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getQuoteByIdFailure" />| ) * </call-template> </else> </filter> </else> </filter> </sequence> </template>
Sample Proxy for Publishing the ZohoCRM Sales Order in QuickBooks as a Sales Receipt
<proxy xmlns="http://ws.apache.org/ns/synapse" name="zohocrm_quickbooks_integration_createSalesOrder" transports="https,http" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence onError="faultHandlerSeq"> <!-- ZohoCRM properties --> <property name="zohoApiUrl" expression="json-eval($.zohoApiUrl)"/> <property name="zohoAccessToken" expression="json-eval($.zohoAccessToken)"/> <property name="zohoScope" expression="json-eval($.zohoScope)"/> <property name="zohoNewFormat" expression="json-eval($.zohoNewFormat)"/> <property name="zohoVersion" expression="json-eval($.zohoVersion)"/> <property name="zohoSelectColumns" value="Quotes(Quote Stage)"/> <property name="zohoSearchCondition" value="(Quote Stage|=|Confirmed)"/> <property name="zohoFromIndex" value="1"/> <property name="zohoToIndex" value="200"/> <property name="zohoModuleType" value="Quotes"/> <property name="zohowfTrigger" expression="json-eval($.zohowfTrigger)"/> <property name="zohoduplicateCheck" expression="json-eval($.zohoduplicateCheck)"/> <!-- Quickbooks parameters --> <property name="qbApiUrl" expression="json-eval($.qbApiUrl)"/> <property name="qbConsumerKey" expression="json-eval($.qbConsumerKey)"/> <property name="qbConsumerSecret" expression="json-eval($.qbConsumerSecret)"/> <property name="qbAccessToken" expression="json-eval($.qbAccessToken)"/> <property name="qbAccessTokenSecret" expression="json-eval($.qbAccessTokenSecret)"/> <property name="qbCompanyId" expression="json-eval($.qbCompanyId)"/> <property name="qbDepartmentRef" expression="json-eval($.qbDepartmentRef)"/> <property name="qbCustomField" expression="json-eval($.qbCustomField)"/> <property name="qbExchangeRate" expression="json-eval($.qbExchangeRate)"/> <property name="qbPrintStatus" expression="json-eval($.qbPrintStatus)"/> <property name="qbGlobalTaxCalculation" expression="json-eval($.qbGlobalTaxCalculation)"/> <property name="qbShipDate" expression="json-eval($.qbShipDate)"/> <property name="qbClassRef" expression="json-eval($.qbClassRef)"/> <property name="qbTxnDate" expression="json-eval($.qbTxnDate)"/> <property name="qbAutoIncrementDocNumber" expression="json-eval($.qbAutoIncrementDocNumber)"/> <property name="qbApplyTaxAfterDiscount" expression="json-eval($.qbApplyTaxAfterDiscount)"/> <property name="qbTrackingNum" expression="json-eval($.qbTrackingNum)"/> <property name="qbPaymentRefNum" expression="json-eval($.qbPaymentRefNum)"/> <property name="qbPaymentMethodRef" expression="json-eval($.qbPaymentMethodRef)"/> <property name="qbCustomerMemo" expression="json-eval($.qbCustomerMemo)"/> <property name="qbBillEmail" expression="json-eval($.qbBillEmail)"/> <property name="qbBillAddr" expression="json-eval($.qbBillAddr)"/> <property name="qbDepositToAccountRef" expression="json-eval($.qbDepositToAccountRef)"/> <property name="qbShipMethodRef" expression="json-eval($.qbShipMethodRef)"/> <property name="qbLinkedTxn" expression="json-eval($.qbLinkedTxn)"/> <property name="qbShipAddr" expression="json-eval($.qbShipAddr)"/> <property name="qbCurrencyRef" expression="json-eval($.qbCurrencyRef)"/> <property name="qbTxnStatus" expression="json-eval($.qbTxnStatus)"/> <property name="qbDocNumber" expression="json-eval($.qbDocNumber)"/> <property name="qbEmailStatus" expression="json-eval($.qbEmailStatus)"/> <property name="qbCustomerRef" expression="json-eval($.qbCustomerRef)"/> <property name="qbTxnTaxDetail" expression="json-eval($.qbTxnTaxDetail)"/> <property name="qbPrivateNote" expression="json-eval($.qbPrivateNote)"/> <property name="quoteEstimateMap" expression="json-eval($.quoteEstimateMap)"/> <property name="uri.var.responseBuilder" value="" scope="operation" /> <property name="uri.var.index" value="0" scope="operation" /> <!-- Calling the getSearchRecords to retrieve the quotes with confirmed status--> <zohocrm.init> <scope>{$ctx:zohoScope}</scope> <accessToken>{$ctx:zohoAccessToken}</accessToken> <apiUrl>{$ctx:zohoApiUrl}</apiUrl> </zohocrm.init> <zohocrm.getSearchRecords> <fromIndex>{$ctx:zohoFromIndex}</fromIndex> <searchCondition>{$ctx:zohoSearchCondition}</searchCondition> <selectColumns>{$ctx:zohoSelectColumns}</selectColumns> <toIndex>{$ctx:zohoToIndex}</toIndex> <newFormat>{$ctx:zohoNewFormat}</newFormat> <version>{$ctx:zohoVersion}</version> <moduleType>{$ctx:zohoModuleType}</moduleType> </zohocrm.getSearchRecords> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getConfirmedQuotes" /> | ) * </call-template> <property name="uri.var.getQuotesResponseString" expression="get-property('uri.var.responseString')" scope="operation" /> <property name="messageType" value="application/xml" scope="axis2" /> <property name="uri.var.quotesCount" expression="count(//response/result/Quotes/row)" scope="operation" /> <filter xpath="0 = get-property('operation', 'uri.var.quotesCount')"> <then> <payloadFactory media-type="json"> <format> { "activity":"zohocrm_retrieveConfirmedQuotesFailure", "activityResponse":"No confirmed quotes were found" } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getConfirmedQuotesFailure" /> | ) * </call-template> <property name="uri.var.responseBuilder" expression="json-eval($)" scope="operation" /> <loopback /> </then> </filter> <!-- Clears the rsponseString to avoid it being appended multiple times --> <property name="uri.var.responseString" value="" /> <iterate id="quotesIterator" expression="//response/result/Quotes/row" sequential="true" continueParent="true" preservePayload="true"> <target> <sequence> <property name="uri.var.zohoQuoteId" expression="//FL[1]/content/text()" /> <call-template target="zohocrm_createQbSalesReceipt"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="zohoApiUrl" value="{$ctx:zohoApiUrl}" /> | <with-param name="zohoAccessToken" value="{$ctx:zohoAccessToken}" /> | <with-param name="zohoScope" value="{$ctx:zohoScope}" /> | <with-param name="zohoQuoteId" value="{$ctx:uri.var.zohoQuoteId}" /> | <with-param name="zohoNewFormat" value="{$ctx:zohoNewFormat}" /> | <with-param name="zohoVersion" value="{$ctx:zohoVersion}" /> | <with-param name="zohowfTrigger" value="{$ctx:zohowfTrigger}" /> | <with-param name="zohoduplicateCheck" value="{$ctx:zohoduplicateCheck}" /> | <with-param name="qbApiUrl" value="{$ctx:qbApiUrl}" /> | <with-param name="qbConsumerKey" value="{$ctx:qbConsumerKey}" /> | <with-param name="qbConsumerSecret" value="{$ctx:qbConsumerSecret}" /> | <with-param name="qbAccessToken" value="{$ctx:qbAccessToken}" /> | <with-param name="qbAccessTokenSecret" value="{$ctx:qbAccessTokenSecret}" /> | <with-param name="qbCompanyId" value="{$ctx:qbCompanyId}" /> | <with-param name="qbDepartmentRef" value="{$ctx:qbDepartmentRef}" /> | <with-param name="qbCustomField" value="{$ctx:qbCustomField}" /> | <with-param name="qbExchangeRate" value="{$ctx:qbExchangeRate}" /> | <with-param name="qbPrintStatus" value="{$ctx:qbPrintStatus}" /> | <with-param name="qbGlobalTaxCalculation" value="{$ctx:qbGlobalTaxCalculation}" /> | <with-param name="qbShipDate" value="{$ctx:qbShipDate}" /> | <with-param name="qbClassRef" value="{$ctx:qbClassRef}" /> | <with-param name="qbTxnDate" value="{$ctx:qbTxnDate}" /> | <with-param name="qbAutoIncrementDocNumber" value="{$ctx:qbAutoIncrementDocNumber}" /> | <with-param name="qbApplyTaxAfterDiscount" value="{$ctx:qbApplyTaxAfterDiscount}" /> | <with-param name="qbTrackingNum" value="{$ctx:qbTrackingNum}" /> | <with-param name="qbPaymentRefNum" value="{$ctx:qbPaymentRefNum}" /> | <with-param name="qbPaymentMethodRef" value="{$ctx:qbPaymentMethodRef}" /> | <with-param name="qbCustomerMemo" value="{$ctx:qbCustomerMemo}" /> | <with-param name="qbBillEmail" value="{$ctx:qbBillEmail}" /> | <with-param name="qbBillAddr" value="{$ctx:qbBillAddr}" /> | <with-param name="qbDepositToAccountRef" value="{$ctx:qbDepositToAccountRef}" /> | <with-param name="qbShipMethodRef" value="{$ctx:qbShipMethodRef}" /> | <with-param name="qbLinkedTxn" value="{$ctx:qbLinkedTxn}" /> | <with-param name="qbShipAddr" value="{$ctx:qbShipAddr}" /> | <with-param name="qbCurrencyRef" value="{$ctx:qbCurrencyRef}" /> | <with-param name="qbTxnStatus" value="{$ctx:qbTxnStatus}" /> | <with-param name="qbDocNumber" value="{$ctx:qbDocNumber}" /> | <with-param name="qbEmailStatus" value="{$ctx:qbEmailStatus}" /> | <with-param name="qbCustomerRef" value="{$ctx:qbCustomerRef}" /> | <with-param name="qbTxnTaxDetail" value="{$ctx:qbTxnTaxDetail}" /> | <with-param name="qbPrivateNote" value="{$ctx:qbPrivateNote}" /> | <with-param name="quoteEstimateMap" value="{$ctx:quoteEstimateMap}" /> | ) * </call-template> <property name="uri.var.index" expression="get-property('operation','uri.var.index') + 1" scope="operation" /> <property name="uri.var.responseBuilder" expression="fn:concat(get-property('operation','uri.var.responseBuilder'), get-property('uri.var.responseString') , ', ')" scope="operation" /> </sequence> </target> </iterate> <filter xpath="get-property('operation', 'uri.var.index') = get-property('operation', 'uri.var.quotesCount')"> <then> <!-- Remove the final comma appended inside the iterator mediator for final response generation inside the outsequence --> <property name="uri.var.responseBuilder" expression="fn:substring(get-property('operation', 'uri.var.responseBuilder'), 0, fn:string-length(get-property('operation', 'uri.var.responseBuilder')))" scope="operation" /> <loopback /> </then> </filter> </inSequence> <outSequence> <property name="messageType" value="application/json" scope="axis2" /> <!-- Generate the chained response of all the API calls in createLeads --> <payloadFactory media-type="json"> <format> { "Response":[ $1, $2 ] } </format> <args> <arg expression="get-property('operation', 'uri.var.getQuotesResponseString')" /> <arg expression="get-property('operation', 'uri.var.responseBuilder')" /> </args> </payloadFactory> <send /> </outSequence> </target> <description/> </proxy>
Sample Request for Publishing the ZohoCRM Sales Order in QuickBooks as a Sales Receipt
{ "zohoApiUrl":"https://crm.zoho.com", "zohoAccessToken":"701582095e37ea22edd751db7aaa5c68", "zohoScope":"crmapi", "zohoNewFormat":1, "zohoVersion":1, "qbConsumerKey": "qyprdJmYnbRcrX2wDkh9YSCR01aIE4", "qbConsumerSecret": "caf6l5we0mvKSeH37xCPFiDWjJxS0lXUdap08j1y", "qbAccessToken": "qyprdOor63MfOqeWyEOItF5ZNLkr1374sfBaYXSggIPnbGxS", "qbAccessTokenSecret": "1gWua4KTJP1EjAu0zRECCBOEKaNUXYb6j2lkV6Wg", "qbApiUrl": "https://qb.sbfinance.intuit.com:443", "qbCompanyId": "1281046125", "quoteEstimateMap":{"1266737000000119023":"16","1266737000000122011":"14"} }
Sample Template for Creating and Retrieving Invoices
<!-- This template creates an invoice in Zoho CRM and then retrieves the invoice details --> <template name="zohocrm-createAndRetrieveInvoice" xmlns="http://ws.apache.org/ns/synapse"> <!-- Zoho CRM parameters --> <parameter name="zohoApiUrl" description="The Zoho api URL" /> <parameter name="zohoAccessToken" description="Encrypted alphanumeric string to authenticate the Zoho credentials" /> <parameter name="zohoScope" description="Zoho CRM scope, Specify the value as crmapi" /> <parameter name="zohoNewFormat" description="The newFormat, an integer determine weather null valus should be excluded(1) or included(2)" /> <parameter name="zohoVersion" description="Coloumns selected" /> <parameter name="zohoXmlData" description="The xml string containing the data of the Invoice to be inserted" /> <parameter name="zohoWfTrigger" description="The wfTrigger parameter is used to trigger the workflow rule while inserting record into CRM account" /> <parameter name="zohoDuplicateCheck" description="Checking the duplicate records and throw an error response" /> <sequence> <!-- zoho CRM properties --> <property name="uri.var.zohoApiUrl" expression="$func:zohoApiUrl"/> <property name="uri.var.zohoAccessToken" expression="$func:zohoAccessToken"/> <property name="uri.var.zohoScope" expression="$func:zohoScope"/> <property name="uri.var.zohoNewFormat" expression="$func:zohoNewFormat"/> <property name="uri.var.zohoVersion" expression="$func:zohoVersion"/> <property name="uri.var.zohoXmlData" expression="$func:zohoXmlData"/> <property name="uri.var.zohoWfTrigger" expression="$func:zohoWfTrigger"/> <property name="uri.var.zohoDuplicateCheck" expression="$func:zohoDuplicateCheck"/> <!-- isApproval property was set to false so the case will immediately add to the account and can proceed with other API calls, otherwise manual approving should be needed--> <property name="uri.var.zohoIsApproval" value="false"/> <property name="uri.var.zohoModuleType" value="Invoices"/> <!-- zoho CRM insert Invoice --> <zohocrm.init> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <scope>{$ctx:uri.var.zohoScope}</scope> </zohocrm.init> <zohocrm.insertRecords> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> <xmlData>{$ctx:uri.var.zohoXmlData}</xmlData> <wfTrigger>{$ctx:uri.var.zohoWfTrigger}</wfTrigger> <duplicateCheck>{$ctx:uri.var.zohoDuplicateCheck}</duplicateCheck> <isApproval>{$ctx:uri.var.zohoIsApproval}</isApproval> <moduleType>{$ctx:uri.var.zohoModuleType}</moduleType> </zohocrm.insertRecords> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohoCRM_insertInvoice" /> | ) * </call-template> <!-- Retrieving created invoice ID --> <property name="uri.var.invoiceId" expression="json-eval($.response.result.recorddetail.FL[0].content)"/> <!-- Check the availability of invoice ID to proceed with other API calls --> <filter source="boolean(get-property('uri.var.invoiceId'))" regex="false"> <loopback/> </filter> <header name="Expires" scope="transport" action="remove" /> <header name="Content-Type" scope="transport" action="remove" /> <header name="Date" scope="transport" action="remove" /> <header name="Server" scope="transport" action="remove" /> <header name="Transfer-Encoding" scope="transport" action="remove" /> <header name="Connection" scope="transport" action="remove" /> <header name="Vary" scope="transport" action="remove" /> <header name="Content-Encoding" scope="transport" action="remove" /> </sequence> </template>
Sample Proxy for Creating Invoices in ZohoCRM and QuickBooks
<proxy xmlns="http://ws.apache.org/ns/synapse" name="zohocrm_quickbooks_createInvoice" transports="https,http" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence> <!-- Zoho CRM API call related properties --> <property name="zohoApiUrl" expression="json-eval($.zohoApiUrl)"/> <property name="zohoAccessToken" expression="json-eval($.zohoAccessToken)"/> <property name="zohoScope" expression="json-eval($.zohoScope)"/> <property name="zohoNewFormat" expression="json-eval($.zohoNewFormat)"/> <property name="zohoVersion" expression="json-eval($.zohoVersion)"/> <property name="zohoWfTrigger" expression="json-eval($.zohoWfTrigger)"/> <property name="zohoDuplicateCheck" expression="json-eval($.zohoDuplicateCheck)"/> <property name="zohoSalesOrderId" expression="json-eval($.zohoSalesOrderId)"/> <!-- Quickbooks API call related properties --> <property name="qbConsumerKey" expression="json-eval($.qbConsumerKey)"/> <property name="qbAccessToken" expression="json-eval($.qbAccessToken)"/> <property name="qbAccessTokenSecret" expression="json-eval($.qbAccessTokenSecret)"/> <property name="qbResponseType" expression="json-eval($.qbResponseType)"/> <property name="qbApiUrl" expression="json-eval($.qbApiUrl)"/> <property name="qbCompanyId" expression="json-eval($.qbCompanyId)"/> <property name="qbConsumerSecret" expression="json-eval($.qbConsumerSecret)"/> <property name="qbDepartmentRef" expression="json-eval($.qbDepartmentRef)"/> <property name="qbHomeTotalAmt" expression="json-eval($.qbHomeTotalAmt)"/> <property name="qbCustomField" expression="json-eval($.qbCustomField)"/> <property name="qbDeposit" expression="json-eval($.qbDeposit)"/> <property name="qbExchangeRate" expression="json-eval($.qbExchangeRate)"/> <property name="qbPrintStatus" expression="json-eval($.qbPrintStatus)"/> <property name="qbGlobalTaxCalculation" expression="json-eval($.qbGlobalTaxCalculation)"/> <property name="qbShipDate" expression="json-eval($.qbShipDate)"/> <property name="qbTotalAmt" expression="json-eval($.qbTotalAmt)"/> <property name="qbTxnDate" expression="json-eval($.qbTxnDate)"/> <property name="qbBalance" expression="json-eval($.qbBalance)"/> <property name="qbSalesTermRef" expression="json-eval($.qbSalesTermRef)"/> <property name="qbTrackingNum" expression="json-eval($.qbTrackingNum)"/> <property name="qbApplyTaxAfterDiscount" expression="json-eval($.qbApplyTaxAfterDiscount)"/> <property name="qbCustomerMemo" expression="json-eval($.qbCustomerMemo)"/> <property name="qbBillEmail" expression="json-eval($.qbBillEmail)"/> <property name="qbDueDate" expression="json-eval($.qbDueDate)"/> <property name="qbBillAddr" expression="json-eval($.qbBillAddr)"/> <property name="qbDepositToAccountRef" expression="json-eval($.qbDepositToAccountRef)"/> <property name="qbShipMethodRef" expression="json-eval($.qbShipMethodRef)"/> <property name="qbLinkedTxn" expression="json-eval($.qbLinkedTxn)"/> <property name="qbShipAddr" expression="json-eval($.qbShipAddr)"/> <property name="qbAllowIPNPayment" expression="json-eval($.qbAllowIPNPayment)"/> <property name="qbCurrencyRef" expression="json-eval($.qbCurrencyRef)"/> <property name="qbDocNumber" expression="json-eval($.qbDocNumber)"/> <property name="qbEmailStatus" expression="json-eval($.qbEmailStatus)"/> <property name="qbCustomerRef" expression="json-eval($.qbCustomerRef)"/> <property name="qbTxnTaxDetail" expression="json-eval($.qbTxnTaxDetail)"/> <property name="qbSalesReceiptId" expression="json-eval($.qbSalesReceiptId)"/> <!-- Check the availability of sales receipt ID to proceed with other API calls --> <filter source="boolean(get-property('qbSalesReceiptId'))" regex="false"> <payloadFactory media-type="json"> <format> { "activity":"zohocrm_getSalesReceiptId", "activityResponse":"Sales receipt ID has not been sent" } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getSalesReceiptId" /> | ) * </call-template> <loopback/> </filter> <script language="js"> <![CDATA[ var qbSalesReceiptId = mc.getProperty('qbSalesReceiptId'); mc.setProperty('qbSalesReceiptId', "'" + qbSalesReceiptId + "'"); ]]> </script> <!-- Retrieveing sales order details --> <zohocrm.init> <apiUrl>{$ctx:zohoApiUrl}</apiUrl> <accessToken>{$ctx:zohoAccessToken}</accessToken> <scope>{$ctx:zohoScope}</scope> </zohocrm.init> <zohocrm.getRecordsById> <id>{$ctx:zohoSalesOrderId}</id> <newFormat>{$ctx:zohoNewFormat}</newFormat> <version>{$ctx:zohoVersion}</version> <moduleType>SalesOrders</moduleType> </zohocrm.getRecordsById> <property name="uri.var.salesOrderAttributes" expression="json-eval($.response.result.SalesOrders.row.FL)"/> <!-- Check the availability of SalesOrder Details to proceed with other API calls --> <filter source="boolean(get-property('uri.var.salesOrderAttributes'))" regex="false"> <then> <payloadFactory media-type="json"> <format> { "activity":"zohocrm_retrieveSalesOrder", "activityResponse":"Could not retrieve sales order details from the given zohoSalesOrderID" } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getIssuesFailure" /> | ) * </call-template> <loopback/> </then> </filter> <!-- Following script will create the xml data to create an Invoice in zohoCRM--> <script language="js"> <![CDATA[ var jsn = eval("(" + mc.getProperty("uri.var.salesOrderAttributes") + ")"); var products; var productAttributes; var xmlData = ''; for (var i = 0; i < jsn.length ; i++) { if(jsn[i].val == "Account Name"){ xmlData += '<FL val="Account Name">' + jsn[i].content + '</FL>'; } if(jsn[i].val == "Subject"){ xmlData += '<FL val="Sales Order">' + jsn[i].content + '</FL>'; mc.setProperty('qbPrivateNote', jsn[i].content) } if(jsn[i].val == "Sub Total"){ xmlData += '<FL val="Sub Total">' + jsn[i].content + '</FL>'; } if(jsn[i].val == "Adjustment"){ xmlData += '<FL val="Adjustment">' + jsn[i].content + '</FL>'; } if(jsn[i].val == "Grand Total"){ xmlData += '<FL val="Grand Total">' + jsn[i].content + '</FL>'; } if(jsn[i].val == "Product Details"){ products = jsn[i].product; xmlData += '<FL val="Product Details">'; if (typeof(products) == "object" && (products.join == undefined)) { // Products is a JSON object, not an array productAttributes = products.FL; xmlData += '<product no="1">'; for (var k = 0; k < productAttributes.length ; k++) { if(productAttributes[k].val == "Product Id"){ xmlData += '<FL val="Product Id">' + productAttributes[k].content + '</FL>'; } if(productAttributes[k].val == "Product Name"){ xmlData += '<FL val="Product Name">' + productAttributes[k].content + '</FL>'; } if(productAttributes[k].val == "Unit Price"){ xmlData += '<FL val="Unit Price">' + productAttributes[k].content + '</FL>'; } if(productAttributes[k].val == "Quantity"){ xmlData += '<FL val="Quantity">' + productAttributes[k].content + '</FL>'; } if(productAttributes[k].val == "Quantity in Stock"){ xmlData += '<FL val="Quantity in Stock">' + productAttributes[k].content + '</FL>'; } if(productAttributes[k].val == "Total"){ xmlData += '<FL val="Total">' + productAttributes[k].content + '</FL>'; } if(productAttributes[k].val == "List Price"){ xmlData += '<FL val="List Price">' + productAttributes[k].content + '</FL>'; } if(productAttributes[k].val == "Net Total"){ xmlData += '<FL val="Net Total">' + productAttributes[k].content + '</FL>'; } } xmlData += '</product>'; }else{ // Products is a JSON array for (var j = 0; j < products.length ; j++) { productAttributes = products[j].FL; xmlData += '<product no="'+ j+1 +'">'; for (var l = 0; l < productAttributes.length ; l++) { if(productAttributes[l].val == "Product Id"){ xmlData += '<FL val="Product Id">' + productAttributes[l].content + '</FL>'; } if(productAttributes[l].val == "Product Name"){ xmlData += '<FL val="Product Name">' + productAttributes[l].content + '</FL>'; } if(productAttributes[l].val == "Unit Price"){ xmlData += '<FL val="Unit Price">' + productAttributes[l].content + '</FL>'; } if(productAttributes[l].val == "Quantity"){ xmlData += '<FL val="Quantity">' + productAttributes[l].content + '</FL>'; } if(productAttributes[l].val == "Quantity in Stock"){ xmlData += '<FL val="Quantity in Stock">' + productAttributes[l].content + '</FL>'; } if(productAttributes[l].val == "Total"){ xmlData += '<FL val="Total">' + productAttributes[l].content + '</FL>'; } if(productAttributes[l].val == "List Price"){ xmlData += '<FL val="List Price">' + productAttributes[l].content + '</FL>'; } if(productAttributes[l].val == "Net Total"){ xmlData += '<FL val="Net Total">' + productAttributes[l].content + '</FL>'; } } xmlData += '</product>'; } } xmlData += '</FL>'; } } xmlData = '<Invoices><row no="1"><FL val="Subject">' + mc.getProperty('qbPrivateNote') + '</FL>' + xmlData +'</row></Invoices>'; mc.setProperty('zohoXmlData', xmlData); ]]> </script> <call-template target="zohocrm-createAndRetrieveInvoice"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="zohoApiUrl" value="{$ctx:zohoApiUrl}" /> | <with-param name="zohoAccessToken" value="{$ctx:zohoAccessToken}" /> | <with-param name="zohoScope" value="{$ctx:zohoScope}" /> | <with-param name="zohoNewFormat" value="{$ctx:zohoNewFormat}" /> | <with-param name="zohoVersion" value="{$ctx:zohoVersion}" /> | <with-param name="zohoXmlData" value="{$ctx:zohoXmlData}" /> | <with-param name="zohoWfTrigger" value="{$ctx:zohoWfTrigger}" /> | <with-param name="zohoDuplicateCheck" value="{$ctx:zohoDuplicateCheck}" /> | ) * </call-template> <!-- Retrieving information about the sales receipt in Quickbooks--> <property name="qbQueryString" expression="fn:concat('select * from SalesReceipt where id =', get-property('qbSalesReceiptId'))"/> <quickbooks.init> <consumerKey>{$ctx:qbConsumerKey}</consumerKey> <accessToken>{$ctx:qbAccessToken}</accessToken> <accessTokenSecret>{$ctx:qbAccessTokenSecret}</accessTokenSecret> <responseType>{$ctx:qbResponseType}</responseType> <apiUrl>{$ctx:qbApiUrl}</apiUrl> <companyId>{$ctx:qbCompanyId}</companyId> <consumerSecret>{$ctx:qbConsumerSecret}</consumerSecret> </quickbooks.init> <quickbooks.query> <queryString>{$ctx:qbQueryString}</queryString> </quickbooks.query> <!-- Obtaining the estimate details--> <property name="uri.var.qbSalesReceiptDetails" expression="json-eval($.QueryResponse.SalesReceipt)"/> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="quickbooks_fetchSalesReceiptData" />| ) * </call-template> <!-- Check whether the quickbooks sales receipt details have been successfully derived --> <filter source="boolean(get-property('uri.var.qbSalesReceiptDetails'))" regex="false"> <then> <loopback/> </then> </filter> <property name="qbLine" expression="json-eval($.QueryResponse.SalesReceipt[0].Line)"/> <property name="qbCustomerRef" expression="json-eval($.QueryResponse.SalesReceipt[0].CustomerRef)"/> <property name="qbPrivateNote" expression="json-eval($.QueryResponse.SalesReceipt[0].PrivateNote)"/> <header name="Expires" scope="transport" action="remove" /> <header name="Content-Type" scope="transport" action="remove" /> <header name="Date" scope="transport" action="remove" /> <header name="Server" scope="transport" action="remove" /> <header name="Transfer-Encoding" scope="transport" action="remove" /> <header name="Connection" scope="transport" action="remove" /> <header name="Vary" scope="transport" action="remove" /> <header name="Content-Encoding" scope="transport" action="remove" /> <quickbooks.init> <consumerKey>{$ctx:qbConsumerKey}</consumerKey> <accessToken>{$ctx:qbAccessToken}</accessToken> <accessTokenSecret>{$ctx:qbAccessTokenSecret}</accessTokenSecret> <responseType>{$ctx:qbResponseType}</responseType> <apiUrl>{$ctx:qbApiUrl}</apiUrl> <companyId>{$ctx:qbCompanyId}</companyId> <consumerSecret>{$ctx:qbConsumerSecret}</consumerSecret> </quickbooks.init> <quickbooks.createInvoice> <departmentRef>{$ctx:qbDepartmentRef}</departmentRef> <homeTotalAmt>{$ctx:qbHomeTotalAmt}</homeTotalAmt> <customField>{$ctx:qbCustomField}</customField> <deposit>{$ctx:qbDeposit}</deposit> <exchangeRate>{$ctx:qbExchangeRate}</exchangeRate> <printStatus>{$ctx:qbPrintStatus}</printStatus> <line>{$ctx:qbLine}</line> <globalTaxCalculation>{$ctx:qbGlobalTaxCalculation}</globalTaxCalculation> <shipDate>{$ctx:qbShipDate}</shipDate> <totalAmt>{$ctx:qbTotalAmt}</totalAmt> <txnDate>{$ctx:qbTxnDate}</txnDate> <balance>{$ctx:qbBalance}</balance> <salesTermRef>{$ctx:qbSalesTermRef}</salesTermRef> <trackingNum>{$ctx:qbTrackingNum}</trackingNum> <applyTaxAfterDiscount>{$ctx:qbApplyTaxAfterDiscount}</applyTaxAfterDiscount> <customerMemo>{$ctx:qbCustomerMemo}</customerMemo> <billEmail>{$ctx:qbBillEmail}</billEmail> <dueDate>{$ctx:qbDueDate}</dueDate> <billAddr>{$ctx:qbBillAddr}</billAddr> <depositToAccountRef>{$ctx:qbDepositToAccountRef}</depositToAccountRef> <shipMethodRef>{$ctx:qbShipMethodRef}</shipMethodRef> <linkedTxn>{$ctx:qbLinkedTxn}</linkedTxn> <shipAddr>{$ctx:qbShipAddr}</shipAddr> <allowIPNPayment>{$ctx:qbAllowIPNPayment}</allowIPNPayment> <currencyRef>{$ctx:qbCurrencyRef}</currencyRef> <docNumber>{$ctx:qbDocNumber}</docNumber> <emailStatus>{$ctx:qbEmailStatus}</emailStatus> <customerRef>{$ctx:qbCustomerRef}</customerRef> <txnTaxDetail>{$ctx:qbTxnTaxDetail}</txnTaxDetail> <privateNote>{$ctx:qbPrivateNote}</privateNote> </quickbooks.createInvoice> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="quickbooks_createInvoice" /> | ) * </call-template> <loopback/> </inSequence> <outSequence> <property name="messageType" value="application/json" scope="axis2" /> <!-- Generate the chained response of all the API calls in createLeads --> <payloadFactory media-type="json"> <format> { "Response":[$1] } </format> <args> <arg expression="get-property('uri.var.responseString')" /> </args> </payloadFactory> <send/> </outSequence> </target> <description/> </proxy>
Sample Request for Creating Invoices in ZohoCRM and QuickBooks
{ "zohoApiUrl": "https://crm.zoho.com", "zohoAccessToken": "701582095e37ea22edd751db7aaa5c68", "zohoScope": "crmapi", "zohoSalesOrderId": "1266737000000127039", "qbSalesReceiptId":"35", "qbApiUrl":"https://qb.sbfinance.intuit.com:443", "qbConsumerKey": "qyprdJmYnbRcrX2wDkh9YSCR01aIE4", "qbConsumerSecret": "caf6l5we0mvKSeH37xCPFiDWjJxS0lXUdap08j1y", "qbAccessToken": "qyprdOor63MfOqeWyEOItF5ZNLkr1374sfBaYXSggIPnbGxS", "qbAccessTokenSecret": "1gWua4KTJP1EjAu0zRECCBOEKaNUXYb6j2lkV6Wg", "qbResponseType":"application/json", "qbCompanyId":"1281046125" }