Payment Intent workflow
How do I implement the Payment Intent workflow?
The Payment Intent workflow is used to accept these payment methods:
Category | Payment Method |
---|---|
Credit & Debit Card payments | Straight card payments Card installments |
E-Wallets | Maya GCash GrabPay |
Buy Now, Pay Later | BillEase |
Direct Online Banking | BPI Online UBP Online BDO Online via Brankas Landbank Online via Brankas Metrobank Online via Brankas |
Scan to Pay | QRPh |
Building an integration with Payment Intents API involves two actions: creating and attaching a PaymentMethod to a PaymentIntent.
A Payment Intent resource represents a single shopping cart or customer session in your application. The Payment Intent holds information such as the supported payment methods, the amount to collect, and the currency.
A Payment Method resource resource represents the billing details of the customer. This includes credit card information, name, email, and address.
Implementation
In navigating this guide, you will encounter Recipes and API References. Recipes are snippets of API calls that differentiates the API call from each Payment Method. API References are the page where you can test out and view the fields for each API call.
1. Creating a PaymentIntent from the server-side
To start receiving payments with Payment Intents API, you must create one first. You must create your Payment Intent from your backend using your secret API key then send the client_key
of the response to the client-side. This client_key will be used to attach a payment method to the payment intent. In this step, the payment intent's status is awaiting_payment_method
. Store the Payment Intent ID.
2. Create a Payment Method from the client-side
Collect billing Information from the client-side with the use of forms. We do not recommend storing this information on your server. Send this information over to us and we'll handle the rest! Create a payment method by calling our Create A Payment Method API: https://developers.paymongo.com/reference#create-a-paymentmethod. Store the Payment Method ID.
NOTE: Do not send the credit card information to your backend, sending the information to your backend requires your platform to conform with PCI-DSS regulations.
3. Attach the Payment Intent to the Payment Method
Attach the Payment Intent to the Payment Method by calling our Attach API. Attaching the Payment Intent can be done on the client side or the server side. The implementation is completely up to the merchant's choice.
On the client side, you need to use the client_key
found in the PaymentIntent to serve as the identifier of PaymentIntent in the attach endpoint.
We do recommend that for those implementing our Save Card, the Attach API call is done on the server side to lessen the amount of routes that are needed to be developed.
Once the Payment Method is attached, the Payment Intent status transitions to awaiting_next_action
, awaiting_payment_method
, processing
or succeeded
. You can check the status of the Payment Intent from the JSON response of the attach payment method endpoint.
4. Redirecting the customer for authentication
If the attach returns an awaiting_next_action
status, it means your customer must authenticate the transaction. The response includes a redirect URL where the customer can proceed with 3D Secure authentication. You can render an iframe in a modal to display the authentication page. Once the user successfully authenticates the transaction, you can recheck the status of Payment Intent.
// The example is using axios as the REST client on the client-side.
// This PaymentMethod ID must be created before the attach action. This is just a sample value to represent a PaymentMethod
var paymentMethodId = 'pm_ajeDG2y6WgnrCXaamWFmPUw2';
// PaymentIntent client_key example
var clientKey = 'pi_1JvFbEiRRnh2fsUE5nJ2F1z7_client_mpe6tJkgaX3pSoiYeSp1AbEU';
// Get the payment intent id from the client key
var paymentIntentId = clientKey.split('_client')[0];
axios.post(
'https://api.paymongo.com/v1/payment_intents/' + paymentIntentId + '/attach',
{
data: {
attributes: {
client_key: clientKey,
payment_method: paymentMethodId
}
}
},
{
headers: {
// Base64 encoded public PayMongo API key.
Authorization: `Basic ${window.btoa(key)}`
}
}
).then(function(response) {
var paymentIntent = response.data.data;
var paymentIntentStatus = paymentIntent.attributes.status;
if (paymentIntentStatus === 'awaiting_next_action') {
// Render your modal for 3D Secure Authentication since next_action has a value. You can access the next action via paymentIntent.attributes.next_action.
} else if (paymentIntentStatus === 'succeeded') {
// You already received your customer's payment. You can show a success message from this condition.
} else if(paymentIntentStatus === 'awaiting_payment_method') {
// The PaymentIntent encountered a processing error. You can refer to paymentIntent.attributes.last_payment_error to check the error and render the appropriate error message.
} else if (paymentIntentStatus === 'processing'){
// You need to requery the PaymentIntent after a second or two. This is a transitory status and should resolve to `succeeded` or `awaiting_payment_method` quickly.
}
})
We send a 3DS-authentication-complete
post message from the iframe to your page once authentication is complete. You can use this event to do further actions once the payment intent status has changed.
window.addEventListener(
'message',
ev => {
if (ev.data === '3DS-authentication-complete') {
// 3D Secure authentication is complete. You can requery the payment intent again to check the status.
// PaymentIntent client_key example
var clientKey = 'pi_1JvFbEiRRnh2fsUE5nJ2F1z7_client_mpe6tJkgaX3pSoiYeSp1AbEU';
axios.get(
'https://api.paymongo.com/v1/payment_intents/' + paymentIntentId + '?client_key=' + clientKey,
{
headers: {
// Base64 encoded public PayMongo API key.
Authorization: `Basic ${window.btoa(key)}`
}
}
).then(function(response) {
var paymentIntent = response.data.data;
var paymentIntentStatus = paymentIntent.attributes.status;
if (paymentIntentStatus === 'succeeded') {
// You already received your customer's payment. You can show a success message from this condition.
} else if(paymentIntentStatus === 'awaiting_payment_method') {
// The PaymentIntent encountered a processing error. You can refer to paymentIntent.attributes.last_payment_error to check the error and render the appropriate error message.
} else if (paymentIntentStatus === 'processing'){
// You need to requery the PaymentIntent after a second or two. This is a transitory status and should resolve to `succeeded` or `awaiting_payment_method` quickly.
}
})
}
},
false
);
awaiting_payment_method
means there are errors after attaching the Payment Method to the PaymentIntent. You can check the attribute last_payment_error
from the response. If this occurs, the customer can try to input their billing information again.
processing
is a transitory status that indicates that the payment is being processed. This status will eventually resolve to succeeded
or awaiting_payment_method
. If this occurs, you should requery the status of the PaymentIntent in 1-2 seconds.
succeeded
means you received the payment of the customer and you can show a success message after this happened.
Whenever you will attach a PaymentMethod to a PaymentIntent and the PaymentIntent succeeds or you encountered a payment error, a Payment is automatically created for you. This means that you don't need to call the create Payment after attaching a PaymentMethod. You can verify if you received the payment by going to the Payments
module of your dashboard or you can also retrieve the PaymentIntent using secret API key and check the payments
attribute.
5. Finish
Get notified when you have successful or failed transactions by using webhooks. To monitor the transition of the PaymentIntent from your backend, you could be notified for successful and failed payments by listening to payment.paid
and payment.failed
events by registering your webhook endpoint using our Webhook API.
Webhooks
You should not create a webhook in your code. You can try using API tools such as Postman or curl to create your webhook once. Please take note that you should not create multiple webhooks for every source that will be created. One webhook with events
payment.paid
andpayment.failed
is enough to receive the payment information.
Event notifications will be sent to your registered webhook endpoint containing relevant payment information as shown below:
{
"data": {
"id": "evt_9w6KTxQY3hmuDQaALHoAZnRp",
"type": "event",
"attributes": {
"type": "payment.paid",
"livemode": false,
"data": {
"id": "pay_JMg1rgaUtg5U79rRSjiDUvLr",
"type": "payment",
"attributes": {
"access_url": null,
"amount": 10000,
"balance_transaction_id": "bal_txn_4LqZEXFNKR9e8GyAmXBgBF1C",
"billing": null,
"currency": "PHP",
"description": null,
"disputed": false,
"external_reference_number": null,
"fee": 1850,
"foreign_fee": 100,
"livemode": false,
"net_amount": 8050,
"origin": "api",
"payment_intent_id": "pi_1Pb5ED9RDLCSsWMwXT5W6Q3K",
"payout": null,
"source": {
"id": "card_iYXhMRiwoiF45V2fDL6aTjqN",
"type": "card",
"brand": "visa",
"country": "US",
"last4": "4345"
},
"statement_descriptor": "Rigorilla Tech",
"status": "paid",
"tax_amount": null,
"refunds": [],
"taxes": [],
"available_at": 1619686800,
"created_at": 1619426488,
"paid_at": 1619426488,
"updated_at": 1619426488
}
},
"previous_data": {},
"created_at": 1619426488,
"updated_at": 1619426488
}
}
}
You can determine if a payment is successful or not by checking the event type or the status of the payment intent.
You may also watch this video guide:
Updated 5 months ago