Http POST 在 Postman 中有效,但在 Flutter 中无效 [英] Http POST works in Postman but not in 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-Id
和 X-Target-Environment
由服务器区分大小写(即它不符合 RFC).>
Dart 的 io.HttpClient
强制标头为小写,因此这会影响 package:http
和 package: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屋!