Subscription using Maya Card Payment Vault
Learn how to save a credit card for future payments or subscriptions
What is Maya Card Payment Vault?
Maya Card Payment Vault allows your application to securely accept credit card information through tokenization for current and future transactions.
Why use Maya Card Payment Vault for card subscriptions?
By subscribing with Maya Card Payment Vault, you will be able to save your customer's credit card for future payments or subscriptions. Just follow these 5 steps:
Step 1 Setup Maya Business Manager
First, set up your Maya Business Manager account.
Step 2 Create a form that will accept credit card details
Maya Card Payment Vault will tokenize the card details without needing you to save it on your database.
οΈοΈοΈIs your platform PCI-DSS certified?
Do not store any card information (i.e. name, card number, expiry dates, cvv/cvc) on your application unless your platform is PCI-DSS certified.
<html>
<head>
<title>Save card</title>
</head>
<body>
<form action="/tokenize-customer-card" method="POST">
<input class="cn" placeholder="Card number">
<input class="date" placeholder="MM / YY">
<input class="cvc" placeholder="CVC" type="password">
<button type="submit">Link a card</button>
</form>
</body>
</html>
Tokenizing the card details
Once the customer has submitted their card information, your server-side application should send this data to Create Payment Token to obtain a paymentTokenId
to be used for the rest of process.
const express = require('express');
const app = express();
const fetch = require('node-fetch');
async app.post('/tokenize-customer-card', async (req, res) => {
const createPaymentTokenUrl = 'https://pg-sandbox.paymaya.com/payments/v1/payment-tokens';
const options = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa('SECRET_KEY')}`
},
method: 'POST',
body: req.body
};
const paymentTokenId = await fetch(url, options)
.then(res => res.json())
.then(json => {
return json.paymentTokenId
})
.catch(err => console.error('error:' + err));
});
app.listen(8080, () => console.log(`Listening on port ${8080}!`));
Step 3 Registering your customer to Maya Card Payment Vault
Your application should have the following fields below available for customer creation to Maya Card Payment Vault
{
"id": "d29f1635-8313-4ed4-94e5-94b6a6018f52",
"firstName": "Maya",
"middleName": "Jose",
"lastName": "Juan",
"contact": {
"phone": "+63(2)1234567890",
"email": "[email protected]"
},
"billingAddress": {
"line1": "6F Launchpad",
"line2": "Sheridan Street",
"city": "Mandaluyong City",
"state": "Metro Manila",
"zipCode": "1552",
"countryCode": "PH"
},
"shippingAddress": {
"firstName": "Maya",
"middleName": "Jose",
"lastName": "Juan",
"line1": "6F Launchpad",
"line2": "Sheridan Street",
"city": "Mandaluyong City",
"state": "Metro Manila",
"zipCode": "1552",
"countryCode": "PH",
"phone": "+63(2)1234567890",
"email": "[email protected]",
"shippingType": "ST"
},
"sex": "F",
"birthday": "1987-07-28",
"customerSince": "2020-12-25",
"createdAt": "2021-07-06T14:01:25.000Z",
"updatedAt": "2021-07-06T14:01:25.000Z"
}
Your application's server will then send those user information to Vault using Create Customer endpoint.
const express = require('express');
const app = express();
const fetch = require('node-fetch');
async app.post('/tokenize-customer-card', async (req, res) => {
const createPaymentTokenUrl = 'https://pg-sandbox.paymaya.com/payments/v1/payment-tokens';
const options = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa('SECRET_KEY')}`
},
method: 'POST',
body: cardData
};
const paymentTokenId = await fetch(createPaymentTokenUrl, options)
.then(res => res.json())
.then(json => {
return json.paymentTokenId
})
.catch(err => console.error('error:' + err));
const createCustomerUrl = 'https://pg-sandbox.paymaya.com/payments/v1/customers';
const options = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa('SECRET_KEY')}`
},
method: 'POST',
body: customerData
};
const customerIdFromMayaVault = await fetch(createCustomerUrl, options)
.then(res => res.json())
.then(json => {
return json.id
})
.catch(err => console.error('error:' + err));
});
app.listen(8080, () => console.log(`Listening on port ${8080}!`));
Step 4 Link the customer to the card token
At this point, you will have 2 variables available customerId
and paymentToken
. Your server side application will need to link the 2 values to successfully vault using Create Card of Customer endpoint.
const express = require('express');
const app = express();
const fetch = require('node-fetch');
async app.post('/tokenize-customer-card', async (request, response) => {
const createPaymentTokenUrl = 'https://pg-sandbox.paymaya.com/payments/v1/payment-tokens';
const options = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa('SECRET_KEY')}`
},
method: 'POST',
body: cardData
};
const paymentTokenId = await fetch(createPaymentTokenUrl, options)
.then(res => res.json())
.then(json => {
return json.paymentTokenId
})
.catch(err => console.error('error:' + err));
const createCustomerUrl = 'https://pg-sandbox.paymaya.com/payments/v1/customers';
const options = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa('SECRET_KEY')}`
},
method: 'POST',
body: customerData
};
const customerIdFromMayaVault = await fetch(createCustomerUrl, options)
.then(res => res.json())
.then(json => {
// Your code to keep the customerId on your application
return json.id
})
.catch(err => console.error('error:' + err));
const createCustomerCardUrl = 'https://pg-sandbox.paymaya.com/payments/v1/customers/${customerIdFromMayaVault}/cards';
const options = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa('SECRET_KEY')}`
},
method: 'POST',
body: {
paymentTokenId,
redirectUrl: {
success: 'http://localhost:8080/success',
failure: 'http://localhost:8080/failure',
cancel: 'http://localhost:8080/cancel',
}
}
};
fetch(createCustomerCardUrl, options)
.then(res => res.json())
.then(json => {
const cardToken = json.cardToken
// Your code to keep the cardToken on your application
response.redirect(303, json.verificationUrl)
})
.catch(err => console.error('error:' + err));
});
app.listen(8080, () => console.log(`Listening on port ${8080}!`));
You will notice that linking of customer to their credit card will return 2 items: cardToken
and verificationUrl
. Your application should redirect to the verificationUrl
in order to trigger user authentication which will depend on the issuing bank's 3DS authentication.
Verification
There are 2 flows to verifying the linked card: through a test charge of Php 10.00 or through payment of their current transaction.
Through a test charge
From the successful call of the endpoint, your application should be redirected to the verificationUrl
from the response data to continue the verification process.
Test Charge
We will be charging Php 10 to the customer's card. This amount will be automatically be refunded back.
Through payment of current transaction
Initiate the payment of the current customer transaction through Create Customer Payment endpoint. The response of the endpoint will give you a new verificationUrl
that your application should redirect to.
Quick test #1
To test out your card linking
- Input card details using one of our test cards
- Click the "Link a card" button.
- You are redirected to Issuing Bank's verification page.
- On successful verification, your customer will be redirected to the success page.
Step 5 Creating the subscription schedule
During this stage, you must have the following values: cardToken
and customerId
obtained from Maya Card Payment Vault.
To create a subscription, you will need to have the totalAmount
and the schedule of the subscription ready.
{
"description": "Sample subscription",
"totalAmount": {
"amount": "1.00",
"currency": "PHP"
},
"interval": "DAY",
"intervalCount": 1,
"startDate": "YYYY-MM-DD"
}
Field | Acceptable Values | Description |
---|---|---|
interval | (string) DAY, MONTH, YEAR | Behavior of the interval (daily, monthly, yearly) |
intervalCount | (integer) 1, 3, 5 | Number of intervals before the next occurrence Example: Daily: intervalCount = 1; interval = 'DAY' Every 15 days: intervalCount = 15; interval = 'DAY' Monthly: intervalCount = 1; interval = 'MONTH' Quarterly: intervalCount = 3; interval = 'MONTH' Annual: intervalCount = 1; interval = 'YEAR' |
Your server side application will then pass the subscription configuration to the Create Subscription endpoint
const express = require('express');
const app = express();
const fetch = require('node-fetch');
async app.post('/create-subscription', async (req, res) => {
const url = `https://pg-sandbox.paymaya.com/payments/v1/customers/${customerId}/cards/${cardToken}/subscriptions`;
const options = {
method: 'POST',
headers: {Accept: 'application/json', 'Content-Type': 'application/json'},
body: req.body
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
res.send('Subscription Created.');
});
app.listen(8080, () => console.log(`Listening on port ${8080}!`));
Subscriptions are scheduled every 11:00pm (GMT+8)
Vault will attempt to charge payments every 11:00pm (GMT+8). If the payment fails, the subscription will become inactive. Inactive Subscriptions will not be charged.
Updated 4 months ago