> ## 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.

# دليل تكامل الهاتف المحمول

> دليل موحد لتكامل مدفوعات دودي في تطبيقات الهاتف المحمول على أندرويد وiOS وReact Native وFlutter.

<CardGroup cols={2}>
  <Card title="Quick Start" icon="rocket" href="#integration-workflow">
    ابدأ تشغيل تكامل الدفع عبر الجوال في 4 خطوات بسيطة
  </Card>

  <Card title="Platform Examples" icon="code" href="#platform-specific-integration">
    أمثلة كود كاملة لأندرويد وiOS وReact Native وFlutter
  </Card>
</CardGroup>

## المتطلبات الأساسية

قبل دمج مدفوعات دودي في تطبيق الهاتف المحمول الخاص بك، تأكد من أنك تمتلك:

* **حساب مدفوعات دودي**: حساب تاجر نشط مع وصول إلى واجهة برمجة التطبيقات
* **بيانات اعتماد واجهة برمجة التطبيقات**: مفتاح واجهة برمجة التطبيقات ومفتاح سرية الويب من لوحة التحكم الخاصة بك
* **مشروع تطبيق الهاتف المحمول**: تطبيق أندرويد أو iOS أو React Native أو Flutter
* **خادم خلفي**: لمعالجة إنشاء جلسة الدفع بشكل آمن

## سير عمل التكامل

يتبع تكامل الهاتف المحمول عملية آمنة من 4 خطوات حيث يتولى الخادم الخلفي لديك معالجة استدعاءات واجهة برمجة التطبيقات بينما يدير تطبيق الهاتف المحمول تجربة المستخدم.

<Steps>
  <Step title="Backend: Create Checkout Session">
    <Card title="Checkout Session API Docs" icon="book" href="/developer-resources/checkout-session">
      تعرف على كيفية إنشاء جلسة دفع في الواجهة الخلفية باستخدام Node.js وPython والمزيد. اطلع على أمثلة كاملة ومراجع المعلمات في الوثائق المخصصة لـ <strong>Checkout Sessions API</strong>.
    </Card>

    <Note>
      **Security**: يجب إنشاء جلسات الدفع على خادم الواجهة الخلفية، وليس داخل تطبيق الجوال. هذا يحمي مفاتيح واجهة برمجة التطبيقات ويضمن التحقق الصحيح.
    </Note>
  </Step>

  <Step title="Mobile: Get Checkout URL">
    يتصل تطبيق الهاتف المحمول الخاص بك بالخادم الخلفي للحصول على عنوان URL للدفع:

    <Tabs>
      <Tab title="iOS (Swift)">
        ```swift theme={null}
        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
        }
        ```
      </Tab>

      <Tab title="Android (Kotlin)">
        ```kotlin theme={null}
        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")
        }
        ```
      </Tab>

      <Tab title="React Native (JavaScript)">
        ```javascript theme={null}
        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;
          }
        };
        ```
      </Tab>
    </Tabs>

    <Note>
      **Security**: تتواصل تطبيقات الجوال مع الواجهة الخلفية فقط، وليس مباشرةً مع Dodo Payments API.
    </Note>
  </Step>

  <Step title="Mobile: Open Checkout in Browser">
    افتح عنوان URL الخاص بصفحة الدفع في متصفح داخل التطبيق آمن لمعالجة الدفع.

    <Card title="See platform-specific integration examples" icon="box" href="#platform-specific-integration">
      اطلع على الكود الكامل وتعليمات الإعداد لمدفوعات Android وiOS وFlutter.
    </Card>
  </Step>

  <Step title="Backend: Handle Payment Completion">
    عالج اكتمال الدفع عبر Webhooks وروابط الإعادة لتأكيد حالة الدفع.
  </Step>
</Steps>

## التكامل الخاص بالمنصة

اختر منصة الهاتف المحمول الخاصة بك أدناه للحصول على أمثلة تنفيذ كاملة:

<Tabs>
  <Tab title="Android">
    ### تكامل أندرويد

    #### تنفيذ علامات التبويب المخصصة في Chrome

    ```kotlin theme={null}
    // 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)
                }
            }
        }
    }
    ```
  </Tab>

  <Tab title="iOS">
    ### تكامل iOS

    #### تنفيذ SFSafariViewController

    ```swift theme={null}
    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:**

    ```xml theme={null}
    <key>CFBundleURLTypes</key>
    <array>
      <dict>
        <key>CFBundleURLName</key>
        <string>myapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
          <string>myapp</string>
        </array>
      </dict>
    </array>
    ```

    **2. معالجة إعادة التوجيه في AppDelegate:**

    ```swift theme={null}
    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. الاستماع لإكمال الدفع:**

    ```swift theme={null}
    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
        }
    }
    ```
  </Tab>

  <Tab title="React Native">
    ### تكامل React Native

    #### استخدام روابط الدفع (InAppBrowser)

    افتح صفحة الدفع المستضافة من دودي في متصفح داخل التطبيق.

    ##### تنفيذ InAppBrowser

    ```javascript theme={null}
    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;
    ```

    #### معالجة الروابط العميقة لردود الدفع

    ```javascript theme={null}
    // 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` الخاص بك:

    ```json theme={null}
    {
      "dependencies": {
        "react-native-inappbrowser-reborn": "^6.4.0"
      }
    }
    ```

    #### أوامر التثبيت

    ```bash theme={null}
    # Install InAppBrowser
    npm install react-native-inappbrowser-reborn
    cd ios && pod install
    ```

    #### تكوين أندرويد

    أضف إلى `android/app/src/main/AndroidManifest.xml`:

    ```xml theme={null}
    <activity
      android:name="com.reactnativeinappbrowserreborn.InAppBrowserActivity"
      android:theme="@style/Theme.AppCompat.Dialog"
      android:exported="false" />
    ```

    #### تكوين iOS

    أضف إلى `ios/YourApp/Info.plist`:

    ```xml theme={null}
    <key>CFBundleURLTypes</key>
    <array>
      <dict>
        <key>CFBundleURLName</key>
        <string>myapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
          <string>myapp</string>
        </array>
      </dict>
    </array>
    ```

    <Tip>
      استخدم InAppBrowser لتجربة متصفح أصلية. عالج الروابط العميقة لردود الدفع.
    </Tip>

    ***

    #### بديل: SDK الدفع الأصلي

    للحصول على تجربة دفع أكثر تكاملاً مع واجهة مستخدم أصلية وخيارات تخصيص كاملة، تقدم مدفوعات دودي SDK لـ React Native.

    <Warning>
      **Regional Compliance**: أدوات تطوير الدفع داخل التطبيقات لها قيود إقليمية. على **iOS**، أدوات الدفع الأصلية قانونية فقط في **الاتحاد الأوروبي** (بموجب شروط DMA). على **Android**، وهي قانونية في أسواق فواتير اختيار المستخدم (UCB). للمناطق الأخرى، استخدم نهج روابط الدفع أعلاه لضمان الامتثال لمتجر التطبيقات ومتجر Play.
    </Warning>

    <Card title="React Native SDK Integration Guide" icon="mobile-screen" href="/developer-resources/react-native-integration">
      دليل كامل لدمج حزمة Dodo SDK لـ React Native مع صفحات الدفع الأصلية، وخيارات التخصيص الكاملة، ومعالجة الدفع المباشرة. يتضمن تعليمات الإعداد والتنفيذ والاختبار.
    </Card>

    <Info>
      راجع دليل تجاوز رسوم متجر التطبيقات [App Store Fee Bypass Guide](/features/bypassing-app-store-fees) لفهم متطلبات الامتثال الإقليمي لتكاملات الدفع داخل التطبيق.
    </Info>
  </Tab>

  <Tab title="Flutter">
    ### تكامل Flutter

    ```dart theme={null}
    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
        }
      }
    }
    ```

    <Tip>
      استخدم WebView لروابط الدفع. عالج عنوان URL لإعادة التوجيه لاكتشاف اكتمال الدفع.
    </Tip>
  </Tab>
</Tabs>

## أفضل الممارسات

* **الأمان**: لا تخزن مفاتيح واجهة برمجة التطبيقات في شيفرة التطبيق الخاصة بك. استخدم التخزين الآمن وتثبيت SSL.
* **تجربة المستخدم**: عرض مؤشرات التحميل، التعامل مع الأخطاء بشكل جيد، وتقديم رسائل واضحة.
* **الاختبار**: استخدم بطاقات اختبار، محاكاة أخطاء الشبكة، واختبر على أجهزة متنوعة.

## استكشاف الأخطاء

### المشكلات الشائعة

* **WebView لا يفتح رابط الدفع**: تأكد من أن رابط الدفع صالح ويستخدم HTTPS.
* **لم يتم استلام رد الاتصال**: تحقق من عنوان URL الخاص بك وإعدادات الويب هوك.
* **أخطاء مفتاح واجهة برمجة التطبيقات**: تحقق من أن مفتاح واجهة برمجة التطبيقات الخاص بك صحيح وله الأذونات اللازمة.

## موارد إضافية

* [دليل دمج الدفع](/developer-resources/integration-guide)
* [توثيق Webhook](/developer-resources/webhooks/intents/webhook-events-guide)
* [عملية الاختبار](/miscellaneous/testing-process)
* [الأسئلة الشائعة التقنية](/miscellaneous/faq)

<Check>
  للاستفسارات أو الدعم، اتصل بـ <a href="mailto:support@dodopayments.com">[support@dodopayments.com](mailto:support@dodopayments.com)</a>.
</Check>
