Snippets Collections
/* ** ******************************************************************* ** * 
 *                                CONSTANTS                                  * 
 * ** ******************************************************************* ** */
// Switch so you don't excidentally create a whole lot of users
final Boolean INSERT_USER = false;

// Switch to deactivate the created users so we dont expose the wrong users
final Boolean DEACTIVATE_USERS = true;

// Username / Email address post fixes, update these to match your sandbox
final String EMAIL_EXTENSION		= '@example.com.invalid';
final String UNAME_EXTENSION		= '@example.com.demo';
final String SYS_ADMIN_PROFILE_NAME	= 'System Administrator';

// Specify a start url so users can easily be redirected during demos
final String START_URL	= '/lightning/n/Tree_Applications';

// Override any values on the user object
final Map<String,Object> CUSTOM_DATA = new Map<String,Object>{
	'FirstName' => 'Henk 07',
	'LastName'	=> 'de Vries 07'
};


/* ** ******************************************************************* ** * 
 *                                VARIABLES                                  * 
 * ** ******************************************************************* ** */
// User counter so multiple users can be created at the same time using the same method
Integer userCounter = 0;


/* ** ******************************************************************* ** * 
 *                            ANONYMOUS EXECUTION                            * 
 * ** ******************************************************************* ** */
try{
	// Create the demo user
	User u = createDemoUser(SYS_ADMIN_PROFILE_NAME, CUSTOM_DATA);
	
	// Create a random password basedon the username (unique) + current timestamp
	String password = EncodingUtil.convertToHex(Crypto.generateDigest('SHA1', Blob.valueOf(u.username + DateTime.now().getTime())));
	
	// Check if the user needs to be inserted into the database
	if(INSERT_USER){
		// Create the user
		insert u;

		// Set the password
		System.setPassword(u.Id,password);
	}

	// Output an easy login url details
	System.debug(password);

	// Very bad, but good for demos 8-)
	System.debug(URL.getSalesforceBaseUrl().toExternalForm() + '/login.jsp?un=' + u.Username +'&startURL='+START_URL);
	
	// Debug the user info
	System.debug(JSON.serializePretty(u));
	
	// Deactivate the users
	if(DEACTIVATE_USERS){
		deactivateUsers();
	}
	
}catch(Exception e){
	System.debug(e.getMessage());
}


/* ** ******************************************************************* ** * 
 *                             PUBLIC SUPPORT METHODS                        * 
 * ** ******************************************************************* ** */
/**
 * Method for creating a demo user record
 */
public User createDemoUser(String profileName, Map<String,Object> dataMap){

	// Check profile name is not blank
	if(String.isBlank(profileName)){
		throw new StringException('Profile name cannot be blank');
	}

	// Query profile Id
	String profileId = [SELECT Id FROM Profile WHERE Name = :profileName WITH SECURITY_ENFORCED LIMIT 1]?.Id;

	// Check the profile exists else throw an error
	if(profileId == null){
		throw new StringException('Profile does not exist, check the profile name');
	}
	
	// Generate a semi random username for a test user
	String userName = EncodingUtil.convertToHex(Crypto.generateDigest('SHA1', Blob.valueOf(UNAME_EXTENSION + userCounter + DateTime.now().getTime()))).substring(0,25);
		
	// Setup a user, so you can run the test code for a specific profile / permission set
	// In out best practice we use permission sets, so it's best to test these permission sets accordingly with the proper user Profile
	User runAsUser = new User();
	runAsUser.Alias 				= userName.subString(0,8);
	runAsUser.UserName		 		= userName + UNAME_EXTENSION;
	runAsUser.Email			 		= userName + EMAIL_EXTENSION;
	runAsUser.LastName				= userName;
	runAsUser.FederationIdentifier	= userName;
	runAsUser.EmailEncodingKey		= 'UTF-8';
	runAsUser.LanguageLocaleKey		= 'en_US';
	runAsUser.LocaleSidKey			= 'en_US';
	runAsUser.TimeZoneSidKey		= 'Europe/London';
	runAsUser.ProfileId				= profileId;
	
	// Allow the developers to populate additional data to the user record or override any of the default values
	populateSObjectDataFromMap(runAsUser,dataMap);
	
	// Update the user counter so the next one can be created
	userCounter++;
		
	// Return the new user
	return runAsUser;
}

/* ** ******************************************************************* ** * 
 *                 PRIVATE SUPPORT METHODS (CLASS SPECIFIC)                  * 
 * ** ******************************************************************* ** */
/**
 * Method to populate data on an sObject from a data map
 */
private static void populateSObjectDataFromMap(sObject sObj, Map<String,Object> dataMap){
	// Null check
	if(sObj ==  null || dataMap == null){return;}

	// Fetch the fields from the metadata so we can check they exist
	Schema.SObjectType sObjectType = sObj.getSObjectType();
	Map<String, Schema.SObjectField> fieldMap = sObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).fields.getMap();

	// Populate the data from the data map
	for(String fieldName : dataMap.keySet()){

		// Check the field exists on the sObject
		if(!fieldMap.containsKey(fieldName)){
			throw new StringException(String.format('The field "{0}" on sObject "{1}" cannot be found in the metadata', new String[]{fieldName,String.valueOf(sObjectType)}));
		}

		// Populate the field
		sObj.put(fieldName,dataMap.get(fieldName));
	}
}

void deactivateUsers(){
	User[] users = [SELECT Id,Name FROM User WHERE CreatedById = :UserInfo.getUserId() AND Id != :UserInfo.getUserId() AND IsActive=true];
	for(User u : users){
		u.isActive = false;
	}
	update users;
	System.debug(JSON.serializePretty(users));
}
{
    "swagger": "2.0",
    "basePath": "/",
    "info": {
        "version": "1.0",
        "title": "External Service for demo bank",
        "description": "### External Service for demo bank",
        "x-vcap-service-name": "DemoBankRestServices"
    },
    "securityDefinitions": {
        "basicAuth": {
            "type": "basic"
        }
    },
    "security": [{
        "basicAuth": []
    }],
    "tags": [{
        "name": "DemoBankRestServices"
    }],
    "paths": {
        "/accounts/{accountName}": {
            "get": {
                "operationId": "getAccount",
                "summary": "Retrieves an account",
                "description": "Retrieves the account with specific name",
                "consumes": ["text/plain"],
                "produces": ["application/json"],
                "parameters": [{
                    "name": "accountName",
                    "in": "path",
                    "required": true,
                    "type": "string",
                    "description": "Name of the account"
                }],
                "responses": {
                    "200": {
                        "description": "The response when system finds an account with given name",
                        "schema": {
                            "$ref": "#/definitions/accountDetails"
                        }
                    },
                    "400": {
                        "description": "Error response if the account name parameter is less than minimum characters",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    },
                    "404": {
                        "description": "Error response if the account is not supported by service or account is not found",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    }
                }
            },
            "delete": {
                "operationId": "DeleteAccount",
                "summary": "Deletes an account",
                "description": "Deletes the account with specific name",
                "consumes": ["text/plain"],
                "produces": ["application/json"],
                "parameters": [{
                    "name": "accountName",
                    "in": "path",
                    "required": true,
                    "type": "string",
                    "description": "Name of the account"
                }],
                "responses": {
                    "204": {
                        "description": "The response when system finds an account with given name",
                        "schema": {
                            "type": "string"
                        }
                    },
                    "400": {
                        "description": "Error response if the account name parameter is less than minimum characters",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    },
                    "404": {
                        "description": "Error response if the account is not supported by service or account is not found",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    }
                }
            },
            "post": {
                "operationId": "addAccount",
                "summary": "Add an account",
                "description": "Add an account to the database",
                "consumes": ["text/plain"],
                "produces": ["application/json"],
                "parameters": [{
                    "name": "accountName",
                    "in": "path",
                    "required": true,
                    "type": "string",
                    "description": "Name of the account"
                }, {
                    "name": "accountType",
                    "in": "query",
                    "required": true,
                    "type": "string",
                    "description": "The type of account"
                }],
                "responses": {
                    "201": {
                        "description": "The response when the account does not already exist and we can create one",
                        "schema": {
                            "$ref": "#/definitions/accountDetails"
                        }
                    },
                    "409": {
                        "description": "The response when the account already exists and we cannot create one",
                        "schema": {
                            "$ref": "#/definitions/accountDetails"
                        }
                    },
                    "400": {
                        "description": "Error response if the account name parameter is less than minimum characters",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    },
                    "404": {
                        "description": "Error response if the account is not supported by service or account is not found",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    }
                }
            },
            "put": {
                "operationId": "updateAccount",
                "summary": "Updates an account",
                "description": "Updates the account with specified name",
                "consumes": ["text/plain"],
                "produces": ["application/json"],
                "parameters": [{
                    "name": "accountName",
                    "in": "path",
                    "required": true,
                    "type": "string",
                    "description": "Name of the account"
                }, {
                    "name": "accountType",
                    "in": "query",
                    "required": true,
                    "type": "string",
                    "description": "The type of account"
                }],
                "responses": {
                    "200": {
                        "description": "The response when system finds an account with given name",
                        "schema": {
                            "$ref": "#/definitions/accountDetails"
                        }
                    },
                    "400": {
                        "description": "Error response if the account name parameter is less than minimum characters",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    },
                    "404": {
                        "description": "Error response if the account is not supported by service or account is not found",
                        "schema": {
                            "$ref": "#/definitions/errorModel"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "accountDetails": {
            "required": ["id", "name", "type", "availableBal"],
            "properties": {
                "id": {
                    "type": "string",
                    "description": "id"
                },
                "name": {
                    "type": "string",
                    "description": "name"
                },
                "type": {
                    "type": "string",
                    "description": "type"
                },
                "availableBal": {
                    "type": "string",
                    "description": "availableBal"
                }
            }
        },
        "errorModel": {
            "required": ["errorCode", "errorMessage"],
            "properties": {
                "errorCode": {
                    "type": "string",
                    "description": "A service-specific error code."
                },
                "errorMessage": {
                    "type": "string",
                    "description": "A service-specific error code."
                }
            }
        }
    }
}
public static String generateXMLSignature(String docBodyString){
	// 1. Apply the Transforms, as determined by the application, to the data object.
	// (no transforms are done, since the body should be delivered in canonicalized form (Force.com offers no canonicalization algorithm))
	
	// 2. Calculate the digest value over the resulting data object. 
	
	Blob bodyDigest = Crypto.generateDigest('SHA1',Blob.valueOf(docBodyString));
	
	// 3. Create a Reference element, including the (optional) identification of the data object, any (optional) transform elements, the digest algorithm and the DigestValue.
	// (Note, it is the canonical form of these references that are signed and validated in next steps.)

	String referenceString = '';
	referenceString += '';
	referenceString += '<ds:Reference URI="#msgBody">';
	referenceString += '<ds:Transforms>';
	referenceString += '<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>';
	referenceString += '<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>';
	referenceString += '</ds:Transforms>';
	referenceString += '<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>';
	referenceString += '<ds:DigestValue>'+EncodingUtil.base64Encode(bodyDigest)+'</ds:DigestValue>';
	referenceString += '</ds:Reference>';		 
	
	// 4. Create SignedInfo element with SignatureMethod, CanonicalizationMethod and Reference(s).
	String signedInfoString = '';
	signedInfoString += '<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">';
	signedInfoString += '<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>';
	signedInfoString += '<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>';
	signedInfoString += referenceString;
	signedInfoString += '</ds:SignedInfo>';
	
	// 5. Canonicalize and then calculate the SignatureValue over SignedInfo based on algorithms specified in SignedInfo.
	// (no canonicalization is done, since the signedinfo element should be delivered in canonicalized form (Force.com offers no canonicalization algorithm))

	String algorithmName = 'RSA-SHA1';
	// decrypted private key pkcs8 format from certificate
	String key = '[decryptedPrivateKeypkcs8formatfromcertificate]';
	Blob privateKey = EncodingUtil.base64Decode(key);
	
	Blob siBlob = Blob.valueOf(signedInfoString);
	
	Blob signatureValue = Crypto.sign(algorithmName, siBlob, privateKey);
	String signatureValueString = EncodingUtil.base64Encode(signatureValue);

	// 6. Construct the Signature element that includes SignedInfo, Object(s) (if desired, encoding may be different than that used for signing), KeyInfo (if required), and SignatureValue. 
	String signatureString = '';
	
	signatureString += '<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">';
	signatureString += signedInfoString; 
	signatureString += '<ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">'+signatureValueString+'</ds:SignatureValue>';
	signatureString += '<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">';
	signatureString += '<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">';
	signatureString += '<ds:X509Certificate xmlns:ds="http://www.w3.org/2000/09/xmldsig#">[the certificate used for signing]</ds:X509Certificate>';
	signatureString += '</ds:X509Data>';
	signatureString += '</ds:KeyInfo>';
	signatureString += '</ds:Signature>';
	
	return signatureString;
}	
// Data and private key. Use a method for getting the keys and signature
// so the example is more readable
private final String DATA		= 'The quick brown fox jumps over the lazy dog';
private final String SIGNATURE	= getSignature();
private final String PUBLIC_KEY	= getPublicKey();
private final String PRIVATE_KEY= getPrivateKey();

// Performance measuring
Integer startTime = Limits.getCpuTime();

// Validate the newly created signature is as expected
System.assertEquals(
	SIGNATURE,
	createSignature(DATA, PRIVATE_KEY),
	'The expected signature does not match the actual signature created using the private key.'
);


// VERIFY the signature is as expected
System.assertEquals(
	true,
	verifySignature(
		DATA,
		SIGNATURE,
		PUBLIC_KEY
	),
	'Error verifying the signature using the public key'
);


// If no errors let us know, also output the time it took, as signatures might be CPU intensive
System.debug('All Key tests were OK. Execution took: ' +( Limits.getCpuTime() - startTime) + 'ms');


/**
 * Method to get the signature when signing some data
 * @param dataToSign	The data that needs to be signed
 * @param privateKey	The RSA Private key
 */
public String createSignature(String dataToSign, String privateKey){
	return EncodingUtil.base64Encode(
		Crypto.sign(
			'RSA-SHA256', // The algorith you want to use
			Blob.valueOf(dataToSign), // Convert the string to a blog
			EncodingUtil.base64Decode(privateKey) // decode converts string into a blob
		)
	);
}


/**
 * Method to verify a signature
 * @param dataToVerify	The data that needs to be verified
 * @param signature		The B64 encoded signature that needs to be verified
 * @param publicKey		The B64 encoded RSA Public key
 */
public Boolean verifySignature(String dataToVerify, String signature, String publicKey){
	return Crypto.verify(
		'RSA-SHA256', // The algorith you want to use
		Blob.valueOf(dataToVerify), // Convert to blob
		EncodingUtil.base64Decode(signature), // Creates Blob from String
		EncodingUtil.base64Decode(publicKey)  // Creates Blob from String
	);
}
	

/**
 * Method to get the expected signature. This is for testing only, just so you have an
 * idea what the output of the signature looks like
 */ 
private String getSignature(){
	return 'RzgwUN39Dicag301cyf79neCKTZjotoguttb34gZjKKvT3kRj1ZvBtmynqHIRWBET0vDKugtKg/MtPu5h1Y8hqSHmZnkXbld/i737ptVEB6PQdRp26izWlLqpEyzkGrJ/FuJYyRNEV1xJdrnsTP3nBZ8qB0NPwCr9ZInZOWfO3DKspCOBWGaQ7H2ewC1OEr0OKdWqB1ThTP7U9+42KjABgNsnLpVge5xsPQja5QPbvqq+1Krl5z66xTTQQNxMvnKQt1fjUMqaDB52vDYbm8yh8iM4+fDPhbfmoDB5eFqwADjQ3b7kcKYgCF2D56KBxrVVHzFMMR70lkn8q6krZ4Ie9djkfBYAkVTkWSwlxwg70u7mg3O123Ddlcbasikg7FihdE3rRXrV69MkG7XzaxPAhEF0Abtubodoe6B78M8GrGUMGGdS8ad13BOGPTkCo9au8uZO7PjjKr16Hi8z4UAc3j6yFAjwkx6Hc5BgBlrVzdmfeRN6GBEMFkj1X5/OdBDLqSgUQ7t8QQr5GE1p24mMOGSHpvp45EQELJjyqGzJb4SL3CIBN82q0HOryKXE3NUd3PiZK+WanAQKYZfjCn3FpeSnbjXpRu+Fst7oqrv5Zkh4FucwihLqjGfEtwJhJ/gG3mUXqNOTHZ0S03pPuIVo4iiWrBRzY4EeqBDwkqgJCc=';
}


/**
 * Method to get a 256 Bit SHA 256 Private key to give an idea of the format
 * Your key should come from a secure certificate or secret store
 * and NEVER be stored in code or where it is user readable
 */
private String getPrivateKey(){
	String privateKey ='';
	privateKey+='MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDaVmKLA1RFOpv5';
	privateKey+='uCI8QgpeAxpDlkNSxksSn+aJGnLHzBjhAQRLD0skGXk3DH8FQp3ffEX3BC6/M8Ga';
	privateKey+='IF7pAdOt+j3xHv+0+dQ7qpDqk433KKYLJaoI6AfDA5R+CfsJH4RcR0W8kTHF/+SB';
	privateKey+='3aNGq5fDFD5AymIJiQeuJ3GO/r3gbRd5MpC6tI8UzGUQlnKFZvBK0W63nnYkxHEk';
	privateKey+='E7gu/JWoZdfY7UcXEfhWte5DjOwtzq3DsGu4J6peGkYCAOtwCCrkpaumiDe3AqrQ';
	privateKey+='eKoDsT+KDj1qMoD4Tnq1buCKMFQEKHY0KqCeT5IrcHZzsSNYZF4zz2gT6h5N+56G';
	privateKey+='+F281mkHAFzIV582N5P0gh38FCJ/Qg6crRyYKeoxqm12sbxVbGEw0pROMURbHYnc';
	privateKey+='nJlTTFQploVz5ZW8jgO8XEEjWbjkF7IBuu+FCgHFZ3JwoPyMeaAcGPPPRBrJAlR7';
	privateKey+='1sm5f2WelHfJZKBLG8vxOFY9W85v7fMLZztE4yL1+0LiI2W7426ADfJRQ3sO2EA/';
	privateKey+='WyOlTrBrk3Mvsj/9bkQ6C2aIIqNsmnvtQU+hzaZ10tyoIuQiUmHuDWvvKHiLw3EQ';
	privateKey+='c7BLSlZaQkwG66kZUf/OUwsf5u2knywxw3oEbptrhuA8iZ17lQWoxbvkum2an6tA';
	privateKey+='J7cL5yOVEYiq+C/O4gIVAXo7OTfDKwIDAQABAoICAQDXbq8zDSjkWi023EnjfSIv';
	privateKey+='mw4aLDTngsLmcKIPG+qvW6IcuV0cFs4Eo6HoAEuAzDdsIXoDfrwFazMXOeOMM4JD';
	privateKey+='QwxFU1npnyybZvQwkUFd41za2OIKga/O60RkjMKHQPLf/m8/3V/oR1KYFTIa9Ar9';
	privateKey+='sIawdUEAuZW7cC3rc021GM81hgAqSSh41CjQkjITkPt+R2Hgidl28+HTQCXXLuEY';
	privateKey+='VM0CvTUM/W01WbPsMSuFE05/LR9MiM7gpTn4liG43EY+b32MBxI6YMZchwLyO70/';
	privateKey+='IkfU9lotJ3qKdQnXMFJl++qOFJWBP3AxrnkiNGF0wSv2IStHoxUdyy2jbYNIZaMg';
	privateKey+='MmQE+kFhUz0mNaiJqHKoELDT6xEBMxWrfEVt8iQeISplCAh4cBtPUL+xFQ94yIFo';
	privateKey+='CFecmgDk3noUwWu5fbEIkx2ui2mb4aWUN2FICd2KLyJSY/wbtFiKJ4eX49mukGId';
	privateKey+='chNlAymrtVWI0k1GVa3JF+rjGbzJHG/hkxp2ccK4aq3Kl7mmvvYyKVXcgRQ3UQiA';
	privateKey+='EuawNmqXtaTXwWOiBFYG6Gq/GIzsMZAPI2slg3pM0rCR1rJx+EqE8Fd8f4/Ua8WM';
	privateKey+='m3rP50izBEtKWuNNSCopWyWDFH/HRvgKixU71NkLYQ5MHvfcpealH4i7zi3W6aeR';
	privateKey+='5weNmGZ47o5l9xz/JIKpsQKCAQEA//Df6UsDNuCAcyk89d0+AELZ2T0i4xk+7p2M';
	privateKey+='hgPo2iTm5MTgRl01NJ/LmsNJJ813h2dwyV6bMzdx+daziGybbivRJpz2mkCOwSqD';
	privateKey+='E4+7wRjyaYRK8/aBY8KbcTYt6GY+UhBMh01Yg7mRZWSmFo0LL6V6vVVo3irkY6Kh';
	privateKey+='Oy3plW6mTa1LNUMoavqEVyn/v9tYVTsRxiZVtvxjzsfcTuQ+gS1INKs8sTIfY9PV';
	privateKey+='keho+gDaJYn/ZmFb1Tt70zSkQblwAG7nIA0pQtuuUF874FzhH7hUkwuASbjv2D5G';
	privateKey+='5TwXOHbrR+MBrp2XbXSQ074DrCCMuw0xofSeELsaADK9c1p0GQKCAQEA2mNJvB1/';
	privateKey+='TrJY2I/uzILEBl2qo66Sr8o8U0FCl/6/kVWzMIPhZz92+KedFKmJ5DGgFTUWri9F';
	privateKey+='vz8ZxoeUDizikQKG9R26ZxZDJtvlkyKqY28ja9D0Iyb3QhV1qwExO4Fo2XCFgzCY';
	privateKey+='2bqEwMCZ9G9LI3vWE3AOXQi0LdE39ImSRLoYJQmgfxDnoNQeofd3v7mbrwkyKuBv';
	privateKey+='6jB+apeysiXSEsK3c/Xmrc2ceNnwHeZbWJJW+9aMWB0g6kK4fneXOz84F6gaAtU5';
	privateKey+='q5kje02qRJZW8tKGBt07DnflhqAQRuuIIipk5yxCFmnJXUVSyzohoO5QSa53NAS4';
	privateKey+='J7a8t9ivhJt54wKCAQA+IxXJhuut3A1zaBSjwGX4HELVihE5P3zW46slMjfLFmB0';
	privateKey+='NBQbIS/0qcL9vOG65xhY6FUqnmxhn9ltBaIqwetucPbjQAJi6r99yDtweVnlBJB9';
	privateKey+='659i4XsCZFHmx3eXz5Lby5c41h9iQ6A4FJp6KR4JIEzPQLgoEBPI2Mf6HShznhyE';
	privateKey+='CUmUEczzRATzQIAV7UPh1Wh4SgBPX7E/l6g2AxXluL+qAdTHVFromppkRR+ParuL';
	privateKey+='l5hJG+P2ve1PFp22UzYM9N/qGSfmUn1ch/J6gzIoyFDILmej/mFEh8Igj1k33S88';
	privateKey+='EbHr2djUuxMaRSyREon4M7jUEBZ8C2DBoY/7PH+pAoIBAF7wqR6ByFWjDSLgt9Tq';
	privateKey+='yGNoFwXfn9+SUNV02omPcyKwmhzuSHCFU6hX3d8csVimBk0R7lE9NdoliYQYbtIW';
	privateKey+='y0x1R8yJ5v5n3Dupf02O1Xoy17hId8pMZ1OwVp5H/2o6ISXeV/ynhNuqzYmqcYOl';
	privateKey+='WooLjQ6YOXZSkVoVyXii0hbUvChl3gM/iyMM9GA/YCzWeQsIOWoQdjbebCbU2he+';
	privateKey+='f2wugGiGL4nBiFO1k0C8Y1vHCs+i/xJTX3rYFLLONM3J9w25w80Ve2PRSG6TXgFB';
	privateKey+='Rn177k5PoRvyHbOAJHNgc6c+vO0O/ZAW3zaQK6U0GWiIEhlmImZX4uNI+xQFvJAu';
	privateKey+='szcCggEAdOOsFRBiTMWgCZ3Q3vqB6rkzIUiqZ9vwJzJHy3mIoENkQLsjZgKSsJBq';
	privateKey+='Ter+eMX8HaObGbKV7f10RBzJnV6yq/z7BohuUbkQ+an8BWYSnveWgu1eHifyaDVG';
	privateKey+='h7SivmPeJDq6HE0Nh2jehfjpsmZmnUSTk0Lz7FBshT5o7R5T8Od7hXWIZMLBoXih';
	privateKey+='CSjMXI6IbT94nG0110GbvlHkwbbK/TN/7rUA3Afepzq74kKgY5zJP3aj6tq1FlCh';
	privateKey+='8Y5Y9uoB29EfrzSWrRkXjZQhR/yiyIulUV/NZS2KqWMtQGJjw9aeUVLqyglIzS5q';
	privateKey+='SB/8ZTFkXV09anyt4L5j8t6Th1DUdA==';
	return privateKey;
}


/**
 * Method to get the public key
 * Again this is just for illustative purposes, you would NEVER put a key like this in your code
 */
private String getPublicKey(){
	String publicKey ='';
	publicKey+='MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2lZiiwNURTqb+bgiPEIK';
	publicKey+='XgMaQ5ZDUsZLEp/miRpyx8wY4QEESw9LJBl5Nwx/BUKd33xF9wQuvzPBmiBe6QHT';
	publicKey+='rfo98R7/tPnUO6qQ6pON9yimCyWqCOgHwwOUfgn7CR+EXEdFvJExxf/kgd2jRquX';
	publicKey+='wxQ+QMpiCYkHridxjv694G0XeTKQurSPFMxlEJZyhWbwStFut552JMRxJBO4LvyV';
	publicKey+='qGXX2O1HFxH4VrXuQ4zsLc6tw7BruCeqXhpGAgDrcAgq5KWrpog3twKq0HiqA7E/';
	publicKey+='ig49ajKA+E56tW7gijBUBCh2NCqgnk+SK3B2c7EjWGReM89oE+oeTfuehvhdvNZp';
	publicKey+='BwBcyFefNjeT9IId/BQif0IOnK0cmCnqMaptdrG8VWxhMNKUTjFEWx2J3JyZU0xU';
	publicKey+='KZaFc+WVvI4DvFxBI1m45BeyAbrvhQoBxWdycKD8jHmgHBjzz0QayQJUe9bJuX9l';
	publicKey+='npR3yWSgSxvL8ThWPVvOb+3zC2c7ROMi9ftC4iNlu+NugA3yUUN7DthAP1sjpU6w';
	publicKey+='a5NzL7I//W5EOgtmiCKjbJp77UFPoc2mddLcqCLkIlJh7g1r7yh4i8NxEHOwS0pW';
	publicKey+='WkJMBuupGVH/zlMLH+btpJ8sMcN6BG6ba4bgPImde5UFqMW75Lptmp+rQCe3C+cj';
	publicKey+='lRGIqvgvzuICFQF6Ozk3wysCAwEAAQ==';
	return publicKey;
}
{
    "messageId": "PfNxko2cChY94KsiU9cvUL",
    "eventId": "client.updated",    
    "eventSchemaVersion": 1.0,
    "eventInstanceOriginationDateTime": "2022-03-07T00:37:23Z",
    "eventData": {
        "siteId": 123,
        "saleId": 96,
        "purchasingClientId": "100001049",
        "payments": [
            {
                "paymentId": 103,
                "paymentMethodId": 14,
                "paymentMethodName": "Cash",
                "paymentAmountPaid": 300,
                "paymentLastFour": null,
                "paymentNotes": null
            }
        ],
        "saleDateTime": "2018-05-03T16:52:23Z",
        "soldById": 10,
        "soldByName": "Jane Doe",
        "locationId": 1,
        "totalAmountPaid": 150,
        "items": [
            {
                "itemId": 78,
                "type": "Service",
                "name": "10 Punch Pass",
                "amountPaid": 150,
                "amountDiscounted": 0,
                "quantity": 1,
                "recipientClientId": "100000009",
                "paymentReferenceId": 44
            },
            {
                "itemId": 79,
                "type": "Service",
                "name": "10 Kick Pass",
                "amountPaid": 150,
                "amountDiscounted": 0,
                "quantity": 1,
                "recipientClientId": "100000009",
                "paymentReferenceId": 44
            }
        ]
    }
}
public class Sale {
public String messageId;
public String eventId;
public Decimal eventSchemaVersion;
public String eventInstanceOriginationDateTime;
public SaleEventData eventData;
}


public class SaleEventData {
public Integer siteId;
public Integer saleId;
public String purchasingClientId;
public List<PaymentDetails> payments;
public String saleDateTime;
public String soldById;
public String soldByName;
public Integer locationId;
public Integer totalAmountPaid;
public List<SaleItemDetails> items;
}

public class PaymentDetails {
public Integer paymentId;
public Integer paymentMethodId;
public String paymentMethodName;
public String paymentAmountPaid;
public Integer paymentLastFour;
public String paymentNotes;
}

public class SaleItemDetails {
public Integer itemId;
public String type;
public String name;
public Integer amountPaid;
public Integer amountDiscounted;
public Integer quantity;
public String recipientClientId;
public Integer paymentReferenceId;
}

Sale mbSale = (Sale)JSON.deserialize(jsonInput, Sale.class);
/* JSON EXAMPLE
{
    "messageId": "PfNxko2cChY94KsiU9cvUL",
    "eventId": "client.updated",    
    "eventSchemaVersion": 1.0,
    "eventInstanceOriginationDateTime": "2022-03-07T00:37:23Z",
    "eventData": {
        "siteId": 123,
        "saleId": 96,
        "purchasingClientId": "100001049",
        "payments": [
            {
                "paymentId": 103,
                "paymentMethodId": 14,
                "paymentMethodName": "Cash",
                "paymentAmountPaid": 300,
                "paymentLastFour": null,
                "paymentNotes": null
            }
        ],
        "saleDateTime": "2018-05-03T16:52:23Z",
        "soldById": 10,
        "soldByName": "Jane Doe",
        "locationId": 1,
        "totalAmountPaid": 150,
        "items": [
            {
                "itemId": 78,
                "type": "Service",
                "name": "10 Punch Pass",
                "amountPaid": 150,
                "amountDiscounted": 0,
                "quantity": 1,
                "recipientClientId": "100000009",
                "paymentReferenceId": 44
            },
            {
                "itemId": 79,
                "type": "Service",
                "name": "10 Kick Pass",
                "amountPaid": 150,
                "amountDiscounted": 0,
                "quantity": 1,
                "recipientClientId": "100000009",
                "paymentReferenceId": 44
            }
        ]
    }
}*/


public class Sale {
public String messageId;
public String eventId;
public Decimal eventSchemaVersion;
public String eventInstanceOriginationDateTime;
public SaleEventData eventData;
}


public class SaleEventData {
public Integer siteId;
public Integer saleId;
public String purchasingClientId;
public List<PaymentDetails> payments;
public String saleDateTime;
public String soldById;
public String soldByName;
public Integer locationId;
public Integer totalAmountPaid;
public List<SaleItemDetails> items;
}

public class PaymentDetails {
public Integer paymentId;
public Integer paymentMethodId;
public String paymentMethodName;
public String paymentAmountPaid;
public Integer paymentLastFour;
public String paymentNotes;
}

public class SaleItemDetails {
public Integer itemId;
public String type;
public String name;
public Integer amountPaid;
public Integer amountDiscounted;
public Integer quantity;
public String recipientClientId;
public Integer paymentReferenceId;
}

Sale mbSale = (Sale)JSON.deserialize(jsonInput, Sale.class);
/* JSON EXAMPLE
{
    "messageId": "PfNxko2cChY94KsiU9cvUL",
    "eventId": "client.updated",    
    "eventSchemaVersion": 1.0,
    "eventInstanceOriginationDateTime": "2022-03-07T00:37:23Z",
    "eventData": {
        "siteId": 123,
        "saleId": 96,
        "purchasingClientId": "100001049",
        "payments": [
            {
                "paymentId": 103,
                "paymentMethodId": 14,
                "paymentMethodName": "Cash",
                "paymentAmountPaid": 300,
                "paymentLastFour": null,
                "paymentNotes": null
            }
        ],
        "saleDateTime": "2018-05-03T16:52:23Z",
        "soldById": 10,
        "soldByName": "Jane Doe",
        "locationId": 1,
        "totalAmountPaid": 150,
        "items": [
            {
                "itemId": 78,
                "type": "Service",
                "name": "10 Punch Pass",
                "amountPaid": 150,
                "amountDiscounted": 0,
                "quantity": 1,
                "recipientClientId": "100000009",
                "paymentReferenceId": 44
            },
            {
                "itemId": 79,
                "type": "Service",
                "name": "10 Kick Pass",
                "amountPaid": 150,
                "amountDiscounted": 0,
                "quantity": 1,
                "recipientClientId": "100000009",
                "paymentReferenceId": 44
            }
        ]
    }
}*/


public class Sale {
public String messageId;
public String eventId;
public Decimal eventSchemaVersion;
public String eventInstanceOriginationDateTime;
public SaleEventData eventData;
}


public class SaleEventData {
public Integer siteId;
public Integer saleId;
public String purchasingClientId;
public List<PaymentDetails> payments;
public String saleDateTime;
public String soldById;
public String soldByName;
public Integer locationId;
public Integer totalAmountPaid;
public List<SaleItemDetails> items;
}

public class PaymentDetails {
public Integer paymentId;
public Integer paymentMethodId;
public String paymentMethodName;
public String paymentAmountPaid;
public Integer paymentLastFour;
public String paymentNotes;
}

public class SaleItemDetails {
public Integer itemId;
public String type;
public String name;
public Integer amountPaid;
public Integer amountDiscounted;
public Integer quantity;
public String recipientClientId;
public Integer paymentReferenceId;
}

Sale mbSale = (Sale)JSON.deserialize(jsonInput, Sale.class);
public Boolean mapContains(Map<id,Object> searchObj, String searchKey, String searchVal){
	for (ID idKey : searchObj.keyset()) {
		System.debug(searchObj.get(idKey).get(searchKey));
		if( searchObj.get(idKey).get(searchKey) == searchVal) {
			System.debug('Match Found'+ searchObj.get(idKey));
			return true;
		}else{
			System.debug('No Match');

		}
	}
	return false;
}
var faturasFechadas = [
    { 
        "valorFatura": {
            "valor": -1665.46, 
            "moeda": "R$" 
            
        },
        "dataFechamento": "2025-03-26T00:00:00", 
    },
    { 
        "valorFatura": {
            "valor": -1665.46, 
            "moeda": "R$" 
            
        }, 
        "dataFechamento": "2025-03-26T00:00:00"
    }
];
    
var detalhesFatura = {
    "numeroCartao": "xxxxxxxxxxxx1193",
    "detalhesLancamentoParcela": {
        "quantidadeParcelas": 12,
        "numeroParcelaTransacao": 7
        
    },
    "dataVencimentoFatura": "2025-03-01T00:00:00"
}

var result = faturasFechadas.map(function(el) {
    var o = Object.assign({}, el);
    o.detalhesFatura = detalhesFatura;
    return o;
});

console.log(JSON.stringify(result));
@wire(callout2Apex,{id: this.recordId})
faturaAbertaWired({ error, data }) {
  if (data) {
    this.arr = JSON.parse(data).keyFromJSON;
    this.loaded = true;
  } else if (error) {
    this.loaded = false;
  };
}
Map<String,String> theOne = new Map<String,String>();
Map<String,String> theTwo = new Map<String,String>();

theOne.put('task', 'Active');
theOne.put('task2', 'Inactive');
theOne.put('task3', 'Inactive');
theOne.put('task4', 'Inactive');

theTwo.put('task', 'Active');
theTwo.put('task2', 'Inactive');
theTwo.put('task3', 'Inactive');
theTwo.put('task4', 'Inactive');

void toggleActive(String taskName, Map<String,String> taskMap){
    taskMap.put(taskName, 'Active'); 
    for(String key : taskMap.keySet()){
        if(key != taskName){
       	 taskMap.put(key, 'Inactive');
        }
    }
}

toggleActive('task3', theTwo);

System.debug(theOne);
System.debug(theTwo);
Human fred = new Human();

fred.setName('Fred');
fred.setAge(18);

fred.Run();
fred.Jump();
fred.Climb();
public class Human {
    public String Name;
    public Integer Age;
    
    public Human(){
      this.Age = 0;
    }
        
    public void setName(String Name){
        this.Name = Name;
    } 
    
    public void setAge(String Name){
        this.Age = Age;
    } 
    
    public void Run(){
        System.debug('Run');
    } 
    
    public void Jump(){
        System.debug('Jump');
    } 
    
    public void Climb(){
        System.debug('Climb');
    } 
}
public class TestClass {
    
    public Static Integer copies = 0;
    
    
    public TestClass(){
        this.add();
    }
    
       
    public void add(){
        copies++;
    } 
    
    public Static void subtract(){
        copies--;
        System.debug(copies);
    } 


}
trigger AccountTrigger on Account (before insert) {

      if(Trigger.isInsert && Trigger.isBefore) {

        
        List<Account> myList = new List<Account>();

        for(Account acct : Trigger.new){
          if(acct.name == 'My Test Account'){
           acct.AnnualRevenue = 0;
           myList.add(acct);
          }
        }

        if(myList.size() >= 0){
          insert myList;
        }
      }   
}
(before insert, after insert,before update, after update, before delete, after delete, after undelete)
trigger ContactTrigger on Contact (before insert) { //Context and Event
   
    if(Trigger.isInsert && Trigger.isBefore) { // Condition
       System.debug(Trigger.new);	// Action
    } 
  
}
public with sharing class ContactTriggerHandler {
    //
    // custom trigger handler setup to handler all triggers received on Contact object
    //
    public Boolean isTriggerExecuted = true;
    private boolean myIsExecuting = false;
    private integer BatchSize = 0;

    public ContactTriggerHandler(boolean isExecuting, integer size) {
        myIsExecuting = isExecuting;
        BatchSize = size;
    }

    //
    // On Before Insert
    //
    public void OnBeforeInsert(List<Contact> contactList){
        List<String> emailList = new  List<String>();
        
        for(Contact contact : contactList){
              emailList.add(contact.email);
        }
        
		List<Contact> newContactList = new List<Contact>();
        List<Lead> leadList = [SELECT id,firstname,lastname, email,LeadSource,phone, MobilePhone,OwnerId,HasOptedOutOfEmail FROM Lead WHERE email IN :emailList];
       
        for(Contact cItem : contactList){
            //Merge
            for(Lead lItem: leadList){
            	cItem.HasOptedOutOfEmail = lItem.HasOptedOutOfEmail;
            	cItem.OwnerId = lItem.OwnerId;
            	cItem.LeadSource = lItem.LeadSource;
            	cItem.MobilePhone = lItem.MobilePhone;
				cItem.phone = lItem.phone;
            	cItem.LeadSource = lItem.LeadSource;
           	 	newContactList.add(cItem);
            }

        }
                

    }

    //
    // On After Insert
    //
    public void OnAfterInsert(List<Contact>  contactList) {
       
        List<String> emailList = new  List<String>(); 
        for(Contact contact : contactList){
              emailList.add(contact.email);
        }
        
        List<Lead> leadList = [SELECT id,firstname,lastname, email,LeadSource,phone, MobilePhone,OwnerId,HasOptedOutOfEmail FROM Lead WHERE email IN :emailList];
        List<Task> taskTransferList = [SELECT Id, Who.Id, Who.Type FROM Task WHERE Who.Type = 'Lead'];
        List<Task> taskUpdate = new List<Task>();
        
        for(Contact cItem : contactList){
            //Move Task to Contact
            for(Lead lItem: leadList){
                if(taskTransferList.size() > 0){
                    for(Task taskItem :taskTransferList){
                        taskItem.whoid = cItem.id;
                        taskUpdate.add(taskItem);
                    }
                }

        
            }
            upsert taskUpdate;
            delete leadList;

        }
  
}
public with sharing class TruncateId {
    public TruncateId() {

    }

    @InvocableMethod(label='Truncate ID' description='Transaction Id on Opportunity Object' category='Opportunity')
    public static void Truncate(List<Opportunity> OppIds){

        ID oppID = OppIds[0].id;

        Opportunity opp = [SELECT id, TranscationId__c, name FROM Opportunity WHERE id = :oppID];

      
        String last6 = opp.TranscationId__c.right(6);
        if(opp.TranscationId__c != null){    
            if(last6 != opp.Name.right(6)){
                opp.name = opp.name + last6;
                update  opp;
            }
        }
      

    }

    public class GetOppId{
        @InvocableVariable(required=true label='Opportunity Id')
        public ID oppID;

    }

}
//Parent to Child
SELECT Name, (SELECT name FROM Sessions__r) FROM Public_Event__c
//Child to Parent
SELECT id, name, Public_Event_Name__r.name, Public_Event_Name__r.id From Sessions__c
public class OutterClass {
    Public String name = 'outterclass';
    
    public void setName(String name){
        this.name = name;
	}
    
    public class InnerClass{
       Public String name = 'innerclass';
    }

}
Integer year = 2021, mon=02, day=12, hour=23, min=50;

Datetime dtGMT = Datetime.newInstanceGMT(year, mon, day, hour, min, 0);

String exTimezone = 'America/Los_Angeles';
String dateTimeForamat = 'yyyy-MM-dd HH:mm:ssz';
String schedulerFormat = 'mm:HH:dd:MM:yyyy';
String crnTemplate = '0 {0} {1} {2} {3} ? {4}';

String localFromatted = dtGMT.format(dateTimeForamat, UserInfo.getTimeZone().getId());
String exFormatted = dtGMT.format(dateTimeForamat, exTimezone);

Datetime localDTValueGMT = Datetime.valueOfGMT(localFromatted);
Datetime exDTVaueGMT = Datetime.valueOfGMT(exFormatted);

Integer minDiff = (Integer)(localDTValueGMT.getTime() - exDTVaueGMT.getTime())/60000;

Datetime scheduleDTGMT = dtGMT.addMinutes(minDiff + 15);

String schFormmated = scheduleDTGMT.formatGMT(schedulerFormat);

String cronExp = String.format(crnTemplate, schFormmated.split(':'));

System.debug('dtGMT : ' + JSON.serialize(dtGMT));
System.debug('localDTValueGMT : ' + JSON.serialize(localDTValueGMT));
System.debug('exDTVaueGMT : ' + JSON.serialize(exDTVaueGMT));
System.debug('scheduleDTGMT : ' + JSON.serialize(scheduleDTGMT));
System.debug('cronExp: ' + cronExp);
star

Fri Aug 12 2022 15:25:54 GMT+0000 (UTC)

#apex
star

Tue Jul 05 2022 14:57:47 GMT+0000 (UTC) https://developer.salesforce.com/forums?id=906F00000008wSGIAY

#apex
star

Mon Jul 04 2022 15:54:08 GMT+0000 (UTC)

#apex
star

Thu Sep 16 2021 17:38:28 GMT+0000 (UTC) https://www.zenintech.org/blog/creating-your-first-apex-class

#apex #salesforce #static #keywords #class
star

Sat Jul 24 2021 14:14:46 GMT+0000 (UTC)

#apex #salesforce #trigger
star

Sat Jul 24 2021 09:42:42 GMT+0000 (UTC)

#apex #salesforce #trigger
star

Fri Jul 23 2021 00:18:27 GMT+0000 (UTC)

#apex #salesforce #trigger
star

Sat Jun 05 2021 06:34:17 GMT+0000 (UTC)

#apex #salesforce
star

Mon Apr 05 2021 17:47:03 GMT+0000 (UTC)

#apex #salesforce
star

Wed Dec 16 2020 17:34:22 GMT+0000 (UTC)

#apex #datetime

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension