相关文章推荐
怕老婆的仙人球  ·  My monitor is going ...·  9 月前    · 
怕老婆的仙人球  ·  CodeIgniter4 Email ...·  9 月前    · 
怕老婆的仙人球  ·  libusb-win32 - ...·  9 月前    · 
怕老婆的仙人球  ·  Sysinternals Desktops ...·  10 月前    · 
怕老婆的仙人球  ·  使用 HttpClient ...·  10 月前    · 
挂过科的企鹅  ·  Java ...·  1小时前    · 
鼻子大的甘蔗  ·  epplus ...·  1小时前    · 
稳重的警车  ·  jquery beforeunload方法 ...·  3 小时前    · 

在开发微信支付的小微商户进件接口时,需要通过表单来上传身份证图片等数据。在微信支付接口文档也说明了,需要使用 multipart/form-data 的方式发送请求。.NET 提供了 MultipartFormDataContent 类型,帮助我们构建表单请求,故有以下代码:

var form = new MultipartFormDataContent()
    {new StringContent("Value"),"Name},
    {new ByteArrayContent(new byte[]{}/*模拟文件数据*/),"File,"FileName}

按照微信支付官方文档提交之后,一直提示参数错误,百思不得其解。

通过 Postman 模拟表单提交,捕获数据包,将其与 C# 的提交代码进行对比,发现了两处问题。

Postman 的原始提交:

POST http://api.mch.weixin.qq.com/secapi/mch/uploadmedia HTTP/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# 代码的提交:

POST http://api.mch.weixin.qq.com/secapi/mch/uploadmedia HTTP/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_hash
33F15BC2D17D6FFBC18FA566EF65722E
--e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=sign
1E377684F9BD583D2ED26FB367916C0C
--e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217--

1. Boundary 的双引号

使用 MultipartFormDataContent 提交的表单请求,外部 Content-Type 的 boundary 值带有 " 号。而 Postman 提交的表单请求,它的 boudary 值是没有双引号的。

那为什么会造成这样的差异呢?参考 这篇 博客的讲解,是由于各个系统/语言针对 RFC 2046 的实现不一致导致的。针对于 MultipartFormDataContent 的行为,如果 Boundary 后面的值带有双引号是符合标准的。

RFC 2612 原文:

2) Although RFC 2046 [40] permits the boundary string to be
quoted, some existing implementations handle a quoted boundary
string incorrectly.

Boundary 的作用,是一个随机生成的字符串,在 HTTP 协议当中用于分割内部多个 Content。为什么是随机生成的呢?就是防止这个分割符跟你内部的 Content 产生重复造成意外。(C# 默认使用的是 Guid 作为随机串,你也可以在构造 MultipartFormDataContent 的时候,通过其构造函数手动指定)

2. 表单内键值对,值的双引号

第二个问题则是表单内的内容,他们的 name 键值对,其值又没有双引号,所以你得在添加 Content 的时候,得手动指定双引号。

两个问题都是由于双引号导致的,所以只需要在真正发起调用之前将内部的双引号替换为空,或者将缺失的双引号添加上即可。

针对问题一,其内部的 ContentType.Parameters ,通过 LINQ 找到 boundary 的键值对,替换内部的双引号即可。

var boundaryValue = form.Headers.ContentType.Parameters.Single(p => p.Name == "boundary");
boundaryValue.Value = boundaryValue.Value.Replace("\"", String.Empty);

针对问题二,在构造内部 Content 的时候,其 Name 手动赋予双引号。

var form = new MultipartFormDataContent
    {new StringContent(mchId), "\"mch_id\""},
    {new ByteArrayContent(bytes), "media", $"\"{HttpUtility.UrlEncode(Path.GetFileName(imagePath))}\""},
    {new StringContent(mediaHash), "\"media_hash\""},
    {new StringContent(sign), "sign"}
                    问题在开发微信支付的小微商户进件接口时,需要通过表单来上传身份证图片等数据。在微信支付接口文档也说明了,需要使用 multipart/form-data 的方式发送请求。.NET 提供了MultipartFormDataContent类型,帮助我们构建表单请求,故有以下代码:var form = new MultipartFormDataContent(){    {new St...
				
https://www.cnblogs.com/hnxxcxg/category/1467290.html 咏南博客 delphi nethttpclient操作cookieTNetHttpClient的用法 TNetHTTPClient演示 TNetHttpClient支持异步访问(Delphi10.1Berlin)http://blog.sina.com.cn/s...
在C#中有HttpWebRequest类,可以很方便用来获取http请求,但是这个类对Post方式没有提供一个很方便的方法来获取数据。网上有很多人提供了解决方法,但都参差不齐,这里我把我使用的方法总结出来,与大家分享。 本文精华:实现了post的候即可以有字符串的key-value,还可以带文件。 Post数据格式 Post提交数据的候最重要就是把Key-Value的数
public class HttpClient { private static String charset = "UTF-8"; // 此方法是POST请求上传的参数中包含本地图片信息File类型 public String request(String url, HashMap<String, Object> fields, HashMap<S...
public static String getStringURLtoPost(String url, Map&lt;String, Object&gt; parms) { if ("".equals(url) || parms == null || url.trim().length() &lt;= 0 || parms.size() &lt;= 0) {
C# StringContent Post 请求报 415 错误错误:解析:解决办法: 错误提示:{“type”:“https://tools.ietf.org/html/rfc7231#section-6.5.13”,“title”:“Unsupported Media Type”,“status”:415,“traceId”:"|ca88308-41f99568b29230bc."} 按照提示,Unsupported Media Type,查看了下 StringContent 的默认
我们经常需要在HttpResponse中设置一些headers,我们使用Spring MVC框架的候我们如何给Response设置Header呢? Sooooooooooooo easy, 看下面的代码:
 
推荐文章