Skip to content

Commit 27bb1ec

Browse files
authored
Merge pull request #111 from ahotko/master
added SlovenianUpnQr payload generator, manual QR version and ECI mode
2 parents 0b8832b + 3399e21 commit 27bb1ec

File tree

2 files changed

+209
-39
lines changed

2 files changed

+209
-39
lines changed

QRCoder/PayloadGenerator.cs

Lines changed: 125 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ namespace QRCoder
99
{
1010
public static class PayloadGenerator
1111
{
12-
public class WiFi
12+
public abstract class Payload
13+
{
14+
public virtual int Version { get { return -1; } }
15+
public virtual QRCodeGenerator.ECCLevel EccLevel { get { return QRCodeGenerator.ECCLevel.M; } }
16+
public virtual QRCodeGenerator.EciMode EciMode { get { return QRCodeGenerator.EciMode.Default; } }
17+
public abstract override string ToString();
18+
}
19+
20+
public class WiFi : Payload
1321
{
1422
private readonly string ssid, password, authenticationMode;
1523
private readonly bool isHiddenSsid;
@@ -45,7 +53,7 @@ public enum Authentication
4553
}
4654
}
4755

48-
public class Mail
56+
public class Mail : Payload
4957
{
5058
private readonly string mailReceiver, subject, message;
5159
private readonly MailEncoding encoding;
@@ -117,7 +125,7 @@ public enum MailEncoding
117125
}
118126
}
119127

120-
public class SMS
128+
public class SMS : Payload
121129
{
122130
private readonly string number, subject;
123131
private readonly SMSEncoding encoding;
@@ -170,7 +178,7 @@ public enum SMSEncoding
170178
}
171179
}
172180

173-
public class MMS
181+
public class MMS : Payload
174182
{
175183
private readonly string number, subject;
176184
private readonly MMSEncoding encoding;
@@ -220,7 +228,7 @@ public enum MMSEncoding
220228
}
221229
}
222230

223-
public class Geolocation
231+
public class Geolocation : Payload
224232
{
225233
private readonly string latitude, longitude;
226234
private readonly GeolocationEncoding encoding;
@@ -258,7 +266,7 @@ public enum GeolocationEncoding
258266
}
259267
}
260268

261-
public class PhoneNumber
269+
public class PhoneNumber : Payload
262270
{
263271
private readonly string number;
264272

@@ -277,7 +285,7 @@ public override string ToString()
277285
}
278286
}
279287

280-
public class SkypeCall
288+
public class SkypeCall : Payload
281289
{
282290
private readonly string skypeUsername;
283291

@@ -296,7 +304,7 @@ public override string ToString()
296304
}
297305
}
298306

299-
public class Url
307+
public class Url : Payload
300308
{
301309
private readonly string url;
302310

@@ -316,7 +324,7 @@ public override string ToString()
316324
}
317325

318326

319-
public class WhatsAppMessage
327+
public class WhatsAppMessage : Payload
320328
{
321329
private readonly string message;
322330

@@ -336,7 +344,7 @@ public override string ToString()
336344
}
337345

338346

339-
public class Bookmark
347+
public class Bookmark : Payload
340348
{
341349
private readonly string url, title;
342350

@@ -357,7 +365,7 @@ public override string ToString()
357365
}
358366
}
359367

360-
public class ContactData
368+
public class ContactData : Payload
361369
{
362370
private readonly string firstname;
363371
private readonly string lastname;
@@ -534,7 +542,7 @@ public enum ContactOutputType
534542
}
535543
}
536544

537-
public class BitcoinAddress
545+
public class BitcoinAddress : Payload
538546
{
539547
private readonly string address, label, message;
540548
private readonly double? amount;
@@ -584,8 +592,8 @@ public override string ToString()
584592
return $"bitcoin:{address}{query}";
585593
}
586594
}
587-
588-
public class SwissQrCode
595+
596+
public class SwissQrCode : Payload
589597
{
590598
//Keep in mind, that the ECC level has to be set to "M" when generating a SwissQrCode!
591599
//SwissQrCode specification: https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-de.pdf
@@ -615,7 +623,7 @@ public class SwissQrCode
615623
public SwissQrCode(Iban iban, Currency currency, Contact creditor, Reference reference, Contact debitor = null, decimal? amount = null, DateTime? requestedDateOfPayment = null, Contact ultimateCreditor = null, string alternativeProcedure1 = null, string alternativeProcedure2 = null)
616624
{
617625
this.iban = iban;
618-
626+
619627
this.creditor = creditor;
620628
this.ultimateCreditor = ultimateCreditor;
621629

@@ -949,7 +957,7 @@ public SwissQrCodeException(string message, Exception inner)
949957
}
950958
}
951959

952-
public class Girocode
960+
public class Girocode : Payload
953961
{
954962
//Keep in mind, that the ECC level has to be set to "M" when generating a Girocode!
955963
//Girocode specification: http://www.europeanpaymentscouncil.eu/index.cfm/knowledge-bank/epc-documents/quick-response-code-guidelines-to-enable-data-capture-for-the-initiation-of-a-sepa-credit-transfer/epc069-12-quick-response-code-guidelines-to-enable-data-capture-for-the-initiation-of-a-sepa-credit-transfer1/
@@ -1073,7 +1081,7 @@ public GirocodeException(string message, Exception inner)
10731081
}
10741082
}
10751083

1076-
public class BezahlCode
1084+
public class BezahlCode : Payload
10771085
{
10781086
//BezahlCode specification: http://www.bezahlcode.de/wp-content/uploads/BezahlCode_TechDok.pdf
10791087

@@ -1629,7 +1637,7 @@ public BezahlCodeException(string message, Exception inner)
16291637
}
16301638
}
16311639

1632-
public class CalendarEvent
1640+
public class CalendarEvent : Payload
16331641
{
16341642
private readonly string subject, description, location, start, end;
16351643
private readonly EventEncoding encoding;
@@ -1678,7 +1686,7 @@ public enum EventEncoding
16781686
}
16791687
}
16801688

1681-
public class OneTimePassword
1689+
public class OneTimePassword : Payload
16821690
{
16831691
//https://github.com/google/google-authenticator/wiki/Key-Uri-Format
16841692
public OneTimePasswordAuthType Type { get; set; } = OneTimePasswordAuthType.TOTP;
@@ -1805,7 +1813,7 @@ private void ProcessCommonFields(StringBuilder sb)
18051813
}
18061814
}
18071815

1808-
public class ShadowSocksConfig
1816+
public class ShadowSocksConfig : Payload
18091817
{
18101818
private readonly string hostname, password, tag, methodStr;
18111819
private readonly Method method;
@@ -1922,7 +1930,7 @@ public ShadowSocksConfigException(string message, Exception inner)
19221930
}
19231931
}
19241932

1925-
public class MoneroTransaction
1933+
public class MoneroTransaction : Payload
19261934
{
19271935
private readonly string address, txPaymentId, recipientName, txDescription;
19281936
private readonly float? txAmount;
@@ -1977,6 +1985,101 @@ public MoneroTransactionException(string message, Exception inner)
19771985
}
19781986
}
19791987

1988+
public class SlovenianUpnQr : Payload
1989+
{
1990+
//Keep in mind, that the ECC level has to be set to "M", version to 15 and ECI to EciMode.Iso8859_2 when generating a SlovenianUpnQr!
1991+
//SlovenianUpnQr specification: https://www.upn-qr.si/uploads/files/NavodilaZaProgramerjeUPNQR.pdf
1992+
1993+
private string _payerName = "";
1994+
private string _payerAddress = "";
1995+
private string _payerPlace = "";
1996+
private string _amount = "";
1997+
private string _code = "";
1998+
private string _purpose = "";
1999+
private string _deadLine = "";
2000+
private string _recipientIban = "";
2001+
private string _recipientName = "";
2002+
private string _recipientAddress = "";
2003+
private string _recipientPlace = "";
2004+
private string _recipientSiModel = "";
2005+
private string _recipientSiReference = "";
2006+
2007+
public override int Version { get { return 15; } }
2008+
public override QRCodeGenerator.ECCLevel EccLevel { get { return QRCodeGenerator.ECCLevel.M; } }
2009+
public override QRCodeGenerator.EciMode EciMode { get { return QRCodeGenerator.EciMode.Iso8859_2; } }
2010+
2011+
private string LimitLength(string value, int maxLength)
2012+
{
2013+
return (value.Length <= maxLength) ? value : value.Substring(0, maxLength);
2014+
}
2015+
2016+
public SlovenianUpnQr(string payerName, string payerAddress, string payerPlace, string recipientName, string recipientAddress, string recipientPlace, string recipientIban, string description, double amount, string recipientSiModel = "SI00", string recipientSiReference = "", string code = "OTHR") :
2017+
this(payerName, payerAddress, payerPlace, recipientName, recipientAddress, recipientPlace, recipientIban, description, amount, null, recipientSiModel, recipientSiReference, code)
2018+
{ }
2019+
2020+
public SlovenianUpnQr(string payerName, string payerAddress, string payerPlace, string recipientName, string recipientAddress, string recipientPlace, string recipientIban, string description, double amount, DateTime? deadline, string recipientSiModel = "SI99", string recipientSiReference = "", string code = "OTHR")
2021+
{
2022+
_payerName = LimitLength(payerName.Trim(), 33);
2023+
_payerAddress = LimitLength(payerAddress.Trim(), 33);
2024+
_payerPlace = LimitLength(payerPlace.Trim(), 33);
2025+
_amount = FormatAmount(amount);
2026+
_code = LimitLength(code.Trim().ToUpper(), 4);
2027+
_purpose = LimitLength(description.Trim(), 42);
2028+
_deadLine = (deadline == null) ? "" : deadline?.ToString("dd.MM.yyyy");
2029+
_recipientIban = LimitLength(recipientIban.Trim(), 34);
2030+
_recipientName = LimitLength(recipientName.Trim(), 33);
2031+
_recipientAddress = LimitLength(recipientAddress.Trim(), 33);
2032+
_recipientPlace = LimitLength(recipientPlace.Trim(), 33);
2033+
_recipientSiModel = LimitLength(recipientSiModel.Trim().ToUpper(), 4);
2034+
_recipientSiReference = LimitLength(recipientSiReference.Trim(), 22);
2035+
}
2036+
2037+
private string FormatAmount(double amount)
2038+
{
2039+
int _amt = (int)Math.Round(amount * 100.0);
2040+
return String.Format("{0:00000000000}", _amt);
2041+
}
2042+
2043+
private int CalculateChecksum()
2044+
{
2045+
int _cs = 5 + _payerName.Length; //5 = UPNQR constant Length
2046+
_cs += _payerAddress.Length;
2047+
_cs += _payerPlace.Length;
2048+
_cs += _amount.Length;
2049+
_cs += _code.Length;
2050+
_cs += _purpose.Length;
2051+
_cs += _deadLine.Length;
2052+
_cs += _recipientIban.Length;
2053+
_cs += _recipientName.Length;
2054+
_cs += _recipientAddress.Length;
2055+
_cs += _recipientPlace.Length;
2056+
_cs += _recipientSiModel.Length;
2057+
_cs += _recipientSiReference.Length;
2058+
_cs += 19;
2059+
return _cs;
2060+
}
2061+
2062+
public override string ToString()
2063+
{
2064+
var _sb = new StringBuilder();
2065+
_sb.Append("UPNQR");
2066+
_sb.Append('\n').Append('\n').Append('\n').Append('\n').Append('\n');
2067+
_sb.Append(_payerName).Append('\n');
2068+
_sb.Append(_payerAddress).Append('\n');
2069+
_sb.Append(_payerPlace).Append('\n');
2070+
_sb.Append(_amount).Append('\n').Append('\n').Append('\n');
2071+
_sb.Append(_code.ToUpper()).Append('\n');
2072+
_sb.Append(_purpose).Append('\n');
2073+
_sb.Append(_deadLine).Append('\n');
2074+
_sb.Append(_recipientIban.ToUpper()).Append('\n');
2075+
_sb.Append(_recipientSiModel).Append(_recipientSiReference).Append('\n');
2076+
_sb.Append(_recipientName).Append('\n');
2077+
_sb.Append(_recipientAddress).Append('\n');
2078+
_sb.Append(_recipientPlace).Append('\n');
2079+
_sb.AppendFormat("{0:000}", CalculateChecksum()).Append('\n');
2080+
return _sb.ToString();
2081+
}
2082+
}
19802083

19812084
private static bool IsValidIban(string iban)
19822085
{
@@ -1998,7 +2101,7 @@ private static string ConvertStringToEncoding(string message, string encoding)
19982101
return iso.GetString(isoBytes);
19992102
#else
20002103
return iso.GetString(isoBytes,0, isoBytes.Length);
2001-
#endif
2104+
#endif
20022105
}
20032106

20042107
private static string EscapeInput(string inp, bool simple = false)

0 commit comments

Comments
 (0)