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 ابدأ تشغيل تكامل الدفع عبر الجوال في 4 خطوات بسيطة
Platform Examples أمثلة كود كاملة لأندرويد وiOS وReact Native وFlutter
المتطلبات الأساسية
قبل دمج مدفوعات دودي في تطبيق الهاتف المحمول الخاص بك، تأكد من أنك تمتلك:
حساب مدفوعات دودي : حساب تاجر نشط مع وصول إلى واجهة برمجة التطبيقات
بيانات اعتماد واجهة برمجة التطبيقات : مفتاح واجهة برمجة التطبيقات ومفتاح سرية الويب من لوحة التحكم الخاصة بك
مشروع تطبيق الهاتف المحمول : تطبيق أندرويد أو iOS أو React Native أو Flutter
خادم خلفي : لمعالجة إنشاء جلسة الدفع بشكل آمن
سير عمل التكامل
يتبع تكامل الهاتف المحمول عملية آمنة من 4 خطوات حيث يتولى الخادم الخلفي لديك معالجة استدعاءات واجهة برمجة التطبيقات بينما يدير تطبيق الهاتف المحمول تجربة المستخدم.
Backend: Create Checkout Session
Checkout Session API Docs تعرف على كيفية إنشاء جلسة دفع في الواجهة الخلفية باستخدام Node.js وPython والمزيد. اطلع على أمثلة كاملة ومراجع المعلمات في الوثائق المخصصة لـ Checkout Sessions API .
Security : يجب إنشاء جلسات الدفع على خادم الواجهة الخلفية، وليس داخل تطبيق الجوال. هذا يحمي مفاتيح واجهة برمجة التطبيقات ويضمن التحقق الصحيح.
Mobile: Get Checkout URL
يتصل تطبيق الهاتف المحمول الخاص بك بالخادم الخلفي للحصول على عنوان URL للدفع: 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 ;
}
};
Security : تتواصل تطبيقات الجوال مع الواجهة الخلفية فقط، وليس مباشرةً مع Dodo Payments API.
Mobile: Open Checkout in Browser
افتح عنوان URL الخاص بصفحة الدفع في متصفح داخل التطبيق آمن لمعالجة الدفع.
See platform-specific integration examples اطلع على الكود الكامل وتعليمات الإعداد لمدفوعات Android وiOS وFlutter.
Backend: Handle Payment Completion
عالج اكتمال الدفع عبر Webhooks وروابط الإعادة لتأكيد حالة الدفع.
التكامل الخاص بالمنصة
اختر منصة الهاتف المحمول الخاصة بك أدناه للحصول على أمثلة تنفيذ كاملة:
Android
iOS
React Native
Flutter
تكامل أندرويد تنفيذ علامات التبويب المخصصة في 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)
}
}
}
}
تكامل iOS تنفيذ 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 ) " )
}
}
}
}
معالجة الروابط العميقة قم بتكوين مخططات URL لمعالجة إعادة توجيه إكمال الدفع: 1. إعداد مخططات URL في Info.plist: < key > CFBundleURLTypes </ key >
< array >
< dict >
< key > CFBundleURLName </ key >
< string > myapp </ string >
< key > CFBundleURLSchemes </ key >
< array >
< string > myapp </ string >
</ array >
</ dict >
</ array >
2. معالجة إعادة التوجيه في 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. الاستماع لإكمال الدفع: 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
}
}
تكامل React Native استخدام روابط الدفع (InAppBrowser) افتح صفحة الدفع المستضافة من دودي في متصفح داخل التطبيق. تنفيذ 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 ;
معالجة الروابط العميقة لردود الدفع // 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 ;
تبعيات الحزمة أضف هذه التبعية إلى package.json الخاص بك: {
"dependencies" : {
"react-native-inappbrowser-reborn" : "^6.4.0"
}
}
أوامر التثبيت # Install InAppBrowser
npm install react-native-inappbrowser-reborn
cd ios && pod install
تكوين أندرويد أضف إلى android/app/src/main/AndroidManifest.xml: < activity
android:name = "com.reactnativeinappbrowserreborn.InAppBrowserActivity"
android:theme = "@style/Theme.AppCompat.Dialog"
android:exported = "false" />
تكوين iOS أضف إلى 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 >
استخدم InAppBrowser لتجربة متصفح أصلية. عالج الروابط العميقة لردود الدفع.
بديل: SDK الدفع الأصلي للحصول على تجربة دفع أكثر تكاملاً مع واجهة مستخدم أصلية وخيارات تخصيص كاملة، تقدم مدفوعات دودي SDK لـ React Native. Regional Compliance : أدوات تطوير الدفع داخل التطبيقات لها قيود إقليمية. على iOS ، أدوات الدفع الأصلية قانونية فقط في الاتحاد الأوروبي (بموجب شروط DMA). على Android ، وهي قانونية في أسواق فواتير اختيار المستخدم (UCB). للمناطق الأخرى، استخدم نهج روابط الدفع أعلاه لضمان الامتثال لمتجر التطبيقات ومتجر Play.
React Native SDK Integration Guide دليل كامل لدمج حزمة Dodo SDK لـ React Native مع صفحات الدفع الأصلية، وخيارات التخصيص الكاملة، ومعالجة الدفع المباشرة. يتضمن تعليمات الإعداد والتنفيذ والاختبار.
تكامل 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
}
}
}
استخدم WebView لروابط الدفع. عالج عنوان URL لإعادة التوجيه لاكتشاف اكتمال الدفع.
أفضل الممارسات
الأمان : لا تخزن مفاتيح واجهة برمجة التطبيقات في شيفرة التطبيق الخاصة بك. استخدم التخزين الآمن وتثبيت SSL.
تجربة المستخدم : عرض مؤشرات التحميل، التعامل مع الأخطاء بشكل جيد، وتقديم رسائل واضحة.
الاختبار : استخدم بطاقات اختبار، محاكاة أخطاء الشبكة، واختبر على أجهزة متنوعة.
استكشاف الأخطاء
المشكلات الشائعة
WebView لا يفتح رابط الدفع : تأكد من أن رابط الدفع صالح ويستخدم HTTPS.
لم يتم استلام رد الاتصال : تحقق من عنوان URL الخاص بك وإعدادات الويب هوك.
أخطاء مفتاح واجهة برمجة التطبيقات : تحقق من أن مفتاح واجهة برمجة التطبيقات الخاص بك صحيح وله الأذونات اللازمة.
موارد إضافية