私は初心者の C# 開発者で、少し行き詰まっています。
HTTP リクエストを行うときに同じセッション ID Cookie を保持する必要があるプロジェクトがあります。リクエストは正常に機能します。API (通貨交換 API) で必要なものを作成します。問題は、購入するための支払いを作成するときに、支払いを承認する必要がある画面に移動するとします。ここには、1.5 分間有効な為替レートがあります。時間が終了すると、レートが更新されます。レートをロックするには、支払いを承認する必要があります。承認すると、支払いを待っている画面に移動します。ここでレートはロックされていますが、問題はレートがロックしたものと同じではないことです。ウェブサイトの所有者は、支払いと承認を作成するためのリクエストでセッション ID が同じでなかったことが原因であると私に言いました。
これは API ドキュメントからのものです。
API 接続は、cURL などの HttpsRequest コンポーネントを介して確立できます。目的の言語バージョンで cURL ライブラリが利用できない場合は、次のように代替手段を提供する必要があります。
- すべての cURL クエリ/リクエスト/データ転送では、HTTPS プロトコルのみを使用する必要があります。
- すべての機密情報は POST メソッドで送信する必要があります。
- SSL 証明書と SSL ホストの検証。DNS ハック攻撃を防ぎます。CURLOPT_SSL_VERIFYHOST & CURLOPT_SSL_VERIFYPEER を参照してください。
- セッションと Cookie のサポート。
私が見つけたサンプル コードは、Curl を使用した PHP でした。これは、LibCurlNet を使用して思いついたものです。
public class Http
{
string _xmlResponse = string.Empty;
private static Easy easy;
private static Easy.WriteFunction wf = null;
public string PerformRequest(string xml, string queryString, string url)
{
try
{
_xmlResponse = string.Empty;
Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);
easy = new Easy();
wf = new Easy.WriteFunction(OnWriteData);
easy.SetOpt(CURLoption.CURLOPT_URL, url);
easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, wf);
easy.SetOpt(CURLoption.CURLOPT_COOKIEFILE, HttpContext.Current.Request.MapPath("~/cookies.txt"));
easy.SetOpt(CURLoption.CURLOPT_COOKIEJAR, HttpContext.Current.Request.MapPath("~/cookies.txt"));
easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYPEER, true);
easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYHOST, true);
easy.SetOpt(CURLoption.CURLOPT_CAINFO, HttpContext.Current.Request.MapPath("~/ssl.crt"));
easy.SetOpt(CURLoption.CURLOPT_HEADER, 0);
easy.SetOpt(CURLoption.CURLOPT_FOLLOWLOCATION, true);
easy.SetOpt(CURLoption.CURLOPT_USERAGENT, "xxx Web XML API");
easy.SetOpt(CURLoption.CURLOPT_BUFFERSIZE, 65536);
easy.SetOpt(CURLoption.CURLOPT_POSTFIELDS, CleanXML(xml));
easy.Perform();
easy.Cleanup();
Curl.GlobalCleanup();
}
catch (Exception ex)
{
return ex.Message;
}
return _xmlResponse;
}
public Int32 OnWriteData(Byte[] buf, Int32 size, Int32 nmemb,
Object extraData)
{
_xmlResponse = _xmlResponse + System.Text.Encoding.UTF8.GetString(buf);
return size * nmemb;
}
private string CleanXML(string xml)
{
char[] sep = Environment.NewLine.ToArray();
string[] lines = xml.Split(sep);
StringBuilder sb = new StringBuilder();
foreach (string line in lines)
{
sb.Append(line.Trim());
}
return sb.ToString();
}
}
問題は、接続するたびに cookie.txt がセッション ID を更新することです。
HttpWebRequest を使用したコード:
public class HttpV2
{
static CookieCollection cookie = new CookieCollection();
string responseFromServer;
public string GetHttpResponse(string Url, string requestBody)
{
//WebRequest request = WebRequest.Create(Url);
HttpWebRequest request = HttpWebRequest.CreateHttp(Url);
X509Certificate Cert = X509Certificate.CreateFromCertFile(@"D:\www_root\xxxxxxxxxxx\xxxxx\ssl.crt");
request.ClientCertificates.Add(Cert);
request.Method = "POST";
//HttpContext context = HttpContext.Current;
request.CookieContainer = new CookieContainer();
request.UserAgent = "TranferMate Web XML API";
if (cookie != null)
{
request.CookieContainer.Add(cookie);
}
byte[] byteArray = Encoding.UTF8.GetBytes(requestBody);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
#region Get the response.
using (WebResponse response = request.GetResponse())
{
if (requestBody.Contains("<FORCE_REFRESH>1</FORCE_REFRESH>"))
{
cookie = ((HttpWebResponse)response).Cookies;
}
if (((HttpWebResponse)response).StatusCode == HttpStatusCode.OK)
using (Stream stream = response.GetResponseStream())
{
if (stream != null)
{
using (StreamReader reader = new StreamReader(stream))
{
responseFromServer = reader.ReadToEnd();
reader.Close();
}
stream.Close();
}
}
response.Close();
}
#endregion
return responseFromServer;
}
}