Flutter Web部署后Razorpay支付页面404错误解决方案求助
Flutter Web部署服务器后Razorpay支付页面404问题解决方案
核心问题原因
本地Web、Android/iOS端正常,但服务器部署后出现404,本质是**assets/payments.html路径无法被服务器正确解析**:本地Flutter环境会自动映射assets资源路径,但服务器部署时,要么assets未被正确打包到部署目录,要么相对路径在服务器环境下失效。
解决方案1:修正Assets路径与打包配置
1. 确认Assets声明
确保payments.html在pubspec.yaml中正确注册:
flutter: assets: - assets/payments.html
2. 替换为绝对路径加载IFrame
将Flutter代码中IFrame的src从相对路径改为基于服务器根目录的绝对路径,避免环境差异导致的路径错误:
// 替换原来的element.src赋值 element.src = '${window.location.origin}/assets/payments.html?name=${widget.name}&price=${widget.price}&keyrzor=${widget.keyrzor}&orderId=${widget.orderId}&email=${widget.email}&mobileNo=${widget.mobileNo}';
3. 服务器配置检查
- 确保服务器(Nginx/Apache等)允许访问
/assets目录下的静态文件,无权限限制。 - Linux服务器注意路径大小写,确认文件名与代码中的引用完全一致。
解决方案2:直接通过JS注入初始化Razorpay(推荐)
彻底抛弃本地HTML文件,直接在Flutter Web中调用Razorpay JS SDK,从根源解决路径问题:
步骤1:在Web入口引入SDK
在web/index.html的<head>标签内添加Razorpay脚本:
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
步骤2:重构Flutter支付页面代码
import 'dart:js' as js; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:dio/dio.dart'; class AcademyWebpayment extends StatefulWidget { final String? name; final String? keyrzor; final int? price; final String? orderId; final String? email; final String? mobileNo; final int? subscriptionId; AcademyWebpayment({ this.name, this.price, this.keyrzor, this.orderId, this.email, this.mobileNo, this.subscriptionId, }); @override _AcademyWebpaymentState createState() => _AcademyWebpaymentState(); } class _AcademyWebpaymentState extends State<AcademyWebpayment> { bool _isLoading = false; @override void initState() { super.initState(); _initRazorpay(); } void _initRazorpay() { // 构造Razorpay配置参数 final options = js.JsObject.jsify({ "key": widget.keyrzor, "amount": widget.price, "currency": "INR", "name": widget.name, "description": "Sports", "order_id": widget.orderId, "prefill": { "name": widget.name, "email": widget.email, "contact": "+91-${widget.mobileNo}", }, "notes": {"address": "Autofy"}, "theme": {"color": "#DF0145"}, "modal": {"ondismiss": _handlePaymentClose} }); // 创建Razorpay实例并绑定回调 final rzp = js.JsObject(js.context['Razorpay'], [options]); rzp.callMethod('on', ['payment.success', _handlePaymentSuccess]); rzp.callMethod('on', ['payment.error', (_) => _handlePaymentClose()]); // 打开支付弹窗 rzp.callMethod('open'); } void _handlePaymentSuccess(js.JsObject response) async { setState(() => _isLoading = true); final paymentId = response['razorpay_payment_id'] as String; final orderId = response['razorpay_order_id'] as String; SharedPreferences prefs = await SharedPreferences.getInstance(); int? userId = prefs.getInt('userId'); final requestBody = { "status": "paid", "user_id": userId, "order_id": orderId, "payment_id": paymentId, "subscription_id": widget.subscriptionId, }; try { Dio dio = Dio(); final resp = await dio.put( "https://api.replsports.com/api/academySubscription/payment", data: requestBody, ); setState(() => _isLoading = false); if (resp.statusCode == 200) { Navigator.push(context, MaterialPageRoute(builder: (_) => BottomNavigation())); Fluttertoast.showToast(msg: "Paid Successfully"); } else { Fluttertoast.showToast(msg: "Payment Failed!"); } } catch (e) { setState(() => _isLoading = false); Fluttertoast.showToast(msg: "Payment Failed!"); print('Payment processing error: $e'); } } void _handlePaymentClose() { Navigator.pop(context); Fluttertoast.showToast(msg: "Payment Failed!"); } @override Widget build(BuildContext context) { return Stack( children: [ const SizedBox.expand(), // 空占位容器 if (_isLoading) Container( color: Colors.black.withOpacity(0.5), child: const Center(child: CircularProgressIndicator()), ), ], ); } }
内容的提问来源于stack exchange,提问作者Kumar Gaurav
相关产品推荐
相关产品推荐

