.NET Core使用HttpClient进行表单提交时遇到的问题
问题#
在开发微信支付的小微商户进件接口时,需要通过表单来上传身份证图片等数据。在微信支付接口文档也说明了,需要使用multipart/form-data的方式发送请求。.NET提供了MultipartFormDataContent类型,帮助我们构建表单请求,故有以下代码:
varform=newMultipartFormDataContent() { {newStringContent("Value"),"Name}, {newByteArrayContent(newbyte[]{}/*模拟文件数据*/),"File,"FileName} }
按照微信支付官方文档提交之后,一直提示参数错误,百思不得其解。
原因#
通过Postman模拟表单提交,捕获数据包,将其与C#的提交代码进行对比,发现了两处问题。
Postman的原始提交:
POSThttp://api.mch.weixin.qq.com/secapi/mch/uploadmediaHTTP/1.1
User-Agent:PostmanRuntime/7.21.0
Accept:*/*
Cache-Control:no-cache
Postman-Token:b6800c0f-3f16-4981-b661-e6d16fc1bb1e
Host:api.mch.weixin.qq.com
Content-Type:multipart/form-data;boundary=--------------------------639275760242036520206377
Accept-Encoding:gzip,deflate
Content-Length:566
Connection:keep-alive----------------------------639275760242036520206377
Content-Disposition:form-data;name="mch_id"1565111111
----------------------------639275760242036520206377
Content-Disposition:form-data;name="media_hash"7215E92A8F3F3D0256484EFFF53A25F6
----------------------------639275760242036520206377
Content-Disposition:form-data;name="sign_type"HMAC-SHA256
----------------------------639275760242036520206377
Content-Disposition:form-data;name="sign"A1D8B094FA24BE5531D1AC198DE25550
----------------------------639275760242036520206377--
C#代码的提交:
POSThttp://api.mch.weixin.qq.com/secapi/mch/uploadmediaHTTP/1.1
Host:api.mch.weixin.qq.com
Content-Type:multipart/form-data;boundary="e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217"
Content-Length:502--e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217
Content-Type:text/plain;charset=utf-8
Content-Disposition:form-data;name=mch_id
--e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217
Content-Type:text/plain;charset=utf-8
Content-Disposition:form-data;name=media_hash33F15BC2D17D6FFBC18FA566EF65722E
--e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217
Content-Type:text/plain;charset=utf-8
Content-Disposition:form-data;name=sign1E377684F9BD583D2ED26FB367916C0C
--e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217--
1.Boundary的双引号
使用MultipartFormDataContent提交的表单请求,外部Content-Type的boundary值带有"号。而Postman提交的表单请求,它的boudary值是没有双引号的。
那为什么会造成这样的差异呢?参考这篇博客的讲解,是由于各个系统/语言针对RFC2046的实现不一致导致的。针对于MultipartFormDataContent的行为,如果Boundary后面的值带有双引号是符合标准的。
RFC2612原文:
2)AlthoughRFC2046[40]permitstheboundarystringtobe
quoted,someexistingimplementationshandleaquotedboundary
stringincorrectly.
Boundary的作用,是一个随机生成的字符串,在HTTP协议当中用于分割内部多个Content。为什么是随机生成的呢?就是防止这个分割符跟你内部的Content产生重复造成意外。(C#默认使用的是Guid作为随机串,你也可以在构造MultipartFormDataContent的时候,通过其构造函数手动指定)
2.表单内键值对,值的双引号
第二个问题则是表单内的内容,他们的name键值对,其值又没有双引号,所以你得在添加Content的时候,得手动指定双引号。
解决#
两个问题都是由于双引号导致的,所以只需要在真正发起调用之前将内部的双引号替换为空,或者将缺失的双引号添加上即可。
针对问题一,其内部的ContentType.Parameters,通过LINQ找到boundary的键值对,替换内部的双引号即可。
varboundaryValue=form.Headers.ContentType.Parameters.Single(p=>p.Name=="boundary"); boundaryValue.Value=boundaryValue.Value.Replace("\"",String.Empty);
针对问题二,在构造内部Content的时候,其Name手动赋予双引号。
varform=newMultipartFormDataContent { {newStringContent(mchId),"\"mch_id\""}, {newByteArrayContent(bytes),"media",$"\"{HttpUtility.UrlEncode(Path.GetFileName(imagePath))}\""}, {newStringContent(mediaHash),"\"media_hash\""}, {newStringContent(sign),"sign"} };
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。