Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I/chromium(13226): [INFO:CONSOLE(1)] "Uncaught TypeError: window.getDeviceDetails is not a function" I/flutter (13226): Payment Error : 1 {"code":"BAD_REQUEST_ERROR","description":"The id provided does not exist","source":null,"step":null,"reason":null,"metadata":{}} #98

Closed
varamsky opened this issue Aug 23, 2020 · 10 comments

Comments

@varamsky
Copy link

I get the following error while using razorpay-flutter plugin for my flutter app:

I/chromium(13226): [INFO:CONSOLE(1)] "Uncaught TypeError: window.getDeviceDetails is not a function", source: https://api.razorpay.com/v1/checkout/public?version=1.5.16&platform=android&library=checkoutjs (1)
I/flutter (13226): Payment Error : 1 {"code":"BAD_REQUEST_ERROR","description":"The id provided does not exist","source":null,"step":null,"reason":null,"metadata":{}}

Description

Below is my complete Razorpay related code:

Please note that if I remove the order ID from the options map below then it works fine, i.e., if I remove
'order_id': 'order_EMBFqjDHEEn80l',
from the code given below then it works fine.


  FirebaseUser currentUser;
  DocumentSnapshot userDataFromFirebase;


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

    razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, successHandler);
    razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, failureHandler);
    razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, externalWalletHandler);

  }

  @override
  void dispose() {
    super.dispose();

    razorpay.clear();
  }

  void openCheckout(double totalPrice) async{

    // finding current user
    currentUser = await FirebaseAuth.instance.currentUser();
    await Firestore.instance.collection('users').getDocuments().then((value){
      for(DocumentSnapshot documentSnapshot in value.documents){
        if(documentSnapshot.documentID == currentUser.phoneNumber.toString().substring(3)){
          userDataFromFirebase = documentSnapshot;
          break;
        }
      }
    });

    var options = {
      'key': 'rzp_test_CphmkEBGNw9BME', // my razorpay API test key
      'amount': totalPrice*100,
      'currency': 'INR',
      'name': 'Company name',
      'description': 'Payment to company',
      //'razorpay_order_id': 'order_EMBFqjDHEEn80l', // I used this as well but it didn't work
      'order_id': 'order_EMBFqjDHEEn80l', // just a random order ID for checking purposes (REMOVING THIS THE CODE WORKS FINE)
      'prefill': {
        'contact': ('+91'+ (await userDataFromFirebase.data['phoneNumber']).toString()).toString(),
        'email': (await userDataFromFirebase.data['email']).toString()
      },
    };

    try{
      razorpay.open(options);
    }
    catch(e){
      print(e.toString());
    }
  }

  void successHandler(PaymentSuccessResponse response) {
    Toast.show("SUCCESS: " + response.paymentId, context,duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);

    razorpay.clear();
  }

  void failureHandler(PaymentFailureResponse response) {
    print('Payment Error : ${response.code.toString()} ${response.message.toString()}');
    Toast.show("ERROR: " + response.code.toString() + " - " + response.message, context,duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);

    razorpay.clear();
  }

  void externalWalletHandler(ExternalWalletResponse response) {
    print('External wallet ${response.walletName}');

    Toast.show("EXTERNAL_WALLET: " + response.walletName, context,duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);

    razorpay.clear();
  }

Flutter Version :

My flutter doctor -v result:

[✓] Flutter (Channel stable, 1.20.2, on Linux, locale en_IN)
    • Flutter version 1.20.2 at /home/shubham/flutter
    • Framework revision bbfbf1770c (10 days ago), 2020-08-13 08:33:09 -0700
    • Engine revision 9d5b21729f
    • Dart version 2.9.1

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at /home/shubham/Android/Sdk
    • Platform android-30, build-tools 30.0.1
    • Java binary at: /usr/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_265-8u265-b01-0ubuntu2~20.04-b01)
    • All Android licenses accepted.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).

[✓] Connected device (1 available)
    • Lenovo K33a42 (mobile) • 3531de61 • android-arm • Android 7.0 (API 24)

! Doctor found issues in 1 category.

This is my complete response when I run the app

Launching lib/main.dart on Lenovo K33a42 in debug mode...
Running Gradle task 'assembleDebug'...
Plugin project :firebase_auth_web not found. Please update settings.gradle.
Plugin project :firebase_core_web not found. Please update settings.gradle.
Plugin project :cloud_firestore_web not found. Please update settings.gradle.
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Waiting for Lenovo K33a42 to report its views...
Debug service listening on ws://127.0.0.1:36739/ZEVgbycZ38c=/ws
Syncing files to device Lenovo K33a42...
I/BiChannelGoogleApi(13226): [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzao@35edc86
W/DynamiteModule(13226): Local module descriptor class for providerinstaller not found.
I/DynamiteModule(13226): Considering local module providerinstaller:0 and remote module providerinstaller:0
W/ProviderInstaller(13226): Failed to load providerinstaller module: No acceptable module found. Local version is 0 and remote version is 0.
V/NativeCrypto(13226): Registering com/google/android/gms/org/conscrypt/NativeCrypto's 286 native methods...
D/NetworkSecurityConfig(13226): No Network Security Config specified, using platform default
I/ProviderInstaller(13226): Installed default security provider GmsCore_OpenSSL
W/art     (13226): Before Android 4.1, method double java.util.concurrent.ThreadLocalRandom.internalNextDouble(double, double) would have incorrectly overridden the package-private method in java.util.Random
W/art     (13226): Before Android 4.1, method int java.util.concurrent.ThreadLocalRandom.internalNextInt(int, int) would have incorrectly overridden the package-private method in java.util.Random
W/art     (13226): Before Android 4.1, method long java.util.concurrent.ThreadLocalRandom.internalNextLong(long, long) would have incorrectly overridden the package-private method in java.util.Random
I/BiChannelGoogleApi(13226): [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzao@35edc86
D/FirebaseAuth(13226): Notifying id token listeners about user ( Iw8VCX0JHXaQmdsUYh6amXg0OrA2 ).
D/FirebaseAuth(13226): Notifying id token listeners about user ( Iw8VCX0JHXaQmdsUYh6amXg0OrA2 ).
V/BoostFramework(13226): mAcquireFunc method = public int com.qualcomm.qti.Performance.perfLockAcquire(int,int[])
V/BoostFramework(13226): mReleaseFunc method = public int com.qualcomm.qti.Performance.perfLockRelease()
V/BoostFramework(13226): mAcquireTouchFunc method = public int com.qualcomm.qti.Performance.perfLockAcquireTouch(android.view.MotionEvent,android.util.DisplayMetrics,int,int[])
V/BoostFramework(13226): mIOPStart method = public int com.qualcomm.qti.Performance.perfIOPrefetchStart(int,java.lang.String)
V/BoostFramework(13226): mIOPStop method = public int com.qualcomm.qti.Performance.perfIOPrefetchStop()
V/BoostFramework(13226): BoostFramework() : mPerf = com.qualcomm.qti.Performance@6e0b20
I/flutter (13226): pressed add
I/flutter (13226): pressed cart
I/flutter (13226): clicked on Proceed to pay
I/art     (13226): Do partial code cache collection, code=23KB, data=30KB
I/art     (13226): After code cache collection, code=19KB, data=28KB
I/art     (13226): Increasing code cache capacity to 128KB
I/WebViewFactory(13226): Loading com.android.chrome version 84.0.4147.125 (code 414712570)
I/cr_LibraryLoader(13226): Loaded native library version number "84.0.4147.125"
I/cr_CachingUmaRecorder(13226): Flushed 5 samples from 5 histograms.
W/ResourceType(13226): Failure getting entry for 0x7f130588 (t=18 e=1416) (error -2147483647)
W/ResourceType(13226): Attempt to retrieve bag 0x7f0c0000 which is invalid or in a cycle.
I/DpmTcmClient(13226): RegisterTcmMonitor from: com.android.okhttp.TcmIdleTimerMonitor
W/cr_media(13226): Requires BLUETOOTH permission
E/libEGL  (13226): validate_display:99 error 3008 (EGL_BAD_DISPLAY)
I/chromium(13226): [INFO:CONSOLE(1)] "Uncaught TypeError: window.getDeviceDetails is not a function", source: https://api.razorpay.com/v1/checkout/public?version=1.5.16&platform=android&library=checkoutjs (1)
I/flutter (13226): Payment Error : 1 {"code":"BAD_REQUEST_ERROR","description":"The id provided does not exist","source":null,"step":null,"reason":null,"metadata":{}}

Expected Results

I expect it to successfully complete the payment process and return the correct payment ID and Order ID.

@ambujap94
Copy link

Please make sure the order id must have been generated using the same key id you are using to create the payment request.
In this case, we can see that the order id has been generated using a different key than you are using in the checkout. Please implement and try the resolution and provide a correct order id.

@jithinjoycy
Copy link

Please make sure the order id must have been generated using the same key id you are using to create the payment request.
In this case, we can see that the order id has been generated using a different key than you are using in the checkout. Please implement and try the resolution and provide a correct order id.

keyId is same

@varamsky
Copy link
Author

Please make sure the order id must have been generated using the same key id you are using to create the payment request.
In this case, we can see that the order id has been generated using a different key than you are using in the checkout. Please implement and try the resolution and provide a correct order id.

What do you mean?? @ambujap94

I thought that you could use any type of orderID and it didn't have to be generated using the key or the payment ID!!

I thought that if I had key as rzp_test_CphmkEBGNw9BME, the payment ID as pay_054540g48g5 and the order ID any anything for example, OR547 it would be fine!!

If not, please help me in generating a proper orderID. I am using flutter and the Razorpay documentation only specified the process for generating orderID using the Orders API by using languages like JAVA, NODEJS, etc... Please guide me how to generate a valid orderID using Flutter.

@ambujap94
Copy link

The integration step would be to generate the order id on the server using your API key and then pass the same to the checkout options to proceed with the payment. please follow steps 6 and 7 on the documentation. Please find the orders API for further reference.

@varamsky
Copy link
Author

The integration step would be to generate the order id on the server using your API key and then pass the same to the checkout options to proceed with the payment. please follow steps 6 and 7 on the documentation. Please find the orders API for further reference.

What if I don't have a dedicated backend?

I don't have a backend server to " generate the order id on my server using my API key"!!

@vivekshindhe
Copy link
Contributor

vivekshindhe commented Aug 24, 2020

@varamsky In the Razorpay docs, you can find APIs to create the order_id. Now,this is an API which can be called from your backend server, or this can be called directly from your application itself. Its upto you. We usually prefer doing this on the server as the keys will be safe, but if that's not an option it can be created like this as well. Just ensure you have the keys safe so that it won't be accessible elsewhere. Once you create the order_id with the key you are using to initialize checkout, it should start working.

Let us know if you need any more assistance on this.

Thanks,
Vivek

@varamsky
Copy link
Author

Thank you very much for your help @ambujap94 and @vivekshindhe . I was able to solve the issue.

For anyone who is not able to solve it yet, please read the Razorpay documentation as they are guiding developers to switch to the Orders API for generating their Order IDs. Please refer to this Razorpay documentation.

From what I have learned from it, you cannot generate a random Order ID (like "#ORD1") as per your convenience. You have to let Razorpay generate an Order ID for you by sending a request to them, something like this,

curl -u <YOUR_KEY_ID>:<YOUR_SECRET> \
-X POST https://api.razorpay.com/v1/orders \
-H "content-type: application/json" \
-d '{
  "amount": 50000,
  "currency": "INR",
  "receipt": "receipt#1",
  "payment_capture": 1
}'

I created a separate method to generate an Order ID for my application. Here it is,

import 'dart:convert';
import 'package:http/http.dart' as http;

Future<String> generateOrderId(String key, String secret,int amount) async{
  var authn = 'Basic ' + base64Encode(utf8.encode('$key:$secret'));

  var headers = {
    'content-type': 'application/json',
    'Authorization': authn,
  };

  var data = '{ "amount": $amount, "currency": "INR", "receipt": "receipt#R1", "payment_capture": 1 }'; // as per my experience the receipt doesn't play any role in helping you generate a certain pattern in your Order ID!!

  var res = await http.post('https://api.razorpay.com/v1/orders', headers: headers, body: data);
  if (res.statusCode != 200) throw Exception('http.post error: statusCode= ${res.statusCode}');
  print('ORDER ID response => ${res.body}');

  return json.decode(res.body)['id'].toString();
}

@varamsky
Copy link
Author

I am closing the issue for now :)

@nisargsuthar
Copy link

nisargsuthar commented Jun 3, 2021

@varamsky's method works perfectly, this is worth documenting. To return the favour, I have written the method to verify the hmac sha256 signature if anyone would want to use that too. Inside your _handlePaymentSuccess() method, you can check if the payment source was authentic by doing so:

Make sure to:
import 'dart:convert';
import 'package:crypto/crypto.dart'; (Uses crypto plugin)

void _handlePaymentSuccess(PaymentSuccessResponse response) {
    final key = utf8.encode('<YOUR_KEY>');
    final bytes = utf8.encode('$orderId|${response.paymentId}');

    final hmacSha256 = Hmac(sha256, key);
    final Digest generatedSignature = hmacSha256.convert(bytes);

    if (generatedSignature.toString() == response.signature) {
      print("Payment was successful!");
      //Proceed further to handle events for a successful payment.
    } else {
      print("Payment was unauthentic!");
    }
  }

@karthiKN-sk
Copy link

5\android\src\main\kotlin\com\razorpay\razorpay_flutter\RazorpayFlutterPlugin.kt. This is likely to due to an incorrect androidPackage: com.razorpay.razorpay_flutter or mainClass entry in the plugin's pubspec.yaml.
If you are the author of this plugin, fix the androidPackage entry or move the main class to any of locations used above. Otherwise, please contact the author of this plugin and consider using a different plugin in the meanwhile.
exit code 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants