我正在实施 payfast 付款集成,因此我创建了一个表单,用户在其中填写金额和商品名称,然后我想通过 http 调用将这些详细信息发送到 Payfast 付款页面以显示在 Web 视图上。所以现在,当我按下支付按钮时,它不会导航或显示网络视图,并且没有错误。请有人帮助我如何使用下面的代码实现此目的
请检查下面我的代码:
class PayfastPayment extends StatefulWidget {
PayfastPayment({Key? key}) : super(key: key);
@override
_PayfastPaymentState createState() => _PayfastPaymentState();
}
class _PayfastPaymentState extends State<PayfastPayment> {
GlobalKey<FormState> formstate = new GlobalKey<FormState>();
TextEditingController amountController = TextEditingController();
TextEditingController itemNameController = TextEditingController();
PaymentViewModel? model;
var client = http.Client();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(centerTitle: true, title: const Text("Payment Page")),
body: Form(
key: formstate,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFormField(
controller: amountController,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Amount',
),
),
const SizedBox(
height: 100,
),
TextFormField(
controller: itemNameController,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Item Name',
),
),
SizedBox(
width: 220,
height: 100,
child: InkWell(
onTap: () {
print(
"Amount: ${amountController.text} Item: ${itemNameController.text}");
model?.payment(
amountController.text, itemNameController.text);
},
child: Container(
alignment: Alignment.center,
color: Colors.blue,
child: const Center(
child: Text("Pay",
style: TextStyle(fontSize: 22, color: Colors.white))),
),
),
),
],
),
),
);
}
}
class WebViewPage extends StatefulWidget {
const WebViewPage({Key? key}) : super(key: key);
@override
WebViewPageState createState() => WebViewPageState();
}
class WebViewPageState extends State<WebViewPage> {
PaymentViewModel? model;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Web View"),
),
body: Column(children: [
Expanded(
child: WebView(
initialUrl: model?.payFast,
javascriptMode: JavascriptMode.unrestricted,
onPageFinished: _onUrlChange,
debuggingEnabled: true,
))
]));
}
_onUrlChange(String url) {
print('Page finished loading: $url');
if (mounted) {
setState(() {
if (url.contains("http://localhost:8080/#/onSuccess")) {
Navigator.pushNamed(context, "/onSuccess");
} else if (url.contains("http://localhost:8080/#/onCancel")) {
Navigator.pushNamed(context, "/onCancel");
}
});
}
}
}
class PaymentViewModel {
TextEditingController amountController = TextEditingController();
TextEditingController itemNameController = TextEditingController();
API? api;
String? errorMessage;
String? payFast;
void payment(String? amount, String? item_name) {
//amount = amountController.text;
item_name = itemNameController.text;
api
?.payFastPayment(amount: amount, item_name: item_name)
.then((createdPayment) {
if (createdPayment == null) {
errorMessage = "Something went wrong. Please try again.";
} else {
payFast = createdPayment;
}
print("It reaches here");
}).catchError((error) {
errorMessage = '${error.toString()}';
});
}
}
class API {
static String baseURL = 'https://sandbox.payfast.co.za';
var client = new http.Client();
Future<String> payFastPayment({
String? amount,
String? item_name,
}) async {
Map<String, String>? requestHeaders;
final queryParameters = {
'merchant_key': '46f0cd694581a',
'merchant_id': '10000100',
'amount': '$amount',
'item_name': '$item_name',
'return_url': 'http://localhost:8080/#/onSuccess',
'cancel_url': 'http://localhost:8080/#/onCancel',
};
Uri uri = Uri.https(baseURL, "/eng/process", queryParameters);
print("URI ${uri.data}");
final response = await client.put(uri, headers: requestHeaders);
print("Response body ${response.body}");
if (response.statusCode == 200 ||
response.statusCode == 201 ||
response.statusCode == 203 ||
response.statusCode == 204) {
return response.body;
} else if (response.body != null) {
return Future.error(response.body);
} else {
return Future.error('${response.toString()}');
}
}
}
class OnSuccess extends StatelessWidget {
const OnSuccess({Key? key}) : super(key: key);
static const String route = 'onSuccess';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"This is on Success",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 33),
),
SizedBox(width: 15),
Icon(
Icons.check,
color: Colors.green,
size: 40,
)
],
)),
);
}
}
class OnCancel extends StatelessWidget {
const OnCancel({Key? key}) : super(key: key);
static const String route = 'OnCancel';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"This is on Cancel",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 33),
),
SizedBox(width: 15),
Icon(
Icons.close,
color: Colors.red,
size: 40,
)
],
)),
);
}
}
您的初始网址似乎为空。您已创建名为 model 的 paymentViewModel 实例。并在 webview 的初始 url 中调用它。在 paymentViewModel 中 payFast 只是一个可为空的字符串。所以 url 可能为空。请检查
class PaymentProvider with ChangeNotifier {
final String merchantId = 'xxxxx';
final String merchantKey = 'xxxxx';
final String passphrase = 'xxxx';
final String returnUrl = 'YourWeb';
final String cancelUrl = 'YourWeb';
final String notifyUrl = 'YourWeb';
String webviewUrl = '';
bool testingMode = true;
double cartTotal = 20.0;
Future<String> createPaymentRequest(String paymentId, String firstName,
String lastName, String emailAddress) async {
try {
Map<String, String> data = {
'merchant_id': merchantId,
'merchant_key': merchantKey,
'return_url': returnUrl,
'cancel_url': cancelUrl,
'notify_url': notifyUrl,
'name_first': firstName,
'name_last': lastName,
'email_address': emailAddress,
'm_payment_id': paymentId,
'amount': cartTotal.toStringAsFixed(2),
'item_name': 'Order#$paymentId',
};
String signature = await generateSignature(data, passphrase);
data['signature'] = signature;
String pfHost =
testingMode ? 'sandbox.payfast.co.za' : 'www.payfast.co.za';
String paymentUrl = 'https://$pfHost/eng/process?';
data.forEach((key, value) {
paymentUrl += '$key=${Uri.encodeComponent(value)}&';
});
webviewUrl = paymentUrl;
notifyListeners();
return paymentUrl;
} catch (e) {
log('error at createPaymentRequest: ${e.toString()}');
return '';
}
}
Future<String> generateSignature(Map<String, String> data, String passphrase) async {
return 'signature_placeholder';
}
}
之后你可以在flutetr webview(WebViewWidget)中使用webviewUrl