-
Notifications
You must be signed in to change notification settings - Fork 629
/
SetupIntent.kt
245 lines (206 loc) · 7.9 KB
/
SetupIntent.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
package com.stripe.android.model
import com.stripe.android.core.model.StripeModel
import com.stripe.android.model.parsers.SetupIntentJsonParser
import kotlinx.parcelize.Parcelize
import org.json.JSONObject
import java.util.regex.Pattern
/**
* A [SetupIntent] guides you through the process of setting up a customer's payment credentials for
* future payments.
*
* - [Setup Intents Overview](https://stripe.com/docs/payments/setup-intents)
* - [SetupIntents API Reference](https://stripe.com/docs/api/setup_intents)
*/
@Parcelize
data class SetupIntent internal constructor(
/**
* Unique identifier for the object.
*/
override val id: String?,
/**
* Reason for cancellation of this [SetupIntent].
*/
val cancellationReason: CancellationReason?,
/**
* Time at which the object was created. Measured in seconds since the Unix epoch.
*/
override val created: Long,
/**
* Country code of the user.
*/
override val countryCode: String?,
/**
* The client secret of this SetupIntent. Used for client-side retrieval using a
* publishable key.
*
* The client secret can be used to complete payment setup from your frontend. It should not
* be stored, logged, embedded in URLs, or exposed to anyone other than the customer. Make
* sure that you have TLS enabled on any page that includes the client secret.
*/
override val clientSecret: String?,
/**
* An arbitrary string attached to the object. Often useful for displaying to users.
*/
override val description: String?,
/**
* Has the value `true` if the object exists in live mode or the value
* `false` if the object exists in test mode.
*/
override val isLiveMode: Boolean,
/**
* The expanded [PaymentMethod] represented by [paymentMethodId].
*/
override val paymentMethod: PaymentMethod? = null,
/**
* ID of the payment method used with this [SetupIntent].
*/
override val paymentMethodId: String?,
/**
* The list of payment method types (e.g. card) that this [SetupIntent] is allowed to set up.
*/
override val paymentMethodTypes: List<String>,
/**
* [Status](https://stripe.com/docs/payments/intents#intent-statuses) of this [SetupIntent].
*/
override val status: StripeIntent.Status?,
/**
* Indicates how the payment method is intended to be used in the future.
*
* Use [StripeIntent.Usage.OnSession] if you intend to only reuse the payment method when the
* customer is in your checkout flow. Use [StripeIntent.Usage.OffSession] if your customer may
* or may not be in your checkout flow. If not provided, this value defaults to
* [StripeIntent.Usage.OffSession].
*/
val usage: StripeIntent.Usage?,
/**
* The error encountered in the previous [SetupIntent] confirmation.
*/
val lastSetupError: Error? = null,
/**
* Payment types that have not been activated in livemode, but have been activated in testmode.
*/
override val unactivatedPaymentMethods: List<String>,
/**
* Payment types that are accepted when paying with Link.
*/
override val linkFundingSources: List<String>,
override val nextActionData: StripeIntent.NextActionData?
) : StripeIntent {
override val nextActionType: StripeIntent.NextActionType?
get() = when (nextActionData) {
is StripeIntent.NextActionData.SdkData -> StripeIntent.NextActionType.UseStripeSdk
is StripeIntent.NextActionData.RedirectToUrl -> StripeIntent.NextActionType.RedirectToUrl
is StripeIntent.NextActionData.DisplayOxxoDetails -> StripeIntent.NextActionType.DisplayOxxoDetails
is StripeIntent.NextActionData.VerifyWithMicrodeposits ->
StripeIntent.NextActionType.VerifyWithMicrodeposits
else -> null
}
override val isConfirmed: Boolean
get() = setOf(
StripeIntent.Status.Processing,
StripeIntent.Status.Succeeded
).contains(status)
override val lastErrorMessage: String?
get() = lastSetupError?.message
override fun requiresAction(): Boolean {
return status === StripeIntent.Status.RequiresAction
}
override fun requiresConfirmation(): Boolean {
return status === StripeIntent.Status.RequiresConfirmation
}
/**
* The error encountered in the previous [SetupIntent] confirmation.
*
* See [last_setup_error](https://stripe.com/docs/api/setup_intents/object#setup_intent_object-last_setup_error).
*/
@Parcelize
data class Error internal constructor(
/**
* For some errors that could be handled programmatically, a short string indicating the
* [error code](https://stripe.com/docs/error-codes) reported.
*/
val code: String?,
/**
* For card errors resulting from a card issuer decline, a short string indicating the
* [card issuer’s reason for the decline](https://stripe.com/docs/declines#issuer-declines)
* if they provide one.
*/
val declineCode: String?,
/**
* A URL to more information about the
* [error code](https://stripe.com/docs/error-codes) reported.
*/
val docUrl: String?,
/**
* A human-readable message providing more details about the error. For card errors,
* these messages can be shown to your users.
*/
val message: String?,
/**
* If the error is parameter-specific, the parameter related to the error.
* For example, you can use this to display a message near the correct form field.
*/
val param: String?,
/**
* The PaymentMethod object for errors returned on a request involving a PaymentMethod.
*/
val paymentMethod: PaymentMethod?,
/**
* The type of error returned.
*/
val type: Type?
) : StripeModel {
enum class Type(val code: String) {
ApiConnectionError("api_connection_error"),
ApiError("api_error"),
AuthenticationError("authentication_error"),
CardError("card_error"),
IdempotencyError("idempotency_error"),
InvalidRequestError("invalid_request_error"),
RateLimitError("rate_limit_error");
internal companion object {
internal fun fromCode(typeCode: String?): Type? {
return values().firstOrNull { it.code == typeCode }
}
}
}
internal companion object {
internal const val CODE_AUTHENTICATION_ERROR = "setup_intent_authentication_failure"
}
}
internal data class ClientSecret(internal val value: String) {
internal val setupIntentId: String =
value.split("_secret".toRegex())
.dropLastWhile { it.isEmpty() }.toTypedArray()[0]
init {
require(isMatch(value)) {
"Invalid Setup Intent client secret: $value"
}
}
internal companion object {
private val PATTERN = Pattern.compile("^seti_[^_]+_secret_[^_]+$")
fun isMatch(value: String) = PATTERN.matcher(value).matches()
}
}
/**
* Reason for cancellation of a [SetupIntent].
*/
enum class CancellationReason(private val code: String) {
Duplicate("duplicate"),
RequestedByCustomer("requested_by_customer"),
Abandoned("abandoned");
internal companion object {
internal fun fromCode(code: String?): CancellationReason? {
return values().firstOrNull { it.code == code }
}
}
}
companion object {
@JvmStatic
fun fromJson(jsonObject: JSONObject?): SetupIntent? {
return jsonObject?.let {
SetupIntentJsonParser().parse(it)
}
}
}
}