1
1
package io.stepuplabs.spaydkmp
2
2
3
- import io.stepuplabs.spaydkmp.common.Account
4
- import io.stepuplabs.spaydkmp.common.AccountList
3
+ import com.ionspin.kotlin.bignum.decimal.BigDecimal
4
+ import io.stepuplabs.spaydkmp.common.BankAccount
5
+ import io.stepuplabs.spaydkmp.common.BankAccountList
5
6
import io.stepuplabs.spaydkmp.common.Key
6
7
import io.stepuplabs.spaydkmp.common.NotificationType
8
+ import io.stepuplabs.spaydkmp.common.PaymentType
7
9
import io.stepuplabs.spaydkmp.common.Validator
8
10
import io.stepuplabs.spaydkmp.exception.*
9
- import kotlin.math.log10
10
11
import kotlinx.datetime.LocalDate
11
12
import kotlinx.datetime.format
12
13
import net.thauvin.erik.urlencoder.UrlEncoderUtil
@@ -25,42 +26,41 @@ class Spayd(
25
26
26
27
// Convenience constructor that accepts all values in form of named parameters
27
28
constructor (
28
- account : Account ,
29
- alternateAccounts : AccountList ? = null ,
30
- currency : String? = null ,
31
- amount: Double ? = null ,
32
- date : LocalDate ? = null ,
33
- senderReference : Int? = null ,
29
+ bankAccount : BankAccount ,
30
+ alternativeBankAccounts : BankAccountList ? = null ,
31
+ currencyCode : String? = null ,
32
+ amount: BigDecimal ? = null ,
33
+ dueDate : LocalDate ? = null ,
34
+ referenceForRecipient : Int? = null ,
34
35
recipientName: String? = null ,
35
- paymentType: String ? = null ,
36
+ paymentType: PaymentType ? = null ,
36
37
message: String? = null ,
37
38
notificationType: NotificationType ? = null ,
38
39
notificationAddress: String? = null ,
39
- repeat : Int? = null ,
40
+ daysToRepeatIfUnsuccessfull : Int? = null ,
40
41
variableSymbol: Long? = null ,
41
42
specificSymbol: Long? = null ,
42
43
constantSymbol: Long? = null ,
43
- identifier : String? = null ,
44
+ referenceForSender : String? = null ,
44
45
url: String? = null ,
45
46
): this (
46
47
parameters = arrayOf(
47
- Key .ACCOUNT to account,
48
- alternateAccounts?.let { Key .ALTERNATE_ACCOUNTS to it },
49
- alternateAccounts?.let { Key .ALTERNATE_ACCOUNTS to it },
50
- currency?.let { Key .CURRENCY to it },
48
+ Key .BANK_ACCOUNT to bankAccount,
49
+ alternativeBankAccounts?.let { Key .ALTERNATIVE_BANK_ACCOUNTS to it },
50
+ currencyCode?.let { Key .CURRENCY_CODE to it },
51
51
amount?.let { Key .AMOUNT to it },
52
- date ?.let { Key .DATE to it },
53
- senderReference ?.let { Key .SENDER_REFERENCE to it },
52
+ dueDate ?.let { Key .DUE_DATE to it },
53
+ referenceForRecipient ?.let { Key .REFERENCE_FOR_RECIPIENT to it },
54
54
recipientName?.let { Key .RECIPIENT_NAME to it },
55
55
paymentType?.let { Key .PAYMENT_TYPE to it },
56
56
message?.let { Key .MESSAGE to it },
57
57
notificationType?.let { Key .NOTIFY_TYPE to it },
58
58
notificationAddress?.let { Key .NOTIFY_ADDRESS to it },
59
- repeat ?.let { Key .REPEAT to it },
59
+ daysToRepeatIfUnsuccessfull ?.let { Key .DAYS_TO_REPEAT_IF_UNSUCCESSFUL to it },
60
60
variableSymbol?.let { Key .VARIABLE_SYMBOL to it },
61
61
specificSymbol?.let { Key .SPECIFIC_SYMBOL to it },
62
62
constantSymbol?.let { Key .CONSTANT_SYMBOL to it },
63
- identifier ?.let { Key .IDENTIFIER to it },
63
+ referenceForSender ?.let { Key .REFERENCE_FOR_SENDER to it },
64
64
url?.let { Key .URL to it },
65
65
)
66
66
)
@@ -77,7 +77,7 @@ class Spayd(
77
77
78
78
// payment parameters
79
79
for (parameter in parameters.filterNotNull()) {
80
- getEntry(parameter.first.key , parameter.second)?.let { parts.add(it) }
80
+ getEntry(parameter.first, parameter.second)?.let { parts.add(it) }
81
81
}
82
82
83
83
// merge into one string
@@ -109,7 +109,7 @@ class Spayd(
109
109
validator.validate(key = parameter.first, value = parameter.second)
110
110
111
111
when (parameter.first) {
112
- Key .ACCOUNT -> hasAccount = true
112
+ Key .BANK_ACCOUNT -> hasAccount = true
113
113
Key .NOTIFY_TYPE -> hasNotificationType = true
114
114
Key .NOTIFY_ADDRESS -> hasNotificationAddress = true
115
115
else -> continue
@@ -126,12 +126,18 @@ class Spayd(
126
126
}
127
127
128
128
// Get parameter:value key for SPAYD
129
- private fun getEntry (parameter : String , value : Any? ): String? {
129
+ private fun getEntry (parameter : Key , value : Any? ): String? {
130
130
if (value == null ) {
131
131
return null
132
132
}
133
133
134
- return " $parameter :$value "
134
+ val valStr = when (parameter.type) {
135
+ LocalDate ::class -> (value as LocalDate ).format(LocalDate .Formats .ISO_BASIC )
136
+ BigDecimal ::class -> (value as BigDecimal ).toStringExpanded()
137
+ else -> sanitize(" $value " )
138
+ }
139
+
140
+ return " ${parameter.key} :$valStr "
135
141
}
136
142
137
143
// Get parameter:value key for SPAYD
@@ -147,44 +153,16 @@ class Spayd(
147
153
}
148
154
149
155
entries.append(
150
- escape (value.toString()),
156
+ sanitize (value.toString()),
151
157
)
152
158
}
153
159
154
160
return " $parameter :$entries "
155
161
}
156
162
157
- // Get parameter:value key for SPAYD
158
- private fun getEntry (parameter : String , date : LocalDate ? ): String? {
159
- if (date == null ) {
160
- return null
161
- }
162
-
163
- return " $parameter :${date.format(LocalDate .Formats .ISO_BASIC )} "
164
- }
165
-
166
163
// Sanitize values for SPAYD
167
- private fun escape (value : String ): String {
168
- val escapedValue = StringBuilder ()
169
-
170
- for (char in value) {
171
- if (char.code > 127 ) {
172
- escapedValue.append(UrlEncoderUtil .encode(char.toString()))
173
- } else {
174
- if (char.compareTo(' *' ) == 0 ) { // spayd value separator
175
- escapedValue.append(" %2A" )
176
- } else if (char.compareTo(' +' ) == 0 ) {
177
- escapedValue.append(" %2B" )
178
- } else if (char.compareTo(' %' ) == 0 ) {
179
- escapedValue.append(" %25" )
180
- } else {
181
- escapedValue.append(char)
182
- }
183
- }
184
- }
185
-
186
- return escapedValue.toString()
187
- }
164
+ private fun sanitize (value : String ): String = Regex (" [^A-Za-z0-9 @$%+\\ -/:.,]" )
165
+ .replace(value, " " )
188
166
189
167
companion object {
190
168
const val MIME_TYPE : String = " application/x-shortpaymentdescriptor"
0 commit comments