上傳圖片需要使用證書
#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表示安裝密碼,默認為商戶號