PhonePe / phonepe-pg-sdk-flutter

12 stars 7 forks source link

Success message is coming even the payment request is cancelled from the selected source at phone pe #22

Open zaid-debug opened 2 months ago

zaid-debug commented 2 months ago

import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:phonepe_payment_sdk/phonepe_payment_sdk.dart'; import '../model/success_model.dart'; import '../utill/app_constants.dart'; import '../utill/app_events.dart'; import '../utill/shared_preference.dart'; import '../view/widget/custom_payment_dialog.dart';

class PhonePeController extends GetxController { //Phonepe Object? result; final String _environmentValue = 'PRODUCTION'; final String _appId = ""; final String _merchantId = "M22OYS8NI0XNS"; final bool _enableLogs = true;

String _type = '';

//Update payment final Dio _dio = Dio(); final isUpdateLoading = false.obs; final isUpdateSuccess = false.obs; SuccessModel successModel = SuccessModel();

@override void onInit() { super.onInit(); initPhonePeSdk(); }

void initPhonePeSdk() { PhonePePaymentSdk.init(_environmentValue, _appId, _merchantId, _enableLogs) .then((isInitialized) { debugPrint("PhonePeController $isInitialized"); result = 'PhonePe SDK Initialized - $isInitialized'; }).catchError((error) { debugPrint("PhonePeController Init Error $error"); handleError(error); return error; }); }

void handleError(error) { if (error is Exception) { result = error.toString(); } else { result = {"error": error}; } }

void startTransaction( String body, String callBackUrl, String checksum, String type1, String orderId, String paymentId, num amount, String mobile, String userUniId) async { _type = type1; AppEvents().sendInitCheckoutEvent( amount.toString(), orderId.toString(), userUniId.toString(), type1); try { PhonePePaymentSdk.startTransaction(body, callBackUrl, checksum, "") .then((response) { if (response != null) { String status = response['status'].toString(); String error = response['error'].toString(); if (status == 'SUCCESS') { result = "Flow Completed - Status: Success!"; AppEvents().sendPaymentSuccessEvent(amount.toString(), orderId.toString(), userUniId.toString(), type1); updateOnlinePayment(orderId, paymentId); } else { result = "Flow Completed - Status: $status and Error: $error"; Get.dialog( AlertDialog( title: const Text('Payment Failed'), actions: [ ElevatedButton( onPressed: () { Get.back(); // Close the dialog }, child: const Text('OK'), ), ], ), ); } } else { Get.dialog( AlertDialog( title: const Text('Payment Failed'), actions: [ ElevatedButton( onPressed: () { Get.back(); // Close the dialog }, child: const Text('OK'), ), ], ), ); result = "Flow Incomplete"; } }).catchError((error) { debugPrint("PhonePeController catchError $error"); handleError(error); return error; }); } catch (error) { debugPrint("PhonePeController catch $error"); handleError(error); } }

Future updateOnlinePayment(String orderId, String paymentId) async { CustomPaymentDialog.showDialog(); isUpdateLoading(true);

try {
  String? apiKey =
      await SharedPreferencesHelper.getData(AppConstants.userApiKey);
  String? uniId =
      await SharedPreferencesHelper.getData(AppConstants.userUniId);
  String? paymentMethod =
      await SharedPreferencesHelper.getData(AppConstants.paymentGateway);
  final response =
      await _dio.post(AppConstants.updatePaymentRequest, data: {
    'api_key': apiKey,
    "user_uni_id": uniId,
    "payment_method": paymentMethod,
    "order_id": orderId,
    "payment_id": paymentId
  });
  if (response.statusCode == 200) {
    if (kDebugMode) {
      print('OnApiSuccess updateOnlinePayment ${response.data.toString()}');
    }
    CustomPaymentDialog.dismissDialog();
    successModel = SuccessModel.fromJson(response.data);
    if (successModel.status == AppConstants.success) {
      isUpdateSuccess(true);
    } else {
      isUpdateSuccess(false);
    }
  } else {
    CustomPaymentDialog.dismissDialog();
    if (kDebugMode) {
      print('OnApiError updateOnlinePayment');
    }
  }
} catch (e) {
  CustomPaymentDialog.dismissDialog();
  isUpdateSuccess(false);
  if (kDebugMode) {
    print('OnException updateOnlinePayment==> ${e.toString()}');
  }
} finally {
  isUpdateLoading(false);
  Get.dialog(
    AlertDialog(
      title: const Text('Payment Successful'),
      content: Text('Payment ID: $paymentId'),
      actions: [
        ElevatedButton(
          onPressed: () {
            Get.back(); //Close Dialog
            if (_type.isNotEmpty) {
              if (_type == AppConstants.jeevini) {
                //JEEVINI
                Get.offAllNamed('/paid_orders_tab_screen',
                    arguments: {'index': 0});
              } else if (_type == AppConstants.divineCode) {
                //DIVINE
                Get.offAllNamed('/paid_orders_tab_screen',
                    arguments: {'index': 1});
              } else if (_type == AppConstants.pdfBook) {
                //BOOKS
                Get.offAllNamed('/paid_orders_tab_screen',
                    arguments: {'index': 2});
              } else if (_type == AppConstants.report) {
                //REPORT
                Get.offAllNamed('/paid_orders_tab_screen',
                    arguments: {'index': 3});
              } else if (_type == AppConstants.shop) {
                //SHOP
                Get.offAllNamed('/orders_tab_screen',
                    arguments: {'index': 1});
              } else if (_type == AppConstants.serviceOrder) {
                //Service
                Get.offAllNamed('/orders_tab_screen',
                    arguments: {'index': 2});
              } else if (_type == AppConstants.architect) {
                //Architect
                Get.offAllNamed('/architect_orders_tab_screen');
              } else {
                Get.offAllNamed('/dashboard');
              }
            } else {
              Get.offAllNamed('/dashboard');
            }
          },
          child: const Text('OK'),
        ),
      ],
    ),
  );
}

}

void showSuccessDialog(String paymentId, String type) { Get.dialog( AlertDialog( title: const Text('Payment Successful'), content: Text('Payment ID: $paymentId'), actions: [ ElevatedButton( onPressed: () { Get.back(); //Close Dialog if (type == AppConstants.jeevini) { //JEEVINI Get.offAllNamed('/paid_orders_tab_screen', arguments: {'index': 0}); } else if (type == AppConstants.divineCode) { //DIVINE Get.offAllNamed('/paid_orders_tab_screen', arguments: {'index': 1}); } else if (type == AppConstants.pdfBook) { //BOOKS Get.offAllNamed('/paid_orders_tab_screen', arguments: {'index': 2}); } else if (type == AppConstants.report) { //REPORT Get.offAllNamed('/paid_orders_tab_screen', arguments: {'index': 3}); } else if (type == AppConstants.shop) { //Service Get.offAllNamed('/orders_tab_screen', arguments: {'index': 1}); } else if (type == AppConstants.serviceOrder) { //Service Get.offAllNamed('/orders_tab_screen', arguments: {'index': 2}); } else if (type == AppConstants.architect) { //Service Get.offAllNamed('/architect_orders_tab_screen'); } else { Get.offAllNamed('/dashboard'); } }, child: const Text('OK'), ), ], ), ); } } phonepe_payment_sdk: ^2.0.3

**The issue I am facing right now is, that when the user goes to pay throgh phone pe PG, like the user opted for google pay upi, he went there, but he changed his mind and di not made payment, the code shows success. his should not occur, please help me solve.

pvr-07 commented 2 months ago

Kindly share the issue with merchant-pgsupport@phonepe.com. They will be able to help with the issue.

zaid-debug commented 2 months ago

We mailed but no reverts. Could you please help us here, if there is a mistake in the code, or in the flutter dependency of phone pe.

pvr-07 commented 2 months ago

Share your email Id

zaid-debug commented 2 months ago

Well, I am so sorry but, I am a junior employ who dont have access to that mail id, I am just trying to solve the issue. Well, I could give you reference, import 'package:crypto/crypto.dart'; import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:phonepe_payment_sdk/phonepe_payment_sdk.dart';

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

@override State createState() => _PhonepepaymentState(); }

class _PhonepepaymentState extends State { String environment = "SANDBOX"; // String environment = "RELEASE"; String appId = ""; // String merchantId = "M22OYS8NI0XNS"; String merchantId = "PGTESTPAYUAT86"; bool enableLogging = true;

String checksum = ""; String saltKey = "96434309-7796-489d-8924-ab56988a6076"; String saltIndex = "1";

String callbackurl = "https://webhook.site/callback-url";

String body = "";

String apiEndPoint = "/pg/v1/pay";

Object? result;

getChecksum(){ final requestData = { "merchantId": merchantId, "merchantTransactionId": "transaction_123", "merchantUserId": "90223250", "amount": 1000, "mobileNumber": "9999999999", "callbackUrl": callbackurl, "paymentInstrument": { "type": "PAY_PAGE"} };

String jsonBody = jsonEncode(requestData); String base64Body = base64Encode(utf8.encode(jsonBody));

checksum = '${sha256.convert(utf8.encode(base64Body + apiEndPoint + saltKey)).toString()}###$saltIndex'; print("CHECKSUM:::::::::::::"+checksum);

return base64Body; }

@override void initState() { // TODO: implement initState super.initState();

phonepeInit();

body = getChecksum().toString();
print("BODY:::::::::::::"+body);

}

@override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Phone Pe Payment Gateway"), ),body: Column( children: [ ElevatedButton( onPressed: (){ startPgTransaction(); }, child: Text("Proceed to Pay"), ),

        const SizedBox(
          height: 20,
        ),
        Text("Result \n $result")
      ],
    ),
  ),
);

}

void phonepeInit() { PhonePePaymentSdk.init(environment, appId, merchantId, enableLogging) .then((val) => { setState(() { result = 'PhonePe SDK Initialized - $val'; }) }) .catchError((error) { handleError(error); return {}; }); }

void startPgTransaction() async{ PhonePePaymentSdk.startTransaction(body, callbackurl, checksum, "").then((response) => { setState(() { if (response != null) { String status = response['status'].toString(); String error = response['error'].toString(); if (status == 'CANCELLED' || error == 'USER_CANCELLED') { print("Payment was cancelled by the user."); } else if (status == 'SUCCESS') { print("Success"); // "Flow Completed - Status: Success!"; } else { print("Error"); // "Flow Completed - Status: $status and Error: $error"; } } else { print("Error"); // "Flow Incomplete"; } }) }).catchError((error) { // handleError(error) return {}; }); }

void handleError(error){ setState(() { result = {"error" : error}; }); } }

Even in the Sandbox environment, with test keys, you can check, it is the same issue. The user enters UPI id on phone pay page, and it directs to say Google Pay for payment, and the user cancels the payment there, or do not pay, but the phone pe sdk, returns success. Please check this out.

pvr-07 commented 2 months ago

You can share any other email Id through which the support team can reach out to and if required they will setup a call.

zaid-debug commented 2 months ago

Sure here's my id zaidfirebase002@gmail.com