-
Notifications
You must be signed in to change notification settings - Fork 629
/
StripeIntent.kt
288 lines (243 loc) · 9.24 KB
/
StripeIntent.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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
package com.stripe.android.model
import android.net.Uri
import android.os.Parcelable
import androidx.annotation.RestrictTo
import com.stripe.android.core.model.StripeModel
import com.stripe.android.utils.StripeUrlUtils
import kotlinx.parcelize.Parcelize
/**
* An interface for methods available in [PaymentIntent] and [SetupIntent]
*/
sealed interface StripeIntent : StripeModel {
/**
* Unique identifier for the object.
*/
val id: String?
/**
* Time at which the object was created. Measured in seconds since the Unix epoch.
*/
val created: Long
/**
* Country code of the user.
*/
val countryCode: String?
/**
* An arbitrary string attached to the object. Often useful for displaying to users.
*/
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.
*/
val isLiveMode: Boolean
/**
* The expanded [PaymentMethod] represented by [paymentMethodId].
*/
val paymentMethod: PaymentMethod?
val paymentMethodId: String?
/**
* The list of payment method types (e.g. card) that this PaymentIntent is allowed to use.
*/
val paymentMethodTypes: List<String>
val nextActionType: NextActionType?
val clientSecret: String?
val status: Status?
val nextActionData: NextActionData?
/**
* Whether confirmation has succeeded and all required actions have been handled.
*/
val isConfirmed: Boolean
val lastErrorMessage: String?
/**
* Payment types that have not been activated in livemode, but have been activated in testmode.
*/
val unactivatedPaymentMethods: List<String>
/**
* Payment types that are accepted when paying with Link.
*/
val linkFundingSources: List<String>
fun requiresAction(): Boolean
fun requiresConfirmation(): Boolean
/**
* Type of the next action to perform.
*/
enum class NextActionType(val code: String) {
RedirectToUrl("redirect_to_url"),
UseStripeSdk("use_stripe_sdk"),
DisplayOxxoDetails("oxxo_display_details"),
AlipayRedirect("alipay_handle_redirect"),
BlikAuthorize("blik_authorize"),
WeChatPayRedirect("wechat_pay_redirect_to_android_app"),
VerifyWithMicrodeposits("verify_with_microdeposits");
override fun toString(): String {
return code
}
internal companion object {
internal fun fromCode(code: String?): NextActionType? {
return values().firstOrNull { it.code == code }
}
}
}
/**
* - [The Intent State Machine - Intent statuses](https://stripe.com/docs/payments/intents#intent-statuses)
* - [PaymentIntent.status API reference](https://stripe.com/docs/api/payment_intents/object#payment_intent_object-status)
* - [SetupIntent.status API reference](https://stripe.com/docs/api/setup_intents/object#setup_intent_object-status)
*/
enum class Status(val code: String) {
Canceled("canceled"),
Processing("processing"),
RequiresAction("requires_action"),
RequiresConfirmation("requires_confirmation"),
RequiresPaymentMethod("requires_payment_method"),
Succeeded("succeeded"),
// only applies to Payment Intents
RequiresCapture("requires_capture");
override fun toString(): String {
return code
}
internal companion object {
internal fun fromCode(code: String?): Status? {
return values().firstOrNull { it.code == code }
}
}
}
/**
* See [setup_intent.usage](https://stripe.com/docs/api/setup_intents/object#setup_intent_object-usage) and
* [Reusing Cards](https://stripe.com/docs/payments/cards/reusing-cards).
*/
enum class Usage(val code: String) {
/**
* Use on_session if you intend to only reuse the payment method when your customer is
* present in your checkout flow.
*/
OnSession("on_session"),
/**
* Use off_session if your customer may or may not be in your checkout flow.
*/
OffSession("off_session"),
OneTime("one_time");
override fun toString(): String {
return code
}
internal companion object {
internal fun fromCode(code: String?): Usage? {
return values().firstOrNull { it.code == code }
}
}
}
sealed class NextActionData : StripeModel {
@Parcelize
data class DisplayOxxoDetails(
/**
* The timestamp after which the OXXO expires.
*/
val expiresAfter: Int = 0,
/**
* The OXXO number.
*/
val number: String? = null,
/**
* URL of a webpage containing the voucher for this OXXO payment.
*/
val hostedVoucherUrl: String? = null
) : NextActionData()
/**
* Contains instructions for authenticating by redirecting your customer to another
* page or application.
*/
@Parcelize
data class RedirectToUrl(
/**
* The URL you must redirect your customer to in order to authenticate.
*/
val url: Uri,
/**
* If the customer does not exit their browser while authenticating, they will be redirected
* to this specified URL after completion.
*/
val returnUrl: String?
) : NextActionData()
@Parcelize
internal data class AlipayRedirect constructor(
val data: String,
val authCompleteUrl: String?,
val webViewUrl: Uri,
val returnUrl: String? = null
) : NextActionData() {
internal constructor(data: String, webViewUrl: String, returnUrl: String? = null) :
this(data, extractReturnUrl(data), Uri.parse(webViewUrl), returnUrl)
private companion object {
/**
* The alipay data string is formatted as query parameters.
* When authenticate is complete, we make a request to the
* return_url param, as a hint to the backend to ping Alipay for
* the updated state
*/
private fun extractReturnUrl(data: String): String? = runCatching {
Uri.parse("alipay://url?$data")
.getQueryParameter("return_url")?.takeIf {
StripeUrlUtils.isStripeUrl(it)
}
}.getOrNull()
}
}
/**
* When confirming a [PaymentIntent] or [SetupIntent] with the Stripe SDK, the Stripe SDK
* depends on this property to invoke authentication flows. The shape of the contents is subject
* to change and is only intended to be used by the Stripe SDK.
*/
sealed class SdkData : NextActionData() {
@Parcelize
data class Use3DS1(
val url: String
) : SdkData()
/**
* Contains all parameters needed to perform a 3DS2 authentication.
*
* @param threeDS2IntentId The id of the PI/SI used to authenticate using 3DS2. When
* non-null, indicates that a different PI/SI is used for authentication. That is the
* case for payments using Link, for example, which use a global merchant for
* authentication since the payment method is added to the consumer's global (not
* merchant-specific) account.
* @param publishableKey The publishable key that should be used to make 3DS2-related
* API calls. It will only be non-null when the 3DS2 calls should be made with a key
* different than the original merchant's key.
*/
@Parcelize
data class Use3DS2(
val source: String,
val serverName: String,
val transactionId: String,
val serverEncryption: DirectoryServerEncryption,
val threeDS2IntentId: String?,
val publishableKey: String?
) : SdkData() {
@Parcelize
data class DirectoryServerEncryption(
val directoryServerId: String,
val dsCertificateData: String,
val rootCertsData: List<String>,
val keyId: String?
) : Parcelable
}
}
@Parcelize
object BlikAuthorize : NextActionData() {
override fun hashCode(): Int {
return 0
}
override fun equals(other: Any?): Boolean {
return this === other
}
}
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Parcelize
data class WeChatPayRedirect(val weChat: WeChat) : NextActionData()
@Parcelize
data class VerifyWithMicrodeposits(
val arrivalDate: Long,
val hostedVerificationUrl: String,
val microdepositType: MicrodepositType
) : NextActionData()
}
}