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

# Flutter

> Flutter से system browser tab में Dodo Payments का hosted checkout खोलें और एक ही call में typed result प्राप्त करें।

<Info>
  यह आधिकारिक Dodo Payments Flutter package है (`dodopayments_checkout`
  pub.dev पर)। एक अलग, community-built package भी उपलब्ध है, देखें
  [Community Projects](/community/projects)।
</Info>

<CardGroup cols={2}>
  <Card title="Checkout Sessions API" icon="cart-shopping" href="/developer-resources/checkout-session">
    अपने backend से वह checkout\_url बनाएँ जिसे यह SDK खोलेगा।
  </Card>

  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    देखें कि यह पूरे mobile payment flow में कैसे शामिल होता है।
  </Card>
</CardGroup>

`dodopayments_checkout`, iOS पर Dodo का hosted checkout
`SFSafariViewController` में और Android पर Chrome Custom Tab में खोलता है — वही
native cores जिन्हें standalone [iOS](/developer-resources/sdks/ios) और
[Android](/developer-resources/sdks/android) SDKs इस्तेमाल करते हैं। Checkout का पूरा logic
उन्हीं native cores में रहता है; Dart layer typed
[Pigeon](https://pub.dev/packages/pigeon) channel के माध्यम से call आगे भेजती है। इसमें कोई API key नहीं होती और
यह कभी भी Dodo Payments API को call नहीं करता।

इसके लिए Flutter 3.44+ / Dart 3.12+, iOS 16+ और Android `minSdk` 23 आवश्यक हैं।

## Installation

<Steps>
  <Step title="Add the Dependency">
    ```yaml pubspec.yaml theme={null}
    dependencies:
      dodopayments_checkout: ^1.0.0
    ```
  </Step>

  <Step title="Register a Callback URL Scheme">
    <Tabs>
      <Tab title="iOS">
        अपने scheme के लिए `ios/Runner/Info.plist` में URL type जोड़ें:

        ```xml ios/Runner/Info.plist theme={null}
        <key>CFBundleURLTypes</key>
        <array>
          <dict>
            <key>CFBundleURLName</key>
            <string>myapp</string>
            <key>CFBundleURLSchemes</key>
            <array>
              <string>myapp</string>
            </array>
          </dict>
        </array>
        ```

        इसके बाद आने वाले URLs को (उदाहरण के लिए
        [`app_links`](https://pub.dev/packages/app_links) के माध्यम से) SDK में forward करें, क्योंकि
        `SFSafariViewController` अपना return URL स्वयं catch नहीं कर सकता:

        ```dart theme={null}
        import 'package:dodopayments_checkout/dodopayments_checkout.dart';

        DodoCheckout.instance.handleOpenURL(url);
        ```

        <Note>
          यहाँ हर URL को forward करना सुरक्षित है। `handleOpenURL` केवल उन URLs पर काम करता है
          जो आपके registered `returnUrl` से match करते हैं और अन्य सभी के लिए
          `false` resolve करता है।
        </Note>
      </Tab>

      <Tab title="Android">
        अपने callback scheme को Gradle manifest placeholder के रूप में सेट करें:

        ```kotlin android/app/build.gradle theme={null}
        android {
            defaultConfig {
                manifestPlaceholders["dodoCallbackScheme"] = "myapp"
            }
        }
        ```

        <Warning>
          यदि `MainActivity`, `android:taskAffinity=""` सेट करता है (यह standard `flutter
                    create` default है), तो इसे हटाएँ या SDK की activities को वही
          affinity दें। अन्यथा कुछ OEM Android builds चल रहे
          checkout को खो सकते हैं और `PLATFORM_ERROR` return कर सकते हैं।
        </Warning>
      </Tab>
    </Tabs>
  </Step>
</Steps>

## Usage

```dart theme={null}
import 'package:dodopayments_checkout/dodopayments_checkout.dart';

final result = await DodoCheckout.instance.start(
  CheckoutParams(
    checkoutUrl: Uri.parse(checkoutUrl), // from your backend's checkout session
    returnUrl: Uri.parse('myapp://checkout/return'), // scheme must be registered (see Setup)
    onEvent: (event) => print(event.type), // logging only
  ),
);

switch (result.status) {
  case CheckoutStatus.succeeded: showSuccess(result.paymentId);
  case CheckoutStatus.failed:    showFailure();
  case CheckoutStatus.cancelled: dismiss();
  case CheckoutStatus.pending:   showPending();
  case CheckoutStatus.expired:   showExpired();
}
```

## Result का अर्थ

<Warning>
  `result.status` एक UI hint है, payment का proof नहीं। हर payment की पुष्टि अपने
  backend से, `payment.succeeded` / `subscription.active`
  webhook के माध्यम से करें।
</Warning>

<ParamField body="status" type="CheckoutStatus" required>
  इनमें से एक: `succeeded`, `failed`, `cancelled`, `pending`, `expired`।
</ParamField>

<ParamField body="paymentId" type="String?">
  जब return URL में इनमें से कोई शामिल हो, तब set होता है। इसे UI में दिखाएँ, access देने के लिए इसका उपयोग न करें। नीचे Verify the Payment देखें।
</ParamField>

<ParamField body="subscriptionId" type="String?">
  Subscription checkouts के लिए set होता है।
</ParamField>

<ParamField body="licenseKeys" type="List<String>?">
  जब checkout में license key products शामिल होते हैं, तब set होता है।
</ParamField>

<ParamField body="customerEmail" type="String?">
  जब checkout कोई email capture करता है, तब set होता है।
</ParamField>

<ParamField body="raw" type="Map<String, String>">
  Return URL का हर query parameter, verbatim।
</ParamField>

## Payment की पुष्टि करें

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/developer-resources/webhooks">
    Payment सफल होने या subscription activate होने पर Dodo Payments आपके backend को call करता है।
  </Card>

  <Card title="Get Payment Detail" icon="magnifying-glass" href="/api-reference/payments/get-payments-1">
    इसकी स्थिति सीधे जाँचने के लिए अपने secret key से `paymentId` को look up करें।
  </Card>
</CardGroup>

Access तभी दें जब इनमें से कोई payment की पुष्टि करे, केवल
`result.status` के आधार पर कभी नहीं।

## Errors

`start` केवल misuse या platform failure के लिए `CheckoutException` throw करता है।
Cancelled या declined payment हमेशा result होता है, exception कभी नहीं।

* `invalidCheckoutUrl` (`INVALID_CHECKOUT_URL`): valid `checkout.dodopayments.com` session URL नहीं है।
* `invalidReturnUrl` (`INVALID_RETURN_URL`): valid absolute URL नहीं है।
* `alreadyInProgress` (`ALREADY_IN_PROGRESS`): एक checkout पहले से चल रहा है।
* `platformError` (`PLATFORM_ERROR`): unexpected platform failure।

## Abandoned Sessions

<Info>
  यदि checkout के बीच में app बंद हो जाए, तो अगली launch पर session recover करें और
  इसे अपने backend के साथ reconcile करें।
</Info>

```dart theme={null}
import 'package:dodopayments_checkout/dodopayments_checkout.dart';

final abandoned = await DodoCheckout.instance.getAbandonedSession();
if (abandoned != null) {
  // reconcile abandoned.sessionId with your backend, then:
  await DodoCheckout.instance.clearAbandonedSession();
}
```

## संबंधित सामग्री

<CardGroup cols={2}>
  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    Android, iOS और React Native के लिए वही contract।
  </Card>

  <Card title="Community Projects" icon="users" href="/community/projects">
    एक अलग, community-built Flutter package भी उपलब्ध है।
  </Card>
</CardGroup>
