Xano
Encaissez depuis un backend Xano : deux endpoints, zéro dépendance externe.
À savoir avant de commencer
- L'offre gratuite de Xano suffit : appels HTTP sortants, endpoints publics et variables d'environnement y sont disponibles.
- Xano sert souvent de backend à Bubble, FlutterFlow, WeWeb, Glide ou Softr : cette intégration donne l'encaissement Mobupay à toutes ces applications.
- Modèle « page hébergée » : votre backend crée un lien de paiement, le client paie chez Mobupay, votre backend reçoit un webhook signé. Aucune donnée carte ne transite par Xano.
- Chaque endpoint Xano est éditable en XanoScript (vue code de l'endpoint) : les scripts complets, validés de bout en bout, sont fournis ci-dessous.
1. Variables d'environnement
- 1Récupérez votre clé API (
sk_test_…pour commencer,sk_live_…en production) dans l'espace marchand, rubrique Développeurs. - 2Récupérez votre secret webhook de compte (
whsec_…) via l'API (voir ci-dessous). Attention : c'est ce secret qui signe les livraisons vers votrenotificationUrl, pas le secret d'un endpoint webhook créé dans l'espace marchand. - 3Dans Xano, menu Keys & Variables : créez
MOBUPAY_API_KEYetMOBUPAY_WEBHOOK_SECRET.
curl -s https://api.mobupay.nc/api/v1/webhooks/signing-secret \
-H "Authorization: Bearer sk_test_VOTRE_CLE"
# -> { "webhookSecret": "whsec_..." }2. Endpoint de réception du webhook (à créer en premier)
Menu APIs : créez un groupe (par exemple mobupay), puis un endpoint POST /mobupay-webhook, et collez ce XanoScript. Il vérifie la signature avant tout traitement (403 sinon), rejette les livraisons de plus de 5 minutes (anti-rejeu), puis route l'événement. Copiez ensuite son URL publique (forme https://…xano.io/api:XXXX/mobupay-webhook) : elle sert à l'étape 3.
query "mobupay-webhook" verb=POST {
api_group = "mobupay"
input {
}
stack {
// encoding "none" obligatoire : la signature porte sur le corps brut exact
util.get_raw_input {
encoding = "none"
exclude_middleware = false
} as $raw_body
var $ts { value = $env.$http_headers|get:"X-Mobupay-Timestamp" }
var $sig { value = $env.$http_headers|get:"X-Mobupay-Signature-V2" }
var $signed { value = $ts ~ "." ~ $raw_body }
var $expected { value = $signed|hmac_sha256:$env.MOBUPAY_WEBHOOK_SECRET }
precondition ($expected == $sig) {
error_type = "accessdenied"
error = "Signature Mobupay V2 invalide"
}
var $age_s { value = (("now"|to_timestamp) / 1000) - ($ts|to_int) }
precondition ($age_s < 300 && $age_s > -300) {
error_type = "accessdenied"
error = "Webhook Mobupay expire (anti-rejeu 5 min)"
}
var $event { value = $raw_body|json_decode }
// payment.authorized OU payment.captured = paye ; rapprochez via externalId.
// C'est ici que vous ecrivez en base (traitement idempotent) :
// payment.failed / .cancelled / .expired -> echec ;
// payment.refunded / .partially_refunded -> remboursee.
var $paid {
value = ($event.type == "payment.authorized") || ($event.type == "payment.captured")
}
}
response = {received: true, type: $event.type, externalId: $event.data.externalId, paid: $paid}
}3. Endpoint de création du lien de paiement
Même groupe : créez un endpoint POST /pay et collez ce script. Remplacez redirectUrl (votre page de remerciement) et notificationUrl (l'URL copiée à l'étape 2). Le montant est en unité mineure (centimes EUR, ou unité XPF).
query pay verb=POST {
api_group = "mobupay"
input {
text reference? filters=trim
int amount?
text currency? filters=trim
}
stack {
api.request {
url = "https://api.mobupay.nc/api/v1/payments/links"
method = "POST"
params = {order: {reference: $input.reference, amount: $input.amount, currency: $input.currency}, redirectUrl: "https://VOTRE-SITE/merci", notificationUrl: "https://VOTRE-INSTANCE.xano.io/api:XXXX/mobupay-webhook", externalId: $input.reference}
headers = []|push:"Content-Type: application/json"|push:"Authorization: Bearer " ~ $env.MOBUPAY_API_KEY|push:"Idempotency-Key: " ~ $input.reference
} as $mobupay_api
}
response = $mobupay_api.response.result
}La réponse contient linkUrl : votre application l'ouvre ou l'affiche, le client paie sur la page hébergée Mobupay. Rejouer la création avec la même référence renvoie le même lien (idempotence via l'en-tête Idempotency-Key) : pas de doublon sur un nouvel essai réseau.
Pièges connus (si vous montez la pile à la main)
- Les champs
headersetparamsde l'étape External API Request doivent être saisis en mode expression. En mode texte, les variables ne sont pas évaluées et la requête part enx-www-form-urlencoded(erreur 415 côté Mobupay). Get All Raw Input: gardezencoding = "none". Avec"json", le corps est parsé puis re-sérialisé et la signature ne correspondra jamais. Ne re-sérialisez jamais le JSON avant vérification.$env.$http_headersest un objet dont les clés contiennent des tirets : lisez les en-têtes avec le filtreget, pas en notation pointée.- Le filtre
hmac_sha256renvoie l'empreinte en hexadécimal, directement comparable àX-Mobupay-Signature-V2. - Le flux carte réel émet
payment.authorized; le bac à sable émetpayment.captured. Routez les deux comme « payé ».
Tester
Avec une clé sk_test_…, le parcours complet se rejoue sans argent réel : créez un lien via votre endpoint /pay, payez avec une carte de test, et observez la livraison signée dans le Request History de votre endpoint webhook. Voir aussi les guides Webhooks et No-code & automatisation (pattern général, Make, Zapier, n8n).