首页 > 解决方案 > 未能从 http.post [http: 499] 得到响应

问题描述

我想使用支付页面提供商构建支付页面。因此,我创建了一个类,它使用 futureBuilder 构建所需的小部件。我想从一个 API 接收一个我想嵌入 iFrame 的 URL。但是,未来的数据是每次null和快照都有错误。但不幸的是,这个错误是空的。从 FlutterDevTools Network 我可以看到 http 请求仍处于待处理状态。在 Python 中,我尝试执行此请求并且它在那里工作(最后我发布了我的脚本的相关代码)

我在两件事上挣扎。1)当错误仍然为空时,我没有找到如何解决问题的信息,以及 2)为什么 http 请求一直处于挂起状态?

我试过了

try {
      response = await http.post(uriUrl, headers: headers, body: body);
    } catch (e) {
      print(e.toString());
    }

但是错误是空的。所以它也没有帮助。

[更新 21.10.21 ]:我从 API 联系了人们,他们看到了一个传入的请求,但我的一方(客户端)在服务器能够响应之前取消。

在此处输入图像描述

我发现 499 是一个 CLIENT CLOSED REQUEST,它是 nginx 引入的非标准状态代码,用于在 nginx 处理请求时客户端关闭连接的情况。

我发现NGINX 499 错误代码的可能原因,人们建议增加超时,但老实说,我不知所措,因为我对更复杂的 http 问题没有经验。

class _PaymentState extends State<Payment> {
  late Future<PaymentPage> paymentPage;

  @override
  void initState() {
    paymentPage =
        APIManagerSaferpay().getPaymentPage(widget.price, widget.description);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: FutureBuilder<PaymentPage>(
            future: paymentPage,
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                // the code ends up here
                return Center(child: Text(snapshot.error.toString()));
              }
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                  break;
                case ConnectionState.active:
                  return const Center(child: CircularProgressIndicator());
                case ConnectionState.done:
                  //debugger();
                  String url = snapshot.data!.redirectUrl;
                  return Center(
                      child: WebView(
                    initialUrl: Uri.dataFromString(
                            '<html><body><iframe src="$url"></iframe></body></html>',
                            mimeType: 'text/html')
                        .toString(),
                    javascriptMode: JavascriptMode.unrestricted,
                  ));

这就是我编写该方法getPaymentPage调用的异步函数的initState()方式。

class APIManagerSaferpay {
  final String customerId = '******';
  final String terminalId = '********';
  String url = 'https://test.saferpay.com';
  final String authHeader = 'API_******_********:JsonApiPwd1_************';


  Future<PaymentPage> getPaymentPage(double total, String description) async {
    url = 'https://test.saferpay.com/api/Payment/v1/PaymentPage/Initialize';
    var bytes = utf8.encode(authHeader);
    var base64StrCred = base64.encode(bytes);
    var page = null;

    final queryParameters = {
      "RequestHeader": {
        "SpecVersion": "1.24",
        "CustomerId": "******",
        "RequestId": "1234567890",
        "RetryIndicator": 0
      },
      "TerminalId": "********",
      "PaymentMethods": ["Twint"],
      "Payment": {
        "Amount": {"Value": "$total", "CurrencyCode": "CHF"},
        "OrderId": "1234",
        "Description": "Lunchroom"
      },
      "ReturnUrls": {
        "Success": "https://amazon.com", // atm just arbitrary pages
        "Fail": "https://youtube.com"
      }
    };
    final body = jsonEncode(queryParameters);
    final uriUrl = Uri.parse(url);
    final headers = {
      'Authorization': 'Basic $base64StrCred',
      'Content-Type': 'application/json; charset=utf-8',
      'Accept': 'application/json'
    };
    var response = null;
    response = await http.post(uriUrl, headers: headers, body: body);

    if (response.statusCode == 200) {
      // this code is never reached
      var jsonString = response.body;
      var decoded = utf8.decode(jsonString.runes.toList());
      page = PaymentPageFromJson(decoded);
    }
    if (response.statusCode >= 400) {
      // this code is never reached
    }
    return page;
  }
}

FlutterDevTools 的截图:

Flutter 开发者工具网络 (1/2)

即使我定义了请求标头,请求仍然为空:

有趣的是,请求头是空的

屏幕截图显示代码中断后请求仍处于挂起状态 ( // the code ends up here)

http请求仍然挂起

运行 Python 代码

import base64

...
authHeader = f'{username}:{pw}'
encodedCredentials = base64.b64encode(authHeader.encode()).decode()
header = {"Authorization": f"Basic {encodedCredentials}", "Content-Type": "application/json; charset=utf-8", "accept": "application/json"}

queryParameters = {
    "RequestHeader": {
        "SpecVersion": "1.24",
        "CustomerId": ******,
        "RequestId": "ccfbac3a8ef5151ae98035f45a609741",
        "RetryIndicator": 0
    },
    "TerminalId": ********,
    "PaymentMethods": ["TWINT"],
    "Payment": {
        "Amount": {"Value": "200", "CurrencyCode": "CHF"},
        "OrderId": "2",
        "Description": 'Lunchroom:'
    },
    "ReturnUrls": {
        "Success": 'https://amazon.com',
        "Fail": 'https://youtube.com'
    }
}


response = requests.post(url="https://test.saferpay.com/api/Payment/v1/PaymentPage/Initialize", headers=header, json=queryParameters)

标签: flutterhttpdartrequestdart-io

解决方案


推荐阅读