为什么在Flutter => Uncaught TypeError:Rowow.getDeviceDetails不是函数和BAD_REQUEST_ERROR时使用Razorpay会出现此错误?

问题描述

在我的Flutter应用程序中使用razorpay-Flutter插件时出现以下错误

codeGeneration

说明 以下是我完整的Razorpay相关代码

请注意,如果我从下面的选项图中删除了订单ID,则可以正常运行 ,即,如果我删除

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":{}}

然后从下面给出的代码中可以正常工作。

'order_id': 'order_EMBFqjDHEEn80l',

这是我运行应用程序时的完整回复


  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,gravity: Toast.BottOM);

    razorpay.clear();
  }

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

    Toast.show("EXTERNAL_WALLET: " + response.walletName,gravity: Toast.BottOM);

    razorpay.clear();
  }

预期结果:

我希望它能成功完成付款过程并返回正确的付款ID和订单ID。

我也在 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","Metadata":{}} 的Github页面上打开了一个问题,请查看并帮助我解决此问题。

Github页面上的问题:https://github.com/razorpay/razorpay-flutter/issues/98

解决方法

幸运的是,我能够解决这个问题:)

对于尚无法解决该问题的任何人,请阅读Razorpay文档,因为他们正在指导开发人员切换到Orders API以生成其订单ID。请参阅此Razorpay documentation

据我了解,您无法根据您的方便生成随机的订单ID(例如“#ORD1”)。您必须让Razorpay通过向他们发送请求来为您生成订单ID,

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
}'

我创建了一个单独的方法来为我的应用生成订单ID。在这里,

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,"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();
}