348 lines
20 KiB
OpenEdge ABL
348 lines
20 KiB
OpenEdge ABL
public with sharing class salesforceAuthenticationController {
|
|
|
|
list<HIC_ShopifySync__Configuration__c> listofConfiguration = new list<HIC_ShopifySync__Configuration__c>();
|
|
|
|
String clientIdProduction;
|
|
String clientSecretproduction;
|
|
String salesforceUrl = system.url.getsalesforcebaseurl().toexternalform();
|
|
String myURL = Url.getOrgDomainUrl().toExternalForm();
|
|
String Viewmode;
|
|
|
|
public boolean isConnectionSuccessful{get;set;}
|
|
|
|
public Pagereference handleAuthentication(){
|
|
PageReference pr;
|
|
if(ShopifyController.isSiteSupportedOrg()){
|
|
System.debug('>>> THIS IS SITE SUPPORTED ORG');
|
|
pr = authenticate();
|
|
}else{
|
|
System.debug('>>> THIS IS NON SITE SUPPORTED ORG');
|
|
pr = authenticateSalesforce();
|
|
}
|
|
return pr;
|
|
// return null;
|
|
}
|
|
|
|
public pagereference authenticate(){
|
|
system.debug('>>> SITE SUPPORTED ORG METHOD');
|
|
String isLwcApp = 'false';
|
|
String query = 'Select '+CheckAccessibility.isAccessible('id,name,HIC_ShopifySync__ClientId__c,HIC_ShopifySync__ClientSecret__c','HIC_ShopifySync__Configuration__c')+' from HIC_ShopifySync__Configuration__c where '+CheckAccessibility.isAccessible('name','HIC_ShopifySync__Configuration__c')+' = \'Default\' LIMIT 1';
|
|
String finalQuery = String.escapeSingleQuotes(query).remove('\\');
|
|
listofConfiguration = database.query(finalQuery);
|
|
//listofConfiguration = [select id,name,HIC_Shopi fySync__ClientId__c,HIC_ShopifySync__ClientSecret__c from HIC_ShopifySync__Configuration__c where name = 'Default' limit 1];
|
|
if(listofConfiguration.isEmpty()){
|
|
return null;
|
|
}
|
|
|
|
clientIdProduction = listofConfiguration[0].HIC_ShopifySync__ClientId__c;
|
|
clientSecretproduction = listofConfiguration[0].HIC_ShopifySync__ClientSecret__c;
|
|
|
|
|
|
if(apexpages.currentpage().getparameters().containsKey('viewmode') && apexpages.currentpage().getparameters().get('viewmode') != null && apexpages.currentpage().getparameters().get('viewmode') != '' ){
|
|
ViewMode = apexpages.currentpage().getparameters().get('viewmode');
|
|
}
|
|
if(apexpages.currentpage().getparameters().containsKey('islwcapp') && apexpages.currentpage().getparameters().get('islwcapp') != null && apexpages.currentpage().getparameters().get('islwcapp') != '' ){
|
|
isLwcApp = 'true';
|
|
}
|
|
|
|
String mainOrgUrl = 'https://hicshopifymadeeasy-dev-ed.my.salesforce-sites.com/thankYouPageSuccessfulAuthentication';
|
|
|
|
if(!apexpages.currentpage().getparameters().containsKey('code') ){
|
|
Organization orgRecord;
|
|
if(Schema.sObjectType.organization.isAccessible() &&
|
|
Schema.sObjectType.organization.fields.issandbox.isAccessible() &&
|
|
Schema.sObjectType.organization.fields.id.isAccessible() ){
|
|
orgRecord = [select id,issandbox from organization LIMIT 1];
|
|
}
|
|
|
|
// PKCE: generate verifier, derive challenge, and pack verifier into state so it
|
|
// can be recovered at token-exchange time (cross-org via publisher Site).
|
|
String verifier = PkceUtil.generateCodeVerifier();
|
|
String challenge = PkceUtil.generateCodeChallenge(verifier);
|
|
String pkceParams = '&code_challenge=' + challenge + '&code_challenge_method=S256';
|
|
|
|
if(orgRecord.issandbox){
|
|
if(isLwcApp == 'true'){
|
|
String state = PkceUtil.embedVerifierInState(salesforceUrl+'test'+ViewMode+'islwcapp', verifier);
|
|
pagereference p = new pagereference(salesforceUrl+'/services/oauth2/authorize?response_type=code&client_id='+clientIdProduction+'&redirect_uri='+mainOrgUrl+'&islwcapp=true&state='+EncodingUtil.urlEncode(state, 'UTF-8')+pkceParams);
|
|
return p;
|
|
}else{
|
|
// NEW SALESFORCE URL
|
|
String state = PkceUtil.embedVerifierInState(salesforceUrl+'test'+ViewMode, verifier);
|
|
pagereference p = new pagereference(salesforceUrl+'/services/oauth2/authorize?response_type=code&client_id='+clientIdProduction+'&redirect_uri='+mainOrgUrl+'&islwcapp=true&state='+EncodingUtil.urlEncode(state, 'UTF-8')+pkceParams);
|
|
return p;
|
|
}
|
|
|
|
}else{
|
|
if(isLwcApp == 'true'){
|
|
//NEW SALESFORCE URL
|
|
String state = PkceUtil.embedVerifierInState(salesforceUrl+'login'+ViewMode+'islwcapp', verifier);
|
|
pagereference p = new pagereference(salesforceUrl+'/services/oauth2/authorize?response_type=code&client_id='+clientIdProduction+'&redirect_uri='+mainOrgUrl+'&state='+EncodingUtil.urlEncode(state, 'UTF-8')+pkceParams);
|
|
return p;
|
|
}else{
|
|
String state = PkceUtil.embedVerifierInState(salesforceUrl+'login'+ViewMode, verifier);
|
|
pagereference p = new pagereference(salesforceUrl+'/services/oauth2/authorize?response_type=code&client_id='+clientIdProduction+'&redirect_uri='+mainOrgUrl+'&state='+EncodingUtil.urlEncode(state, 'UTF-8')+pkceParams);
|
|
return p;
|
|
}
|
|
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
// Method that will run for Non Site Supporting Org
|
|
public Pagereference authenticateSalesforce(){
|
|
system.debug('>>> NON SITE SUPPORTED ORG METHOD');
|
|
//System.debug('SalesforceAuthorizationController called');
|
|
String code = ApexPages.currentPage().getParameters().get('code');
|
|
// String state = ApexPages.currentPage().getParameters().get('state');
|
|
String storeName;
|
|
|
|
// if (state != null) {
|
|
// List<String> redirectParams = state.split('_');
|
|
|
|
// // Ensure that 'parts' has at least two elements before accessing 'parts[1]'
|
|
// if (redirectParams.size() > 1 && redirectParams[1] != null) {
|
|
// List<String> subParts = redirectParams[1].split('=');
|
|
// if (subParts.size() > 1 && subParts[1] != null) {
|
|
// storeName = subParts[1];
|
|
// }
|
|
// }
|
|
// }
|
|
Organization orgRecord;
|
|
if(Schema.sObjectType.organization.isAccessible() &&
|
|
Schema.sObjectType.organization.fields.issandbox.isAccessible() &&
|
|
Schema.sObjectType.organization.fields.id.isAccessible() ){
|
|
orgRecord = [select id,issandbox from organization LIMIT 1];
|
|
}
|
|
String endPoint;
|
|
Map<String , String> headerMap = new Map<String , String>();
|
|
String query = 'Select '+CheckAccessibility.isAccessible('id,name,HIC_ShopifySync__ClientId__c,HIC_ShopifySync__Salesforce_Site_URL__c,HIC_ShopifySync__ClientSecret__c','HIC_ShopifySync__Configuration__c')+' from HIC_ShopifySync__Configuration__c where '+CheckAccessibility.isAccessible('name','HIC_ShopifySync__Configuration__c')+' = \'Default\' LIMIT 1';
|
|
String finalQuery = String.escapeSingleQuotes(query).remove('\\');
|
|
listofConfiguration = database.query(finalQuery);
|
|
//listofConfiguration = [select id,name,HIC_Shopi fySync__ClientId__c,HIC_ShopifySync__ClientSecret__c from HIC_ShopifySync__Configuration__c where name = 'Default' limit 1];
|
|
if(listofConfiguration.isEmpty()){
|
|
System.debug('@@@ Checking List of configuration :: '+listofConfiguration);
|
|
// return null;
|
|
}
|
|
if(orgRecord.isSandbox){
|
|
clientIdProduction = '3MVG9G9pzCUSkzZv4NsQV0kOphuwhNCDbV2xJ4wazQQkD_nyOa73sUwa0Z0DtHz1t5woA9d9AVNwcHvqbQy45';
|
|
clientSecretproduction = 'FE5D62CA3C108BF836DDD3DB01C6B063E66F28FFAC5EC3BF43BC6EB248466F4A';
|
|
}else{
|
|
clientIdProduction = '3MVG9G9pzCUSkzZv4NsQV0kOphm0Il0eDJK5e0YicZLcCZKQcDHS0FORFMYHW8LzqJWPeMxzGUxeyshwEBOin';
|
|
clientSecretproduction = '2CF544F99E959C43977763BFBFA5999D4488E0C69757A99149D101EEB62E92B3';
|
|
}
|
|
String middlewareUrl = listofConfiguration[0].HIC_ShopifySync__Salesforce_Site_URL__c;
|
|
// clientIdProduction = listofConfiguration[0].HIC_ShopifySync__ClientId__c;
|
|
// clientSecretproduction = listofConfiguration[0].HIC_ShopifySync__ClientSecret__c;
|
|
// clientSecretproduction = listofConfiguration[0].HIC_ShopifySync__ClientSecret__c;
|
|
if(apexpages.currentpage().getparameters().containsKey('viewmode') && apexpages.currentpage().getparameters().get('viewmode') != null && apexpages.currentpage().getparameters().get('viewmode') != '' ){
|
|
ViewMode = apexpages.currentpage().getparameters().get('viewmode');
|
|
}
|
|
if(apexpages.currentpage().getparameters().containsKey('storeName') && apexpages.currentpage().getparameters().get('storeName') != null && apexpages.currentpage().getparameters().get('storeName') != '' ){
|
|
storeName = apexpages.currentpage().getparameters().get('storeName');
|
|
}
|
|
if(apexpages.currentpage().getparameters().containsKey('storeName') && apexpages.currentpage().getparameters().get('storeName') != null && apexpages.currentpage().getparameters().get('storeName') != '' ){
|
|
storeName = apexpages.currentpage().getparameters().get('storeName');
|
|
}
|
|
|
|
|
|
try {
|
|
System.debug('@@@ Inside Try Method :: ');
|
|
|
|
if(code != null && code != ''){
|
|
System.debug('@@@ Found Code :: '+code);
|
|
|
|
// PKCE: recover the code_verifier that was packed into state at /authorize time.
|
|
String stateParam = ApexPages.currentPage().getParameters().get('state');
|
|
String codeVerifier = PkceUtil.extractVerifier(stateParam);
|
|
|
|
headerMap.put('Content-Type' , 'application/x-www-form-urlencoded');
|
|
headerMap.put('Accept' , 'application/json');
|
|
headerMap.put('Content-length' , '307');
|
|
//String body = 'grant_type=authorization_code&code='+code + '&redirect_uri=https://hic192-dev-ed.develop.my.salesforce-sites.com/thankYouPageSuccessfulAuthentication';
|
|
String body = 'grant_type=authorization_code&code='+code + '&redirect_uri=';
|
|
// String mainOrgUrl = 'https://hicshopifymadeeasy-dev-ed.my.salesforce-sites.com/thankYouPageSuccessfulAuthentication';
|
|
if(orgRecord.isSandbox){
|
|
body += 'https://test.salesforce.com/apex/HIC_ShopifySync__SalesforceAuthentication';
|
|
//body += 'https://hic192-dev-ed.develop.my.salesforce-sites.com/thankYouPageSuccessfulAuthentication';
|
|
//endPoint for sandbox
|
|
endPoint = 'https://test.salesforce.com/services/oauth2/token';
|
|
|
|
body += '&client_id=' +clientIdProduction+ '&client_secret=' +clientSecretproduction+'&islwcapp=true&state=test'+ViewMode+'islwcapp';
|
|
}else{
|
|
body+='https://login.salesforce.com/apex/HIC_ShopifySync__SalesforceAuthentication';
|
|
// body+=mainOrgUrl;
|
|
|
|
//endPoint for Production
|
|
endPoint = 'https://login.salesforce.com/services/oauth2/token';
|
|
|
|
body += '&client_id=' +clientIdProduction+ '&client_secret=' +clientSecretproduction+'&islwcapp=true&state=prod'+ViewMode+'islwcapp';
|
|
}
|
|
if(String.isNotBlank(codeVerifier)){
|
|
body += '&code_verifier=' + codeVerifier;
|
|
}
|
|
HttpResponse tokenResp = makeCallout(body, endpoint, headerMap, 'POST');
|
|
if(tokenResp != null){ System.debug('@@@ Token exchange status :: '+tokenResp.getStatusCode()); }
|
|
// Null-check: makeCallout returns null on any callout failure (timeout/DNS/cert).
|
|
if(tokenResp != null && tokenResp.getStatusCode() == 200){
|
|
Map<String , Object> jsonMap = (Map<String , Object>) JSON.deserializeUntyped(tokenResp.getBody());
|
|
String newAccess = (String) jsonMap.get('access_token');
|
|
String newRefresh = (String) jsonMap.get('refresh_token');
|
|
|
|
// A 200 that lacks a FULL token pair is NOT a successful auth. Never report
|
|
// 'connected' with nothing persisted — that strands the org (this is the recovery
|
|
// path for a dead org, and the OAuth code is single-use). Fail instead of redirecting.
|
|
if(String.isBlank(newAccess) || String.isBlank(newRefresh)){
|
|
isConnectionSuccessful = false;
|
|
System.debug('@@@ token exchange returned 200 but missing access/refresh — treating as failure');
|
|
return null;
|
|
}
|
|
|
|
// Best-effort push to the middleware. This is a CALLOUT, so it runs BEFORE the token
|
|
// DML (never a callout-after-DML) and it must NEVER gate the authoritative local save
|
|
// — if the middleware is down the org must still keep its freshly issued token.
|
|
try {
|
|
Map<String , Object> qbDataPassToDataBase = new Map<String , Object>();
|
|
qbDataPassToDataBase.put('storeId','salesforceUrl');
|
|
qbDataPassToDataBase.put('accessToken' , newAccess);
|
|
qbDataPassToDataBase.put('refreshToken' , newRefresh);
|
|
qbDataPassToDataBase.put('isSandbox' , orgRecord.isSandbox);
|
|
qbDataPassToDataBase.put('orgId' , UserInfo.getOrganizationId());
|
|
qbDataPassToDataBase.put('instanceUrl' , URL.getOrgDomainURL().toExternalForm());
|
|
Map<String , String> mwHeaders = new Map<String , String>();
|
|
mwHeaders.put('Content-Type' , 'application/json');
|
|
mwHeaders.put('Accept' , '*/*');
|
|
makeCallout(JSON.serialize(qbDataPassToDataBase), middlewareUrl+'/api/auth/callback', mwHeaders, 'POST');
|
|
} catch(Exception mwEx) {
|
|
System.debug('@@@ Middleware push failed (non-fatal) :: '+mwEx.getMessage());
|
|
}
|
|
|
|
// AUTHORITATIVE local save — the LAST durable action, independent of the middleware.
|
|
// updateCredentials throws if it cannot persist, so we never falsely report success.
|
|
updateCredentials(newAccess, newRefresh);
|
|
isConnectionSuccessful = true;
|
|
PageReference ref = new PageReference('/lightning/n/HIC_ShopifySync__SME_Settings');
|
|
ref.setRedirect(true);
|
|
return ref;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex) {
|
|
System.debug('@@@@ ERROR OCCURED WHILE AUTHORIZING ! at line :: '+ex.getLineNumber()+' with message :: '+ex.getMessage());
|
|
}
|
|
return null;
|
|
|
|
}
|
|
|
|
// public static HttpResponse saveTokenToMiddleWare(Map<String , Object> qbDataPassToDataBase, String endpoint){
|
|
// Map<String , String> headerMap = new Map<String , String>();
|
|
// headerMap.put('Content-Type' , 'application/json');//;charset=UTF-8');
|
|
// // headerMap.put('Accept' , 'application/json');
|
|
// headerMap.put('Accept' , '*/*');
|
|
// HttpResponse httpResponse = makeCallout(JSON.serialize(qbDataPassToDataBase), endpoint, headerMap, 'POST');
|
|
// return httpResponse;
|
|
// }
|
|
|
|
public PageReference redirectToApp(){
|
|
PageReference ref = new PageReference('/lightning/n/HIC_ShopifySync__SME_Settings');
|
|
ref.setRedirect(true);
|
|
return ref;
|
|
}
|
|
|
|
public Static void updateCredentials(String accessToken, String refreshToken){
|
|
if(String.isBlank(accessToken) || String.isBlank(refreshToken)) return;
|
|
// Serialize on the Default row (FOR UPDATE) and FAIL LOUD: a freshly issued token that cannot
|
|
// be saved must surface as an error, never a silent success. The OAuth code is single-use, so
|
|
// a swallowed save here would leave the org permanently without a token.
|
|
Exception last;
|
|
for(Integer attempt = 0; attempt < 3; attempt++){
|
|
try {
|
|
List<HIC_ShopifySync__Configuration__c> rows = [
|
|
SELECT Id FROM HIC_ShopifySync__Configuration__c WHERE Name = 'Default' LIMIT 1 FOR UPDATE
|
|
];
|
|
if(rows.isEmpty()) return;
|
|
update new HIC_ShopifySync__Configuration__c(
|
|
Id = rows[0].Id,
|
|
HIC_ShopifySync__Access_Token__c = accessToken,
|
|
HIC_ShopifySync__Refresh_Token__c = refreshToken
|
|
);
|
|
return;
|
|
} catch(Exception e){
|
|
last = e;
|
|
}
|
|
}
|
|
if(last != null) throw last; // never report success after failing to persist the token
|
|
}
|
|
|
|
// Updating Tokens on server
|
|
public static void updateAppServer(){
|
|
List<HIC_ShopifySync__Configuration__c> cyptokeyquery = ShopifyController.getCryptoKey();
|
|
if(cyptokeyquery == null || cyptokeyquery.isEmpty()){
|
|
return;
|
|
}
|
|
Organization orgRecord;
|
|
if(Schema.sObjectType.organization.isAccessible() &&
|
|
Schema.sObjectType.organization.fields.issandbox.isAccessible() &&
|
|
Schema.sObjectType.organization.fields.id.isAccessible() ){
|
|
orgRecord = [select id,issandbox from organization LIMIT 1];
|
|
}
|
|
String middlewareUrl = cyptokeyquery[0].HIC_ShopifySync__Salesforce_Site_URL__c;
|
|
// Setting Body to sent to Server
|
|
Map<String , Object> qbDataPassToDataBase = new Map<String , Object>();
|
|
qbDataPassToDataBase.put('storeId','salesforceUrl');
|
|
qbDataPassToDataBase.put('accessToken' , cyptokeyquery[0].HIC_ShopifySync__Access_Token__c);
|
|
qbDataPassToDataBase.put('refreshToken' , cyptokeyquery[0].HIC_ShopifySync__Refresh_Token__c);
|
|
qbDataPassToDataBase.put('isSandbox' ,orgRecord.isSandbox);
|
|
qbDataPassToDataBase.put('orgId' , (UserInfo.getOrganizationId()));
|
|
String sfdcBaseURL = URL.getOrgDomainURL().toExternalForm();
|
|
qbDataPassToDataBase.put('instanceUrl' , sfdcBaseURL);
|
|
Map<String , String> headerMap = new Map<String , String>();
|
|
String endPoint = middlewareUrl+'/api/auth/callback';
|
|
// Setting Headers
|
|
headerMap = new Map<String , String>();
|
|
headerMap.put('Content-Type' , 'application/json');
|
|
headerMap.put('Accept' , '*/*');
|
|
HttpResponse httpResponse = makeCallout(JSON.serialize(qbDataPassToDataBase), endpoint, headerMap, 'POST');
|
|
}
|
|
|
|
public static HttpResponse makeCallout(String body , String endpoint , Map<String , String> headers , String method){
|
|
System.debug('@@@ Inside Cllout Method :: '+endpoint);
|
|
try{
|
|
|
|
System.debug('@@@ body : '+body);
|
|
System.debug('@@@ endpoint : '+endpoint);
|
|
System.debug('@@@ headers : '+headers);
|
|
System.debug('@@@ method : '+method);
|
|
HttpRequest httpRequestObject = new HttpRequest();
|
|
httpRequestObject.setEndpoint(endpoint);
|
|
httpRequestObject.setMethod(method);
|
|
httpRequestObject.setTimeout(120000);
|
|
if(String.isNotEmpty(method)){
|
|
if(method.equalsIgnoreCase('POST')){
|
|
httpRequestObject.setBody(body);
|
|
}
|
|
if(method.equalsIgnoreCase('PUT')){
|
|
httpRequestObject.setBody(body);
|
|
}
|
|
}
|
|
if(headers != null && !headers.isEmpty()){
|
|
for(String headerKey : headers.keySet()){
|
|
httpRequestObject.setHeader(headerKey, headers.get(headerKey));
|
|
}
|
|
|
|
}
|
|
|
|
Http httpObject = new Http();
|
|
HttpResponse httpResponseObject = httpObject.send(httpRequestObject);
|
|
|
|
return httpResponseObject;
|
|
}
|
|
catch (Exception ex) {
|
|
System.debug('@@@ Exception OCcured at line : '+ex.getLineNumber()+' with message :: '+ex.getMessage());
|
|
return null;
|
|
}
|
|
|
|
}
|
|
} |