(This article was originally published on Medium)

This is the second part of our guide to implementing a payments gateway into PowerApps/Dynamics portals. The first part can be found here. This guide takes you through the Azure function, creating processing pages, rendering notification pop-ups and pages, all the way to receipts.

Azure function

As illustrated earlier, the operation to confirm the payment status must be implemented on the server-side. It cannot originate from a client (browser) as it will contain some sensitive information like the payment gateway account API secret key.

The server-side can be implemented:

  • On the platform (CDS) as a plugin.
  • Off the platform as an external code.

While the creation of plugins is a bread and butter topic well covered around, I’ll consider here the other option where you may want to host this function as an Azure Function. If you prefer the plugin way, you can do that, I just don’t cover it here.

Functions are “serverless” code that doesn’t require you to provision any fixed infrastructure. The cost of the Functions is per execution (on the Consumption plan) and is very cheap unless you start making thousands and thousands of transactions.

I assume you may have already or create a new trial Azure subscription (set up is not covered here).

The function we will create does a very basic thing: on a client’s HTTP request it invokes the eWAY’s Transaction Query API https://eway.io/api-v3/#transaction-query passing the required credentials, the “AccessCode” transaction reference and returns the response as is to the client.

  1. Follow the steps here to create a basic Azure Function: https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function
  2. Choose the Runtime stack as JavaScript (Node.js)
  3. Choose Windows as a platform
  4. Name the function: PaymentStatus
  5. Insert the following code as the function body. You can use Visual Studio Code as explained here: https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code

Let’s see what’s happening here.

  • These lines extract the payment token reference from the request (from the Processing page as you will see later):
var request = require(‘request’);
var transaction = context.req.query.transaction;
  • These lines invoke the payment gateway transaction verification API using the credentials stored in the environment variables or the Function itself (not a recommended practice). In either case, make sure that you replace the username and password from the ones provided by the payment gateway:
url : 'https://api.sandbox.ewaypayments.com/Transaction/' + transaction,            
auth: {
user: "<your eWAY username goes here>", // or use process.env["EWAY_APP_KEY"],
password: "<your eWAY password goes here>"//or use process.env["EWAY_PASSWORD"]
}

These lines handle the response and send it back to the client:

if (!error && response.statusCode == 200) {
context.log(body);
context.res = { status: 200, body: body };
}context.done();

And these handle error (ew, can be done better, but will work in our case):

if (error) {
context.log(error);
}

Processing page

This page will check the status of the payment submitted on the previous step, fills in the Payment’s Entity Form, submits it and redirect the user to the next step on success. On failure, this page will redirect the user to the previous step (Payment page) with an error flag.

Entity form

Go to Entity Forms and create a new one:

  • Name: Payment
  • Entity Name: Payment
  • Form Name: <the form in CDS you created>
  • Mode: Insert

On the Success settings tab:

  • On Success: Redirect
  • Redirect to Web Page: Receipt Page
  • Append Record ID To Query String: select
  • Record ID Query String Parameter Name: payment

Web Template

  1. Create a “ProcessingWebTemplate” web template and place the following layout code there. It defines the basic layout, but also includes the hidden (style=”display:none”) entity form that we will define later.

2. At the bottom of the above code add the following script (you will need to replace the “cr591” with the prefixes of your fields as mentioned earlier!):

Let’s break down script a bit.

  • The first two lines extract the “AccessCode” — this is the transaction reference token issued by eWAY when the card details were submitted on the previous step. This parameters and value are added by the eWAY payment form when redirecting to this page.
var urlParams = new URLSearchParams(window.location.search);var access_code = urlParams.get('AccessCode');
  • The JQuery’s “$.ajax” section calls the Azure function that we will create at the next step.
// Request payment confimration from teh payment gateway 
$.ajax({
url: "https://paymentrequest2.azurewebsites.net/api/PaymentStatus?transaction=" + access_code,
dataType: 'json',
  • If the response is received, it’s not empty and contains TransactionStatus=true, then the payment has been confirmed by the gateway. The code fills in the “reference”, “verification” and “amount” fields of your Entity Form and submits it. The redirect to the next Receipt page is initiated by the “On Success Settings” of the Entity Form.
if( response && 
response.Transactions.length > 0 &&
response.Transactions[0].TransactionStatus ){// Fill in the fields and submit the entity form

$("#cr591_reference").val(
transaction = response.Transactions[0].TransactionID);

$("#cr591_verification").val(access_code);

$("#cr591_amount").val(
response.Transactions[0].TotalAmount / 100 );

$("#InsertButton").click();
}
  • On error, the script redirects the browser to the previous step and adds “error=true” to the query string to indicate the error condition.

3. Save the web template.

Page Template

Create a Page Template:

  • Name: ProcessingPageTemplate
  • Type: Web Template
  • Web Template: ProcessingWebTemplate

Web Page

Create a Web Page:

  • Name: Processing
  • Parent Page: Home
  • Partial URL: processing
  • Page Template: ProcessingPageTemplate
  • Published state: Published
  • Entity Form: Payment

Test it

  1. Go to <your portal url>/payment page, click Pay Now and enter test card details:
  2. Number: 4242 4242 4242 4242
  3. Name on card: Any name
  4. Expiry date: anything in the future
  5. CCV: Any 3 digits, e.g. 111
  6. Click PayNow. You should be redirected twice. Firstly, you will be redirected to the processing page where you should see “Processing the payment, please wait…” message
  7. After a while* you should be redirected to the receipt page displaying your transaction details: reference number and amount. You should get the view like this:

You can also check:

  • the Payment entity in CDS that it has a new record
  • eWAY portal sandbox displays your transactions as on the screen below:

*) This may take quite a long time (up to a minute!) first time if you use form rarely as the first execution of the function starts up the environment behind. If you want to avoid or minimise the delays, you may consider using “App plan” instead of “Consumption plan” for your function. Check out more details in this post: https://markheath.net/post/avoiding-azure-functions-cold-starts

Conclusion and the next steps

OK, it’s been hard work and what you’ve created if followed these steps is the following.

Portal renders a payment page (1) with an embedded payment form from the payment gateway that submits (2) the card details securely and redirects the user (3) to the next step. The processing step calls the Azure Function (4) that queries the transaction verification API (5) and submits a payment record on success (6) and redirect to the receipt page (7). The receipt page retrieves the record (8) and displays the details to the user. If the verification fails then the user is directed to the initial page with an error flag (9). Well done!

You can try now to implement this pattern for your case, replacing receipt page with your business process or try using another payment gateway, for example, PayPal using their “Smart Payment Button” here: https://developer.paypal.com/docs/checkout/

Leave the comments on how it went or ask questions. Good luck!