Skip to main content

Elements

Learn how to receive payments through PayRex Elements by embedding a payment form in your application. The client and server-side code creates a checkout form with PayRex Elements.

Checkout

1. Set up the server-side

Install the server-side SDK and initialize with your secret API key

Install the appropriate SDK depending on your programming language and import it. If we don't support yet the programming language you're using, you may skip this step and use your preferred REST client.

  npm install payrex-node
create_payment_intent.js
// Protect your PayRex Secret API key at all costs. One common approach
// to store it in an environment variable.
// Add your PayRex test secret API key.
const payrexSecretApiKey = '';

const payrex = require('payrex-node')(payrexSecretApiKey);

// Create a PaymentIntent with amount and currency
const paymentIntent = await payrex.paymentIntents.create({
// Amount is in cents. The sample below is 100.00.
amount: 10000,
currency: 'PHP',
payment_methods: ['gcash', 'card'],
});

const output = {
clientSecret: paymentIntent.clientSecret,
}

console.log(JSON.stringify(output));

Create a payment intent

info

The example below creates a PaymentIntent via ajax. If you prefer to create a payment intent before you render your checkout page, you can adjust the code below.

Create a PaymentIntent on the server side. A PaymentIntent resource tracks the customer's payment lifecycle, keeping track of any failed payment attempts and ensuring the customer is only charged once. Return the PaymentIntent's client secret in the response to finish the payment on the client.

After initializing the SDK with your secret API key, you must create a PaymentIntent. A PaymentIntent is a resource that manages your customer's payment lifecycle. It tracks all failed payment attempts and ensures that your customer is charged correctly. Once a PaymentIntent is created, return the PaymentIntent's client_secret attribute in the response. The PaymentIntent's client_secret will be used on the client side, which is the next step of the integration process.

create_payment_intent.js
// Protect your PayRex Secret API key at all costs. One common approach
// to store it in an environment variable.
// Add your PayRex test secret API key.
const payrexSecretApiKey = '';

const payrex = require('payrex-node')(payrexSecretApiKey);

// Create a PaymentIntent with amount and currency
const paymentIntent = await payrex.paymentIntents.create({
// Amount is in cents. The sample below is 100.00.
amount: 10000,
currency: 'PHP',
payment_methods: ['gcash', 'card'],
});

const output = {
clientSecret: paymentIntent.clientSecret,
}

console.log(JSON.stringify(output));

2. Create a checkout page on the client-side.

Load Payrex.js

From the client side, load the PayRex javascript library called Payrex.js. This javascript library helps you to maintain compliance such as PCIDSS by making sure that payment information are not passing to your server and sent directly to PayRex.

warning

Payrex.js domain is js.payrexhq.com and make sure that you load the javascript library from this domain. Do not store a copy of this javascript library.

info

If you prefer CommonJS or ES6 modules when importing PayRex.JS, you can use our official library.

checkout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="A demo application of PayRex payments product" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PHP Demo Application for PayRex</title>
<link rel="stylesheet" href="checkout.css" />
</head>
<body>
<div class="container">
<button id="btn-pay" type="button" onClick="payAction()">
<div class="spinner hidden" id="spinner"></div>
<span id="btn-pay-text">Pay</span>
</button>
<div id="payment-element">
<!--Payrex.js will mount the Payment Element here. -->
</div>
</div>
<!-- Include PayRexJS script -->
<script type="text/javascript" src="https://js.payrexhq.com"></script>
<script type="text/javascript" src="checkout.js" defer></script>
</body>
</html>

Add a payment element placeholder div

Add an empty placeholder div within your checkout page where the Payment Element will be mounted. PayRex will insert the payment form to this placeholder div to collect payment information.

checkout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="A demo application of PayRex payments product" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PHP Demo Application for PayRex</title>
<link rel="stylesheet" href="checkout.css" />
</head>
<body>
<div class="container">
<button id="btn-pay" type="button" onClick="payAction()">
<div class="spinner hidden" id="spinner"></div>
<span id="btn-pay-text">Pay</span>
</button>
<div id="payment-element">
<!--Payrex.js will mount the Payment Element here. -->
</div>
</div>
<!-- Include PayRexJS script -->
<script type="text/javascript" src="https://js.payrexhq.com"></script>
<script type="text/javascript" src="checkout.js" defer></script>
</body>
</html>

Initialize Payrex.js

Once the payment form is created and Payrex.js is loaded, initialize Payrex.js with your public API key from the client side. You will use Payrex.js to create an instance of a Payment Element and complete the payment on the client.

checkout.js
// Add your PayRex Public API key.
const payrex = window.Payrex('');
let elements;

initialize();
checkPaymentIntentStatus();

async function payAction() {
showLoading(true)
await payrex.attachPaymentMethod({
elements,
options: {
// Return URL is where the customer will be redirected after completing a payment.
return_url: "http://localhost:4242/checkout.html",
},
});
showLoading(false)
}

function showLoading(flag) {
const btnPayText = document.querySelector("#btn-pay-text");
const spinner = document.querySelector("#spinner");

if (flag) {
// Disable the button and show a spinner
spinner.classList.remove("hidden");
btnPayText.classList.add("hidden");
} else {
spinner.classList.add("hidden");
btnPayText.classList.remove("hidden");
}
}

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret
});

const paymentElementOptions = {
layout: "accordion",
};

const paymentElement = elements.create(
"payment",
paymentElementOptions
);

paymentElement.mount("#payment-element");
}

// Fetches the payment intent status after payment submission
async function checkPaymentIntentStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const paymentIntent = await payrex.getPaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
window.alert("Payment succeeded.")
break;
case "processing":
window.alert("Payment is still being processed.")
break;
case "awaiting_payment_method":
window.alert("Payment was not successful. Try again..")

break;
default:
window.alert("Something went wrong")

break;
}
}

Fetch the PaymentIntent from the server-side

Call the API endpoint you created from the server-side to create a PaymentIntent once your checkout page loads. The clientSecret attribute returned by your API endpoint is used to complete the payment.

checkout.js
// Add your PayRex Public API key.
const payrex = window.Payrex('');
let elements;

initialize();
checkPaymentIntentStatus();

async function payAction() {
showLoading(true)
await payrex.attachPaymentMethod({
elements,
options: {
// Return URL is where the customer will be redirected after completing a payment.
return_url: "http://localhost:4242/checkout.html",
},
});
showLoading(false)
}

function showLoading(flag) {
const btnPayText = document.querySelector("#btn-pay-text");
const spinner = document.querySelector("#spinner");

if (flag) {
// Disable the button and show a spinner
spinner.classList.remove("hidden");
btnPayText.classList.add("hidden");
} else {
spinner.classList.add("hidden");
btnPayText.classList.remove("hidden");
}
}

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret
});

const paymentElementOptions = {
layout: "accordion",
};

const paymentElement = elements.create(
"payment",
paymentElementOptions
);

paymentElement.mount("#payment-element");
}

// Fetches the payment intent status after payment submission
async function checkPaymentIntentStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const paymentIntent = await payrex.getPaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
window.alert("Payment succeeded.")
break;
case "processing":
window.alert("Payment is still being processed.")
break;
case "awaiting_payment_method":
window.alert("Payment was not successful. Try again..")

break;
default:
window.alert("Something went wrong")

break;
}
}

Initialize PayRex Elements

Initialize the PayRex Elements UI library with the PaymentIntent client secret. PayRex Elements manages the UI components that will help you to collect payment details from your customers.

checkout.js
// Add your PayRex Public API key.
const payrex = window.Payrex('');
let elements;

initialize();
checkPaymentIntentStatus();

async function payAction() {
showLoading(true)
await payrex.attachPaymentMethod({
elements,
options: {
// Return URL is where the customer will be redirected after completing a payment.
return_url: "http://localhost:4242/checkout.html",
},
});
showLoading(false)
}

function showLoading(flag) {
const btnPayText = document.querySelector("#btn-pay-text");
const spinner = document.querySelector("#spinner");

if (flag) {
// Disable the button and show a spinner
spinner.classList.remove("hidden");
btnPayText.classList.add("hidden");
} else {
spinner.classList.add("hidden");
btnPayText.classList.remove("hidden");
}
}

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret
});

const paymentElementOptions = {
layout: "accordion",
};

const paymentElement = elements.create(
"payment",
paymentElementOptions
);

paymentElement.mount("#payment-element");
}

// Fetches the payment intent status after payment submission
async function checkPaymentIntentStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const paymentIntent = await payrex.getPaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
window.alert("Payment succeeded.")
break;
case "processing":
window.alert("Payment is still being processed.")
break;
case "awaiting_payment_method":
window.alert("Payment was not successful. Try again..")

break;
default:
window.alert("Something went wrong")

break;
}
}

[OPTIONAL] Override the style of payment element

PayRex Elements allows you to match the color branding of your application so that the payment form looks like a part of your website. If you want to override the default color of the payment form, you can add the style attribute when initializing an Element object.

checkout.js
// redacted code

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret: clientSecret,
style: {
variables: {
// Replace the hexadecimal color with your brand color
primaryColor: '#F63711'
}
}
});

// redacted code

Create an instance of a Payment Element

Create an instance of Payment Element and mount it to the placeholder <div> in your checkout page. This embeds a payment form, allowing your customer to select a payment method. The payment form collects the payment details for the selected payment method.

checkout.js
// Add your PayRex Public API key.
const payrex = window.Payrex('');
let elements;

initialize();
checkPaymentIntentStatus();

async function payAction() {
showLoading(true)
await payrex.attachPaymentMethod({
elements,
options: {
// Return URL is where the customer will be redirected after completing a payment.
return_url: "http://localhost:4242/checkout.html",
},
});
showLoading(false)
}

function showLoading(flag) {
const btnPayText = document.querySelector("#btn-pay-text");
const spinner = document.querySelector("#spinner");

if (flag) {
// Disable the button and show a spinner
spinner.classList.remove("hidden");
btnPayText.classList.add("hidden");
} else {
spinner.classList.add("hidden");
btnPayText.classList.remove("hidden");
}
}

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret
});

const paymentElementOptions = {
layout: "accordion",
};

const paymentElement = elements.create(
"payment",
paymentElementOptions
);

paymentElement.mount("#payment-element");
}

// Fetches the payment intent status after payment submission
async function checkPaymentIntentStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const paymentIntent = await payrex.getPaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
window.alert("Payment succeeded.")
break;
case "processing":
window.alert("Payment is still being processed.")
break;
case "awaiting_payment_method":
window.alert("Payment was not successful. Try again..")

break;
default:
window.alert("Something went wrong")

break;
}
}

[OPTIONAL] Providing default values in billing information

If you already have the customer's billing information in your system and want to speed up the payment process, you can add the' defaultValues' attribute to supply default values to the payment element.

checkout.js
  // redacted code

const paymentElementOptions = {
layout: "accordion",
defaultValues: {
billingDetails: {
name: "John Smith",
phone: "+639170000000",
email: "johnsmith@somedomain.com",
address: {
line1: "Address Line 1",
line2: "Address Line 2",
country: "PH",
city: "Address City",
state: "Address State",
postalCode: "1902",
},
},
},
};

// redacted code

3. Complete the payment on the client

info

For test cards, you can use credit card number 4242424242424242 and any expiry date as long as it's a future date. We will provide you different test cards for different scenarios soon.

Handle the submit event of the pay button

Listen to the onClick event of your own pay button and attach a PaymentMethod resource to the PaymentIntent through the PayRex API. If you prefer to listen to a form submit event, it could be your alternative approach.

checkout.js
// Add your PayRex Public API key.
const payrex = window.Payrex('');
let elements;

initialize();
checkPaymentIntentStatus();

async function payAction() {
showLoading(true)
await payrex.attachPaymentMethod({
elements,
options: {
// Return URL is where the customer will be redirected after completing a payment.
return_url: "http://localhost:4242/checkout.html",
},
});
showLoading(false)
}

function showLoading(flag) {
const btnPayText = document.querySelector("#btn-pay-text");
const spinner = document.querySelector("#spinner");

if (flag) {
// Disable the button and show a spinner
spinner.classList.remove("hidden");
btnPayText.classList.add("hidden");
} else {
spinner.classList.add("hidden");
btnPayText.classList.remove("hidden");
}
}

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret
});

const paymentElementOptions = {
layout: "accordion",
};

const paymentElement = elements.create(
"payment",
paymentElementOptions
);

paymentElement.mount("#payment-element");
}

// Fetches the payment intent status after payment submission
async function checkPaymentIntentStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const paymentIntent = await payrex.getPaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
window.alert("Payment succeeded.")
break;
case "processing":
window.alert("Payment is still being processed.")
break;
case "awaiting_payment_method":
window.alert("Payment was not successful. Try again..")

break;
default:
window.alert("Something went wrong")

break;
}
}

Attach a PaymentMethod to the PaymentIntent

Call .attachPaymentMethod() from Payrex.js and pass along the Payment Element instance and a return_url to instruct PayRex to redirect your customer after they complete the payment.

For payment methods that require authentication such as credit card, PayRex will display a modal for authentication e.g. 3DS for credit or debit cards or redirects your customer to an authentication page depending on the payment method. After your customer completes the authentication process, they will be redirected to your nominated return_url.

checkout.js
// Add your PayRex Public API key.
const payrex = window.Payrex('');
let elements;

initialize();
checkPaymentIntentStatus();

async function payAction() {
showLoading(true)
await payrex.attachPaymentMethod({
elements,
options: {
// Return URL is where the customer will be redirected after completing a payment.
return_url: "http://localhost:4242/checkout.html",
},
});
showLoading(false)
}

function showLoading(flag) {
const btnPayText = document.querySelector("#btn-pay-text");
const spinner = document.querySelector("#spinner");

if (flag) {
// Disable the button and show a spinner
spinner.classList.remove("hidden");
btnPayText.classList.add("hidden");
} else {
spinner.classList.add("hidden");
btnPayText.classList.remove("hidden");
}
}

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret
});

const paymentElementOptions = {
layout: "accordion",
};

const paymentElement = elements.create(
"payment",
paymentElementOptions
);

paymentElement.mount("#payment-element");
}

// Fetches the payment intent status after payment submission
async function checkPaymentIntentStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const paymentIntent = await payrex.getPaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
window.alert("Payment succeeded.")
break;
case "processing":
window.alert("Payment is still being processed.")
break;
case "awaiting_payment_method":
window.alert("Payment was not successful. Try again..")

break;
default:
window.alert("Something went wrong")

break;
}
}

Show success/failed status message after redirection

Once PayRex redirects your customer to your nominated return_url, Payrex.js appends the payment_intent_client_secret query parameter which is the PaymentIntent's client_secret. Use this parameter to retrieve the PaymentIntent to determine if the payment succeeds or not and show the relevant message to your customer.

checkout.js
// Add your PayRex Public API key.
const payrex = window.Payrex('');
let elements;

initialize();
checkPaymentIntentStatus();

async function payAction() {
showLoading(true)
await payrex.attachPaymentMethod({
elements,
options: {
// Return URL is where the customer will be redirected after completing a payment.
return_url: "http://localhost:4242/checkout.html",
},
});
showLoading(false)
}

function showLoading(flag) {
const btnPayText = document.querySelector("#btn-pay-text");
const spinner = document.querySelector("#spinner");

if (flag) {
// Disable the button and show a spinner
spinner.classList.remove("hidden");
btnPayText.classList.add("hidden");
} else {
spinner.classList.add("hidden");
btnPayText.classList.remove("hidden");
}
}

async function initialize() {
const {clientSecret} = await fetch(
"/create_payment_intent.php",
{
method: "POST",
}
).then((r) => r.json());

elements = payrex.elements({
clientSecret
});

const paymentElementOptions = {
layout: "accordion",
};

const paymentElement = elements.create(
"payment",
paymentElementOptions
);

paymentElement.mount("#payment-element");
}

// Fetches the payment intent status after payment submission
async function checkPaymentIntentStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const paymentIntent = await payrex.getPaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
window.alert("Payment succeeded.")
break;
case "processing":
window.alert("Payment is still being processed.")
break;
case "awaiting_payment_method":
window.alert("Payment was not successful. Try again..")

break;
default:
window.alert("Something went wrong")

break;
}
}