1
1
using FastReport . Utils ;
2
2
using System ;
3
3
using System . Collections . Generic ;
4
+ using System . Globalization ;
5
+ using System . Linq ;
4
6
using System . Security . Policy ;
5
7
using System . Text ;
6
8
using System . Text . RegularExpressions ;
@@ -704,7 +706,7 @@ class QRSwiss : QRData
704
706
private Iban iban ;
705
707
private string amount ;
706
708
private Contact creditor , ultimateCreditor , debitor ;
707
- private Currency currency ;
709
+ private string currency ;
708
710
private Reference reference ;
709
711
private AdditionalInformation additionalInformation ;
710
712
private MyRes res ;
@@ -713,7 +715,7 @@ class QRSwiss : QRData
713
715
public Contact Creditor { get { return creditor ; } set { creditor = value ; } }
714
716
public Contact Debitor { get { return debitor ; } set { debitor = value ; } }
715
717
public string Amount { get { return amount ; } }
716
- public Currency _Currency { get { return currency ; } set { currency = value ; } }
718
+ public string _Currency { get { return currency ; } set { currency = value ; } }
717
719
public Reference _Reference { get { return reference ; } set { reference = value ; } }
718
720
public AdditionalInformation _AdditionalInformation { get { return additionalInformation ; } set { additionalInformation = value ; } }
719
721
public string AlternativeProcedure1 { get { return alternativeProcedure1 ; } set { alternativeProcedure1 = value ; } }
@@ -743,11 +745,53 @@ public QRSwiss(QRSwissParameters parameters)
743
745
744
746
if ( ! String . IsNullOrEmpty ( parameters . Amount ) )
745
747
if ( ! parameters . Amount . StartsWith ( "[" ) || ! parameters . Amount . EndsWith ( "]" ) )
746
- if ( parameters . Amount . Length > 12 )
747
- throw new SwissQrCodeException ( res . Get ( "SwissAmountLength" ) ) ;
748
+ {
749
+ //Amount has to use . as decimal separator in any case. See https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf page 27.
750
+ decimal . TryParse ( parameters . Amount , NumberStyles . Number , CultureInfo . InvariantCulture , out decimal decAmount ) ;
751
+ decimal roundedAmount = decimal . Round ( decAmount , 2 , MidpointRounding . AwayFromZero ) ;
752
+
753
+ // if the parameters.Amount contains "0", or "0.", or ".0"
754
+ if ( Regex . IsMatch ( parameters . Amount , @"^0(\.0+)?$" ) )
755
+ {
756
+ roundedAmount = 0m ;
757
+ }
758
+ else
759
+ {
760
+ // If the rounded number is less than or equal to 0, then set it to the minimum allowed value
761
+ if ( roundedAmount <= 0 )
762
+ {
763
+ roundedAmount = 0.01m ;
764
+ }
765
+
766
+ // If the rounded number is greater than 999999999.99, then set it to the maximum allowed value
767
+ if ( roundedAmount > 999999999.99m )
768
+ {
769
+ roundedAmount = 999999999.99m ;
770
+ }
771
+ }
772
+
773
+ parameters . Amount = roundedAmount . ToString ( "0.00" , CultureInfo . InvariantCulture ) ;
774
+
775
+ // in theory, this check is no longer needed
776
+ // if (parameters.Amount.Length > 12)
777
+ // throw new SwissQrCodeException(res.Get("SwissAmountLength"));
778
+ }
748
779
this . amount = parameters . Amount ;
749
780
750
- this . currency = parameters . Currency . Value ;
781
+ switch ( parameters . Currency )
782
+ {
783
+ case nameof ( Currency . EUR ) :
784
+ parameters . Currency = Currency . EUR . ToString ( ) ;
785
+ break ;
786
+ case nameof ( Currency . CHF ) :
787
+ parameters . Currency = Currency . CHF . ToString ( ) ;
788
+ break ;
789
+ default :
790
+ if ( ! parameters . Currency . StartsWith ( "[" ) || ! parameters . Currency . EndsWith ( "]" ) )
791
+ parameters . Currency = Currency . EUR . ToString ( ) ;
792
+ break ;
793
+ }
794
+ this . currency = parameters . Currency ;
751
795
this . debitor = parameters . Debitor ;
752
796
753
797
if ( iban . IsQrIban && parameters . Reference . RefType != Reference . ReferenceType . QRR )
@@ -799,17 +843,30 @@ public override void Unpack(string data)
799
843
}
800
844
counter += 7 ;
801
845
if ( ! datas [ counter ] . StartsWith ( "[" ) || ! datas [ counter ] . EndsWith ( "]" ) )
802
- amount = datas [ counter ] == String . Empty ? amount = null : Decimal . Parse ( datas [ counter ] . Replace ( '.' , ',' ) ) . ToString ( ) ;
846
+ {
847
+ //Amount has to use . as decimal separator in any case. See https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf page 27.
848
+ string invariantSeparator = CultureInfo . InvariantCulture . NumberFormat . NumberDecimalSeparator ;
849
+ string clearQRSwissAmount = datas [ counter ] . Replace ( "," , invariantSeparator ) . Replace ( "/" , invariantSeparator ) ;
850
+
851
+ decimal . TryParse ( clearQRSwissAmount , NumberStyles . Number , CultureInfo . InvariantCulture , out decimal decAmount ) ;
852
+ amount = datas [ counter ] == String . Empty ? amount = null : decAmount . ToString ( CultureInfo . InvariantCulture ) ;
853
+ }
803
854
else amount = datas [ counter ] == String . Empty ? amount = null : datas [ counter ] ;
804
855
counter ++ ;
805
856
806
857
switch ( datas [ counter ] )
807
858
{
808
- case "EUR" :
809
- this . currency = Currency . EUR ;
859
+ case nameof ( Currency . EUR ) :
860
+ this . currency = Currency . EUR . ToString ( ) ;
861
+ break ;
862
+ case nameof ( Currency . CHF ) :
863
+ this . currency = Currency . CHF . ToString ( ) ;
810
864
break ;
811
- case "CHF" :
812
- this . currency = Currency . CHF ;
865
+ default :
866
+ if ( datas [ counter ] . StartsWith ( "[" ) && datas [ counter ] . EndsWith ( "]" ) )
867
+ currency = datas [ counter ] ;
868
+ else
869
+ currency = Currency . EUR . ToString ( ) ;
813
870
break ;
814
871
}
815
872
counter ++ ;
@@ -837,10 +894,20 @@ public override void Unpack(string data)
837
894
iban . TypeIban = Iban . IbanType . Iban ;
838
895
if ( ! String . IsNullOrEmpty ( reference . ReferenceText ) )
839
896
{
840
- if ( reference . ChecksumMod10 ( reference . ReferenceText ) )
841
- reference . _ReferenceTextType = Reference . ReferenceTextType . QrReference ;
842
- else if ( Regex . IsMatch ( reference . ReferenceText , "^[a-zA-Z0-9 ]+$" ) )
843
- reference . _ReferenceTextType = Reference . ReferenceTextType . CreditorReferenceIso11649 ;
897
+ if ( reference . ReferenceText . StartsWith ( "[" ) && reference . ReferenceText . EndsWith ( "]" ) )
898
+ {
899
+ if ( reference . RefType == Reference . ReferenceType . QRR )
900
+ reference . _ReferenceTextType = Reference . ReferenceTextType . QrReference ;
901
+ else
902
+ reference . _ReferenceTextType = Reference . ReferenceTextType . CreditorReferenceIso11649 ;
903
+ }
904
+ else
905
+ {
906
+ if ( reference . ChecksumMod10 ( reference . ReferenceText ) )
907
+ reference . _ReferenceTextType = Reference . ReferenceTextType . QrReference ;
908
+ else if ( Regex . IsMatch ( reference . ReferenceText , "^[a-zA-Z0-9 ]+$" ) )
909
+ reference . _ReferenceTextType = Reference . ReferenceTextType . CreditorReferenceIso11649 ;
910
+ }
844
911
}
845
912
846
913
if ( ! iban . _Iban . StartsWith ( "[" ) || ! iban . _Iban . EndsWith ( "]" ) )
@@ -892,18 +959,8 @@ public override string Pack()
892
959
893
960
894
961
//CcyAmtDate "logical" element
895
- //Amoutn has to use . as decimal seperator in any case. See https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf page 27.
896
- //SwissQrCodePayload += (amount != null ? amount.ToString().Replace(",", ".") : string.Empty) + br; //Amt
897
962
if ( amount != null )
898
- {
899
- string strAmount = amount ;
900
- if ( ! strAmount . StartsWith ( "[" ) || ! strAmount . EndsWith ( "]" ) )
901
- if ( ! strAmount . Contains ( "." ) )
902
- strAmount = amount . ToString ( ) . Replace ( "," , "." ) ;
903
- else
904
- strAmount += ".00" ;
905
- SwissQrCodePayload += strAmount ;
906
- }
963
+ SwissQrCodePayload += amount ;
907
964
else
908
965
SwissQrCodePayload += string . Empty ;
909
966
SwissQrCodePayload += br ;
@@ -922,7 +979,17 @@ public override string Pack()
922
979
923
980
//RmtInf "logical" element
924
981
SwissQrCodePayload += reference . RefType . ToString ( ) + br ; //Tp
925
- SwissQrCodePayload += ( ! string . IsNullOrEmpty ( reference . ReferenceText ) ? reference . ReferenceText : string . Empty ) + br ; //Ref
982
+ if ( ! string . IsNullOrEmpty ( reference . ReferenceText ) )
983
+ {
984
+ if ( reference . ReferenceText . StartsWith ( "[" ) && reference . ReferenceText . EndsWith ( "]" ) )
985
+ SwissQrCodePayload += reference . ReferenceText + br ;
986
+ else
987
+ SwissQrCodePayload += new string ( reference . ReferenceText . Where ( c => char . IsLetterOrDigit ( c ) ) . ToArray ( ) ) . ToUpper ( ) + br ; //Ref
988
+ }
989
+ else
990
+ {
991
+ SwissQrCodePayload += string . Empty + br ; //Ref
992
+ }
926
993
927
994
928
995
//AddInf "logical" element
0 commit comments