Skip to content

Commit 27b7bfb

Browse files
committed
Initial version of RussianPaymentPayload
Grep from @AlexandreZaytsev
1 parent fe63074 commit 27b7bfb

File tree

1 file changed

+188
-0
lines changed

1 file changed

+188
-0
lines changed

QRCoder/PayloadGenerator.cs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,6 +2386,194 @@ public SlovenianUpnQr(string payerName, string payerAddress, string payerPlace,
23862386
_recipientSiReference = LimitLength(recipientSiReference.Trim(), 22);
23872387
}
23882388

2389+
public class RussiaPaymentOrder : Payload
2390+
{
2391+
//https://docs.cntd.ru/document/1200110981
2392+
//https://roskazna.gov.ru/upload/iblock/5fa/gost_r_56042_2014.pdf
2393+
//https://sbqr.ru/standard/files/standart.pdf
2394+
2395+
//base
2396+
private CharacterSets characterSet;
2397+
// [Required(ErrorMessage = "Name must be a filled string max. 160 characters", AllowEmptyStrings = true)]
2398+
private readonly string Name;// { get; set; } // 1-160 char
2399+
private readonly string PersonalAcc; // 20 digit (UInt64)
2400+
private readonly string BankName; // 1-45 char
2401+
private readonly string BIC; // 9 digit (UInt32)
2402+
private readonly string CorrespAcc = "0"; // up to 20 digit (0-default) (UInt64)
2403+
//extend
2404+
private readonly string Sum;
2405+
private readonly string Purpose;
2406+
private readonly string PayeeINN;
2407+
private readonly string PayerINN;
2408+
private readonly string DrawerStatus;
2409+
private readonly string KPP;
2410+
private readonly string CBC;
2411+
private readonly string OKTMO;
2412+
private readonly string PaytReason;
2413+
private readonly string ТaxPeriod;
2414+
private readonly string DocNo;
2415+
private readonly DateTime? DocDate;
2416+
private readonly string TaxPaytKind;
2417+
//other
2418+
private readonly string LastName;
2419+
private readonly string FirstName;
2420+
private readonly string MiddleName;
2421+
private readonly string PayerAddress;
2422+
private readonly string PersonalAccount;
2423+
private readonly string DocIdx;
2424+
private readonly string PensAcc;
2425+
private readonly string Contract;
2426+
private readonly string PersAcc;
2427+
private readonly string Flat;
2428+
private readonly string Phone;
2429+
private readonly string PayerIdType;
2430+
private readonly string PayerIdNum;
2431+
private readonly string ChildFio;
2432+
private readonly DateTime? BirthDate;
2433+
private readonly string PaymTerm;
2434+
private readonly string PaymPeriod;
2435+
private readonly string Category;
2436+
private readonly string ServiceName;
2437+
private readonly string CounterId;
2438+
private readonly string CounterVal;
2439+
private readonly string QuittId;
2440+
private readonly DateTime? QuittDate;
2441+
private readonly string InstNum;
2442+
private readonly string ClassNum;
2443+
private readonly string SpecFio;
2444+
private readonly string AddAmount;
2445+
private readonly string RuleId;
2446+
private readonly string ExecId;
2447+
private readonly string RegType;
2448+
private readonly string UIN;
2449+
private readonly TechCode techCode;
2450+
2451+
public RussiaPaymentOrder(CharacterSets characterSet, string Name, string PersonalAcc, string BankName, string BIC, string CorrespAcc = "0")
2452+
{
2453+
this.characterSet = characterSet;
2454+
this.Name = Name;
2455+
this.PersonalAcc = PersonalAcc;
2456+
this.BankName = BankName;
2457+
this.BIC = BIC;
2458+
this.CorrespAcc = CorrespAcc;
2459+
}
2460+
public RussiaPaymentOrder(CharacterSets characterSet, string Name, string PersonalAcc, string BankName, string BIC, string CorrespAcc = "0",
2461+
string PayeeINN = "", string LastName = "", string FirstName = "", string MiddleName = "", string Purpose = "", string PayerAddress = "", string Sum = "0")
2462+
{
2463+
this.characterSet = characterSet;
2464+
this.Name = Name;
2465+
this.PersonalAcc = PersonalAcc;
2466+
this.BankName = BankName;
2467+
this.BIC = BIC;
2468+
this.CorrespAcc = CorrespAcc;
2469+
2470+
if (!string.IsNullOrEmpty(PayeeINN) && !(PayeeINN.Length >= 10 && Regex.IsMatch(PayeeINN.Replace(" ", ""), @"^[0-9]+$")))
2471+
throw new RussiaPaymentOrderException("PayeeINN must be a filled 1-10(12) digits.");
2472+
if (!string.IsNullOrEmpty(Sum) && !(Sum.Length <= 18 && Regex.IsMatch(Sum.Replace(" ", ""), @"^[0-9]+$")))
2473+
throw new Exception("Sum must be a filled 1-18 digits (*including Sum/100 (the last two digits) without a separator sign)");
2474+
2475+
this.PayeeINN = PayeeINN;
2476+
this.LastName = LastName;
2477+
this.FirstName = FirstName;
2478+
this.MiddleName = MiddleName;
2479+
this.Purpose = Purpose;
2480+
this.PayerAddress = PayerAddress;
2481+
this.Sum = Sum;
2482+
2483+
/*
2484+
if (string.IsNullOrEmpty(Name))
2485+
throw new RussiaPaymentOrderException("Name must be a filled string max. 160 characters.");
2486+
if (string.IsNullOrEmpty(PersonalAcc))
2487+
throw new RussiaPaymentOrderException("PersonalAcc must be a filled string max. 20 characters.");
2488+
if (string.IsNullOrEmpty(BankName))
2489+
throw new RussiaPaymentOrderException("BankName must be a filled string max. 45 characters.");
2490+
if (string.IsNullOrEmpty(BIC))
2491+
throw new RussiaPaymentOrderException("BIC must be a filled string max. 9 characters.");
2492+
if (string.IsNullOrEmpty(CorrespAcc))
2493+
throw new RussiaPaymentOrderException("CorrespAcc must be a filled string max. 20 characters.");
2494+
*/
2495+
2496+
}
2497+
2498+
public override string ToString()
2499+
{
2500+
if (string.IsNullOrEmpty(Name) && PersonalAcc.Length <= 160)
2501+
throw new Exception("Name must be a filled string 1-160 characters");
2502+
if (!(!string.IsNullOrEmpty(PersonalAcc) && PersonalAcc.Length == 20 && Regex.IsMatch(PersonalAcc.Replace(" ", ""), @"^[0-9]+$")))
2503+
throw new Exception("PersonalAcc must be a filled strong 20 digits");
2504+
if (string.IsNullOrEmpty(BankName) && BankName.Length <= 45)
2505+
throw new Exception("BankName must be a filled string 1-45 characters");
2506+
if (!(!string.IsNullOrEmpty(BIC) && BIC.Length == 9 && Regex.IsMatch(BIC.Replace(" ", ""), @"^[0-9]+$")))
2507+
throw new Exception("BIC must be a filled strong 9 digits");
2508+
if (!(!string.IsNullOrEmpty(CorrespAcc) && CorrespAcc.Length <= 20 && Regex.IsMatch(CorrespAcc.Replace(" ", ""), @"^[0-9]+$")))
2509+
throw new Exception("CorrespAcc must be a filled 1-20 digits or 0 value if empty");
2510+
2511+
string ret = $"ST0001" + ((int)characterSet).ToString() + $"|Name={this.Name}" +
2512+
$"|PersonalAcc={this.PersonalAcc}" +
2513+
$"|BankName={this.BankName}" +
2514+
$"|BIC={this.BIC}" +
2515+
$"|CorrespAcc={this.CorrespAcc}" +
2516+
$"|PayeeINN={this.PayeeINN}" +
2517+
$"|LastName={this.LastName}" +
2518+
$"|FirstName={this.FirstName}" +
2519+
$"|MiddleName={this.MiddleName}" +
2520+
$"|Purpose={this.Purpose}" +
2521+
$"|PayerAddress={this.PayerAddress}" +
2522+
$"|Sum={this.Sum}"
2523+
;
2524+
2525+
string page = this.characterSet.ToString().Replace("_", "-");
2526+
return Encoding.GetEncoding(page).GetString(Encoding.Convert(Encoding.Default, Encoding.GetEncoding(page), Encoding.GetEncoding(page).GetBytes(ret)));
2527+
}
2528+
2529+
/// <summary>
2530+
/// Перечень значений технического кода платежа
2531+
/// (List of values of the technical code of the payment)
2532+
/// </summary>
2533+
private enum TechCode
2534+
{
2535+
Мобильная_связь_стационарный_телефон = 01,
2536+
Коммунальные_услуги_ЖКХAFN = 02,
2537+
ГИБДД_налоги_пошлины_бюджетные_платежи = 03,
2538+
Охранные_услуги = 04,
2539+
Услуги_оказываемые_УФМС = 05,
2540+
ПФР = 06,
2541+
Погашение_кредитов = 07,
2542+
Образовательные_учреждения = 08,
2543+
Интернет_и_ТВ = 09,
2544+
Электронные_деньги = 10,
2545+
Отдых_и_путешествия = 11,
2546+
Инвестиции_и_страхование = 12,
2547+
Спорт_и_здоровье = 13,
2548+
Благотворительные_и_общественные_организации = 14,
2549+
Прочие_услуги = 15
2550+
}
2551+
2552+
public enum CharacterSets
2553+
{
2554+
windows_1251 = 1, // Encoding.GetEncoding("windows-1251")
2555+
utf_8 = 2, // Encoding.UTF8
2556+
koi8_r = 3 // Encoding.GetEncoding("koi8-r")
2557+
2558+
}
2559+
2560+
public class RussiaPaymentOrderException : Exception
2561+
{
2562+
public RussiaPaymentOrderException()
2563+
{
2564+
}
2565+
public RussiaPaymentOrderException(string message)
2566+
: base(message)
2567+
{
2568+
}
2569+
public RussiaPaymentOrderException(string message, Exception inner)
2570+
: base(message, inner)
2571+
{
2572+
}
2573+
}
2574+
2575+
}
2576+
23892577
private string FormatAmount(double amount)
23902578
{
23912579
int _amt = (int)Math.Round(amount * 100.0);

0 commit comments

Comments
 (0)