Http POST 在 Postman 中有效,但在 Flutter 中无效 [英] Http POST works in Postman but not in Flutter

查看:32
本文介绍了Http POST 在 Postman 中有效,但在 Flutter 中无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Http 包对我的 Flutter 应用程序执行 POST 请求.我首先在 Api 沙盒网站上测试了我的请求,然后在 Postman 中测试了我的请求.它在那里运行良好,但一旦在 Flutter 中,我总是收到 400 Bad Request.

这是我在 Flutter 中的代码:

import 'package:http/http.dart';导入'包:uuid/uuid.dart';导入 'package:wave_app/env/secrets.dart';导入 'package:wave_app/models/momo_token.dart';String url = "https://sandbox.momodeveloper.mtn.com/collection/v1_0/requesttopay";var uuid = Uuid();String requestId = uuid.v4();MomoToken 令牌 = await _createMomoNewTokenCollection();String auth = "Bearer " + token.accessToken;映射<字符串,字符串>标题 = {授权":auth,"X-Target-Environment": "沙盒","X-Reference-Id": requestId,"内容类型": "应用程序/json","Ocp-Apim-Subscription-Key": momoCollectionSubscriptionKey};String jsonBody = '{"amount": "5","currency": "EUR", "externalId": "123", "payer": {"partyIdType": "MSISDN","partyId": "46733123454"}, "payerMessage": "tripId-123456","payeeNote": "driverId-654321"}';响应 response = await post(url, headers: headers, body: jsonBody);int statusCode = response.statusCode;打印(状态代码请求支付" + statusCode.toString());打印(response.reasonPhrase.toString());打印(response.body.toString());如果(状态码 == 202){返回 response.body.toString();} 别的 {返回空;}}

API 文档在这里:https://momodeveloper.mtn.com/docs/services/collection/operations/requesttopay-POST?

这是我的 Postman 请求的 curl 代码(使用 requestId、auth、momoCollectionSubscriptionKey 上面的相同变量)

curl --request POST \--url https://sandbox.momodeveloper.mtn.com/collection/v1_0/requesttopay \--header '接受:*/*' \--header 'Accept-Encoding: gzip, deflate' \--header '授权:承载eyJ0eXAiOiJKV1QiLCJhbGciOiJSMjU2In0.eyJjbGllbnRJZCI6IjFmY2MzMjBhLTM0NWQtMTFlYS04NTBkLTJlNzI4Y2U4ODEyNSIsImV4cGlyZXMiOiIyMDIwLTAxLTExVDE1OjU3OjE4Ljc3NyIsInNlc3Npb25JZCI6ImZmYzc1OGE2LTM2MWEtNDM4ZS1hYjE5LWQ1ZGQ4ZmU4ZjEyOSJ9.DeoJyU6Hb0he_or1XeBxW-6S-xwdtmi0cUrYjQe0Z796bIGvvT-VJ214JaZItG-CBQpgv7dHbLfXNqr8D05Q7U9XiOtpr8mtYWQlY-MseGIHAyxp1qBuQkwjmBYBlDxQOYYfzG9SZ8tGFUI1_k59LMNYIhDlXXKa68Ym1sylZ8wfWjGuHaKVzMEH25ubiBwCLev5IHPchuF3toVP99U-HC8t95E3zrEt9dHgzn0hnwvpB31wcsu_b3vb-YZ1idHgosPc2GmKFsDruX14VniKBicCsnGHqZAkSPXwaOR6SIn4JZEEwhAIj3Oe2H5dwxloiX5rzaApdkwEg6KSoBXk8A' \--header '缓存控制:无缓存' \--header '连接:保持活动' \--header '内容长度:194' \--header '内容类型:应用程序/json' \--header '主机:sandbox.momodeveloper.mtn.com' \--header 'Ocp-Apim-Subscription-Key: 281eb****************' \--header '邮递员令牌:ece19062-1f0b-4873-a3ed-1bd4ada8746a,528004b2-410d-4653-9909-5197a3dc95db' \--header '用户代理:PostmanRuntime/7.20.1' \--header 'X-Reference-Id: 062f8aad-f529-4d0a-804c-affb888c2b8b' \--header 'X-Target-Environment: 沙箱' \--header '缓存控制:无缓存' \--data '{\r\n "amount": "5",\r\n "currency": "EUR",\r\n "externalId": "123",\r\n "payer": {\r\n "partyIdType": "MSISDN",\r\n "partyId": "46733123454"\r\n },\r\n "payerMessage": "hi",\r\n "payeeNote": "嗨"\r\n}'

在邮递员和他们的网站上,我总是收到 202 Accepted 回复.我不确定,我在这里做错了什么.任何帮助将不胜感激!

------------ 编辑-------------------

我也尝试过 HttpClient,这是代码,但仍然收到 400 Bad Request

HttpClient httpClient = new HttpClient();HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));request.headers.set("Authorization", "Bearer" + token.accessToken);request.headers.set('content-type', 'application/json');request.headers.set("X-Target-Environment", "沙箱");request.headers.set("X-Reference-Id", requestId);request.headers.set("Ocp-Apim-Subscription-Key", momoCollectionSubscriptionKey);request.add(utf8.encode(jsonBody));HttpClientResponse 响应 = 等待 request.close();打印(状态代码"+ response.statusCode.toString() +" + response.reasonPhrase);字符串回复 = 等待 response.transform(utf8.decoder).join();打印(回复"+回复);httpClient.close();

解决方案

这肯定是服务器的问题.两个标头 X-Reference-IdX-Target-Environment 由服务器区分大小写(即它不符合 RFC).>

Dart 的 io.HttpClient 强制标头为小写,因此这会影响 package:httppackage:dio,它们都依赖于它.有一个 request 允许客户端保留标题的大小写,但它即将到来慢慢地,因为这是一个突破性的变化.

与此同时,请尝试使用保留标头大小写的客户端的这个分支.https://pub.dev/packages/alt_http/

I am trying to do a POST request on my flutter application using the Http package. I tested my request first on the Api sandbox website, and then in Postman. It works well there, but once in Flutter, I always get a 400 Bad Request.

Here is my code in Flutter:

import 'package:http/http.dart';
import 'package:uuid/uuid.dart';
import 'package:wave_app/env/secrets.dart';
import 'package:wave_app/models/momo_token.dart';

    String url = "https://sandbox.momodeveloper.mtn.com/collection/v1_0/requesttopay";
    var uuid = Uuid();
    String requestId = uuid.v4();
    MomoToken token = await _createMomoNewTokenCollection();

    String auth = "Bearer " + token.accessToken;

    Map<String, String> headers = {
      "Authorization": auth,
      "X-Target-Environment": "sandbox",
      "X-Reference-Id": requestId,
      "Content-Type": "application/json",
      "Ocp-Apim-Subscription-Key": momoCollectionSubscriptionKey
    };

    String jsonBody = '{"amount": "5","currency": "EUR", "externalId": "123", "payer": {"partyIdType": "MSISDN","partyId": "46733123454"}, "payerMessage": "tripId-123456","payeeNote": "driverId-654321"}';

    Response response = await post(url, headers: headers, body: jsonBody);
    int statusCode = response.statusCode;

    print("STATUS CODE REQUEST TO PAY " + statusCode.toString());
    print(response.reasonPhrase.toString());
    print(response.body.toString());

    if (statusCode == 202) {
      return response.body.toString();
    } else {
      return null;
    }
  }

The api doc is here: https://momodeveloper.mtn.com/docs/services/collection/operations/requesttopay-POST?

And here is the code in curl of my Postman request (using the same variable above requestId, auth, momoCollectionSubscriptionKey)

curl --request POST \
  --url https://sandbox.momodeveloper.mtn.com/collection/v1_0/requesttopay \
  --header 'Accept: */*' \
  --header 'Accept-Encoding: gzip, deflate' \
  --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSMjU2In0.eyJjbGllbnRJZCI6IjFmY2MzMjBhLTM0NWQtMTFlYS04NTBkLTJlNzI4Y2U4ODEyNSIsImV4cGlyZXMiOiIyMDIwLTAxLTExVDE1OjU3OjE4Ljc3NyIsInNlc3Npb25JZCI6ImZmYzc1OGE2LTM2MWEtNDM4ZS1hYjE5LWQ1ZGQ4ZmU4ZjEyOSJ9.DeoJyU6Hb0he_or1XeBxW-6s-xwdtmi0cUrYjQe0Z796bIGvvT-VJ214JaZItG-CBQpgv7dHbLfXNqr8D05Q7U9XiOtpr8mtYWQlY-MseGIHAyxp1qBuQkwjmBYBlDxQOYYfzG9SZ8tGFUI1_k59LMNYIhDlXXKa68Ym1sylZ8wfWjGuHaKVzMEH25ubiBwCLev5IHPchuF3toVP99U-HC8t95E3zrEt9dHgzn0hnwvpB31wcsu_b3vb-YZ1idHgosPc2GmKFsDruX14VniKBicCsnGHqZAkSPXwaOR6SIn4JZEEwhAIj3Oe2H5dwxloiX5rzaApdkwEg6KSoBXk8A' \
  --header 'Cache-Control: no-cache' \
  --header 'Connection: keep-alive' \
  --header 'Content-Length: 194' \
  --header 'Content-Type: application/json' \
  --header 'Host: sandbox.momodeveloper.mtn.com' \
  --header 'Ocp-Apim-Subscription-Key: 281eb****************' \
  --header 'Postman-Token: ece19062-1f0b-4873-a3ed-1bd4ada8746a,528004b2-410d-4653-9909-5197a3dc95db' \
  --header 'User-Agent: PostmanRuntime/7.20.1' \
  --header 'X-Reference-Id: 062f8aad-f529-4d0a-804c-affb888c2b8b' \
  --header 'X-Target-Environment: sandbox' \
  --header 'cache-control: no-cache' \
  --data '{\r\n  "amount": "5",\r\n  "currency": "EUR",\r\n  "externalId": "123",\r\n  "payer": {\r\n    "partyIdType": "MSISDN",\r\n    "partyId": "46733123454"\r\n  },\r\n  "payerMessage": "hi",\r\n  "payeeNote": "hi"\r\n}'

On postman and their website, I always get a 202 Accepted response. I am not sure, what I'm doing wrong here. Any help would be greatly appreciated!

------------ EDIT -------------------

I also tried with HttpClient, here is the code, but still got 400 Bad Request

HttpClient httpClient = new HttpClient();
    HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));

    request.headers.set("Authorization", "Bearer " + token.accessToken);
    request.headers.set('content-type', 'application/json');
    request.headers.set("X-Target-Environment", "sandbox");
    request.headers.set("X-Reference-Id", requestId);
    request.headers.set("Ocp-Apim-Subscription-Key", momoCollectionSubscriptionKey);

    request.add(utf8.encode(jsonBody));
    HttpClientResponse response = await request.close();

    print("STATUS CODE " + response.statusCode.toString() + "   " + response.reasonPhrase);
    String reply = await response.transform(utf8.decoder).join();
    print("REPLY " + reply);
    httpClient.close();

解决方案

This is definitely a problem with the server. The two headers X-Reference-Id and X-Target-Environment are being handled case sensitively by the server (i.e. it is not in compliance with the RFC).

It's Dart's io.HttpClient that forces headers to lower case, so this affects package:http and package:dio which both rely on it. There's a request to allow the client to preserve the case of headers but it's coming slowly as it's a breaking change.

In the meantime, try using this fork of the client which preserves header case. https://pub.dev/packages/alt_http/

这篇关于Http POST 在 Postman 中有效,但在 Flutter 中无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆