Это вторая часть цикла статей, посвященных интеграции UPC
ВСЕ ЧАСТИ МАТЕРИАЛА
ВСЕ ЧАСТИ МАТЕРИАЛА
Пример на ASP.NET MVC3
Теперь собственно этап программирования
что имеем:
1. на руках есть XXXXXXX.pem файл с приватным ключем, с помощью которого нужно по определенным правилом зашифровать сообщение2. раздел документации: "Интерфейс взаимодействия. Руководство администратора торговой системы."
http://ecommerce.upc.ua/docs/shop_gateway_interface.pdf
3. тема на форуме "Пример подключения для платформы .net со всеми деталями"
http://forum.ecommerce.upc.ua/viewtopic.php?f=12&t=468
(скажу сразу, что пример помог, но часть процедур пришлось додумывать самостоятельно)
1. Готовим объект - шлюз
Этот объект нам нужен для отображения полей формы
Как-то так. Если где ошибся с типами, вопросы/пожелания/предложения принимаются.
public class objectEccGateway: MegaUtils_V3.objects.objectMegaBase
{
public int Version;
public string MerchantID;
public string TerminalID;
public long TotalAmount;
public int Currency;
public string Locale; //ru
public string OrderID;
public string PurchaseTime;
public string Gateway;
public string SD;
public string PurchaseDesc;
public string XID;
public string ProxyPanResponse;
public string ApprovalCode;
public int TranCode;
public Int64 Rrn;
public string Signature;
}
2. Готовим объект - параметры системы
В этом объекте я настраивал параметры системы UPC
public class objectCatalogPaymentSystemUPC
{
public string MerchantId;
public string TerminalId;
public string CertificateFile;
public string Gateway;
}
3. Готовим утилиты для работы с файлами ключей
для парсинга приватного ключа из *.pem файла
помогло решение из статьи
http://stackoverflow.com/questions/1162504/decrypting-with-private-key-from-pem-file-in-c-sharp-with-net-crypto-library/1162519#1162519
в статье есть ссылка на файл
http://www.jensign.com/opensslkey/opensslkey.cs
который я взял и полностью вставил в код
(правда одну строчку пришлось закомментиовать там было "(сертификат)UI" - .NET не распознал её как идентификатор. на работоспособности системы она не отразилась)
эта статья тоже ссылается на правильное решение
http://stackoverflow.com/questions/243646/how-to-read-a-pem-rsa-private-key-from-net4. Готовим функцию, которая возвращает объект "поля формы"
также помогла функция PEM отсюда
http://pages.infinit.net/ctech/20040812-0816.html
на эту функцию вела статья
http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvcs/thread/348e1909-4da9-4980-94fc-f412dce07690/
в конце концов код выглядел так:
public class RSACryptoUtils
{
public static string RSASign(string data, string KeyFile)
{
RSACryptoServiceProvider rsaCsp =
LoadCertificateFile(KeyFile);
if (rsaCsp == null) return String.Empty;
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
return Convert.ToBase64String(signatureBytes);
}
public static byte[] PEM(string type, byte[] data)
{
string pem = Encoding.ASCII.GetString(data);
string header = String.Format("-----BEGIN {0}-----", type);
string footer = String.Format("-----END {0}-----", type);
int start = pem.IndexOf(header) + header.Length;
int end = pem.IndexOf(footer, start);
string base64 = pem.Substring(start, (end - start));
return Convert.FromBase64String(base64);
}
public static RSACryptoServiceProvider LoadCertificateFile(string filename)
{
using (FileStream fs = File.OpenRead(filename))
{
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
if (data[0] != 0x30)
{
// maybe it's ASCII PEM base64 encoded ?
data = PEM("RSA PRIVATE KEY", data);
}
if (data != null)
return opensslkey.DecodeRSAPrivateKey(data);
//x509 = new X509Certificate2(data);
throw new ApplicationException("error");
}
//return x509;
throw new ApplicationException("error");
}
}
/// <summary>5. Готовим форму отправки запроса. отображаем поля формы во вьюшке
/// Подготовить поля веб-формы для отправки на сервер
/// </summary>
/// <param name="aUPCParams">параметры мерчанта</param>
/// <param name="aLocale">язык интерфейса "ru" или "en"</param>
/// <param name="aDocRecID">код докуента</param>
/// <param name="aTotalAmont">сумма доакмента</param>
/// <param name="aCurrencyRecID">код валюты 980-гривна</param>
/// <param name="aSessionID">код сессии System.Web.HttpContext.Current.Session.SessionID</param>
/// <returns></returns>
public static objects.objectEccGateway GetRequestFormFields(
objectCatalogPaymentSystemUPC aUPCParams,
string aLocale,
string aDocRecID,
double aTotalAmont,
int aCurrencyRecID,
string aSessionID
)
{
var obj = new tfoBookingUtils.PaymentSystem.UPC.objects.objectEccGateway()
{
Version = 1,
MerchantID = aUPCParams.MerchantId,
TerminalID = aUPCParams.TerminalId,
TotalAmount = (long)(aTotalAmont * 100),
Currency = aCurrencyRecID, //
Locale = aLocale,
OrderID = aDocRecID + "|" + DateTime.Now.ToString("yyMMddHHmmss"),
PurchaseTime = DateTime.Now.ToString("yyMMddHHmmss"),
Gateway = aUPCParams.Gateway,
SD = aSessionID,
PurchaseDesc = string.Format("Заказ {0} на сумму {1:N} грн.", aDocRecID, aTotalAmont)
};
string str = String.Format("{0};{1};{2};{3};{4};{5};{6};",
obj.MerchantID, obj.TerminalID, obj.PurchaseTime, obj.OrderID,
obj.Currency, obj.TotalAmount, obj.SD);
obj.Signature = RSACryptoUtils.RSASign(str, System.Web.HttpContext.Current.Server.MapPath(aUPCParams.CertificateFile));
return obj;
}
@model objectEccGateway;6. Обрабтываем результат
...
<form action="@Model.Gateway" method="post" id="ecommerce_pay">
<input type="hidden" name="Version" value="@Model.Version" />
<input type="hidden" name="MerchantID" value="@Model.MerchantID" />
<input type="hidden" name="TerminalID" value="@Model.TerminalID" />
<input type="hidden" name="TotalAmount" value="@Model.TotalAmount" />
<input type="hidden" name="Currency" value="@Model.Currency" />
<input type="hidden" name="locale" value="@Model.Locale" />
<input type="hidden" name="SD" value="@Model.SD" />
<input type="hidden" name="OrderID" value="@Model.OrderID" />
<input type="hidden" name="PurchaseTime" value="@Model.PurchaseTime" />
<input type="hidden" name="PurchaseDesc" value="@Model.PurchaseDesc" />
<input type="hidden" name="Signature" value="@Model.Signature" />
<input type="submit" name="submit" value="Оплатить" />
</form>
...
В экшене-обработчике результата
пишеи примерно такое
ecc = new objectEccGateway()
{
MerchantID = Request.Params["MerchantID"],
OrderID = Request.Params["OrderID"],
//PurchaseTime = Convert.ToInt64(Request.Params["PurchaseTime"]),
SD = Request.Params["SD"],
TerminalID = Request.Params["TerminalID"],
ProxyPanResponse = Request.Params["ProxyPan"],
Currency = Convert.ToInt32(Request.Params["Currency"]),
ApprovalCode = Request.Params["ApprovalCode"],
Signature = Request.Params["Signature"],
Rrn = Convert.ToInt64(Request.Params["Rrn"]),
XID = Request.Params["XID"],
TranCode = Convert.ToInt32(Request.Params["TranCode"]),
TotalAmount = Convert.ToInt64(Request.Params["TotalAmount"])
};
if (Convert.ToInt32(Request.Params["TranCode"]) == 0)
{
//ok
}
else{
//error
}
Комментариев нет:
Отправить комментарий