DépannageAndroid · iOS · WebView · APK

Mon site marche, mon app ne marche pas

Le même appel, les mêmes fonctions, et pourtant l'intégration passe sur le site et échoue dans l'application. Ce n'est pas un bug : c'est que l'appel n'est pas au bon endroit. Voici pourquoi, et le flux correct.

Le symptôme

Vous avez intégré MonCashConnect sur votre site et tout fonctionne. Vous reprenez le même code dans votre application Android (APK) ou dans une WebView, et l'appel à pay-create échoue, souvent sans message clair. Vous avez mis l'adresse de votre site dans les domaines autorisés, et vous cherchez comment y ajouter l'application.

Cette page existe parce que la réponse n'est pas « ajoutez l'app à la liste ».

Pourquoi ça bloque

La liste des domaines autorisés de votre projet est une règle de navigateur, le CORS. Le navigateur envoie l'origine de la page (par exemple https://monsite.com) ; si elle figure dans votre liste, la réponse porte l'en-tête qui autorise votre code à la lire. Sinon, le navigateur bloque la lecture.

Une application native n'a pas d'origine web à présenter. Le contrôle ne peut donc ni réussir ni être configuré pour elle : il n'y a rien à ajouter dans la liste.

Détail qui trompe beaucoup de monde : la requête de vérification (préflight OPTIONS) réussit depuis n'importe quelle origine. C'est la vraie requête qui est bloquée, et le navigateur interdit à votre code de lire la raison. D'où l'erreur réseau générique, sans explication.

Le vrai risque : la clé secrète

Si votre application appelle pay-create elle-même, c'est que votre clé sk_proj_… est à l'intérieur de l'APK. Un APK est une archive : n'importe qui peut la décompresser et lire la clé, puis créer des paiements sur votre compte. Le problème de CORS vous a en réalité protégé d'une erreur plus grave.

La clé secrète ne doit exister que sur un serveur que vous contrôlez. Cela vaut aussi pour une clé sandbox : même architecture en test et en production.

Le flux correct

  App mobile                Votre serveur              MonCashConnect
     │                           │                           │
     │  POST /api/create-payment │                           │
     ├──────────────────────────>│                           │
     │                           │  POST /v1/pay-create      │
     │                           │  Authorization: sk_proj_  │
     │                           ├──────────────────────────>│
     │                           │<── paymentUrl, reference ─┤
     │<──────── paymentUrl ──────┤                           │
     │                           │                           │
     │  ouvre le paymentUrl (navigateur ou WebView)          │
     │  le client paie sur MonCash                           │
     │  retour vers votre returnUrl (deep link possible)     │
     │                           │<──── webhook signé ───────┤
     │  lit le statut auprès de votre serveur                │

Côté serveur, l'appel est exactement celui de la documentation :

curl -X POST https://api.moncashconnect.com/v1/pay-create \
  -H "Authorization: Bearer sk_proj_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
        "amount": 500,
        "referenceId": "commande-1043",
        "returnUrl": "https://monsite.com/merci"
      }'

Pour le code complet côté application, suivez le guide de votre plateforme : React Native ou Flutter. Les deux montrent l'ouverture du paymentUrl, le retour par deep link et la vérification du webhook.

Cas particulier : une WebView qui charge votre site

Si votre APK n'est qu'une WebView autour de votre site déjà en ligne, la règle ne change pas : l'appel doit rester côté serveur. En revanche deux points méritent attention.

  • L'origine envoyée par la WebView peut différer de celle de votre site (elle peut être absente, ou file:// si vous chargez des fichiers locaux). Si votre page appelle votre propre backend, cela ne vous concerne plus : c'est votre serveur qui parle à MonCashConnect.
  • Le retour de paiement doit rester dans l'application. Donnez un returnUrl que votre WebView sait intercepter, ou une page de votre site qui referme proprement le parcours. Sans cela le client termine son paiement dans un navigateur externe et ne revient jamais dans l'app.

Checklist

Aucune clé sk_proj_ ni sk_test_proj_ dans le code de l'application

L'application appelle votre backend, jamais api.moncashconnect.com directement

Votre backend détient la clé secrète et appelle pay-create

Le paymentUrl est renvoyé à l'application, qui l'ouvre

Le returnUrl ramène le client dans l'application (deep link ou page de retour)

La confirmation vient du webhook signé, ou de pay-status appelé par votre serveur

Les domaines autorisés ne contiennent que vos adresses web réelles

FAQ

Je peux ajouter mon application dans les domaines autorisés ?+
Non, et ce n'est pas un manque : la liste des domaines autorisés est une règle de navigateur (CORS), qui s'applique à une page web servie depuis une adresse. Une application Android ou iOS n'a pas d'adresse web à présenter. Il n'y a donc rien à y inscrire, c'est l'endroit de l'appel qui doit changer.
Pourquoi ça marche sur mon site et pas dans l'APK, avec le même code ?+
Sur votre site, le navigateur envoie l'origine de votre site, qui figure dans votre liste de domaines autorisés, donc la réponse est lisible. Depuis l'application, l'origine est absente ou différente, la réponse ne porte pas l'en-tête d'autorisation et l'appel échoue. Le code est identique, le contexte ne l'est pas.
L'erreur ne dit rien de précis, c'est normal ?+
Oui, et c'est trompeur. La requête de vérification (préflight OPTIONS) réussit, c'est la vraie requête qui est bloquée, et le navigateur interdit à votre code de lire la raison. Vous ne voyez donc qu'une erreur réseau générique.
Et si je n'ai pas de serveur du tout ?+
Alors ce flux ne vous convient pas tel quel. Vous pouvez encaisser sans serveur avec une facture ou un lien de paiement depuis le tableau de bord, mais ces liens créent un encaissement simple : ils ne portent pas votre propre referenceId par commande ni un webhook par commande. Pour une application qui vend, il vous faut un serveur, même minimal.
Le sandbox change quelque chose à ce problème ?+
Non. Une clé sk_test_proj_ dans un APK est aussi extractible qu'une clé live, et la règle des domaines s'applique pareil. Testez en sandbox, mais avec la même architecture qu'en production.