Http POST 在 Postman 中有效,但在 Flutter 中无效
Posted
技术标签:
【中文标题】Http POST 在 Postman 中有效,但在 Flutter 中无效【英文标题】:Http POST works in Postman but not in Flutter 【发布时间】:2020-04-28 22:58:42 【问题描述】:我正在尝试使用 Http 包对我的颤振应用程序执行 POST 请求。我首先在 Api 沙盒网站上测试了我的请求,然后在 Postman 中测试了我的请求。它在那里运行良好,但是一旦在 Flutter 中,我总是收到 400 Bad Request。
这是我在 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;
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 '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'
在邮递员及其网站上,我总是收到 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", "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();
【问题讨论】:
您的 Dart 代码似乎是正确的。但是,如果不将自己注册到您尝试使用的网站,我们就无法真正对此进行测试。 这可能是偶尔出现的服务器问题。post
将通过两种方式修改内容类型。 (1) 它将标头名称小写为content-type
,(2) 它将值更改为application/json; charset=utf-8
。调整你的 curl 命令来模仿这些,看看它是成功还是失败。如果问题是 (2) 解决方案很简单:将 body: jsonBody
更改为 body: utf8.encode(jsonBody)
。 (1) 的解决方案比较棘手。
@RichardHeap 我刚试过这个: --header 'content-type: application/json; charset=utf-8' 在我的卷曲中,我在邮递员中接受了 202。在我的颤振应用程序中仍然有 400 个错误请求。您对问题的根源还有其他想法吗?感谢您的帮助!
尝试其他建议,只是为了好玩。然后断言 curl 适用于 all 小写标题名称,例如ocp-apim-subscription-key
@RichardHeap,我尝试使用小写标题,但在 Postman 上失败了。 opc-apim-subscription-key 小写有效,但 x-target-environment 和 x-reference-id 因 400 bad request 而失败。你知道我如何在颤动中绕过强制小写吗?
【参考方案1】:
这绝对是服务器的问题。服务器正在处理两个标头 X-Reference-Id
和 X-Target-Environment
区分大小写(即它不符合 RFC)。
这是 Dart 的 io.HttpClient
强制标题为小写,因此这会影响 package:http
和 package:dio
两者都依赖它。有一个request 允许客户端保留标头的大小写,但由于这是一项重大更改,因此进展缓慢。
同时,尝试使用保留标头大小写的客户端分支。 https://pub.dev/packages/alt_http/
【讨论】:
好的,非常感谢您的回答和您的时间。我会试试那个包。很抱歉聊天问题,不知道为什么它仍然无法正常工作。 至少你现在应该可以投票了——哈哈 :-)【参考方案2】:通过将 jsonBody 从 String 更改为 Map 解决了同样的问题。
String jsonBody = '"amount": "5","currency": "EUR", "externalId": "123", "payer": "partyIdType": "MSISDN","partyId": "46733123454", "payerMessage": "tripId-123456","payeeNote": "driverId-654321"';
只有当从String -> Map改变时才解决;
Map jsonBody = "amount": "5","currency": "EUR", "externalId": "123", "payer": "partyIdType": "MSISDN","partyId": "46733123454", "payerMessage": "tripId-123456","payeeNote": "driverId-654321";
此外,还包括 jsonEncode
Response response = await post(url, headers: headers, body: jsonEncode(jsonBody));
jsonEncode 需要导入转换库
import 'dart:convert';
【讨论】:
以上是关于Http POST 在 Postman 中有效,但在 Flutter 中无效的主要内容,如果未能解决你的问题,请参考以下文章
postman post请求 header 和body怎么用
Multipart POST 适用于 Postman,但不适用于 Angular Http Client
简单的 POST 请求在 Postman 中有效,但在浏览器中无效
POST 请求在 Postman 中有效,但在 Python 请求中无效(200 响应机器人检测)