上传图片需要使用证书
#region 计算指定文件的MD5值
private static string GetMD5(string fileName)
{
string md5String = string.Empty;
if (System.IO.File.Exists(fileName))
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
MD5 calculator = MD5.Create();
byte[] buffer = calculator.ComputeHash(fs);
calculator.Clear();
//将字节数组转换成十六进制的字符串形式
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < buffer.Length; i++)
{
stringBuilder.Append(buffer[i].ToString("x2"));
}
md5String = stringBuilder.ToString();
}
}
return md5String;
}
#endregion
/// <summary>
/// FormData 传输类
/// </summary>
public class MsMultiPartFormData
{
private List<byte> formData;
public String Boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
private String fieldName = "Content-Disposition: form-data; name=\"{0}\"";
private String fileContentType = "Content-Type: {0}";
private String fileField = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"";
private Encoding encode = Encoding.UTF8;
public MsMultiPartFormData()
{
formData = new List<byte>();
}
public void AddFormField(String FieldName, String FieldValue)
{
String newFieldName = fieldName;
newFieldName = string.Format(newFieldName, FieldName);
formData.AddRange(encode.GetBytes("--" + Boundary + "\r\n"));
formData.AddRange(encode.GetBytes(newFieldName + "\r\n\r\n"));
formData.AddRange(encode.GetBytes(FieldValue + "\r\n"));
}
public void AddFile(String FieldName, String FileName, byte[] FileContent, String ContentType)
{
String newFileField = fileField;
String newFileContentType = fileContentType;
newFileField = string.Format(newFileField, FieldName, FileName);
newFileContentType = string.Format(newFileContentType, ContentType);
formData.AddRange(encode.GetBytes("--" + Boundary + "\r\n"));
formData.AddRange(encode.GetBytes(newFileField + "\r\n"));
formData.AddRange(encode.GetBytes(newFileContentType + "\r\n\r\n"));
formData.AddRange(FileContent);
formData.AddRange(encode.GetBytes("\r\n"));
}
public void AddStreamFile(String FieldName, String FileName, byte[] FileContent)
{
AddFile(FieldName, FileName, FileContent, "application/octet-stream");
}
public void PrepareFormData()
{
formData.AddRange(encode.GetBytes("--" + Boundary + "--"));
}
public List<byte> GetFormData()
{
return formData;
}
}
#region 上传图片
/// <summary>
/// Weixins the upfile.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <param name="key">秘钥</param>
/// <param name="mchid">商户id</param>
/// <param name="CertPath">证书路径</param>
/// <param name="CertPwd"></param>
/// <returns></returns>
public static string WeixinUpfile(string filePath, string key, string mchid, string CertPath, string CertPwd)
{
string path = filePath;
FileStream file = new FileStream(path, FileMode.Open);
byte[] bb = new byte[file.Length];
file.Read(bb, 0, (int)file.Length);
file.Dispose();
string fileName = Path.GetFileName(path);
MsMultiPartFormData form = new MsMultiPartFormData();
string decodeName = HttpUtility.UrlDecode(Path.GetFileName(fileName));//最终服务器会按原文件名保存文件,所以需要将文件名编码下,防止中文乱码
string fileKeyName = "media";
form.AddStreamFile(fileKeyName, fileName, bb);
String hashMd5 = GetMD5(path);
WxPayDataToXiaoWei inputObj = new WxPayDataToXiaoWei();
inputObj.SetValue("mch_id", mchid);
inputObj.SetValue("media_hash", hashMd5);
inputObj.SetValue("sign_type", "HMAC-SHA256");
//inputObj.SetValue("sign", inputObj.MakeSign());//签名
form.AddFormField("mch_id", mchid);
form.AddFormField("media_hash", hashMd5);
form.AddFormField("sign_type", "HMAC-SHA256");
form.AddFormField("sign", inputObj.MakeSign(key));//签名
string SERVICE_URL = "https://api.mch.weixin.qq.com/secapi/mch/uploadmedia";//最终接收文件上传的服务接口
string rst = WeixinXiaoweiService.Post(inputObj.ToXml(), SERVICE_URL, form, true, 10, CertPath, CertPwd);
inputObj = new WxPayDataToXiaoWei();
inputObj.FromXml(rst);
if (inputObj.GetValue("return_code").ToString() == "SUCCESS")
{
return inputObj.GetValue("media_id").ToString();
}
return inputObj.GetValue("return_msg").ToString();
}
#endregion
//FormData传输方式
public static string Post(string xml, string url, MsMultiPartFormData form,
bool isUseCert, int timeout, string CertPath, string CertPwd, WebHeaderCollection Headers = null,
string ContentType = null,
string host = null)
{
System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接
string result = "";//返回结果
HttpWebRequest request = null;
HttpWebResponse response = null;
Stream reqStream = null;
try
{
//设置最大连接数
ServicePointManager.DefaultConnectionLimit = 200;
//设置https验证方式
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(CheckValidationResult);
}
/***************************************************************
* 下面设置HttpWebRequest的相关属性
* ************************************************************/
request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = USER_AGENT;
request.Method = "POST";
request.Timeout = timeout * 1000;
if (ContentType != null)
{
request.ContentType = ContentType;
}
if (host != null)
{
request.Host = host;
}
//设置代理服务器
//WebProxy proxy = new WebProxy(); //定义一个网关对象
//proxy.Address = new Uri(WxPayConfig.PROXY_URL); //网关服务器端口:端口
//request.Proxy = proxy;
//设置POST的数据类型和长度
//request.ContentType = "text/xml";
//byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
//request.ContentLength = data.Length;
if (Headers != null)
{
for (int i = 0; i < Headers.Count; i++)
{
request.Headers.Add(Headers.GetKey(i), Headers.Get(i));
}
}
//是否使用证书
if (isUseCert)
{
X509Certificate2 cert = new X509Certificate2(CertPath, CertPwd);
request.ClientCertificates.Add(cert);
LogHelper.Debug("WxPayApi", "PostXml used cert");
}
//往服务器写入数据
reqStream = request.GetRequestStream();
//reqStream.Write(data, 0, data.Length);
//reqStream.Close();
//处理上传的文件内容
form.PrepareFormData(); //添加最后的行
request.ContentType = "multipart/form-data; boundary=" + form.Boundary;
request.Method = "POST";
foreach (var b in form.GetFormData())
{
reqStream.WriteByte(b);
}
reqStream.Close();
//获取服务端返回
response = (HttpWebResponse)request.GetResponse();
//获取服务端返回数据
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
result = sr.ReadToEnd().Trim();
sr.Close();
}
catch (System.Threading.ThreadAbortException e)
{
LogHelper.Error("HttpService", "Thread - caught ThreadAbortException - resetting.");
LogHelper.Error("Exception message: {0}", e.Message);
System.Threading.Thread.ResetAbort();
}
catch (WebException ex)
{
LogHelper.Error("HttpService", ex.ToString());
if (ex.Status == WebExceptionStatus.ProtocolError)
{
LogHelper.Error("HttpService", "StatusCode : " + ((HttpWebResponse)ex.Response).StatusCode);
LogHelper.Error("HttpService", "StatusDescription : " + ((HttpWebResponse)ex.Response).StatusDescription);
//这里的代码能保证返回401时,正常显示信息
if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Unauthorized ||
((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.BadRequest)
{
response = (HttpWebResponse)ex.Response;
{
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string bstr = sr.ReadToEnd();
return bstr;
}
}
}
//返回错误信息
throw new Exception(ex.ToString());
}
catch (Exception e)
{
LogHelper.Error("HttpService", e.ToString());
throw new Exception(e.ToString());
}
finally
{
//关闭连接和流
if (response != null)
{
response.Close();
}
if (request != null)
{
request.Abort();
}
}
return result;
}
上传图片是
multipart/form-data
,并且需要使用证书
X509Certificate2 cert = new X509Certificate2(CertPath, CertPwd);
CertPath表示证书路径,CertPwd表示安装密码,默认为商户号