Debug School

rakesh kumar
rakesh kumar

Posted on

What are the reason Failed to generate transaction token in paytm integration flutter

Reason for failed to generate transaction token
Verify for Mid is active
Curl Response Handling

When integrating Paytm in a Flutter application, encountering the "Failed to generate transaction token" error typically indicates issues with the transaction setup process. This error can stem from several possible causes:

  1. Incorrect Merchant Details The most common reason for this error is incorrect merchant credentials, such as:

Merchant ID (MID): Ensure that the MID is correct and corresponds to the one provided by Paytm for your account.
Merchant Key: This key must be correct and kept confidential. It should not be hardcoded in the Flutter app for security reasons but rather handled on the server side.

  1. Invalid or Expired Transaction Token
    If the token used for initiating the transaction is invalid, expired, or not generated correctly, this error can occur. The transaction token should be generated server-side to ensure its validity and security.

  2. Configuration Errors
    Errors in the configuration of the Paytm SDK or setup in your code might lead to this issue:

Channel ID
Website Name
Industry Type
Callback URL: The callback URL should be correctly formatted and match the one registered or expected by Paytm.

  1. Network Issues
    Network problems either on the mobile device or on the server-side can cause failures in token generation or communication with Paytm's servers.

  2. Server-Side Problems
    If the server responsible for generating the transaction token is down or having issues, this can also result in a failure to generate the token.

Example Scenario and Code
Suppose you have a basic setup where your server is supposed to provide a transaction token, and you are using this token in your Flutter app. Here’s an example of how you might call a function in Flutter to initiate a transaction, and how you could handle errors:

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void initiatePayment(BuildContext context, String amount, String customerId) async {
  String orderId = DateTime.now().millisecondsSinceEpoch.toString();
  String url = 'https://yourserver.com/generateToken';
  http.Response response = await http.post(
    Uri.parse(url),
    body: {
      'amount': amount,
      'orderId': orderId,
      'customerId': customerId
    }
  );

  if (response.statusCode == 200) {
    String transactionToken = response.body;  // Assuming the token is sent as a plain text response
    startTransaction(context, amount, orderId, transactionToken);
  } else {
    showErrorDialog(context, "Failed to generate transaction token: ${response.body}");
  }
}

void startTransaction(BuildContext context, String amount, String orderId, String transactionToken) {
  // Use the Paytm SDK or relevant method to initiate the transaction using the token
}

void showErrorDialog(BuildContext context, String error) {
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: Text("Error"),
        content: Text(error),
        actions: [
          FlatButton(
            child: Text("OK"),
            onPressed: () {
              Navigator.of(context).pop();
            },
          )
        ],
      );
    },
  );
}
Enter fullscreen mode Exit fullscreen mode

In this example:

  1. The Flutter app requests a transaction token from a server by making a HTTP POST request.
  2. The server should handle the generation of this token by interfacing with Paytm's APIs securely.
  3. Error handling is included to display a dialog if the token cannot be generated . For debugging this specific error, start by ensuring all merchant details are correct, the server-side implementation is secure and functional, and that the mobile device has a stable network connection. If the problem persists, checking server logs and Paytm's developer documentation or support might provide further insights.

Verify for Mid is active

To verify the correctness and activity of your merchant_id (MID) and to ensure the order_id is formatted correctly, you can take the following steps:

  1. Verify Merchant ID (MID) Check with Paytm: The simplest and most reliable way to check if the MID is correct and active is to confirm it directly in your Paytm Merchant Panel or by contacting Paytm's support team. They can verify whether the MID is correctly configured for the transactions. Consistency Check: Make sure the MID used in the staging environment is meant for testing and not for production. Typically, staging and production environments have different MIDs.
  2. Verify Order ID Formatting Format Specifications: Ensure that the order_id meets Paytm's requirements for order IDs. While the exact specifications can vary, generally, an order ID is a unique identifier that: Should not contain special characters or spaces. Typically is alphanumeric. Often has length constraints (verify the exact length with Paytm documentation or support). Unique Order ID: Every transaction request should have a unique order ID. If an order ID is reused, it might cause the transaction to fail or behave unexpectedly.
  3. Check for Errors in API Calls API Documentation: Double-check the API endpoint and parameters as per Paytm's latest API documentation. Make sure the endpoint you are using (https://securegw-stage.paytm.in/theia/api/v1/initiateTransaction) is correct and accepts the parameters you are sending. Test with Static Data: Try sending a request with hardcoded, known-good values that you've previously verified to work. This can help isolate the problem—whether it's with the dynamic data you're passing or your overall setup.
  4. Debugging the API Call Here are some additional debugging steps you can take within your code:

Log Detailed Errors: Enhance the error logging to capture more details. For example:

if ($response === false) {
    $curl_error = curl_error($ch);
    $curl_errno = curl_errno($ch);
    Log::error("Curl error: $curl_error, Error Number: $curl_errno");
    return response()->json(['error' => "Curl error: $curl_error, Error Number: $curl_errno"]);
}
Enter fullscreen mode Exit fullscreen mode

Verify JSON Encoding: Confirm that the JSON encoding of your payload is correct and that no data is malformed:

Log::info("Request Payload: " . $post_data);
if (json_last_error() !== JSON_ERROR_NONE) {
    Log::error("JSON encode error: " . json_last_error_msg());
    return response()->json(['error' => "JSON encode error: " . json_last_error_msg()]);
}
Enter fullscreen mode Exit fullscreen mode

CURL Options Debugging: Ensure that the cURL options set are appropriate for the request. For instance, in some environments, it might be necessary to set other options like CURLOPT_SSL_VERIFYPEER or CURLOPT_TIMEOUT.

  1. Testing and Monitoring Postman or Curl: Use a REST client like Postman or a simple curl command from the command line to make the API request manually. This can help you verify that the API is functioning as expected independently of your application logic. Environment Consistency: Ensure that the environment (local, staging, production) settings in your application (like API keys, MIDs, endpoints) are correctly set according to the environment where the code is running. By taking these steps, you should be able to pinpoint the issue more accurately, whether it's with the MID, the order_id format, or another aspect of your API request setup.
public function testPaytmIntegration()
{
    // Hardcoded, known-good values
    $order_id = 'TESTORDER123'; // Example order ID, make sure this is unique for each test
    $amount = '10.00'; // Test amount
    $customer_id = 'CUST12345'; // Example customer ID

    $merchant_key = config('services.paytm-wallet.merchant_key');
    $merchant_id = config('services.paytm-wallet.merchant_id');
    $website = config('services.paytm-wallet.merchant_website');

    // Building Paytm Params
    $paytmParams = array();
    $paytmParams["body"] = array(
        "requestType"   => "Payment",
        "mid"           => $merchant_id,
        "websiteName"   => $website,
        "orderId"       => $order_id,
        "callbackUrl"   => url('/payment/status'),
        "txnAmount"     => array(
            "value"     => $amount,
            "currency"  => "INR",
        ),
        "userInfo"      => array(
            "custId"    => $customer_id,
        ),
    );

    // Generating checksum
    $checksum = PaytmChecksum::generateSignature(json_encode($paytmParams["body"], JSON_UNESCAPED_SLASHES), $merchant_key);
    $paytmParams["head"] = array(
        "signature" => $checksum
    );

    // Converting array to JSON string
    $post_data = json_encode($paytmParams, JSON_UNESCAPED_SLASHES);

    // URL with query parameters
    $url = "https://securegw-stage.paytm.in/theia/api/v1/initiateTransaction?mid=" . $merchant_id . "&orderId=" . $order_id;

    // Initialize cURL session
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));

    // Execute cURL
    $response = curl_exec($ch);

    // Check for errors and log
    if ($response === false) {
        Log::error('Curl error: ' . curl_error($ch));
    } else {
        $responseArray = json_decode($response, true);
        Log::info("Response from Paytm: " . json_encode($responseArray));
        if (isset($responseArray['body']['txnToken'])) {
            Log::info("Successfully retrieved transaction token: " . $responseArray['body']['txnToken']);
        } else {
            Log::error("Failed to retrieve transaction token. Response: " . json_encode($responseArray));
        }
    }

    // Close cURL session
    curl_close($ch);

    return response()->json(json_decode($response, true));
}
Enter fullscreen mode Exit fullscreen mode

Curl Response Handling

Check how you handle and interpret the response. If $response === false, it generally indicates an issue with the cURL request itself rather than the API you are hitting:

Why response is false

if ($response === false) {
    // Curl failed due to a client-side issue such as a bad URL, timeout, or SSL verification issue
    Log::error("Curl failed with error: " . curl_error($ch));
} else {
    // Curl succeeded, process response
    $responseArray = json_decode($response, true);
    Log::info("Response from Paytm: " . json_encode($responseArray));
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)