com.adobe.cq.mcm.salesforce.SalesforceExportProcess Maven / Gradle / Ivy
/*
* ***********************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
* ************************************************************************
*/
package com.adobe.cq.mcm.salesforce;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.apache.http.osgi.services.HttpClientBuilderFactory;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.JcrResourceConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import aQute.bnd.annotation.ProviderType;
import com.adobe.granite.crypto.CryptoException;
import com.adobe.granite.crypto.CryptoSupport;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.wcm.webservicesupport.Configuration;
import com.day.cq.wcm.webservicesupport.ConfigurationManager;
import com.day.cq.wcm.webservicesupport.ConfigurationManagerFactory;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowData;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
/**
* The SalesforceExportProcess
exports an AEM user to a Salesforce Lead. It is assigned as a workflow step
* */
@ProviderType
@Component
@Service
@Property(name="process.label", value="Export Leads to Salesforce")
public class SalesforceExportProcess implements WorkflowProcess {
private static final Logger log = LoggerFactory.getLogger(SalesforceExportProcess.class);
public static final String INSTANCE_URL = "instanceurl";
public static final String ACCESS_TOKEN = "accesstoken";
public static final String CUSTOMER_KEY = "customerkey";
public static final String CUSTOMER_SECRET = "customersecret";
public static final String REFRESH_TOKEN = "refreshtoken";
public static final String JCR_PATH = "JCR_PATH";
public static final String CQ_CLOUDSERVICECONFIG = "cq:cloudserviceconfig";
public static final String SF_LEAD_MGMT_RESTFUL_PATH = "/services/data/v20.0/sobjects/Lead/";
public static final String APPLICATION_JSON = "application/json";
public static final String HTTP_PATCH = "PATCH";
public static final String HTTP_POST = "POST";
public static final int SF_SUCCESS_UPDATE_CODE = 204;
private static final String SF_ENTITY_DELETED_ERRORCODE = "ENTITY_IS_DELETED";
private static final String SF_REQUIRED_FIELD_MISSING_ERRORCODE = "REQUIRED_FIELD_MISSING";
public static final String ERROR_CODE = "errorCode";
public static final String SF_LEAD_CREATION_SUCCESS = "success";
public static final String SF_LEAD_ID_FIELDNAME = "leadID";
/**
* This reference is kept to prevent increasing the package version to 2.x.
* Do NOT use this service! Use the one from configurationManagerFactory.
*/
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
private ConfigurationManager configurationManager;
@Reference
private ConfigurationManagerFactory configurationManagerFactory;
@Reference
private ResourceResolverFactory resourceResolverFactory;
@Reference
private SalesforceConfiguration salesforceConfiguration;
@Reference
private CryptoSupport cryptoSupport;
@Reference
private SlingRepository repository;
@Reference
private HttpClientBuilderFactory clientBuilderFactory;
/**
* {@inheritDoc}
*/
public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap args) throws WorkflowException{
WorkflowData workflowData = workItem.getWorkflowData();
if(workflowData.getPayloadType().equals(JCR_PATH)){
String userId = (String) workItem.getWorkflow().getMetaDataMap().get("userId");
if (userId == null) {
userId = workItem.getWorkflow().getInitiator();
}
Session impersonateSession = null;
ResourceResolver resolver = null;
ConfigurationManager configurationManager = null;
try {
impersonateSession = repository.impersonateFromService(
null, new SimpleCredentials(userId, new char[] {}), null);
Map map = new HashMap();
map.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, impersonateSession);
resolver = resourceResolverFactory.getResourceResolver(map);
configurationManager = configurationManagerFactory.getConfigurationManager(resolver);
} catch (RepositoryException e) {
throw new WorkflowException(e);
} catch (LoginException e) {
throw new WorkflowException(e);
}
if(configurationManager!=null){
String configPath = args.get(CQ_CLOUDSERVICECONFIG, String.class);
if(configPath!=null){
Configuration salesforceConfig = configurationManager.getConfiguration(configPath);
if(salesforceConfig!=null){
Session session = workflowSession.getSession();
String workflowPayloadPath = workItem.getWorkflowData().getPayload().toString();
try{
if (session.itemExists(workflowPayloadPath)) {
Node node = session.getNode(workflowPayloadPath);
String instanceUrl = salesforceConfig.get(INSTANCE_URL, "");
String accessToken = salesforceConfig.get(ACCESS_TOKEN, "");
String clientId = salesforceConfig.get(CUSTOMER_KEY, "");
String encryptedCustomerSecret = salesforceConfig.get(CUSTOMER_SECRET, "");
String encryptedRefereshToken = salesforceConfig.get(REFRESH_TOKEN, "");
String customerSecret = encryptedCustomerSecret;
String refreshToken = encryptedRefereshToken;
if(cryptoSupport.isProtected(encryptedCustomerSecret)){
customerSecret = cryptoSupport.unprotect(encryptedCustomerSecret);
}
if(cryptoSupport.isProtected(encryptedRefereshToken)){
refreshToken = cryptoSupport.unprotect(encryptedRefereshToken);
}
// CQ Lead Attribute Mapping with SFDC lead
Map fieldsMapping = salesforceConfiguration.getLeadsMapping();
Map httpData = new HashMap();
for(Map.Entry entry: fieldsMapping.entrySet()){
if(node.hasProperty(entry.getKey())){
String fieldValue = node.getProperty(entry.getKey()).getValue().getString();
httpData.put(entry.getValue(), fieldValue);
}
}
// Convert the map into JSON
JSONObject requestData = new JSONObject(httpData);
String requestDataString = requestData.toString();
SalesforceClient salesforceClient = new SalesforceClient();
salesforceClient.setClientBuilderFactory(clientBuilderFactory);
salesforceClient.setAccessToken(accessToken);
salesforceClient.setRefreshToken(refreshToken);
salesforceClient.setClientId(clientId);
salesforceClient.setClientSecret(customerSecret);
salesforceClient.setInstanceURL(instanceUrl);
salesforceClient.setContentType(APPLICATION_JSON);
StringBuilder salesforcePath = new StringBuilder(SF_LEAD_MGMT_RESTFUL_PATH);
if (node.hasProperty(SF_LEAD_ID_FIELDNAME)) {
salesforcePath.append( node.getProperty(SF_LEAD_ID_FIELDNAME).getValue().getString() );
salesforceClient.setStringMethod(HTTP_PATCH);
}
else {
salesforceClient.setStringMethod(HTTP_POST);
}
salesforceClient.setPath(salesforcePath.toString());
salesforceClient.setData(requestDataString);
SalesforceResponse salesforceResponse = salesforceClient.executeRequest();
if(salesforceResponse.getAccessTokenUpdated()){
// Update Access token in Configuration
Node configNode = session.getNode(configPath).getNode(JcrConstants.JCR_CONTENT);
configNode.setProperty(ACCESS_TOKEN, salesforceClient.getAccessToken());
configNode.getSession().save();
}
try{
if(salesforceResponse.getBody()==null && salesforceResponse.getCode() == SF_SUCCESS_UPDATE_CODE){
// Lead Updated Successfully
log.info("Salesforce Lead Updated with Success (id: "
+ node.getProperty(SF_LEAD_ID_FIELDNAME).getValue().getString() + ")");
}
else{
JSONObject responseJson = salesforceResponse.getBodyAsJSON();
if(responseJson.has(SF_LEAD_CREATION_SUCCESS) && responseJson.getBoolean(SF_LEAD_CREATION_SUCCESS)){
// Lead Creation Success
if (!node.hasProperty(SF_LEAD_ID_FIELDNAME)) {
node.setProperty(SF_LEAD_ID_FIELDNAME, responseJson.getString("id"));
session.save();
log.info("New Salesforce Lead Created with Success (id: "
+ responseJson.getString("id") + ")");
}
}
else if(responseJson.has(ERROR_CODE) && responseJson.getString(ERROR_CODE)!=null){
String errorCode = responseJson.getString(ERROR_CODE);
if(SF_ENTITY_DELETED_ERRORCODE.equals(errorCode)){
// Check for WF Flag config
Boolean recreateLeadFlag = args.get("recreateLead",Boolean.class);
if(recreateLeadFlag!=null && recreateLeadFlag.equals(true)){
// Create Lead Again
salesforceClient.setPath(SF_LEAD_MGMT_RESTFUL_PATH);
salesforceClient.setStringMethod(HTTP_POST);
salesforceResponse = salesforceClient.executeRequest();
// Update with new Lead Id
responseJson = salesforceResponse.getBodyAsJSON();
node.setProperty(SF_LEAD_ID_FIELDNAME, responseJson.getString("id"));
session.save();
log.info("Salesforce Lead Created again (after deletion from SF) with " +
"Success (id: "+ responseJson.getString("id") + ")");
}
}
else if(SF_REQUIRED_FIELD_MISSING_ERRORCODE.equals(errorCode)){
// Required Fields Missing to Create a Lead
log.error("Lead Creation failed. Some required fields missing while " +
"creating lead: "+salesforceResponse.getBody());
throw new SalesforceException("Lead Creation failed. Some required fields " +
"missing while creating lead: "+salesforceResponse.getBody());
}
}
}
} catch (JSONException e) {
log.error("JSON Exception while parsing Response from Salesforce in" +
" Lead creation/updation workflow. Response: "+salesforceResponse.getBody());
}
} else {
log.error("Salesforce node could not be found. path: " + workflowPayloadPath);
throw new WorkflowException("Salesforce node could not be found. path: "
+ workflowPayloadPath);
}
}
catch (RepositoryException re){
log.error("Repository Exception in Lead Creation Workflow " + re.getMessage());
throw new WorkflowException("Repository Exception in Lead Creation Workflow "
+ re.getMessage());
}
catch (CryptoException e) {
log.error("Crypto Exception in Lead Creation Workflow: "+e.getMessage());
throw new WorkflowException("Crypto Exception in Lead Creation Workflow: "
+e.getMessage());
}
catch (SalesforceException se){
log.error("Exception while Publishing lead to Salesforce: " + se.getMessage());
throw new WorkflowException("Exception while Publishing lead to Salesforce: "
+ se.getMessage());
}
}
}
}
if (impersonateSession != null) {
impersonateSession.logout();
}
if (resolver != null) {
resolver.close();
}
}
}
}