Flutter Client

Step 1: Create New Order (REST API) ๐Ÿ”—

Please refer Order API Documentation for more details.

Use the below url to create an order in your (backend) server.

Production URL: https://apiv2.payg.in/payment/api/order/CreateIntent

/create


Authorization: basic authentication with base64encoded

PayGAuthentication โ€“
<MerchantAuthenticationKey>:<MerchantAuthenticationToken>:M:<MID>
  
						
                     
                        {
                           "MID": "3EMF9915EF35567",
                           "UniqueRequestId": "TEST512scx3",
                           "UserDefinedData": {
                               "UserDefined1": ""
                           },
                           "ProductData": "{'PaymentReason':'OnlineOrder for OrderNo- 1234'}",
                           "RequestDateTime": "06232023",
                           "RedirectUrl": "https://payg.in",
                           "TransactionData": {
                               "AcceptedPaymentTypes": "",
                               "PaymentType": "UPIINTENT",
                               "SurchargeType": "",
                               "SurchargeValue": "",
                               "RefTransactionId": "",
                               "IndustrySpecificationCode": "",
                               "PartialPaymentOption": ""
                           },
                           "OrderAmount": "3",
                           "OrderType": "",
                           "OrderAmountData": {
                               "AmountTypeDesc": "3",
                               "Amount": "2"
                           },
                           "CustomerData": {
                               "CustomerId": "123456",
                               "CustomerNotes": "Mens clothing",
                               "FirstName": "Ayush",
                               "LastName": "Rane",
                               "MobileNo": "7887673322",
                               "Email": "ayushtesting12@gmail.com",
                               "EmailReceipt": "true",
                               "BillingAddress": "76, Sch. 115",
                               "BillingCity": "Indore",
                               "BillingState": "MP",
                               "BillingCountry": "India",
                               "BillingZipCode": "452011",
                               "ShippingFirstName": "Ayush",
                               "ShippingLastName": "Rane",
                               "ShippingAddress": "76, Sch. 115",
                               "ShippingCity": "Indore",
                               "ShippingState": "MP",
                               "ShippingCountry": "India",
                               "ShippingZipCode": "452011",
                               "ShippingMobileNo": "9987887733"
                           },
                           "IntegrationData": {
                               "UserName": "Ayush",
                               "Source": "3213",
                               "IntegrationType": "11",
                               "HashData": "",
                               "PlatformId": "1"
                           }
                       }
  
 
         
var data = {
   "Merchantkeyid": MerchantKeyId,
   "UniqueRequestId": getRandomString(10),
   "OrderStatus": 'Initiating',
   "UserDefinedData": {"UserDefined1": ''},
   "RequestDateTime": "11/08/2021",
   "RedirectUrl": RedirectUrl,
   "TransactionData": {
      "AcceptedPaymentTypes": '',
      "PaymentType": orderType,
      "SurchargeType": orderType,
      "SurchargeValue": orderType,
      "RefTransactionId": orderType,
      "IndustrySpecificationCode": orderType,
      "PartialPaymentOption": orderType,
   },
   "OrderAmount": orderAmountController.text,
   "OrderType": 'MOBILE',
   "OrderAmountData": {"AmountTypeDesc": amountTypeDesc, "Amount": "20"},
   "CustomerData": {
      'CustomerId': CustomerId,
     'CustomerNotes': customerNotes,
     'FirstName': orderFirstNameController.text,
     'LastName': orderLastNameController.text,
     'MobileNo': mobileNoController.text,
     'Email': email,
     'EmailReceipt': emailReceipt,
     'BillingAddress': billingAddress,
     'BillingCity': billingCity,
     'BillingState': billingState,
     'BillingCountry': billingCountry,
     'BillingZipCode': billingZipCode,
     'ShippingFirstName': shippingFirstName,
     'ShippingLastName': shippingLastName,
     'ShippingAddress': shippingAddress,
     'ShippingCity': shippingCity,
     'ShippingState': shippingState,
     'ShippingCountry': shippingCountry,
     'ShippingZipCode': shippingZipCode,
      'ShippingMobileNo': shippingMobileNo,
   },
   "IntegrationData": {
      "UserName": userName,
      "Source": 'MobileSDK',
      "IntegrationType": "11",
      "HashData": HashData,
      "PlatformId": PlatformId,
   }
   };


      
         {
            "OrderKeyId": "93281250227M10404UTEST512scx3",
            "MerchantKeyId": 10121,
            "UniqueRequestId": "TEST512scx3",
            "OrderType": "PAYMENT",
            "OrderAmount": 3,
            "OrderId": null,
            "OrderStatus": null,
            "OrderPaymentStatus": 0,
            "OrderPaymentStatusText": null,
            "PaymentStatus": 0,
            "PaymentTransactionId": null,
            "PaymentResponseCode": 0,
            "PaymentApprovalCode": null,
            "PaymentReasonCode": null,
            "PaymentTransactionRefNo": null,
            "PaymentResponseText": null,
            "PaymentMethod": null,
            "PaymentAccount": null,
            "OrderRefundTransactionId": 0,
            "RefundPaymentResponseCode": 0,
            "RefundPaymentResponseText": null,
            "RefundDateTime": null,
            "CardType": null,
            "CardLevel": null,
            "OrderNotes": null,
            "PaymentDateTime": null,
            "UpdatedDateTime": null,
            "PaymentProcessUrl": "null",
            "CustomerData": {
                "CustomerId": "123456",
                "CustomerNotes": "Mens clothing",
                "FirstName": "Ayush",
                "LastName": "Rane",
                "MobileNo": "7887673322",
                "Email": "ayushtesting12@gmail.com",
                "EmailReceipt": true,
                "BillingAddress": "76, Sch. 115",
                "BillingCity": "Indore",
                "BillingState": "MP",
                "BillingCountry": "India",
                "BillingZipCode": "452011",
                "ShippingFirstName": "Ayush",
                "ShippingLastName": "Rane",
                "ShippingAddress": "76, Sch. 115",
                "ShippingCity": "Indore",
                "ShippingState": "MP",
                "ShippingCountry": "India",
                "ShippingZipCode": "452011",
                "ShippingMobileNo": "9987887733"
            },
            "ProductData": "{'PaymentReason':'OnlineOrder for OrderNo- 1234'}",
            "OrderPaymentCustomerData": {
                "FirstName": "Ayush",
                "LastName": null,
                "Address": null,
                "City": null,
                "State": null,
                "ZipCode": null,
                "Country": null,
                "MobileNo": "7887673322",
                "Email": "ayushtesting12@gmail.com",
                "UserId": null,
                "IpAddress": null
            },
            "UpiLink": "upi://pay?pa=businesspayg@isis&am=1&tr=Y564417909M21764D543216&cu=INR&mc=2006&pn=Test Account"
            "UserDefinedData": {
                "UserDefined1": "",
                "UserDefined2": null,
                "UserDefined3": null,
                "UserDefined4": null,
                "UserDefined5": null,
                "UserDefined6": null,
                "UserDefined7": null,
                "UserDefined8": null,
                "UserDefined9": null,
                "UserDefined10": null,
                "UserDefined11": null,
                "UserDefined12": null,
                "UserDefined13": null,
                "UserDefined14": null,
                "UserDefined15": null,
                "UserDefined16": null,
                "UserDefined17": null,
                "UserDefined18": null,
                "UserDefined19": null,
                "UserDefined20": null
            },
            "SplitPaymentResponse": null,
            "Id": 93281
        }
  
 

Step 2: Below details you can use for launch a specific UPI app to complete a payment. ๐Ÿ”—

Once your order is created successfully,then you will UPI link in response. This payment url is used to redirect to actual payment screen.

UPI Link is for UPI payment. You can use either payment process URL or UPI based on your requirement.

rana_pay_upi โ€” Usage Guide ๐Ÿ”—

A Flutter plugin to discover installed UPI (Unified Payments Interface) apps on an Android device and launch a specific UPI app to complete a payment.

1. Installation ๐Ÿ”—

Add the package to your pubspec.yaml (adjust source depending on whether you're publishing to pub.dev or using a local):

            
                dependencies:
                flutter:
                sdk: flutter
                rana_pay_upi:
                path: ../rana_pay_upi   # or a pub.dev version 
            

Then run:

            
                flutter pub get
            
2. Android Setup ๐Ÿ”—

Since UPI apps are launched via Android intents, you need to declare the UPI apps you intend to query/launch in your AndroidManifest.xml (required from Android 11 / API 30 onward due to package visibility restrictions):

            
                <queries>
                <intent>
                <action android:name="android.intent.action.VIEW" />
                <data android:scheme="upi" />
                </intent>
                </queries>
            

Without this block, getUpiApps() may return an empty list on newer Android versions even if UPI apps are installed.

3.Importing the Package ๐Ÿ”—
            
                import 'package:rana_pay_upi/rana_pay_upi.dart';
            
4.API Reference & Examples ๐Ÿ”—
4.1. Get Platform Version ๐Ÿ”—

Two ways are exposed to fetch the platform version:

            
                final upi = RanaPayUpi();

// Instance method (via platform interface)
String? version1 = await upi.getPlatformVersion();

// Static method (direct MethodChannel call)
String? version2 = await RanaPayUpi.getPlatformVersionValue();

print('Platform version: $version1');
            
4.2. List Installed UPI Apps ๐Ÿ”—

Returns a list of UpiApp objects (Google Pay, PhonePe, Paytm, BHIM, etc.) that are installed on the device.

            
                List<UpiApp> apps = await RanaPayUpi.getUpiApps();

for (final app in apps) {
  print('${app.appName} (${app.packageName})');
  // app.icon is a Uint8List (decoded PNG/JPEG bytes) or null
}
            

UpiApp fields: ??

Field ๐Ÿ”—
Type ๐Ÿ”—
Description ๐Ÿ”—
packageName String Android package name, e.g. com.google.android.apps.nbu.paisa.user
appName String Human-readable app name, e.g. Google Pay
icon Uint8List? Decoded app icon bytes (nullable)

You can render the icon directly in a widget:

            
                if (app.icon != null) Image.memory(app.icon!)
            
4.3. Launch a UPI App to Make a Payment ๐Ÿ”—

Build a standard UPI deep link and pass it along with the target app's package name:

            
                String upiUrl =
    'upi://pay?pa=merchant@bank&pn=MerchantName&am=100.00&cu=INR&tn=Order1234';

String response = await RanaPayUpi.launchUpiApp(
  'com.phonepe.app', // packageName from getUpiApps()
  upiUrl,
);

print('Raw response: $response');
            
Return value: ๐Ÿ”—

a raw string returned by the UPI app, typically inkey=value&key=value query format, for example:

            
                Status=SUCCESS&txnId=T12345&responseCode=00
            

If something goes wrong (exception, no response from the app), the method falls back to:

            
                Status=PENDING&responseCode=&error=EMPTY_RESPONSE
            
Note on parseResponse(): ๐Ÿ”—

The helper function parseResponse()included in this package expects input shaped like a Dart map string โ€”{Status: SUCCESS, txnId: T12345} โ€” and splits on ", " and ": ". The actual string returned by launchUpiApp() is in UPI'skey=value&key=value format, not the {key: value} format, soparseResponse() will not parse it correctly. Use Uri.splitQueryString() instead โ€” it's built into Dart, handles URL-encoding correctly, and is the approach used in production:

            
                Map<String, String> parseUpiResponse(String response) {
  if (response.isEmpty) return {};
  try {
    return Uri.splitQueryString(response);
  } catch (e) {
    return {};
  }
}
            

Keep parseResponse() around only if some other part of your native/platform code actually returns the {key: value} format.

4.4. Full Example: Pick an App and Pay ๐Ÿ”—
            
               import 'package:flutter/material.dart';
import 'package:rana_pay_upi/rana_pay_upi.dart';

class PaymentScreen extends StatefulWidget {
  const PaymentScreen({super.key});

  @override
  State<PaymentScreen> createState() => _PaymentScreenState();
}

class _PaymentScreenState extends State {
  List<UpiApp> _apps = [];

  @override
  void initState() {
    super.initState();
    _loadApps();
  }

  Future<void>_loadApps() async {
    final apps = await RanaPayUpi.getUpiApps();
    setState(() => _apps = apps);
  }

  Future<void> _pay(UpiApp app) async {
    final url =
        'upi://pay?pa=merchant@bank&pn=MerchantName&am=100.00&cu=INR&tn=Order1234';

    final response = await RanaPayUpi.launchUpiApp(app.packageName, url);
    final parsed = parseUpiResponse(response); // see helper above

    if (parsed['Status'] == 'SUCCESS') {
      // handle success, e.g. show confirmation, verify on backend
    } else {
      // handle pending/failure
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Pay via UPI')),
      body: ListView.builder(
        itemCount: _apps.length,
        itemBuilder: (context, index) {
          final app = _apps[index];
          return ListTile(
            leading: app.icon != null ? Image.memory(app.icon!) : null,
            title: Text(app.appName),
            onTap: () => _pay(app),
          );
        },
      ),
    );
  }
}
            
4.5. Real-World Flow (as used in production) ๐Ÿ”—

This is the pattern actually recommended for a payment screen โ€” list apps โ†’ create an order on your backend to get the UPI deep link โ†’ launch the chosen app โ†’ parse the raw response โ†’ always confirm the final result by calling your payment status API, since the app's on-device response is not proof of payment.

            
                enum _UpiOutcome { none, success, failure, pending, cancelled, error }

Future<void> onAppTapped(UpiApp app) async {
  // 1. Get (or reuse) the UPI deep link for this order from your backend.
  final upiLink = await paymentMethodController.createPaymentOrder(
    getPaymentAppOrderInfoModel: orderInfo,
    isfrom: "UPIINTENT",
    context: context,
  );

  try {
    // 2. Launch the chosen app with that link.
    final response = await RanaPayUpi.launchUpiApp(app.packageName, upiLink);

    // 3. Parse the raw "key=value&key=value" response.
    final parsed = Uri.splitQueryString(response);
    final status = (parsed["Status"] ?? "").toUpperCase();
    final responseCode = parsed["responseCode"] ?? "";

    // 4. Regardless of what the app reported, ask your backend for the
    //    authoritative status โ€” payments can settle even if the client-side
    //    response is empty, delayed, or the user backgrounds the app.
    await paymentMethodController.getPaymentStatus(
      context: context,
      orderKeyId: orderInfo?.orderkeyid,
      isFrom: "UPIINTENT",
      getPaymentAppOrderInfo: orderInfo,
    );

    // 5. Use the client-side response only to drive immediate UI feedback
    //    (e.g. "Payment successful" banner) while the backend call above is
    //    the source of truth for what actually gets recorded.
    if (status == "SUCCESS" && responseCode == "0") {
      // show success banner
    } else if (status == "FAILURE") {
      // show failure banner, offer retry
    } else if (status == "CANCELLED" || status == "CANCELED") {
      // show "you cancelled" banner
    } else {
      // treat as pending โ€” the backend status check will confirm/update this
    }
  } catch (e) {
    // app not installed / launch failed โ€” show an error banner, don't call
    // it a payment failure since no attempt actually reached the bank
  }
}
             
Key points from this pattern: ๐Ÿ”—

Always call your payment status API after launchUpiApp() returns, even on success โ€” the returned string is just what the UPI app chose to report locally, not a settlement confirmation.

Treat any status that isn't a clean SUCCESS + responseCode == "0" aspending, not failed โ€” many UPI apps report ambiguous or empty statuses even when the payment eventually succeeds on the bank's side.

Keep the try/catch around launchUpiApp() separate from response evaluation โ€” a thrown exception means the app couldn't be opened at all (different from the app opening and reporting a failure).

Use Uri.splitQueryString(response) for parsing โ€” see ยง4.3 above.

5. Error Handling Notes ๐Ÿ”—

getUpiApps() swallows exceptions internally and returns an empty list on failure โ€” check for an empty list in your UI (e.g. "No UPI apps found").

launchUpiApp() swallows exceptions and returns a fallbackStatus=PENDING&responseCode=&error=EMPTY_RESPONSE string โ€” always treatPENDING as "verify with your backend," not as a confirmed failure, since UPI payments can complete on the bank's side even if the app response is lost.

Always verify final payment status server-side (via your payment gateway/bank webhook) rather than trusting the client-side response alone โ€” this is standard practice for UPI integrations.

6. iOS Requirements ๐Ÿ”—

UPI itself has no formal iOS equivalent of Android's intent-based app discovery, so iOS support works fundamentally differently and needs its own native setup. This matters because your UI (as shown above) falls back to aDropdownButtonFormField on iOS instead of the app grid used on Android โ€” which only works if the plugin's iOS side is actually able to detect, open, and receive a callback from installed UPI apps.

There are two separate pieces of iOS setup: (A) letting your app query and open other UPI apps, and (B) letting other UPI apps call back into your app once the payment is done. Both are required.

6.1 Query other UPI apps โ€” LSApplicationQueriesSchemes ๐Ÿ”—

iOS can't enumerate "anything that handles upi://" the way Android'sPackageManager can. Each app's scheme must be checked one by one viacanOpenURL, and must be whitelisted in Info.plist:

            
                <key>LSApplicationQueriesSchemes</key>
<array>  
     <string>tez</string>          
      <string>phonepe</string>      
     <string>paytmmp</string>     
     <string>credpay</string>      
     <string>bhim</string>         
     <string>upi</string>                  
    </array>
              

Without this, canOpenURL (and therefore getUpiApps() on iOS) will report every app as "not installed," even if it is.

6.2 Register your own callback scheme โ€” CFBundleURLTypes ๐Ÿ”—

For a UPI app to hand control back to your app after the payment completes, your app needs its own registered URL scheme that you pass as the callback/return URL when building the UPI link. Add this to Info.plist:

            
            <key>CFBundleURLTypes</key>
            <array>
            <dict>
            <key>CFBundleURLName</key>
            <string>com.payg.upi.callback</string>
            <key>CFBundleURLSchemes</key>
            <array>
            <string>payg</string>
            </array>
            </dict>
            </array>
        

Here payg is the scheme the plugin listens on โ€” when a UPI app finishes and redirects to something like payg://response?Status=SUCCESS&..., iOS routes that back into your app rather than dropping it.

6.3 Handle the callback in AppDelegate.swift ๐Ÿ”—

Your AppDelegate needs to forward the incoming URL to the plugin so it can parse it and resolve the Future that launchUpiApp() is waiting on:

            
                // MARK: - Handle URL Scheme Callbacks
override func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
    print("๐Ÿ“ฑ AppDelegate - Received URL: \(url.absoluteString)")

    // Let the RanaPayUpiPlugin handle the URL
    if let plugin = RanaPayUpiPlugin.shared {
        let handled = plugin.handleOpenURL(url)
        if handled {
            print("โœ… RanaPayUpiPlugin handled URL successfully")
            return true
        }
    }

    // Handle Facebook login callback if needed
    if let scheme = url.scheme, scheme.hasPrefix("fb") {
        print("๐Ÿ“ฑ Facebook login callback detected")
        return super.application(app, open: url, options: options)
    }

    // If not handled by plugin, pass to Flutter's default handler
    print("โš ๏ธ URL not handled by plugin, passing to Flutter")
    return super.application(app, open: url, options: options)
}

// MARK: - Handle Universal Links
override func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
    if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
       let url = userActivity.webpageURL {
        print("๐Ÿ“ฑ Received universal link: \(url.absoluteString)")

        if let plugin = RanaPayUpiPlugin.shared {
            if plugin.handleOpenURL(url) {
                print("โœ… Plugin handled universal link")
                return true
            }
        }
    }
    return super.application(application, continue: userActivity, restorationHandler: restorationHandler)
}
           
What each piece is doing: ๐Ÿ”—

application(_:open:options:) fires when a UPI app redirects back into your app via the payg:// custom scheme (ยง6.2). It hands the URL toRanaPayUpiPlugin.shared.handleOpenURL(url), which is presumably what parses the query string and completes the pending launchUpiApp() call on the Dart side.

application(_:continue:restorationHandler:) covers the case where the redirect comes back as a universal link (https://...) instead of a custom scheme โ€” some UPI apps prefer this. Both paths funnel into the samehandleOpenURL, so you don't need separate Dart-side handling for each.

The Facebook (fb...) scheme check is just making sure this callback handler doesn't swallow unrelated URL callbacks your app already relies on โ€” keep any other third-party SDK scheme checks alongside it if you add more in the future.

If neither the plugin nor a known third-party scheme handles it, it falls through to Flutter's own default URL handling so nothing else in your app breaks.

            
                โš ๏ธ Make sure this code lives in your ios/Runner/AppDelegate.swift, and that RanaPayUpiPlugin.shared is actually being set somewhere in the plugin's register(with:) โ€” otherwise plugin will be nil and every callback silently falls through to Flutter's default handler, meaninglaunchUpiApp() will simply hang/timeout on iOS regardless of correctInfo.plist setup.
              
6.4 Other iOS notes ๐Ÿ”—
Launching still uses a UPI deep link, ๐Ÿ”—

but on iOS it goes throughUIApplication.shared.open(url:) rather than an Android Intent. Response handling on the Dart side (Uri.splitQueryString) stays the same regardless of platform, since the returned string format is controlled by your plugin, not by iOS.

๐Ÿ”—No guaranteed callback.

Even with ยง6.2/ยง6.3 wired up correctly, some UPI apps on iOS don't reliably redirect back (less consistent than Android's startActivityForResult pattern). Because of this, the backend payment-status check described in ยง4.5 is even more important on iOS โ€” don't treat a missing callback as a failed payment.

๐Ÿ”—App Store review:

if you whitelist third-party UPI schemes purely to check installation status, be prepared to explain this usage during App Store review, as unused/undeclared scheme queries are sometimes flagged.

7. Platform Summary ๐Ÿ”—
Requirement ๐Ÿ”—
Android ๐Ÿ”—
iOS ๐Ÿ”—
App discovery PackageManager intent query for upi:// scheme Hardcoded scheme list + canOpenURL
Manifest/plist entry (query) <queries>block in AndroidManifest.xml Info.plist
Callback registration Not needed (Activity result is enough) CFBundleURLTypes custom scheme in Info.plist
Callback handling Handled by Android Intent result AppDelegate open url + universal link overrides
Launch mechanism Android Intent UIApplication.shared.open(url:)
Callback reliability Generally reliable Inconsistent โ€” always verify via backend
UI shown in this app Grid of app tiles Dropdown of known apps
8. General Requirements ๐Ÿ”—

AndroidManifest.xml <queries> block for package visibility (Android 11+).

Info.plist LSApplicationQueriesSchemes entries for iOS (querying apps).

Info.plist CFBundleURLTypes entry for iOS (receiving the callback).

AppDelegate.swift URL + universal-link handlers wired to

RanaPayUpiPlugin.shared.handleOpenURL(url).

Real UPI-enabled bank account and VPA (pa) for testing actual payments.

A backend payment-status endpoint โ€” required on both platforms, but especially load-bearing on iOS (see ยง6.4).

Step 3: Order Details (API request Parameters) ๐Ÿ”—

You can get order details by passing the below request parameters.

   
Authorization: basic authentication with base64encoded
PayGAuthentication โ€“
<MerchantAuthenticationKey>:<MerchantAuthenticationToken>:M:<MID>
   
   

   
      {
         "OrderKeyId": "93281250227M10404UTEST512scx3",
         "MID":"3EMF9915EF35567",
         "PaymentType": ""
     }
      
   
   

   
var data = {
   "Merchantkeyid": MerchantKeyId,
   "OrderKeyId": orderIdController.text,
   "PaymentType": '',
};
   
   

   
      {
         "OrderKeyId": "93281250227M10404UTEST512scx3",
         "MerchantKeyId": 10121,
         "UniqueRequestId": "TEST512scx3",
         "OrderType": "PAYMENT",
         "OrderAmount": 3.00,
         "OrderId": null,
         "OrderStatus": "1",
         "OrderPaymentStatus": 0,
         "OrderPaymentStatusText": "Paid",
         "PaymentStatus": 0,
         "PaymentTransactionId": "767926",
         "PaymentResponseCode": 1,
         "PaymentApprovalCode": null,
         "PaymentReasonCode": null,
         "PaymentTransactionRefNo": null,
         "PaymentResponseText": "Approved",
         "PaymentMethod": "CreditCard",
         "PaymentAccount": "41111 - XXXX - 1111",
         "OrderRefundTransactionId": 0,
         "RefundPaymentResponseCode": 0,
         "RefundPaymentResponseText": null,
         "RefundDateTime": null,
         "CardType": null,
         "CardLevel": null,
         "OrderNotes": "Internal",
         "PaymentDateTime": "2/27/2025 1:57:09 PM",
         "UpdatedDateTime": "2/27/2025 1:52:35 PM",
         "PaymentProcessUrl": null,
         "CustomerData": {
             "CustomerId": "123456",
             "CustomerNotes": "Mens clothing",
             "FirstName": "Ayush",
             "LastName": "Rane",
             "MobileNo": "7887673322",
             "Email": "ayushtesting12@gmail.com",
             "EmailReceipt": false,
             "BillingAddress": "76, Sch. 115",
             "BillingCity": "Indore",
             "BillingState": "MP",
             "BillingCountry": "India",
             "BillingZipCode": "452011",
             "ShippingFirstName": "Ayush",
             "ShippingLastName": "Rane",
             "ShippingAddress": "76, Sch. 115",
             "ShippingCity": "Indore",
             "ShippingState": null,
             "ShippingCountry": "India",
             "ShippingZipCode": "452011",
             "ShippingMobileNo": "9987887733"
         },
         "ProductData": "{'PaymentReason':'OnlineOrder for OrderNo- 1234'}",
         "OrderPaymentCustomerData": null,
         "UpiLink": null,
         "OrderPaymentTransactionDetail": [
             {
                 "OrderKeyId": "93281250227M10404UTEST512scx3",
                 "MerchantKeyId": 10404,
                 "TransactionId": 767926,
                 "ResponseCode": 1,
                 "ResponseText": "Approved",
                 "TransactionAmount": 3.00
             }
         ],
         "UserDefinedData": {
             "UserDefined1": "",
             "UserDefined2": null,
             "UserDefined3": null,
             "UserDefined4": null,
             "UserDefined5": null,
             "UserDefined6": null,
             "UserDefined7": null,
             "UserDefined8": null,
             "UserDefined9": null,
             "UserDefined10": null,
             "UserDefined11": null,
             "UserDefined12": null,
             "UserDefined13": null,
             "UserDefined14": null,
             "UserDefined15": null,
             "UserDefined16": null,
             "UserDefined17": null,
             "UserDefined18": null,
             "UserDefined19": null,
             "UserDefined20": null
         },
         "SplitPaymentResponse": null,
         "Id": 93281
     }
   
   

Note: Please check the payment status codes from this URL Payment Response codes Note: Please check the error codes from this URL Error codes