Installing the Papi PrestaShop module
The Papi PrestaShop module allows you to integrate the Papi payment aggregator into a PrestaShop 1.7 or 8.x store.
It allows you to accept payments by Mobile Money (MVola, Orange Money, Airtel Money) and by Visa and Mastercard cards in Madagascar.
Prerequisites
Before installing the module, check the following points:
- You are using PrestaShop 1.7.x or 8.x
- Your site uses PHP version 7.4 minimum
- The PHP cURL extension is enabled
- You have created a store with Papi with a store API key
- You have created a store with PrestaShop
- The PrestaShop store must be configured to accept the MGA currency (Malagasy Ariary)
Download the module
Download the official Papi PrestaShop module Zip file from the Downloads page.
Use the latest release unless Papi support has specifically asked you to install another version. The Downloads page lists official releases from newest to oldest, with each release's Zip file, SHA-256 checksum, compatibility notes, and changelog.
After downloading the file, keep it as a Zip archive. You do not need to unzip it before installing it from the PrestaShop back office.
Install the module from the PrestaShop back office
Installation by upload
- In the PrestaShop back office, open Modules > Module Manager.
- Click Upload a module.
- Select the downloaded
papi_prestashop.zipfile. - Wait for PrestaShop to upload and install the module.
- When the installation finishes, click Configure.
If the upload succeeds, PrestaShop extracts the Zip file automatically and places the module in the correct modules/papi_prestashop/ directory.
Manual installation
Use manual installation only if your PrestaShop back office cannot upload the module Zip file.
- Extract the downloaded
papi_prestashop.zipfile on your computer. - Check that the extracted folder is named
papi_prestashop. - Copy the
papi_prestashop/folder into themodules/directory of your PrestaShop installation. - In the PrestaShop back office, open Modules > Module Manager.
- Search for the Papi module.
- Click Install, then Configure.
During installation, the module automatically performs the following operations:
- Creation of the Awaiting Papi payment order status.
- Storage of this status identifier in the
PAPI_OS_AWAITINGconfiguration. - Association of the module with all currencies via a
-1entry inps_module_currency, so that the payment option can appear at checkout. - Creation of the
ps_papi_transactiontable in the database.
If you reinstall the module, the order status is not recreated if it already exists. The installation is designed to avoid duplicates.
Mandatory MGA currency configuration
Papi currently accepts payments only in Malagasy Ariary (MGA). If the store does not offer MGA as an active currency, the Pay with Papi button may not appear at checkout, or the customer may be redirected back to the cart with an error message.
Import the MGA currency
- In the back office, open International > Localization.
- In the Localization tab, use the Import a localization pack block.
- Select Madagascar.
- Run the import.
This operation creates, among other things, the MGA currency and the Madagascar geographic zone.
Set MGA as the default currency
- In the back office, open International > Localization.
- Scroll down to the Configuration panel.
- In the Default currency field, select Malagasy Ariary (MGA).
- Save.
The default currency change may not be immediately visible on the front office if the browser keeps an old currency in session. To test properly, use the store currency selector and explicitly switch to MGA.
Check the store display
Prices must be displayed in Ar on product pages and in the cart. If prices remain in euros, switch the currency from the PrestaShop theme currency selector.
When MGA is the active currency, some native payment modules such as cheque, bank transfer, or cash on delivery may disappear from checkout. This is normal PrestaShop behavior when these modules do not declare their compatibility with the active currency.
Module configuration
- In the back office, open Modules > Module Manager.
- Search for the Papi module.
- Click Configure.
- Fill in the required fields.
| Field | Description |
|---|---|
| API key | Store key provided by the Papi dashboard. The module performs a validation call when saving. |
| Notification URL (override) | Leave empty in production. Use only in certain local development scenarios. |
| Test mode | Enable during tests. In test mode, Papi does not actually charge cards. Disable before going live. |
After saving, a success message confirms that the configuration has been saved and that the API key is valid.
If API key validation fails with a 401 or 403 error, the key is incorrect or revoked. Other network errors, such as a timeout or temporary server error, do not necessarily block saving the key, but must be monitored before going live.
Papi webhook configuration
The webhook is the URL of your store called by Papi after each payment status change. This mechanism allows your PrestaShop store to automatically update the payment status of orders.
In production
- In the Papi dashboard, configure your store notification URL.
- The URL generated by the module follows this format:
https://your-store.mg/en/module/papi_prestashop/notification
This URL is displayed in the description of the Notification URL field on the module configuration page.
In production, leave the Notification URL (override) field empty. PrestaShop then automatically generates the correct URL.
When you save the module configuration with a valid API key, the module sends the notification URL to Papi.
The notification URL must be publicly accessible from the Internet. A local server, a server behind a VPN, or an environment that is not publicly exposed will not receive Papi notifications.
In local development
If PrestaShop is running locally, for example on http://localhost:8080, Papi cannot directly call your machine.
Two approaches are possible.
Option A: ngrok tunnel
- Install and configure ngrok.
- Start a tunnel to your local port:
ngrok http 8080
- Retrieve the public URL provided by ngrok.
- In the module configuration, enter the full URL in the override field:
https://xxx.ngrok-free.app/en/module/papi_prestashop/notification
Known limitation: PrestaShop performs a domain check and may redirect incoming requests to the store’s canonical domain. In this case, a request relayed by ngrok may receive a 302 Found response instead of being processed as a webhook. In production, this issue does not occur when Papi calls the store’s real public domain.
Option B: direct command-line test
To test webhook processing without going through Papi, retrieve a valid JSON payload and replay it directly to your local PrestaShop.
PowerShell example:
$body = '{"paymentStatus":"SUCCESS","merchantPaymentReference":"YOUR_REF","notificationToken":"YOUR_TOKEN","paymentMethod":"MVOLA","currency":"MGA","amount":89661}'
Invoke-WebRequest -Uri "http://localhost:8080/en/module/papi_prestashop/notification" `
-Method POST `
-ContentType "application/json" `
-Body $body
curl example:
curl -X POST http://localhost:8080/en/module/papi_prestashop/notification \
-H "Content-Type: application/json" \
-d '{"paymentStatus":"SUCCESS","merchantPaymentReference":"YOUR_REF","notificationToken":"YOUR_TOKEN","paymentMethod":"MVOLA","currency":"MGA","amount":89661}'
A 200 OK response with the content OK confirms that the webhook was processed correctly.
Purchase flow verification
Before going live, test the full flow:
- Select a product and add it to the cart.
- Go to checkout.
- At the payment step, check that the Pay with Papi button appears with the Papi logo.
- Click Pay with Papi.
- Check that PrestaShop creates an order with the Awaiting Papi payment status.
- Check the redirect to the Papi payment page.
- Make a test payment on the Papi page.
- Return to the store and check the confirmation page.
- After receiving the webhook, check that the order status changes to Payment accepted in the back office.
A carrier must be configured and active for the customer’s geographic zone. Without an available carrier, checkout may stop at the delivery step before even displaying the payment methods. For Madagascar, check that at least one carrier covers the Africa zone or the zone used by your PrestaShop configuration.
Order statuses
| PrestaShop status | When | Notes |
|---|---|---|
| Awaiting Papi payment | As soon as the user clicks Pay with Papi | Status created by the module during installation. |
| Payment accepted | SUCCESS webhook received | Native PrestaShop _PS_OS_PAYMENT_ status. |
| Payment error | FAILED webhook received | Native PrestaShop _PS_OS_ERROR_ status. |
| Canceled | Papi API error when creating the payment link | The order is canceled and the customer is redirected back to the cart. |
If the call to the Papi API fails when creating the payment link, the PrestaShop order may already have been created. In this case, the module automatically changes it to the Canceled status and redirects the customer back to the cart with an error message.
Papi Transaction panel in the back office
On each order page paid via Papi, a Papi Transaction panel is displayed at the bottom of the page.
This panel contains:
- Order reference: PrestaShop reference, for example
YHTFKHOIH. - Papi status: accepted, pending, or failed, with a visual badge.
- Amount: amount formatted in
MGA. - Payment link: Papi link generated during payment.
- Dates: transaction creation date and last update date.
- Raw Papi response: full JSON received during the latest webhook, viewable for diagnostic purposes.
The displayed raw response corresponds to the notification webhook sent by Papi after payment. It does not correspond to the response received when creating the payment link. These two exchanges are distinct: the first creates the paymentLink, the second notifies the payment result.
Testing the webhook in local development
To test the webhook locally, first retrieve the notification_token value associated with the latest transaction:
SELECT payment_reference, notification_token
FROM ps_papi_transaction
ORDER BY date_add DESC
LIMIT 1;
Then send a test notification:
$body = '{
"paymentStatus": "SUCCESS",
"merchantPaymentReference": "YOUR_ORDER_REFERENCE",
"notificationToken": "YOUR_NOTIFICATION_TOKEN",
"paymentMethod": "MVOLA",
"currency": "MGA",
"amount": 89661
}'
Invoke-WebRequest -Uri "http://localhost:8080/en/module/papi_prestashop/notification" `
-Method POST `
-ContentType "application/json" `
-Body $body
Expected result: StatusCode: 200 and content OK.
The Papi documentation may mention paymentReference as the field containing the merchant order reference. In practice, the field received for this reference is merchantPaymentReference, while paymentReference contains the internal Papi UUID. The module takes this behavior into account.
Technical points to watch
Sending email during status changes
When updating the order status by webhook, the module tries to send a notification email to the customer via OrderHistory::addWithemail().
If the PrestaShop Symfony container is not available in the execution context, which may happen in some environments, the module falls back to OrderHistory::add() in order to update the status without email. A warning is recorded in the PrestaShop logs.
On a standard PrestaShop production installation, OrderHistory::addWithemail() should normally work.
Module display at checkout
The module checks the currency at the redirect controller stage, not only when displaying the button. If the store is in euros at the moment of the click, the customer may see the button but be redirected back to the cart with a message explaining that the MGA currency is required.
Payment link validity period
The Papi payment link displayed on the order page remains valid for the duration configured when it was created, by default 60 minutes. After expiration, it remains displayed for information purposes.
Multiple orders on the same cart
PrestaShop creates the order before redirecting to Papi. If the customer abandons payment and tries again from the cart, a new cart and a new order may be created. The old order remains with the Awaiting Papi payment status and can be manually canceled from the back office if necessary.
Module structure
papi_prestashop/
├── papi_prestashop.php
├── logo.png
├── classes/
│ ├── PapiApiClient.php
│ └── PapiApiException.php
├── controllers/
│ └── front/
│ ├── redirect.php
│ ├── notification.php
│ ├── success.php
│ └── failure.php
├── sql/
│ ├── install.sql
│ └── uninstall.sql
└── views/
├── img/
│ └── logo-papi.png
├── css/
│ └── checkout.css
└── templates/
├── hook/
│ ├── payment_option.tpl
│ └── admin_order.tpl
└── front/
├── success.tpl
└── failure.tpl
| File | Role |
|---|---|
papi_prestashop.php | Main module class, extending PaymentModule. |
classes/PapiApiClient.php | HTTP client for the Papi API. |
classes/PapiApiException.php | Business exception used for Papi errors. |
controllers/front/redirect.php | Receives the checkout click, creates the order, and calls Papi. |
controllers/front/notification.php | POST webhook endpoint called by Papi. |
controllers/front/success.php | Return page after successful payment. |
controllers/front/failure.php | Return page after failed payment. |
sql/install.sql | Creation of the ps_papi_transaction table. |
sql/uninstall.sql | Deletion of the ps_papi_transaction table. |
views/templates/hook/payment_option.tpl | Block displayed under the Pay with Papi button. |
views/templates/hook/admin_order.tpl | Papi Transaction panel in the back-office order page. |
ps_papi_transaction table
The module stores Papi transactions in the ps_papi_transaction table.
| Column | Type | Description |
|---|---|---|
id_order | int | PrestaShop order ID. |
id_cart | int | PrestaShop cart ID. |
payment_reference | varchar | PrestaShop order reference, for example YHTFKHOIH. |
notification_token | varchar | Security token returned by Papi when creating the payment link. |
payment_link | varchar | URL of the Papi payment page. |
amount | decimal | Amount in MGA. |
currency | varchar | Currency code, normally MGA. |
status | varchar | Internal status: pending, success, or failed. |
raw_response | text | Full JSON from the latest webhook received. |
date_add | datetime | Creation date. |
date_upd | datetime | Last update date. |
Uninstallation
Uninstallation from Modules > Uninstall performs the following operations:
- Deletion of the Awaiting Papi payment order status.
- Deletion of the module configuration values, such as
PAPI_API_KEYandPAPI_TEST_MODE. - Deletion of the
ps_papi_transactiontable.
Deletion of the ps_papi_transaction table is irreversible. If the store contains ongoing transactions or if the history must be preserved, back up this table before uninstalling the module.