Call Actions using Dynamics CRM Web API with Output Parameter


Let me share one scenario where I was working on payment gateway integration with Dynamics CRM . We were redirecting to payment page once user click on ribbon button and redirect to CRM on successful payment. Since we need to pass secure hash as a part of payment URL which is generated using secret key and some security sequence string. Since secret key is secure information so we should not pass to JavaScript so we decided to create Actions which will take some input and generate the Secure Hash using algorithm(SHA-256 HMAC) and return to output parameters.

So mainly 3 steps involve in complete requirement.
1. Create Actions with Input and Output parameter
2. Create Web API to Call Actions to get Secure Hash which will be used to pass as parameter to payment gateway.
3. Call JavaScript function from ribbon button which internally call Web API.

Here is my Actions with input and output parameters

Below is my Plugin code which I registered on “mc_GetSecureHash” message for custom entity called “mc_receipts”.

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace MC.CRM.PlugIns
{
public class GetSecureHash : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
string vendorName = string.Empty;
string merchantId = string.Empty;
string accessCode = string.Empty;
string secretKey = string.Empty;
string transactionType = string.Empty;
string sequenceStringForHash = string.Empty;
string secureHash = string.Empty;

// Obtain the execution context service from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// Obtain the tracing service from the service provider.
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

// Obtain the Organization Service factory service from the service provider
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

// Use the factory to generate the Organization Service.
IOrganizationService service = factory.CreateOrganizationService(context.UserId);

try
{
if (context.InputParameters.Contains(“Target”) && context.InputParameters[“Target”] is EntityReference)
{
EntityReference receipts = (EntityReference)context.InputParameters[“Target”];
sequenceStringForHash = (string)context.InputParameters[“sequencestring”];

vendorName = (string)context.InputParameters[“vendorname”];

}

EntityCollection paymentGatewaySettings = GetPaymentGatewayInformtion(service, vendorName);
if (paymentGatewaySettings.Entities.Count > 0)
{
Entity paymentSettings = paymentGatewaySettings.Entities[0];
if (paymentSettings.Attributes.Contains(“mc_merchantid”))
{
merchantId = paymentSettings.Attributes[“mc_merchantid”].ToString();
}
if (paymentSettings.Attributes.Contains(“mc_secretkey”))
{
secretKey = paymentSettings.Attributes[“mc_secretkey”].ToString();
}
if (paymentSettings.Attributes.Contains(“mc_accesscode”))
{
accessCode = paymentSettings.Attributes[“mc_accesscode”].ToString();
}

secureHash = GenerateSHA512String(secretKey, sequenceStringForHash);

context.OutputParameters[“securehash”] = secureHash;
}
}
catch (FaultException<OrganizationServiceFault> e)
{
throw new InvalidPluginExecutionException(e.Message);
}

}

public string GenerateSHA512String(string secretKey, string sequenceString)
{
byte[] hashmessage;
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secretKey);
byte[] messageBytes = encoding.GetBytes(sequenceString);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
hashmessage = hmacsha256.ComputeHash(messageBytes);
}
return Convert.ToBase64String(hashmessage);
}

private EntityCollection GetPaymentGatewayInformtion(IOrganizationService service, string venderName)
{

QueryByAttribute paymentGateway = new QueryByAttribute(“mc_paymentgatewaysettings”);
paymentGateway.ColumnSet = new ColumnSet(“mc_name”, “mc_merchantid”, “mc_secretkey”, “mc_accesscode”);
paymentGateway.Attributes.AddRange(“mc_name”);
paymentGateway.Values.AddRange(venderName);
EntityCollection paymentgatewaysettings = service.RetrieveMultiple(paymentGateway);

return paymentgatewaysettings;

}
}
}

Then finally Web API which calling the above Plugins

function GetSecureHash(requestStringForHash) {
debugger;

try
{
var secureHash;
var vendorName = “<>”;
var Id = Xrm.Page.data.entity.getId().substring(1, 37);
console.log(“Receipt Id:” + Id);
var data = {
“receiptid”: Id,
“vendorname”: vendorName,
“sequencestring”: requestStringForHash
};
var clientURL = Xrm.Page.context.getClientUrl();
var req = new XMLHttpRequest();

req.open(“POST”, clientURL + “/api/data/v8.2/mc_receiptses(” + Id + “)/Microsoft.Dynamics.CRM.mc_GetSecureHash”, false);
req.setRequestHeader(“Accept”, “application/json”);
req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
req.setRequestHeader(“OData-MaxVersion”, “4.0”);
req.setRequestHeader(“OData-Version”, “4.0”);
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 200) {
var receipts = JSON.parse(this.response);
secureHash = receipts.securehash;
}
else {
var error = JSON.parse(this.response).error;
console.log(error.message);
}
}
};
req.send(JSON.stringify(data));
console.log(“secureHash: ” + secureHash);

}
catch (e) {
console.error(e.message);
}
return secureHash;

}

Using this Web API, we got secure hash to build the complete payment URL and then redirect to payment gateway.

Some reference URL for Action and Web API for more details
https://community.dynamics.com/crm/b/crminogic/archive/2018/01/04/fixed-executing-action-with-complex-output-parameters-through-web-api-in-dynamics-365-v9-0
Invoke your Custom Action from Dynamics CRM Web API–Dynamics CRM 2016

Hope this help you.

%d bloggers like this: