C#通過http post方式調用需要證書的webservice
前一段時間做花旗銀行的項目,用到花旗的接口是websevice,由於很多原因直接在項目中引用webservice不成功,於是就用了http post方式請求,把請求信息(xml格式)組裝之後發送到服務器,返回結果。
下面就把我當時做的方法分享,希望對大家有用。
1,首先在webconfig中配置需要的信息
注:RewardUrl為url地址中公用的部分,因為後面調用不同的接口,地址是不一樣的,所以就抽出來單獨定義了,CommonUrl為IP+端口號,因為這個地址有可能更換所以也單獨定義了。
<appSettings>
<add key="CerPath" value="E:\\avantouch.pfx" />
<add key="CommonUrl" value="https://192.168.1.1:15121"/>
<add key="RewardUrl" value="/SvcImpl/cards/reward/"/>
</appSettings>
2,定義全局變量,獲取webconfig中的值,以及後面要用到的變量
private static readonly string CommonUrl = ConfigurationManager.AppSettings["CommonUrl"].ToString();
private static readonly string RewardUrl = ConfigurationManager.AppSettings["RewardUrl"].ToString();
private static readonly string CerPath = ConfigurationManager.AppSettings["CerPath"].ToString();
string PostUrl = "";
3,寫公共的方法,這個方法我子啊項目中多個地方要用到,看似很多余的,可以整合到下面的方法中,但是在我的這個項目中需要這樣會比較方便,所以我沒有整合,大家可以根據自己的需要進行整合。
復制代碼
/// <summary>
/// 獲取結果(這個方法主要是獲取PostUrl 然後調用下面的方法)
/// </summary>
/// <param name="xml"></param>
/// <param name="interfaceName">需要調用的對方接口方法名</param>
/// <returns></returns>
private string GetResCode(string xml, string interfaceName)
{
PostUrl = RewardUrl + interfaceName;//ip以及端口號之後的地址
byte[] data = Encoding.UTF8.GetBytes(xml.ToString());
string resCode = GetPostRequest(data, PostUrl);//方法在下面
Log.Info("Response:" + resCode);
return resCode;
}
復制代碼
4,寫第三部中的代碼用到的方法,這部比較重要。
復制代碼
/// <summary>
/// Post方式請求獲取返回值
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private string GetPostRequest(byte[] data, string url)
{
try
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(CommonUrl + url);//完整的請求地址(ip:端口號/+url)
//X509證書
X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(CerPath, "證書密碼", X509KeyStorageFlags.MachineKeySet);
myRequest.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
//設定驗證回調(總是同意)
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
myRequest.Method = "POST";
myRequest.ContentType = "text/xml;charset=\"utf-8\"";
myRequest.Accept = "text/xml";
myRequest.Headers.Add("SOAPAction", url);//我做的過程中,這一步沒加的時候一直出錯,加上了這個就OK了。//是否和請求一起發送
myRequest.UseDefaultCredentials = true;
myRequest.ContentLength = data.Length;
myRequest.ClientCertificates.Add(cert);//把證書添加進http請求中
Stream newStream = myRequest.GetRequestStream();
// Send the data.
newStream.Write(data, 0, data.Length);
newStream.Close();
// Get response
var response = (HttpWebResponse)myRequest.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("UTF-8")))
{
string result = reader.ReadToEnd();
reader.Close();
response.Close();
return result;
}
}
catch (Exception ex)
{
Log.Info(ex);
return ex.ToString();
}
}
//回調方法
public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{ // 總是接受
return true;
}
復制代碼
5,方法完畢,這時候只要把你的xml報文傳過去,和你要調用的接口名稱傳過去,調用第三步的方法,例如:
GetResCode(xml,“Login”),這樣就返回了信息,我做的項目返回的是xml格式的信息,解析xml就可以得到你想要的結果了。