(The below has been described and tested for Canvas Power Apps. This has not yet been tested and adapted for Model-driven apps. As for the Power App Portal app, another integration pattern is appropriate, to be discussed later)

This package for import in your CDS environment and source code of the control are packaged here: https://github.com/andrew-grischenko/StripePaymentsPCF

Architecture

The solution facilitates a safe, PCI DSS compliant way to accept credit card payments in Canvas Power Apps and consist of two components – a custom connector and a code component (PCF).

The architecture of the solution is explained below:

Credit card form (B3)
Credit card form (B3)
StripePayments Component (A2)
StripePayments Component (A2)
Your Canvas Power App (A)
Your Canvas Power App (A)
PaymentIntents Connector (A1)
PaymentIntents Connector (A…
Connection (A3)
Connection (A3)
PaymentIntent.client_secret
PaymentIntent.client_secret
StripeClientKey
StripeClientKey
Authorization
Authorization
Stripe SaaS (B)
Stripe SaaS (B)
PaymentIntents API (B1)
PaymentIntents API (B1)
Stripe.js (B2)
Stripe.js (B2)
Viewer does not support full SVG 1.1

Your Canvas Power App application (A) hosts the payment component (A2) on one of the screens. The component loads the Stripe.js client (B2) from the Stripe SaaS CDN (B) and injects the credit card capture fields (B3) as an iframe to enable secure and compliant payment flow. A client API key (public) need to be specified as part of the component setup.

In order to facilitate a payment, the PaymentIntent must be registered on Stripe API declaring which amount and currency the payment is going to be. The result of the registration is the client_secret which is used then to confirm the payment. The StripePaymentIntents custom connector (A1) exposes the operation CreatePaymentIntent() which interacts with PaymetIntent API (B1) and returns the PaymentIntent object including the client_secret value, which is then used by the payment component (A2). The connector requires the API key to be provided as part of the establishing a connection (A3).

Please note, in the architecture, the credit card details are NOT exposed to any part of your application or connector API, but instead are sent directly to Stripe’s secure endpoint. This is the (only) recommended integration pattern, it ensures the security and PCI DSS requirements compliance.

Install & use

Import the managed solution package into the environment as per the usual process. As a result, you should get the following:

  1. Custom connector to the Stripe PaymentIntents API
  2. Code PCF component hosting the credit capture form from Stripe
  3. Demo canvas PowerApp using the above two

Demo canvas Power App

Launch the StripePaymentsDemo app to see the demonstration of the components in action:

Set up your Stripe account

Sign up for Stripe APIs and SaaS here: https://dashboard.stripe.com/register – it’s free for testing purposes. You will receive 2 keys – publishable and secret – as explained below and this is where you will see the payments transactions and access heaps more needed functions.

Set up the custom connector StripePaymentIntents

  1. Add a new connector to your Power App – find the StripePaymentIntents connector (added by the imported solution).
The connector required for Stripe payments

Please do NOT use the standard Stripe connector as it doesn’t provide the required payment API methods.

Do not use that

2. Create a new connection for the custom connector and specify as API key the string as:

Bearer your_stripe_api_secret_key

where:

  • Bearer (and the following space character) – the required authentication keyword.
  • your_stripe_api_secret_key – the secret key from the Stripe account Dashboard (usually starting with sk_)

Setup the code component StripePayments and app logic

  1. Import a code component through “Insert > Custom > Import component”

2. Set up the properties of the component:

  • StripeClientKey – the Publishable key from the your Stripe account

3. Setup the Customer attribute with a customer reference as a string (optional)

4. Setup the visual appearance (optional):

  • CardFontSize – font size of the card number capture element
  • ButtonFontSize – font size for the Pay button
  • ErrorFontSize – font size of the error messages

4. Get the PaymentIntent object when the payment amount is known. Execute the connector function CreatePaymentIntent and store it in a variable, e.g:

Set(payment_intent, StripePaymentIntent.CreatePaymentIntent(
   { 
      amount: price * 100, 
      currency: "aud", 
      description: "test payment"
   }
));

where:

  • payment_intent – the variable to be used on the next step
  • StripePaymentIntent – the connector object
  • amount – the numeric value of the payment amount in hundredths of currency (e.g. cents).
    • please note, it cannot be less or more than the specified limits on payment amount, otherwise, you will get an error like “StripePaymentIntent.CreatePaymentIntent failed: { “error”: { “code”: “parameter_invalid_integer”, “doc_url”: “https://stripe.com/docs/error-codes/parameter-invalid-integer”, “message”: “This value must be greater than or equal to 1.”, “param”: “amount”, “type”: “invalid_request_error” } }
  • 100 – the multiplier to get the expected amount
  • “aud” – currency code, must be one supported by Stripe.
  • description – any string, can be empty

If you get the following error, it’s like

5. Set the property PaymentIntentClientSecret of the StripePayment component to use the PaymentIntent’s object’s client_secret value:

payment_intent.client_secret

6. Handle the payment events – success and errors – OnChange handler of the component by verifying the PaymentStatus attribute, e.g.

If(StripeWidget.PaymentStatus = "completed", Navigate(Receipt)) 

7. For test integration, you can use the test credit card numbers as described here. You can use card number “4242424242424242” with any future expiry date and any 3 digit CVV code.

Please feel free to reach out to andrew@technomancy.com.au for any feedback, support and business enquiries.