Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pay plugin #4

Merged
merged 11 commits into from
Apr 6, 2021
9 changes: 8 additions & 1 deletion stripe/example/lib/screens/setup_future_payment_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ class _SetupFuturePaymentScreenState extends State<SetupFuturePaymentScreen> {
}

Future<void> _handlePayPress() async {
// just for testing purposes
final test = await Stripe.instance.confirmPaymentMethod(
'paymentIntentClientSecret',
PaymentMethodParams.card(
cardDetails: CardFieldInputDetails.cardFromToken(
token: 'examplePaymentMethodToken')));
print(test);
if (_card == null) {
return;
}
Expand All @@ -65,7 +72,7 @@ class _SetupFuturePaymentScreenState extends State<SetupFuturePaymentScreen> {
.confirmSetupIntent(
clientSecret,
PaymentMethodParams.card(
details: _card,
cardDetails: _card,
//billingDetails,
))
.then((setupIntentResult) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import android.app.Activity;
import android.content.Intent;

import androidx.annotation.Nullable;

public interface ActivityEventListener {
public void onActivityResult(Activity a, int requestCode, int resultCode, Intent data);
public boolean onActivityResult(@Nullable Activity a, int requestCode, int resultCode, @Nullable Intent data);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.facebook.react.bridge

import android.content.Intent
import com.stripe.android.Stripe
import io.flutter.plugin.common.PluginRegistry.ActivityResultListener

abstract class BaseActivityEventListener : ActivityEventListener, ActivityResultListener {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
return onActivityResult(null, requestCode, resultCode, data)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -275,12 +275,16 @@ internal fun mapToPaymentMethodCreateParams(cardData: ReadableMap): PaymentMetho
}

internal fun mapToCard(card: ReadableMap): PaymentMethodCreateParams.Card {
return PaymentMethodCreateParams.Card.Builder()
.setCvc(card.getString("cvc"))
.setExpiryMonth(card.getInt("expiryMonth"))
.setExpiryYear(card.getInt("expiryYear"))
.setNumber(card.getString("number").orEmpty())
.build()
if (card.hasKey("token")) {
return PaymentMethodCreateParams.Card.create(card.getString("token"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to do `PaymentMethodCreateParams.Card.create(card.getString("token")!!) otherwise Android would throw a type mismatch error. Did you not get that build error?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, compiled and worked fine on the device for me with Android Studio 4.1.3

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The React Native project also? Looks like it might be related to RN
image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't know it was marked nullable on React Native - my bad
Can you quickly fix it? Otherwise I'll send a PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yah, no worries, already done before merging: stripe/stripe-react-native@407fd89

Just wanted to flag with you in case it applied here also.

} else {
return PaymentMethodCreateParams.Card.Builder()
.setCvc(card.getString("cvc"))
.setExpiryMonth(card.getInt("expiryMonth"))
.setExpiryYear(card.getInt("expiryYear"))
.setNumber(card.getString("number").orEmpty())
.build()
}
}

fun getValOr(map: ReadableMap, key: String, default: String? = ""): String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ class PaymentMethodCreateParamsFactory(private val clientSecret: String, private
return when (paymentMethodType) {
PaymentMethod.Type.Card -> createCardPaymentConfirmParams()
PaymentMethod.Type.Ideal -> createIDEALPaymentConfirmParams(paymentMethodType)
PaymentMethod.Type.Alipay -> createAlipayPaymentConfirmParams()
PaymentMethod.Type.Bancontact -> createBancontactPaymentConfirmParams()
PaymentMethod.Type.Giropay -> createGiropayPaymentConfirmParams()
PaymentMethod.Type.Eps -> createEPSPaymentConfirmParams()
PaymentMethod.Type.GrabPay -> createGrabPayPaymentConfirmParams()
PaymentMethod.Type.P24 -> createP24PaymentConfirmParams()
else -> {
throw Exception("This paymentMethodType is not supported yet")
}
Expand All @@ -28,6 +34,7 @@ class PaymentMethodCreateParamsFactory(private val clientSecret: String, private
return when (paymentMethodType) {
PaymentMethod.Type.Card -> createCardPaymentSetupParams()
PaymentMethod.Type.Ideal -> createIDEALPaymentSetupParams(paymentMethodType)
PaymentMethod.Type.Bancontact -> createBancontactPaymentSetupParams()
else -> {
throw Exception("This paymentMethodType is not supported yet")
}
Expand Down Expand Up @@ -56,6 +63,25 @@ class PaymentMethodCreateParamsFactory(private val clientSecret: String, private
)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createP24PaymentConfirmParams(): ConfirmPaymentIntentParams {
val billingDetails = billingDetailsParams?.let { it } ?: run {
throw PaymentMethodCreateParamsException("You must provide billing details")
}
if (urlScheme == null) {
throw PaymentMethodCreateParamsException("You must provide urlScheme")
}

val params = PaymentMethodCreateParams.createP24(billingDetails)

return ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(
paymentMethodCreateParams = params,
clientSecret = clientSecret,
returnUrl = mapToReturnURL(urlScheme)
)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createCardPaymentConfirmParams(): ConfirmPaymentIntentParams {
val cardParams = getMapOrNull(params, "cardDetails")
Expand Down Expand Up @@ -122,6 +148,99 @@ class PaymentMethodCreateParamsFactory(private val clientSecret: String, private
return ConfirmSetupIntentParams
.create(paymentMethodParams, clientSecret)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createAlipayPaymentConfirmParams(): ConfirmPaymentIntentParams {
return ConfirmPaymentIntentParams.createAlipay(clientSecret)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createGrabPayPaymentConfirmParams(): ConfirmPaymentIntentParams {
if (urlScheme == null) {
throw PaymentMethodCreateParamsException("You must provide urlScheme")
}
val billingDetails = billingDetailsParams ?: PaymentMethod.BillingDetails()
val params = PaymentMethodCreateParams.createGrabPay(billingDetails)

return ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(
paymentMethodCreateParams = params,
clientSecret = clientSecret,
returnUrl = mapToReturnURL(urlScheme)
)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createBancontactPaymentConfirmParams(): ConfirmPaymentIntentParams {
val billingDetails = billingDetailsParams?.let { it } ?: run {
throw PaymentMethodCreateParamsException("You must provide billing details")
}
if (urlScheme == null) {
throw PaymentMethodCreateParamsException("You must provide urlScheme")
}
val params = PaymentMethodCreateParams.createBancontact(billingDetails)

return ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(
paymentMethodCreateParams = params,
clientSecret = clientSecret,
returnUrl = mapToReturnURL(urlScheme)
)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createBancontactPaymentSetupParams(): ConfirmSetupIntentParams {
val billingDetails = billingDetailsParams?.let { it } ?: run {
throw PaymentMethodCreateParamsException("You must provide billing details")
}
if (urlScheme == null) {
throw PaymentMethodCreateParamsException("You must provide urlScheme")
}
val params = PaymentMethodCreateParams.createBancontact(billingDetails)

return ConfirmSetupIntentParams
.create(
paymentMethodCreateParams = params,
clientSecret = clientSecret,
returnUrl = mapToReturnURL(urlScheme)
)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createEPSPaymentConfirmParams(): ConfirmPaymentIntentParams {
val billingDetails = billingDetailsParams?.let { it } ?: run {
throw PaymentMethodCreateParamsException("You must provide billing details")
}
if (urlScheme == null) {
throw PaymentMethodCreateParamsException("You must provide urlScheme")
}
val params = PaymentMethodCreateParams.createEps(billingDetails)

return ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(
paymentMethodCreateParams = params,
clientSecret = clientSecret,
returnUrl = mapToReturnURL(urlScheme)
)
}

@Throws(PaymentMethodCreateParamsException::class)
private fun createGiropayPaymentConfirmParams(): ConfirmPaymentIntentParams {
val billingDetails = billingDetailsParams?.let { it } ?: run {
throw PaymentMethodCreateParamsException("You must provide billing details")
}
if (urlScheme == null) {
throw PaymentMethodCreateParamsException("You must provide urlScheme")
}
val params = PaymentMethodCreateParams.createGiropay(billingDetails)

return ConfirmPaymentIntentParams
.createWithPaymentMethodCreateParams(
paymentMethodCreateParams = params,
clientSecret = clientSecret,
returnUrl = mapToReturnURL(urlScheme)
)
}
}

class PaymentMethodCreateParamsException(message:String): Exception(message)
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ class StripeSdkModule(context: ActivityPluginBinding) : ReactContextBaseJavaModu
private var confirmSetupIntentPromise: Promise? = null

private val mActivityEventListener = object : BaseActivityEventListener() {

override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent) {
stripe.onSetupResult(requestCode, data, object : ApiResultCallback<SetupIntentResult> {
override fun onActivityResult(activity: Activity?, requestCode: Int, resultCode: Int, data: Intent?): Boolean {
val onSetupResult = stripe.onSetupResult(requestCode, data, object : ApiResultCallback<SetupIntentResult> {
override fun onSuccess(result: SetupIntentResult) {
val setupIntent = result.intent
when (setupIntent.status) {
Expand All @@ -46,12 +45,14 @@ class StripeSdkModule(context: ActivityPluginBinding) : ReactContextBaseJavaModu
}
})

stripe.onPaymentResult(requestCode, data, object : ApiResultCallback<PaymentIntentResult> {
val onPaymentResult = stripe.onPaymentResult(requestCode, data, object : ApiResultCallback<PaymentIntentResult> {
override fun onSuccess(result: PaymentIntentResult) {
val paymentIntent = result.intent

when (paymentIntent.status) {
StripeIntent.Status.Succeeded -> {
StripeIntent.Status.Succeeded,
StripeIntent.Status.Processing,
StripeIntent.Status.RequiresCapture -> {
confirmPromise?.resolve(mapFromPaymentIntentResult(paymentIntent))
handleCardActionPromise?.resolve(mapFromPaymentIntentResult(paymentIntent))
}
Expand Down Expand Up @@ -81,13 +82,15 @@ class StripeSdkModule(context: ActivityPluginBinding) : ReactContextBaseJavaModu
handleCardActionPromise?.reject(NextPaymentActionErrorType.Failed.toString(), e.toString())
}
})

return onSetupResult || onPaymentResult
}
}

private lateinit var stripe: Stripe

init {
context.addActivityResultListener(mActivityEventListener)
context.addActivityResultListener(mActivityEventListener);
}

private fun configure3dSecure(params: ReadableMap) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class MethodChannelStripe extends StripePlatform {
]) async {
final result = await _methodChannel.invokeMethod('confirmPaymentMethod', {
'paymentIntentClientSecret': paymentIntentClientSecret,
'data': params.toJson(),
'params': params.toJson(),
'options': options,
});
return PaymentIntent.fromJson(result.unfoldToNonNull());
Expand Down
10 changes: 8 additions & 2 deletions stripe_platform_interface/lib/src/models/card_field_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ class ColorKey {

@freezed
class CardFieldInputDetails with _$CardFieldInputDetails {
const factory CardFieldInputDetails() = _CardFieldInputDetailsDefault;

@JsonSerializable(explicitToJson: true)
const factory CardFieldInputDetails({
const factory CardFieldInputDetails.card({
required String last4,
required int expiryMonth,
required int expiryYear,
required CardBrand brand,
required bool complete,
required String? postalCode,
}) = _CardFieldInputDetails;
}) = _CardFieldInputDetailsCard;

const factory CardFieldInputDetails.cardFromToken({
required String token,
}) = _CardFieldInputDetailsWithToken;

factory CardFieldInputDetails.fromJson(Map<String, dynamic> json) =>
_$CardFieldInputDetailsFromJson(json);
Expand Down
Loading