Flutter发送JSON Array格式POST请求的实现与报错排查
问题修复方案
你当前遇到的报错分为两类,分别是SSL证书校验失败、请求格式不符合接口要求,对应解决方法如下:
1. 修复HandshakeException证书报错
报错核心原因是目标服务端的SSL证书已过期,Flutter内置的网络请求客户端默认会严格校验SSL证书有效性,而Postman默认开启了忽略证书无效的配置,因此可以正常发起请求。
注意:测试阶段可临时绕过证书校验快速调试,生产环境必须要求服务端更换有效SSL证书,长期绕过校验存在中间人攻击的安全风险。
临时绕过证书校验的实现:不要直接使用http包默认的客户端,自定义基于dart:ioHttpClient的请求客户端,配置证书校验回调:
import 'dart:io'; import 'package:http/io_client.dart'; // 构造测试用忽略证书校验的客户端 HttpClient _httpClient = HttpClient() ..badCertificateCallback = (X509Certificate cert, String host, int port) => true; final httpClient = IOClient(_httpClient);
2. 修复POST请求体格式错误
你当前代码有四个格式问题:
- 接口要求请求体最外层是JSON数组(最外层包裹
[]),你直接传入了单个JSON对象(最外层是{}),不符合接口格式要求 - 请求头的键名写错:
Content type应为标准头字段Content-Type,否则服务端无法正确识别JSON请求体 merchantKey字符串拼接错误:原字符串的$符号被Dart识别为字符串插值语法,导致值和接口要求的不一致,需要用raw字符串(前缀加r)避免转义- 手动拼接
items字段的JSON字符串容易出现转义错误,直接通过jsonEncode序列化商品列表得到字符串即可。
核心请求体修正逻辑:将模型对象放入数组后再进行JSON编码,即:
// 错误写法:直接编码单个对象,最外层是{} // body: convert.jsonEncode(siPayModel.toJson()) // 正确写法:放入数组后编码,最外层是[] body: convert.jsonEncode([siPayModel.toJson()])
3. 修正后的完整请求代码
import 'dart:convert' as convert; import 'dart:io'; import 'package:http/http.dart' as http; import 'package:http/io_client.dart'; import '../model/sipayjson.dart'; class SiPay { static const testUrl = "https://provisioning.sipay.com.tr/ccpayment/api/paySmart2D"; static const liveUrl = "https://app.sipay.com.tr/ccpayment/api/paySmart2D"; static const sKey = "b46a67571aa1e7ef566f1712a"; static const pKey = "6d4a7e9374a7315b0b9"; // 用r前缀声明raw字符串,避免$被识别为插值语法 static const merchantKey = r"$2y$10$HmRgYosneqcwHj.UH7upGuyCZqpQ1ITgSMj9Vvxn.t6f.Vdf2SQFO"; // 修正请求头键名 Map<String, String> header = { "Content-Type": "application/json", "Authorization": "Bearer", "Accept": "application/json", }; // 构造测试用客户端,临时忽略证书校验 final http.Client _client = IOClient( HttpClient()..badCertificateCallback = (cert, host, port) => true ); Future<void> doPayment() async { // 构造商品列表,直接序列化得到JSON字符串,避免手动转义出错 final itemsList = [ {"name":"pr001","price":"2.30","quantity":1,"description":"pr001"}, {"name":"pr001","price":"2.70","quantity":1,"description":"pr001"}, {"name":"pr001","price":"5.00","quantity":2,"description":"pr001"} ]; final itemsStr = convert.jsonEncode(itemsList); SiPayModel siPayModel = SiPayModel( ccHolderName: "John Dao", ccNo: "4508034508034509", expiryMonth: 12, expiryYear: 2026, cvv: 543, currencyCode: "TRY", installmentsNumber: 1, invoiceId: 5874544, invoiceDescription: "5974544 Ödemesi", name: "John", surname: "Dao", total: 458, merchantKey: merchantKey, items: itemsStr, cancelUrl: "string", returnUrl: "string", hashKey: "", // 后续按照接口签名规则计算出正确值替换即可 orderType: 0 ); var res = await _client.post( Uri.parse(testUrl), headers: header, // 核心:将模型对象放入数组后再编码,匹配接口要求的数组格式 body: convert.jsonEncode([siPayModel.toJson()]) ); if (res.statusCode == 200) { print(res.statusCode); print(res.body); } else { print(res.statusCode); throw Exception("Payment error"); } } }
补充说明
如果请求格式正确后仍返回101 Unauthorized错误,是因为你还未按照接口文档的签名规则生成合法的hash_key值,该问题属于接口鉴权逻辑范畴,和Flutter请求实现无关,按照文档要求计算出对应签名值传入即可。
内容的提问来源于stack exchange,提问作者mohamad kattan
相关产品推荐
相关产品推荐

