Power Pages PayPal integration

Andrew GrischenkoPower Apps11 months ago10 Views

This post provides guidance on PayPal integration in the Power Pages site. It was inspired by a few requests on this topic, so I’ve decided to publish this guide.

Microsoft Power Pages evolve fast, and the Stripe integration is now available out of the box. I wrote a post about the Anatomy of the Stripe payments in Power Pages and How to improve Stripe payments in Power Pages. Check those out if you are interested in this topic. This post will focus on how to add PayPal to your Power Pages site, as it’s still not available natively.

Disclaimers

Please note that some approaches demonstrated here are incomplete for the production level of use and don’t cover all important aspects (e.g. error handling).

Also, this article covers a payment page implementation demo and is not a complete e-commerce or service flow. For example, the payment amount is just hardcoded for demo purposes, and there is no receipt page, etc.

With these excuses said, let’s jump into the actual implementation, and we will start with the architecture.

High-level architecture

If your business accepts payments from customers using credit cards, the last thing you want is to store or process the actual card details. Payment gateways are the businesses that outsource the risks and compliance for you and provide applications and infrastructure to manage payments on your behalf.

The typical high-level architecture involves 4 key participants: a customer, a merchant, a bank and a payment gateway:

The interactions between them are typically as follows:

  1. The Customer initiates an order and an intent to pay with the Merchant. While the Customer may type card details on the shop’s page, they never reach the Merchant (see below).
  2. The Merchant hosts the Payment gateway’s integration and exchanges reference details regarding the payment (tokens, nonce) but not the actual card details, which are unknown to the Merchant.
  3. The Customer shares the card details with the Payment gateway bypassing Merchat’s site.
  4. The Payment gateway and the Bank exchange the card details via a protected channel, and the Bank confirms the validity and funds available on the card (or responds with a declined result).
  5. Again, the Payment gateway responds to the Merchant on the payment status by earlier issued reference.
  6. Finally, the Merchant responds to the Customer on their order status.

The exact sequence of the above steps and details of the information exchanged vary from one payment gateway to another, while the pattern generally applies for the most.

Now, let’s look at how to specifically implement PayPal on Power Pages!

PayPal integration pattern

PayPal offers Checkout integration for processing online payments. This option combines client code (JavaScript for a browser) and server-side logic. The sequence diagram for such integration is listed on the PayPal documentation page.

As we will interact with PayPal Order APIs, we need to authenticate and get an access token – see the Authentication section on the PayPal API documentation. This requires a client ID and a client secret values. Obviously, no secret shall be stored and passed from the browser, so the connectivity with the API needs to be established on the server side.

Also, assuming that we want to write the payment transaction details to Dataverse, we need a secure place to do so. While the Power Pages Web API allows to connect securely from a browser under the Power Pages session, this is not a good option for the payments architecture, as explained in the previous section. For example, it could be vulnerable to tampering with the transaction details (e.g. amount).

We have several options for implementing the server-side component, but in this post, I want to demonstrate how the Power Platform can achieve this with a low-code approach. Let’s consider these options and their pros and cons:

  • Custom connector. This option is great for calling external APIs securely, with the minimum processing logic. Unfortunately, Power Platform custom connectors don’t support the OAuth 2 “client credentials” flow, which is required to authenticate with PayPal! Also, as the intention is to write the results to Dataverse, this would not be an ideal place to put such logic. So, this option is out.
  • Dataverse Plugin. This is a default approach to host some processing for data on Dataverse, but it has some constraints on the duration of calls, and it would be asynchronous execution from the client’s point of view. Also, this is a code approach and requires compiling binaries (brrr!). Not today.
  • Azure Function. This solution is great as it allows the hosting of processing logic to be serverless and would not require compiling binaries or containers. In addition, it’s cheap to run in the consumption pricing tier. The issue is that it requires some effort to secure the function endpoint properly and the need for Azure infrastructure, including monitoring services, storage accounts, etc. Consider this is needed for both dev/test and production environments. This is definitely a great option, and I used it not once, but we will try something different today.
  • Power Automate cloud flow. Until recently, executing cloud flow from a browser client would be an asynchronous operation. Also, the HTTP trigger endpoint needs to be secured from public access. Thanks to the relatively recent GA availability of Power Automate cloud flows integration with Power Pages, this is an excellent option to choose because it’s:
    • Synchronous – we can get the response from the flow execution as the script awaits it.
    • Secured with Power Pages infrastructure and Web role.
    • It is a low-code approach, and no additional infrastructure is required.

So, I’ll use the Power Automate cloud flow integration from Power Pages for this demo.

Specific architecture

The specific architecture of this implementation is pictured below. Can you recognise the corresponding components from the high-level diagram earlier? (Hint: there is no Bank on this one).

To implement this architecture we will need:

  • A PayPal developer account with a REST API application registered (A).
  • A Power Pages website page (B) loaded dynamically with a PayPal script from the website (C).
  • Two Power Automate cloud flows:
    • one to create an order via Orders API (V2) on PayPal (D);
    • another is to capture the payment via Orders API (V2) when user submits the card details and confirm the payment (E).
  • A table to hold payment info on Dataverse (F). Two options are listed further in the post – use one from the Power Pages payments integration or create your own.

Step-by-step guide

This guide assumes some basic knowledge of the Power Platform: working with solutions, cloud flows, environment variables etc. The screenshots are provided where required to clear the ambiguity or highlight critical points.

PayPal developer account sign-up

1. Sign up for a PayPal developer account if you don’t have one yet.

2. In the PayPal Developer Dashboard, on the Apps & Credentials tab, create a new REST API application. Give it a name of your choice, and you will receive a client ID and a client secret needed later to authenticate the API calls. So, keep the browser tab open.

Create a solution for customization

3. Go to the Power Pages maker environment https://make.powerpages.microsoft.com/ and in the Solutions section create a new solution and give it a name of your choice, e.g. PayPal Integration.

4. Create 2 environment variables:

  • PAYPAL_CLIENT_ID – and set the current value of Client ID from PayPal REST API app created at step 2.
  • PAYPAL_CLIENT_SECRET – the value of Secret from the REST API app.

NOTE: For production use case you should use the “secret” type for the environment variable type. This would require an Azure account with the Secrets vault service created in it.

5. Go to the Power Pages Studio and select the Data section on the left. You will see a settings cog near the Data label as shown by an arrow on the screenshot below. Click that cog and select the solution you’ve just created (e.g. PayPal Integration).

Create a Power Pages site and payment page

In this section we will do a few things:

  • Create a Power Pages website and a new Payment page.
  • Create a snippet to place a PayPal form in.
  • Create a handling JavaScript.

6. Log in to the Power Pages maker portal and create a new site (unless you have one already).

7. Create a new page on the Power Pages site and name it Order Payment or similar.

8. Go to the Power Pages Management app, accessible from the ellipsis menu “…” just below the Set up section:

9. Create a content snippet in the Portal Management app (select type HTML). See the Power Pages documentation for more details if needed.

10. Copy the following code into the content of the snippet. It does two things:

  • <div> tag creates an HTML structure and loads the form via the external script.
  • <script> tag is a basic placeholder function to render the form and PayPal buttons. Note that the createOrder() and onApprove() functions are stubs and will be filled in on the next steps. Check that the PayPal buttons appear on the Payment page.
<div>
<div id="paypal-button-container" style="width: 350px;"></div>
<p id="result-message"></p>
<!-- Replace for production the "test" client-id value with your client-id -->
<script src="https://www.paypal.com/sdk/js?client-id=test&currency=USD"></script>
</div>

<script language="JavaScript">
if (window.top != window.self){
window.paypal.Buttons({
async createOrder() {},
async onApprove(data, actions) {}
})
.render("#paypal-button-container");

function resultMessage(message) {
const container = document.querySelector("#result-message");
container.innerHTML = message;
}
}
</script>

11. In the Power Pages Management app, in the section Web Pages find the Order Payment page you created. In the Localized content section you should see another record calls Order payment which represents the localised version of the page and this is the one we need to put the content on – click on it.

12. Add the following code to the page and note the use of the content snippet you’ve just created (Liquid markup):

<div id="i3jhx6" class="row sectionBlockLayout text-left" style="display: flex; flex-wrap: wrap; margin: 0px; min-height: auto; padding: 8px;">
<div id="ibdmvz" class="container" style="padding: 0px; display: flex; flex-wrap: wrap;">
<div id="iykqyu" class="col-md-4 columnBlockLayout" style="flex-grow: 1; display: flex; flex-direction: column; min-width: 250px; word-break: break-word;"><img src="/Cat-PC.png" id="i8dr8i" alt="Cat-PC" name="Cat-PC.png" style="max-width: 100%; object-fit: contain; margin: 0 50px 0 0;" /></div>
<div id="i0sicq" class="col-md-8 columnBlockLayout" style="flex-grow: 1; display: flex; flex-direction: column; min-width: 250px; word-break: break-word;">
<p id="i0kgrm">Payment</p>
{{ snippets["PayPal payment"] }}
</div>
</div>
</div>

If everything has been done correctly so far, you should see the page with a cat and two PayPal buttons as below. (You would need to login to see that page as we set it up authenticated).

Create or reuse the Payment table

You have 2 options for implementing the Dataverse table to capture payment transaction details.

Option 1 (recommended) – “out of the box”

If you already using the Power Pages Stripe integration (in Preview) or if you want to have a solution compatible with the payments solutions for Power Pages from Microsoft, you may want to use the Payments table that comes when this feature is enabled. It comes as part of Stripe integration, but don’t worry, you don’t need to have or use Stripe to enable the Payment table. It’s not payment gateway specific and can be extended nicely as explained below.

Follow these steps to enable it:

13a. In the Power Pages Studio select Set up section on the left panel and then find the External apps (preview) section.

14a. You will see 2 integrations available – DocuSign and Stripe. We are interested in the latter today, so select Install in the Stripe row below. Click Start installation in the pop up dialog to confirm and wait until it completes.

15a. Go to your solution created at step 8 and Add existing -> Table and select the Payment table that has been added to your environment.

16a. In the same solution, use Add existing -> More -> Choice and select Provider choice. Customize the choice by adding a new provider – PayPal.

This is it, you don’t need to do anything else. No need to setup Stripe keys as you age not going to use it. Move to the section Create Order flow and script.

Option 2 – “do it yourself”

If you don’t want to get bound by the additional component in your solution, you can create your own payments page. I recommend the columns for the table as outlined below for compatibility with the rest of the guide.

Follow these steps to create the table:

13b. Create a new Table and call it Payment, leaving everything else by default.

14b. Add the following additional columns to it with the type specified:

  • Amount: Currency
  • Payment date time: Date & time
  • Payment identifier: String
  • Payment method: String
  • Payment status: Choice of Created, Succeeded or Failed
  • Payment status reason: String
  • Provider: Choice of PayPal and Other

Create Order flow and script

Now we have the required components to create the first step in the payment flow: create a PayPal Order object and initiate a new record in the Payment table as not yet completed payment.

This is an overview of the flow steps described below. You can find the solution (unmanaged) with all flows and other components in this GitHub repository.

17. Create a new Instant Power Automate flow.

  • Name it “Create Order” and skip the trigger selection at that step. For some reason Power Pages trigger is still not available in the list of triggers on the initial creation page, I hope it will be fixed soon.
  • Select trigger When Power Pages calls a flow:
  • Add an input parameter of type Number and name it amount.

18. Add the following actions:

  • Action: HTTP Request (authentication request to receive access token)
    • Name: Authenticate request
    • Method: POST
    • URI: https://api-m.sandbox.paypal.com/v1/oauth2/token
    • Headers: "Content-Type": "application/x-www-form-urlencoded"
    • Body: grant_type=client_credentials
    • Authentication: Basic
    • Username: Environment variable PAYPAL_CLIENT_ID
    • Password: Environment variable PAYPAL_CLIENT_SECRET
  • Action: Parse JSON (pase the results of the previous action to retrieve access_token for the next step)
    • Name: Parse Authenticate response
    • Content: @{body('Authenticate_request')}
    • Schema:
{
"type": "object",
"properties": {
"scope": {
"type": "string"
},
"access_token": {
"type": "string"
},
"token_type": {
"type": "string"
},
"app_id": {
"type": "string"
},
"expires_in": {
"type": "integer"
},
"nonce": {
"type": "string"
}
}
}
  • Action: HTTP Request (actual call to the Order API to create an order)
{
"intent": "CAPTURE",
"purchase_units": [
{
"amount": {
"currency_code": "USD",
"value": @{triggerBody()['number']}
}
}
],
"payment_source": {
"paypal": {
"experience_context": {
"payment_method_preference": "IMMEDIATE_PAYMENT_REQUIRED",
"brand_name": "EXAMPLE INC",
"locale": "en-US",
"shipping_preference": "NO_SHIPPING",
"user_action": "PAY_NOW"
}
}
}
}
  • Action: Parse JSON (parse results of the Create order call)
    • Name: Parse Create Order response
    • Content: @{body('Create_Order_request')}
    • Schema:
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"status": {
"type": "string"
},
"payment_source": {
"type": "object",
"properties": {
"paypal": {
"type": "object",
"properties": {}
}
}
},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"href": {
"type": "string"
},
"rel": {
"type": "string"
},
"method": {
"type": "string"
}
},
"required": [
"href",
"rel",
"method"
]
}
}
}
}
  • Action: Add a new row (Dataverse)
    • Table name: Payments
    • Amount: @{triggerBody()['number']}
    • Payment date time: @{utcNow()}
    • Payment identifier: @{body('Parse_Create_Order_response')?['id']}
    • Payment method: PayPal
    • Payment status: Created
    • Provider: PayPal
  • Action: Return value(s) to Power Pages
    • String parameter name: order_id
    • Parameter value: @body('Parse_Create_Order_response')?['id']

We are done with the first flow – make sure to save it!

19. Register the created flow on the Power Pages site. Go to the Design Studio of the website, section Set up and select Cloud flows. Select the button Add existing flow:

20. In the pop up panel on the right select the Create Order flow and add a web role allowed to access this flow: Authenticated Users and click Add. Here is our security for the flow endpoints out of the box!

21. Once the flow is added, a specific endpoint URL will be assigned. Copy it to the clipboard.

22. In the Portal Management app, create a Settings record with the name “Payments/PayPal/CreateOrderURL” and the value of the power automate flow endpoint from the previous step, e.g.: /_api/cloudflow/v1.0/trigger/9397822b-dfdf...

23. In the same Portal Management app, go to Content Snippets, find the one you created earlier and in the snippet content replace the line async createOrder() {}, with the following block:

async createOrder() {
const url = "{{ settings["Payments/PayPal/CreateOrderURL"] }}";

const payload = {
eventData: JSON.stringify({
amount: 100
})
};
var orderId;

await shell
.ajaxSafePost({
type: "POST",
contentType: "application/json",
url: url,
data: JSON.stringify(payload),
processData: false,
global: false,
})

.done(function (response) {
const orderData = JSON.parse(response);
console.log(response);

if (orderData.order_id) {
orderId = orderData.order_id;
} else {
const errorDetail = orderData.details[0];
const errorMessage = errorDetail
? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})`
: JSON.stringify(orderData);

throw new Error(errorMessage);
}
})
.fail(function () {
console.error(error);
resultMessage(`Could not initiate PayPal Checkout...<br><br>${error}`);
});

return orderId;

},

What’s happening here is a call to the Power Automate cloud flow Create Order created at the previous step and results handler, including:

  • Reading site settings for the URL of the cloud flow
  • Hardcoded amount. NOTE: If you are integrating PayPal into your purchase flow, it will be when the payment amount is defined and the user is ready to make a payment.
  • Packing the flow input parameter – note the use of eventData and JSON.strigify()
  • Endpoint (trigger) call – note use of shell.ajaxSafePost
  • Handling the response and extraction of an Order ID
  • Error handling

24. Now, you can Sync and Preview the Payment page. What you should expect as a result of it, when the page loads you will see the two PayPal buttons (as before), but when you click on it, a card details and billing information section will appear.

25. Check the Create Order flow history and make sure that this flow has run successfully or fix errors if there were any.

Should you get lost with the steps or code changes, you can find the complete solution with Power Automate flow and script for the snippet in this GitHub repository.

Capture Order flow and script

Now, we can finalise the implementation by handling the capture payment event when a user submits credit card details.

26. Create a new Instant Power Automate flow:

  • Name it Capture Order and Skip the trigger selection at that step.
  • Select trigger When Power Pages calls a flow.
  • Add a String input parameter and name it order_id

27. Add the following actions to the flow:

  • Action: HTTP Request (authentication request to receive access token – exactly as in the previous flow)
    • Name: Authenticate request
    • Method: POST
    • URI: https://api-m.sandbox.paypal.com/v1/oauth2/token
    • Headers: "Content-Type": "application/x-www-form-urlencoded"
    • Body: grant_type=client_credentials
    • Authentication: Basic
    • Username: Environment variable PAYPAL_CLIENT_ID
    • Password: Environment variable PAYPAL_CLIENT_SECRET
  • Action: Parse JSON (pase the results of the previous action to retrieve access_token for the next step)
    • Content: @{body('Authenticate_request')}
    • Schema:
{
"type": "object",
"properties": {
"scope": {
"type": "string"
},
"access_token": {
"type": "string"
},
"token_type": {
"type": "string"
},
"app_id": {
"type": "string"
},
"expires_in": {
"type": "integer"
},
"nonce": {
"type": "string"
}
}
}
  • Action: Parse JSON (parse results of the Capture order call)
    • Name: Parse JSON
    • Content: @{body('Capture_Order_request')}
    • Schema:
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"status": {
"type": "string"
},
"payment_source": {
"type": "object",
"properties": {
"paypal": {
"type": "object",
"properties": {
"email_address": {
"type": "string"
},
"account_id": {
"type": "string"
},
"account_status": {
"type": "string"
},
"name": {
"type": "object",
"properties": {
"given_name": {
"type": "string"
},
"surname": {
"type": "string"
}
}
},
"address": {
"type": "object",
"properties": {
"country_code": {
"type": "string"
}
}
}
}
}
}
},
"purchase_units": {
"type": "array",
"items": {
"type": "object",
"properties": {
"reference_id": {
"type": "string"
},
"payments": {
"type": "object",
"properties": {
"captures": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"status": {
"type": "string"
},
"amount": {
"type": "object",
"properties": {
"currency_code": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"final_capture": {
"type": "boolean"
},
"seller_protection": {
"type": "object",
"properties": {
"status": {
"type": "string"
}
}
},
"seller_receivable_breakdown": {
"type": "object",
"properties": {
"gross_amount": {
"type": "object",
"properties": {
"currency_code": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"paypal_fee": {
"type": "object",
"properties": {
"currency_code": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"net_amount": {
"type": "object",
"properties": {
"currency_code": {
"type": "string"
},
"value": {
"type": "string"
}
}
}
}
},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"href": {
"type": "string"
},
"rel": {
"type": "string"
},
"method": {
"type": "string"
}
},
"required": [
"href",
"rel",
"method"
]
}
},
"create_time": {
"type": "string"
},
"update_time": {
"type": "string"
}
},
"required": [
"id",
"status",
"amount",
"final_capture",
"seller_protection",
"seller_receivable_breakdown",
"links",
"create_time",
"update_time"
]
}
}
}
}
},
"required": [
"reference_id",
"payments"
]
}
},
"payer": {
"type": "object",
"properties": {
"name": {
"type": "object",
"properties": {
"given_name": {
"type": "string"
},
"surname": {
"type": "string"
}
}
},
"email_address": {
"type": "string"
},
"payer_id": {
"type": "string"
},
"address": {
"type": "object",
"properties": {
"country_code": {
"type": "string"
}
}
}
}
},
"links": {
"type": "array",
"items": {
"type": "object",
"properties": {
"href": {
"type": "string"
},
"rel": {
"type": "string"
},
"method": {
"type": "string"
}
},
"required": [
"href",
"rel",
"method"
]
}
}
}
}

  • Action: List rows (Dataverse) – find the record created previously by Create Order flow.
    • Table name: Payments
    • Filter rows: pp_paymentidentifier eq '@{triggerBody()['text']}'
  • Action: Update a row (Dataverse)
    • Table name: Payments
    • Row ID: @{first(outputs('List_rows')?['body/value'])?['pp_paymentid']}
    • Payment status: Succeeded
    • Payment details: @{body('Parse_JSON')?['purchase_units']?[0]?['payments']?['captures']?[0]?['id']}
    • Payment status reason: @{body('Parse_JSON')?['status']}
  • Action: Return value(s) to Power Pages
    • First parameter:
      • String parameter name: status_code
      • Parameter value: @outputs('Capture_Order_request')['statusCode']
    • Second parameter:
      • String parameter name: order_data
      • Parameter value: @{body('Capture_Order_request')}

28. Register the created flow on the Power Pages site. Go to the Design Studio of the website, section Set up and select Cloud flows. Select the button Add existing flow and in the pop up panel on the right select the Capture Order flow and add a web role allowed to access this flow: Authenticated Users and click Add.

29. In the Portal Management app, create a Settings record with the name “Payments/PayPal/CaptureOrderURL” and the value of the power automate flow endpoint from the previous step, e.g.: /_api/cloudflow/v1.0/trigger/9397822b-dfdf...

30. Go to the content snippet in the Portal Management app, find the content snippet you created and changed previously and replace the line async onApprove(data, actions) {} with the following block:

async onApprove(data, actions) {
const url = "{{ settings["Payments/PayPal/CaptureOrderURL"] }}";
const payload = {
eventData: JSON.stringify({
order_id: data.orderID
})
};

await shell
.ajaxSafePost({
type: "POST",
contentType: "application/json",
url: url,
data: JSON.stringify(payload),
processData: false,
global: false,
})

.done(function (response) {
console.log(`Capture response: ${response}`);
const flowResponse = JSON.parse(response);
const orderData = JSON.parse(flowResponse.order_data);
console.log(`Order data: ${orderData}`);
if (orderData.details) {
const errorDetail = orderData.details[0];

if (errorDetail.issue === "INSTRUMENT_DECLINED") {
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
// recoverable state, per https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/
return actions.restart();
} else {
// (2) Other non-recoverable errors -> Show a failure message
throw new Error(`${errorDetail.description} (${orderData.debug_id})`);
};
};

if (!orderData.purchase_units)
throw new Error(JSON.stringify(orderData));

// (3) Successful transaction -> Show confirmation or thank you message
// Or go to another URL: actions.redirect('thank_you.html');
const transaction =
orderData.purchase_units[0].payments.captures[0] ||
orderData.purchase_units[0].payments.authorizations[0];
resultMessage(
`Transaction ${transaction.status}: ${transaction.id}<br><br>See console for all available details`,
);
console.log(
"Capture result",
orderData,
JSON.stringify(orderData, null, 2),
);
})
.fail(function () {
console.error(error);
resultMessage(`Could not capture PayPal order...<br><br>${error}`);
});


}

hat’s happening here is a call to the Power Automate cloud flow Capture Order created at the previous step and results handler, including:

  • Reading site settings for the URL of the cloud flow
  • Packing the flow input parameter – note the use of JSON.strigify() and order_id: data.orderID
  • Endpoint (trigger) call – note use of shell.ajaxSafePost
  • Handling the response and errors

Time for the final end-to-end test!

Test the PayPal integration

The test is now to confirm that the transaction is successfully recorded on both PayPal and Dataverse side and the Payments table is updated with the PayPal transaction information.

31. Reload the payment page, click the Debit or Credit Card button and, after a small delay, a section to enter card and billing details will appear, as before. Enter the test card details below and click Pay now. You can find more testing card numbers for different scenarios on PayPal website.

  • Card number: 2223000048400011
  • Expiry date: any date in the future, e.g. 12/28
  • CVV: any 3digit number, e.g. 123
  • Billing address details and name: Any

You should see a successful message after some delay and the browser console log will show you the API response details:

32. Once the transaction is successful and a message is displayed, open your PayPal developer dashboard, Event logs section https://developer.paypal.com/dashboard/dashboard/sandbox. You should see there 2 records – one event from the Create Order flow when the payment section was open and another one when you clicked Pay Now.

33. Return to Power Pages Studio, select Data section and select the Payments table. You should see a row or few. Sort by the column Payment date time to see the latest transaction and add the columns Payment details, Payment identifier and Payment status if not selected yet. You should see the transaction details.

Possible errors and troubleshooting:

  • The form is not displayed
  • Nothing happens after I click
  • Nothing happens after I click Submit
  • Transaction is visible on the PayPal side, but not in Payments table.

Conclusion and what’s next

Well, this post turned out to be much longer than I expected and would like it to be. But it dives into many details and aims to give you a big picture. I hope you found it useful, please let me know if it did!

The solution built using this guide is in no way complete. To bring this to your actual site you need to take care of at least the following:

  • Integrate into the flow of where your purchase journey starts and the payment amount is determined. Replace the hard-coded value with the actual amount to be paid.
  • Create a proper successful payment confirmation page or receipt and ensure a redirect to it.
  • Do proper error handling for different scenarios and display relevant messages to customers.

I hope this guide helped you to start on this journey and provided a demonstration of Power Automate cloud flows integration in Power Pages. Please let me know what you want to know more! Please comment or reach out to me any time at andrew@technomancy.com.au.

Original Post https://cloudminded.blog/2024/03/06/power-pages-paypal-integration/

0 Votes: 0 Upvotes, 0 Downvotes (0 Points)

Leave a reply

Follow
Sign In/Sign Up Sidebar Search
Popular Now
Loading

Signing-in 3 seconds...

Signing-up 3 seconds...