пятница, 14 декабря 2012 г.

Хеш-таблица HashTable вида ключ-значение в Delphi 7


Задача
использовать хеш-таблицу вида ключ-значение (где значение может быть integer, string или TObject)

Среда: Delphi 7

Решение
Код взял отюда
http://read.pudn.com/downloads76/sourcecode/p2p/289231/Hashes.pas__.htm

на код навела статья из stackoverflow
http://stackoverflow.com/questions/2866144/is-there-anything-like-a-map-or-a-hashtable-in-delphi-6

Вставил модуль в проект. Скомпилировалось сразу. Методы работы легко посмотреть в коде.


Альтернативное решение
преимущество: использует только стандартные библиотеки Delphi без необходимости использования сторонних библиотек
недостаток: решение только частного случая: хэш-таблица integer->string

Модуль: IniFiles
классы: TStringHash, THashedStringList

спасибо за совет xen2:
http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=113797&msg=13631299


Еще одно решение
(похоже на подходящее, но сам пока не попробовал)
Использовать ...Hash... из AcedUtils

http://acedutils.narod.ru/AcedUtils.htm

опять спасибо за совет  xen2
http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=113797&msg=13631895




вторник, 11 декабря 2012 г.

Оптимизация Битрикса на виртуальной машине на примере хостинга 1gb.ua

Ситуация
Готовлю 2 сайта на Битриксе в режиме мультисайтовости.  Хостинг-провайдер http://1gb.ua. Для нормальной работы мультисайтовости виртуальный хостинг не подходит, поэтому покупаю виртуальный сервер. Тариф "VZ-профи". Сам я не большой специалист по linux и apache.

Проблема
Апач работает нестабильно, даже при 2-х запросах: при попытке одновременного открытия сайтов из разных вкладок. вываливает или 
"Service Temporarily Unavailable
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later."
Или ответ выдется, но разметка сайтов сбита.

Решение
(помогла служба поддержки 1gb.ua)
увеличить директиву MaxProcessors до 100, в файле /etc/apache2/modules.d/00_mpm.conf. 

Это решение помогло. Вопрос на текущий момент закрыт.

правда замер производительности Битрикса тестами Битрикса не очень хороший: 7.82

На будущее поддержка посоветовала смотреть такие материалы

pinba
http://habrahabr.ru/post/129042/ 
http://pinba.org/wiki/Main_Page 

atop
Используйте утилиту atop. В режиме сбора статистики atop запускается как демон и раз в N времени (обычно 10 мин) скидывает состояние в двоичный журнал. Потом по этому журналу atop'ом же (ключ -r и имя лог-файла) можно бегать вперёд-назад кнопками T и t, наблюдая показания atop'а с усреднением за 10 минут в любой интересный момент времени. 
2012-12-11 16:59 1Gb.ua: Ставите так: emerge atop, его мануал http://www.opennet.ru/man.shtml?topic=atop&category=1&russian=2 




понедельник, 3 декабря 2012 г.

UPC eCommerceConnect Интеграция на платформе .NET: Часть 2. Программирование

Это вторая часть цикла статей, посвященных интеграции 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-net

также помогла функция 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");
}
}
4. Готовим функцию, которая возвращает объект "поля формы"
/// <summary>
/// Подготовить поля веб-формы для отправки на сервер
/// </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;
}
5. Готовим форму отправки запроса. отображаем поля формы во вьюшке

@model objectEccGateway;
...
<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>
...
6. Обрабтываем результат

В экшене-обработчике результата
пишеи примерно такое

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
}

UPC eCommerceConnect Интеграция на платформе .NET: Часть 3. Тестирование

Это третья часть цикла статей, посвященных интеграции UPC
ВСЕ ЧАСТИ МАТЕРИАЛА

Для тестирования пользуюсь информацией из этого файла

Интеграция и тестирование. Руководство разработчика торговой системы.

http://ecommerce.upc.ua/docs/testing.pdf

в частности для проверки корректного результата оплаты
использую такие параметры тестовой карточки

параметры для тестирования
#карты: 4999999999990011
действует до: 12/2012
cvv2: 999

UPC eCommerceConnect Интеграция на платформе .NET: Часть 1. Организационные вопросы

Это первая часть цикла статей, посвященных интеграции UPC

ВСЕ ЧАСТИ МАТЕРИАЛА




Для начала работы я завел свой тестовый аккаунт
1. Заявка на регистрацию

1. скачал отсюда http://ecommerce.upc.ua/docs.html
2. заполнил своими реквизитами (написал, что модуль нужен в тестовых целях)
3. отправил на адрес ec@upc.ua
Получаю ответ на заявку
(в моем случае менеджеры системы откликнулись быстро, это заняло порядка 15-ти минут)



Ответ выглядит примерно так:

Здравствуйте,

Тестовые данные:


Адрес шлюза : https://secure.upc.ua/ecgtest/enter
MerchantID=XXXXXXX

TerminalID=YYYYYYY
Интерфейс торговца :https://secure.upc.ua/ecgtest/merchant
Логин / Пароль :XXXXXXX/в следующем письме

Сертификат сервера - в аттаче

Также необходимо, чтобы Вы выслали сертификат торговца (файл с именем XXXXXXX.crt) на адрес ec@upc.ua

Вся необходимая документация: здесь: http://ecommerce.upc.ua/site/docs.html
Тестовые карты здесь: http://ecommerce.upc.ua/docs/Testing.pdf
(See attached file: test-server.cert)
В архиве batch.rar документация и примеры по формированию подписи.

(See attached file: batch.rar)
password: 1

где
XXXXXXX-код мерчанта
YYYYYYYY-код терминала
Согласно письма, следующее действие - подготовка ключей и сертификатов

2. Подготовка ключей и сертификатов
(эту часть делаем согласно readme-файла вложенного письма, только с поправкой на 64-х битность Windows-системы)
1. Выкачиваю OpenSSL-библиотеки
с сайта http://slproweb.com/products/Win32OpenSSL.html
Выкачиваю такие файлы
Visual C++ 2008 Redistributables (x64)
тут шла ссылка на сайт микрософт
Win64 OpenSSL v1.0.1c Light
тут версия 1.0.1с актуальна на 2012 12
2. Запускаю выкачанные инсталлянты
По умолчанию библиотеки OpenSSL установились в директорию C:\OpenSSL-Win64

3. Прописываю библиотеки в переменной Path
(пример для Windows 7 x64)
Панель управления\Все элементы панели управления\Система

дополнительные параметры системы

вкладка "Дополнительно" кнопка "Переменные среды"
Область "системные переменные"
переменная PATH

Добавляю тута путь: C:\OpenSSL-Win64\bin
4. правлю конфиг-файл config.dat
устанавливаю там параметры согласно заявке
(поля в разделе [req] не трогал)

5. Собственно гененрирую файлы ключей и сертификатов
для этого запускаю

run.bat XXXXXXX

где
XXXXXXX-мой код мерчанта
На выходе получаю файлы
XXXXXXX.pem – приватный ключ
XXXXXXX.pub – публичный ключ
XXXXXXX.crt – сертификат
6. Файл сертификата (*.crt) отправляю в UPC на адрес ec@upc.ua
7. Получаю ответ от UPC
В моем случае все было достаточно быстро и лаконично : "подгружен"
Еще я естествеено проверил их веб-интерфейс залогинившись под своим именем/паролем.
Пароль, кстати, система сразу предложила сменить.

3. Настройка путей ответа.
в веб-интерфейсе заходим в раздел "терминалы". выбираем редактированиее терминала.
и заполняем поля:
страницы для ответов сервера (эти страницы должны быть в вашем веб-приложении и содержать обработку ответов сервера).

UPC eCommerceConnect Интеграция на платформе .NET

Делал интеграцию платежной системы UPC на платформе .NET

Возможно мой опыт кому-то окажется полезен.

материала достаточно много, поэтому разбил на части

1. Орг вопросы
2. Программирование
3. Тестирование

Пожелания/предложения принимаются в комментариях.

ссылки по теме:
Сайт платежной системы
http://ecommerce.upc.ua/
Сайт организации-владельца системы
https://upc.ua/ua.htm
Документация по системе
http://ecommerce.upc.ua/docs.html
блог разработчика с полезной информацией
http://mac-blog.org.ua/upc-visa-mastercard-payment/
форум
http://forum.ecommerce.upc.ua/viewforum.php?f=9