# MavisPay Integration Documentation
MavisPay allows you to collect payments for goods and services through the Ronin blockchain network.

## Key Features
MavisPay provides an easy checkout expierence and handles the wallet connection as well as processing and validating payments on the blockchain.
MavisPay is integrated with Katana. This allows the customer to chose the currency they want to pay with and the merchant the currency they wish to receive. A customer could pay with AXS and the merchant ultimately received USDC.
Update about a MavisPay Payment are send to the merchants backend server via webhook calls.
## Getting Access
MavisPay is not generally available. If you wish to get access talk to your partner manager at SkyMavis.
If access is granted an engineer from our Ecosystem team will get in touch to walk you through the setup and integration process.
---
# MavisPay API
## Basics & Authentication
MavisPay is integrated with our developer portal. To authenticate your API calls you have to send your api key in the `X-API-Key` header field of each request.
Use the following API hosts:
| Environment | Call Type | Host |
| -------- | -------- | -------- |
| Development | Private | `https://api-gateway.skymavis.one/mavispay/v1` |
| Development | Public | `https://api-gateway.skymavis.com/mavispay-public/v1` |
| Production | Private | `https://api-gateway.skymavis.com/mavispay/v1` |
| Production | Public | `https://api-gateway.skymavis.com/mavispay-public/v1` |
> Private API Calls require your api Key. Public calls don't.
## Create a new Payment Request
To create a payment request you have to submit information to this API endpoint.
`POST /merchant/payments`
### Request Body:
```json!
{
"amount": "27500000",
"currency": "usdc",
"items": [
{
"name": "AxieCon 2022 Backpack",
"quantity": 1
}
],
"reference": "55f56c89-b454-4677-a1a1-d3271f47db6f",
"redirect_url": "https://localhost:3000/checkout"
}
```
| Field | Description | Example / Note |
| -------- | -------- | -------- |
| amount | The full amount of currency to pay without decimal places. | USDC has 6 decimals places so 27500000 equals 27.5 USDC |
| currency| The currency you as a merchant want to receive. | Supported values: usdc, axs, weth, slp, ron. Merchant must have enbaled currency via smartcontract. |
| items | The items in the users cart. An array of objects wiht name and quantity | ``` [{"name": "AxieCon 2022 Backpack", "quantity": 1}] ``` |
| reference | A payment reference generated by the merchant to later identify incoming webhook notifications | We suggest UUID |
| redirect_url | The URL where the MavisPay frontend redirect users after the payment is complete or expired | This url must have been added to the merchant account by a SkyMavis employee and must begin with https - even for testing |
### Response:
```json!
{
"ID": 1,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"DeletedAt": null,
"payment_id": "99e9f183-e509-478b-8eda-02f6d38c57ab",
"merchant_id": "65e141ec-a735-47fe-8d57-fe514e03ddb6",
"amount": 27500000,
"currency": {
"Name": "USDC",
"Address": "0x067fbff8990c58ab90bae3c97241c5d736053f77"
},
"redirect_url": "https://localhost:3000/checkout",
"reference": "55f56c89-b454-4677-a1a1-d3271f47db6f",
"blockchain_reference": "1683256082984259400_40b20d1d-52dc-40cc-8767-14bdd54cf730",
"status": "created",
"transaction_id": "",
"items": [
{
"name": "AxieCon 2022 Backpack",
"quantity": 1
}
],
"expiresAt": "2023-05-05T05:13:02.9842594+02:00",
"createdAt": "2023-05-05T05:08:02.9853351+02:00",
"updatedAt": "2023-05-05T05:08:02.9853351+02:00"
}
```
After receiving the payment details from the API the customer needs to be send to the following URL:
##### Production:
`https://mavispay.skymavis.com/pay?id=`
##### Development:
`https://mavispay.skymavis.one/pay?id=`
You have to append the value of `payment_id` to these urls which was returned from the create payment endpoint.
---
> **Important**
> Payments expire automatically after 300 seconds (5 Minutes). This is a global setting and can not be changed on a per-merchant or per-payment basis.
## WebHook Notification
As a merchant you are required to setup a webhook receiver via https. This endpoint will receive POST requests sent by MavisPay with updates about payments.
Updates include the following events:
#### Payment Created:
> A new payment was created through the API
```json
{
"payment": {
"payment_id": "0459991c-c0a6-4819-b0bc-4aa7a9775f82",
"reference": "2c912268-4327-4bd7-b778-2632e3421ba5",
"status": "created"
}
}
```
#### Payment Expired:
> The payment was not completed within 5 minutes.
```json
{
"payment": {
"payment_id": "31830bbb-ee10-4970-bd50-18e1e272544b",
"reference": "4a9a29b8-4601-4b1a-8373-fdbca4a96018",
"status": "expired",
"transaction_hash": ""
}
}
```
#### Payment Completed:
> The payment was completed and the funds are in the merchants wallet
```json
{
"payment": {
"payment_id": "5d6feb44-d40a-44e2-8a1d-41b19f117e20",
"reference": "1dde7e08-4379-462d-949b-4e5cd9e373a4",
"status": "completed",
"transaction_hash": "0xf7d5c3ad0ad15a285d430503c2a798dd6103a80a5f1bd59f047952d1718bfd05"
}
}
```
#### Payment Failed:
> The transaction was included in a block but failed to execute. Eg ran out of gas.
```json
{
"payment": {
"payment_id": "6eeef102-eb9a-459e-9b1f-6cc584181868",
"reference": "796387aa-ba2c-4bdb-8ec4-0e3d3cc83393",
"status": "failed",
"transaction_hash": "0x6233691e7459f7a057d1a2b2ae7997715b6ead0c7574cd8ebcfc8098c45dee4b"
}
}
```
---
### Verification
To verify the authenticity of the webhook request you first have to extract the webhook signature from the `x-signature` header of the request.
The signature is a JWT token which must be validated using the public JWKS at:
#### Production
https://api-gateway.skymavis.com/mavispay-public/.well-known/jwks.json
#### Development
https://api-gateway.skymavis.com/mavispay-public/.well-known/jwks.json
#### Example:
```typescript!
import jwt from 'jsonwebtoken';
import JwksRsa from 'jwks-rsa';
// Your JWT token
const signature = 'your_jwt_token_here';
// JWKS URL
const jwksUrl = 'your_jwks_url_here';
// Initialize JWKS client
const client = JwksRsa({
jwksUri: jwksUrl
});
// Function to get the signing key
function getKey(header: jwt.JwtHeader, callback: jwt.SigningKeyCallback) {
client.getSigningKey(header.kid, (err, key) => {
const signingKey = key.getPublicKey();
callback(null, signingKey);
});
}
// Verify the token
jwt.verify(signature, getKey, (err, decoded) => {
if (err) {
console.log('Token is invalid:', err);
} else {
console.log('Token is valid. Decoded payload:', decoded);
}
});
```