Documentation Index Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
Use this file to discover all available pages before exploring further.
Quick Start Lancez votre intégration de paiement mobile en 4 étapes simples
Platform Examples Exemples de code complets pour Android, iOS, React Native et Flutter
Prérequis
Avant d’intégrer Dodo Payments dans votre application mobile, assurez-vous d’avoir :
Compte Dodo Payments : Compte marchand actif avec accès API
Identifiants API : Clé API et clé secrète de webhook depuis votre tableau de bord
Projet d’application mobile : Application Android, iOS, React Native ou Flutter
Serveur backend : Pour gérer en toute sécurité la création de sessions de paiement
Flux d’intégration
L’intégration mobile suit un processus sécurisé en 4 étapes où votre backend gère les appels API et votre application mobile gère l’expérience utilisateur.
Backend: Create Checkout Session
Checkout Session API Docs Découvrez comment créer une session de paiement dans votre backend en utilisant Node.js, Python et plus encore. Consultez des exemples complets et les références des paramètres dans la documentation dédiée Checkout Sessions API .
Sécurité : les sessions de paiement doivent être créées sur votre serveur backend, jamais dans l’application mobile. Cela protège vos clés API et assure une validation correcte.
Mobile: Get Checkout URL
Votre application mobile appelle votre backend pour obtenir l’URL de paiement : func getCheckoutURL ( productId : String , customerEmail : String , customerName : String ) async throws -> String {
let url = URL ( string : "https://your-backend.com/api/create-checkout-session" ) !
var request = URLRequest ( url : url)
request. httpMethod = "POST"
request. setValue ( "application/json" , forHTTPHeaderField : "Content-Type" )
let requestData: [ String : Any ] = [
"productId" : productId,
"customerEmail" : customerEmail,
"customerName" : customerName
]
request. httpBody = try JSONSerialization. data ( withJSONObject : requestData)
let (data, _ ) = try await URLSession. shared . data ( for : request)
let response = try JSONDecoder (). decode (CheckoutResponse. self , from : data)
return response. checkout_url
}
suspend fun getCheckoutURL (productId: String , customerEmail: String , customerName: String ): String {
val client = OkHttpClient ()
val requestBody = JSONObject (). apply {
put ( "productId" , productId)
put ( "customerEmail" , customerEmail)
put ( "customerName" , customerName)
}. toString (). toRequestBody ( "application/json" . toMediaType ())
val request = Request. Builder ()
. url ( "https://your-backend.com/api/create-checkout-session" )
. post (requestBody)
. build ()
val response = client. newCall (request). execute ()
val responseBody = response.body?. string ()
val jsonResponse = JSONObject (responseBody ?: "" )
return jsonResponse. getString ( "checkout_url" )
}
const getCheckoutURL = async ( productId , customerEmail , customerName ) => {
try {
const response = await fetch ( 'https://your-backend.com/api/create-checkout-session' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
productId ,
customerEmail ,
customerName
})
});
const data = await response . json ();
return data . checkout_url ;
} catch ( error ) {
console . error ( 'Failed to get checkout URL:' , error );
throw error ;
}
};
Sécurité : les applications mobiles ne communiquent qu’avec votre backend, jamais directement avec l’API Dodo Payments.
Mobile: Open Checkout in Browser
Ouvrez l’URL de paiement dans un navigateur intégré sécurisé pour le traitement.
See platform-specific integration examples Consultez le code complet et les instructions d’installation pour les paiements mobiles Android, iOS et Flutter.
Backend: Handle Payment Completion
Traitez la finalisation du paiement via des webhooks et des URL de redirection pour confirmer le statut du paiement.
Choisissez votre plateforme mobile ci-dessous pour des exemples d’implémentation complets :
Android
iOS
React Native
Flutter
Intégration Android Mise en œuvre des onglets personnalisés Chrome // Add Chrome Custom Tabs dependency to build.gradle
implementation 'androidx.browser:browser:1.5.0'
// In your Activity
class PaymentActivity : AppCompatActivity () {
private var customTabsSession: CustomTabsSession ? = null
private var customTabsClient: CustomTabsClient ? = null
private var customTabsServiceConnection: CustomTabsServiceConnection ? = null
override fun onCreate (savedInstanceState: Bundle ?) {
super . onCreate (savedInstanceState)
// Initialize Custom Tabs
customTabsServiceConnection = object : CustomTabsServiceConnection () {
override fun onCustomTabsServiceConnected (name: ComponentName , client: CustomTabsClient ) {
customTabsClient = client
customTabsClient?. warmup ( 0L )
customTabsSession = customTabsClient?. newSession ( object : CustomTabsCallback () {
override fun onNavigationEvent (navigationEvent: Int , extras: Bundle ?) {
// Handle navigation events
}
})
}
override fun onServiceDisconnected (name: ComponentName ) {
customTabsClient = null
}
}
CustomTabsClient. bindCustomTabsService (
this ,
"com.android.chrome" ,
customTabsServiceConnection !!
)
// Get checkout URL from backend and launch
lifecycleScope. launch {
try {
val checkoutURL = getCheckoutURL ( "prod_123" , "customer@example.com" , "Customer Name" )
val customTabsIntent = CustomTabsIntent. Builder (customTabsSession)
. build ()
customTabsIntent. launchUrl ( this@PaymentActivity , Uri. parse (checkoutURL))
} catch (e: Exception ) {
// Handle error
Log. e ( "PaymentActivity" , "Failed to get checkout URL" , e)
}
}
}
}
Intégration iOS Mise en œuvre de SFSafariViewController import SafariServices
class PaymentViewController : UIViewController {
override func viewDidLoad () {
super . viewDidLoad ()
Task {
do {
let checkoutURL = try await getCheckoutURL (
productId : "prod_123" ,
customerEmail : "customer@example.com" ,
customerName : "Customer Name"
)
if let url = URL ( string : checkoutURL) {
let safariVC = SFSafariViewController ( url : url)
present (safariVC, animated : true , completion : nil )
}
} catch {
// Handle error
print ( "Failed to get checkout URL: \( error ) " )
}
}
}
}
Gestion des liens profonds Configurez les schémas d’URL pour gérer les redirections de finalisation de paiement : 1. Configurez les schémas d’URL dans Info.plist : < key > CFBundleURLTypes </ key >
< array >
< dict >
< key > CFBundleURLName </ key >
< string > myapp </ string >
< key > CFBundleURLSchemes </ key >
< array >
< string > myapp </ string >
</ array >
</ dict >
</ array >
2. Gérez les redirections dans AppDelegate : func application ( _ app : UIApplication, open url : URL, options : [UIApplication.OpenURLOptionsKey : Any ] = [ : ]) -> Bool {
if url.scheme == "myapp" && url.host == "payment-status" {
NotificationCenter. default . post ( name : . paymentCompleted , object : url)
return true
}
return false
}
3. Écoutez la finalisation du paiement : NotificationCenter. default . addObserver ( self , selector : #selector ( handlePaymentCompletion (_:)), name : . paymentCompleted , object : nil )
@objc func handlePaymentCompletion ( _ notification : Notification) {
if let url = notification.object as? URL {
safariVC ? . dismiss ( animated : true )
// Parse payment status from URL parameters
let components = URLComponents ( url : url, resolvingAgainstBaseURL : false )
let paymentId = components ? . queryItems ? . first ( where : { $0 . name == "payment_id" }) ? . value
let status = components ? . queryItems ? . first ( where : { $0 . name == "status" }) ? . value
// Handle payment completion
}
}
Intégration React Native Utilisation des liens de paiement (InAppBrowser) Ouvrez la page de paiement hébergée par Dodo dans un navigateur intégré. Mise en œuvre de InAppBrowser import React from 'react' ;
import { View , TouchableOpacity , Text , Alert } from 'react-native' ;
import { InAppBrowser } from 'react-native-inappbrowser-reborn' ;
const PaymentButton = ({ productId , onPaymentComplete }) => {
const openPaymentLink = async () => {
try {
// Get checkout URL from backend
const checkoutURL = await getCheckoutURL (
productId ,
'customer@example.com' ,
'Customer Name'
);
const result = await InAppBrowser . open ( checkoutURL , {
// iOS options
dismissButtonStyle: 'cancel' ,
preferredBarTintColor: '#453AA4' ,
preferredControlTintColor: 'white' ,
readerMode: false ,
animated: true ,
modalPresentationStyle: 'fullScreen' ,
modalTransitionStyle: 'coverVertical' ,
modalEnabled: true ,
enableBarCollapsing: false ,
// Android options
showTitle: true ,
toolbarColor: '#453AA4' ,
secondaryToolbarColor: 'black' ,
navigationBarColor: 'black' ,
navigationBarDividerColor: 'white' ,
enableUrlBarHiding: true ,
enableDefaultShare: true ,
forceCloseOnRedirection: false ,
animations: {
startEnter: 'slide_in_right' ,
startExit: 'slide_out_left' ,
endEnter: 'slide_in_left' ,
endExit: 'slide_out_right'
},
headers: {
'my-custom-header' : 'my custom header value'
}
});
// Handle payment completion based on result
if ( result . type === 'dismiss' ) {
// User dismissed the browser
console . log ( 'Payment browser dismissed' );
}
} catch ( error ) {
Alert . alert ( 'Error' , 'Failed to open payment page' );
console . error ( 'InAppBrowser error:' , error );
}
};
return (
< View style = { { padding: 20 } } >
< TouchableOpacity
style = { {
backgroundColor: '#007AFF' ,
padding: 15 ,
borderRadius: 8 ,
alignItems: 'center'
} }
onPress = { openPaymentLink }
>
< Text style = { { color: 'white' , fontSize: 16 , fontWeight: 'bold' } } >
Pay Now
</ Text >
</ TouchableOpacity >
</ View >
);
};
export default PaymentButton ;
Gestion des liens profonds pour les rappels de paiement // App.js or your main component
import React , { useEffect } from 'react' ;
import { Linking } from 'react-native' ;
const App = () => {
useEffect (() => {
// Handle deep links when app is already running
const handleDeepLink = ( url ) => {
if ( url . includes ( 'payment-status' )) {
const urlParams = new URLSearchParams ( url . split ( '?' )[ 1 ]);
const paymentId = urlParams . get ( 'payment_id' );
const status = urlParams . get ( 'status' );
// Handle payment completion
handlePaymentCallback ( paymentId , status );
}
};
// Listen for deep links
const subscription = Linking . addEventListener ( 'url' , ({ url }) => {
handleDeepLink ( url );
});
// Handle deep link if app was opened from a link
Linking . getInitialURL (). then (( url ) => {
if ( url ) {
handleDeepLink ( url );
}
});
return () => subscription ?. remove ();
}, []);
const handlePaymentCallback = ( paymentId , status ) => {
if ( status === 'succeeded' ) {
// Navigate to success screen or show success message
console . log ( 'Payment successful:' , paymentId );
} else {
// Handle payment failure
console . log ( 'Payment failed:' , paymentId );
}
};
// Your app components...
};
export default App ;
Dépendances de package Add this dependency to your package.json : {
"dependencies" : {
"react-native-inappbrowser-reborn" : "^6.4.0"
}
}
Commandes d’installation # Install InAppBrowser
npm install react-native-inappbrowser-reborn
cd ios && pod install
Configuration Android Add to android/app/src/main/AndroidManifest.xml : < activity
android:name = "com.reactnativeinappbrowserreborn.InAppBrowserActivity"
android:theme = "@style/Theme.AppCompat.Dialog"
android:exported = "false" />
Configuration iOS Add to ios/YourApp/Info.plist : < key > CFBundleURLTypes </ key >
< array >
< dict >
< key > CFBundleURLName </ key >
< string > myapp </ string >
< key > CFBundleURLSchemes </ key >
< array >
< string > myapp </ string >
</ array >
</ dict >
</ array >
Utilisez InAppBrowser pour une expérience de navigateur native. Gérez les liens profonds pour les retours de paiement.
Alternative : SDK de paiement natif Pour une expérience de paiement plus intégrée avec une interface utilisateur native et une personnalisation complète, Dodo Payments propose un SDK React Native. Conformité régionale : les SDK de paiement intégrés sont soumis à des restrictions régionales. Sur iOS , les SDK de paiement natifs ne sont légaux que dans l’UE (conformément aux conditions DMA). Sur Android , ils sont légaux dans les marchés User Choice Billing (UCB). Pour les autres régions, utilisez l’approche des liens de paiement ci-dessus afin de garantir la conformité avec l’App Store et le Play Store.
React Native SDK Integration Guide Guide complet pour intégrer le SDK React Native de Dodo avec des feuilles de paiement natives, des options de personnalisation complètes et la gestion directe des paiements. Comprend les instructions d’installation, de mise en œuvre et de test.
Intégration Flutter import 'package:flutter/material.dart' ;
import 'package:webview_flutter/webview_flutter.dart' ;
import 'package:http/http.dart' as http;
import 'dart:convert' ;
Future < String > getCheckoutURL ( String productId, String customerEmail, String customerName) async {
final response = await http. post (
Uri . parse ( 'https://your-backend.com/api/create-checkout-session' ),
headers : { 'Content-Type' : 'application/json' },
body : json. encode ({
'productId' : productId,
'customerEmail' : customerEmail,
'customerName' : customerName,
}),
);
if (response.statusCode == 200 ) {
final data = json. decode (response.body);
return data[ 'checkout_url' ];
} else {
throw Exception ( 'Failed to get checkout URL: ${ response . statusCode } ' );
}
}
class PaymentScreen extends StatefulWidget {
@override
_PaymentScreenState createState () => _PaymentScreenState ();
}
class _PaymentScreenState extends State < PaymentScreen > {
late WebViewController _controller;
String ? checkoutURL;
@override
void initState () {
super . initState ();
_getCheckoutURL ();
}
Future < void > _getCheckoutURL () async {
try {
final url = await getCheckoutURL ( 'prod_123' , 'customer@example.com' , 'Customer Name' );
setState (() {
checkoutURL = url;
});
} catch (e) {
// Handle error
print ( 'Failed to get checkout URL: $ e ' );
}
}
@override
Widget build ( BuildContext context) {
return Scaffold (
appBar : AppBar (title : Text ( 'Payment' )),
body : checkoutURL == null
? Center (child : CircularProgressIndicator ())
: WebView (
initialUrl : checkoutURL,
javascriptMode : JavascriptMode .unrestricted,
onWebViewCreated : ( WebViewController webViewController) {
_controller = webViewController;
},
navigationDelegate : ( NavigationRequest request) {
if (request.url. contains ( 'payment_id' ) && request.url. contains ( 'status' )) {
// Handle payment completion
final uri = Uri . parse (request.url);
final paymentId = uri.queryParameters[ 'payment_id' ];
final status = uri.queryParameters[ 'status' ];
handlePaymentCompletion (paymentId, status);
return NavigationDecision .prevent;
}
return NavigationDecision .navigate;
},
),
);
}
void handlePaymentCompletion ( String ? paymentId, String ? status) {
if (status == 'succeeded' ) {
// Payment successful
} else {
// Payment failed
}
}
}
Utilisez WebView pour les liens de paiement. Gérez l’URL de redirection pour détecter la finalisation du paiement.
Meilleures pratiques
Sécurité : Ne stockez jamais les clés API dans le code de votre application. Utilisez un stockage sécurisé et le pinning SSL.
Expérience utilisateur : Affichez des indicateurs de chargement, gérez les erreurs avec soin et fournissez des messages clairs.
Tests : Utilisez des cartes de test, simulez des erreurs réseau et testez sur divers appareils.
Dépannage
Problèmes courants
WebView n’ouvre pas le lien de paiement : Assurez-vous que le lien de paiement est valide et utilise HTTPS.
Rappel non reçu : Vérifiez votre URL de retour et la configuration du webhook.
Erreurs de clé API : Vérifiez que votre clé API est correcte et dispose des autorisations nécessaires.
Ressources supplémentaires