Skip to content

Commit

Permalink
Sync with latest sources (#162)
Browse files Browse the repository at this point in the history
* sync android code

* implement new parsing cardfield and paymentintent

* comply to new result propagation for setupintent

* sync ios

* Update dart layer

* Throw errors for easy debug + cancel login when error

* workaround for stripe/stripe-react-native#368, also adjusted canceledAt

* migrate to flutter_lints because pedantic is deprecated

* implement create token method (#165)

* implement create token method

* add create token to example app

* Add createToken for iOS

* Make example tiles scrollable

Co-authored-by: Jaime Blasco <[email protected]>

* improve documentation for Android and issues #155 #142

* fix merge issue

* add  urlscheme to initialise method

* BREAKING: rename threedsecure button config and add config theme for other buttons

* BREAKING make paymentIntentClientSecret nullable and add setupIntentClientSecret for paymentsheet

* add fontfamily and dangerouslyGetFullCardDetails to cardfield

Co-authored-by: Remon <[email protected]>
Co-authored-by: Remon Helmond <[email protected]>
Co-authored-by: Jaime Blasco <[email protected]>
  • Loading branch information
4 people committed Jul 4, 2021
1 parent ffe334b commit a679954
Show file tree
Hide file tree
Showing 65 changed files with 3,791 additions and 753 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ dart pub add flutter_stripe

- Android 5.0 (API level 21) and above
- Kotlin version 1.5.0 and above: [example](https://github.com/flutter-stripe/flutter_stripe/blob/79b201a2e9b827196d6a97bb41e1d0e526632a5a/example/android/build.gradle#L2)
- Using a descendant of `Theme.AppCompact` for your activity: [example](https://github.com/flutter-stripe/flutter_stripe/blob/384d390c8a90d19dc62c73faa5226fa931fd6d44/example/android/app/src/main/res/values/styles.xml#L15)
- Using a descendant of `Theme.AppCompact` for your activity: [example](https://github.com/flutter-stripe/flutter_stripe/main/example/android/app/src/main/res/values/styles.xml#L15), [example night theme](https://github.com/flutter-stripe/flutter_stripe/blob/main/example/android/app/src/main/res/values-night/styles.xml#L16)
- Using an up-to-date Android gradle build tools version: [example](https://github.com/flutter-stripe/flutter_stripe/blob/main/example/android/build.gradle#L9) and an up-to-date gradle version accordingly: [example](https://github.com/flutter-stripe/flutter_stripe/blob/main/example/android/gradle/wrapper/gradle-wrapper.properties#L6)
- Using `FlutterFragmentActivity` instead of `FlutterActivity` in `MainActivity.kt`: [example](https://github.com/flutter-stripe/flutter_stripe/blob/79b201a2e9b827196d6a97bb41e1d0e526632a5a/example/android/app/src/main/kotlin/com/flutter/stripe/example/MainActivity.kt#L6)

This is caused by the Stripe SDK requires the use of the AppCompact theme for their UI components and the Support Fragment Manager for the Payment Sheets
Expand Down
2 changes: 1 addition & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# include: ../analysis_options.yaml
#
include: package:pedantic/analysis_options.1.11.0.yaml
include: package:flutter_lints/flutter.yaml

# TODO (albertus-stripe): Add "public_member_api_docs" linter after all public member documentation are finished.

Expand Down
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class _HomePageState extends State<HomePage> {
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(children: [
body: ListView(children: [
...ListTile.divideTiles(
context: context,
tiles: [
Expand Down
73 changes: 73 additions & 0 deletions example/lib/screens/legacy_token_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:stripe_example/widgets/loading_button.dart';
import 'package:stripe_platform_interface/stripe_platform_interface.dart';

class LegacyTokenScreen extends StatefulWidget {
@override
_LegacyTokenScreenState createState() => _LegacyTokenScreenState();
}

class _LegacyTokenScreenState extends State<LegacyTokenScreen> {
CardFieldInputDetails? _card;

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Padding(
padding: EdgeInsets.all(16),
child: CardField(
onCardChanged: (card) {
setState(() {
_card = card;
});
},
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: LoadingButton(
onPressed:
_card?.complete == true ? _handleCreateTokenPress : null,
text: 'Create token',
),
),
],
),
);
}

Future<void> _handleCreateTokenPress() async {
if (_card == null) {
return;
}

try {
// 1. Gather customer billing information (ex. email)

final address = Address(
city: 'Houston',
country: 'US',
line1: '1459 Circle Drive',
line2: '',
state: 'Texas',
postalCode: '77063',
); // mocked data for tests

// 2. Create payment method
await Stripe.instance.createToken(
CreateTokenParams(type: TokenType.Card, address: address));

ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Success!: The token was created successfully}!')));
return;
} catch (e) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Error: $e')));
rethrow;
}
}
}
1 change: 1 addition & 0 deletions example/lib/screens/no_webhook_payment_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class _NoWebhookPaymentScreenState extends State<NoWebhookPaymentScreen> {
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')));
rethrow;
}
}

Expand Down
2 changes: 2 additions & 0 deletions example/lib/screens/payment_sheet_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class _PaymentSheetScreenState extends State<PaymentSheetScreen> {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
rethrow;
}
}

Expand Down Expand Up @@ -107,6 +108,7 @@ class _PaymentSheetScreenState extends State<PaymentSheetScreen> {
content: Text('$e'),
),
);
rethrow;
}
}
}
5 changes: 5 additions & 0 deletions example/lib/screens/screens.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '../screens/no_webhook_payment_screen.dart';
import '../screens/setup_future_payment_screen.dart';
import '../screens/webhook_payment_screen.dart';
import 'cvc_re_collection_screen.dart';
import 'legacy_token_screen.dart';
import 'payment_sheet_screen.dart';
import 'themes.dart';

Expand Down Expand Up @@ -51,5 +52,9 @@ class Example {
title: 'Payment sheet',
builder: (context) => PaymentSheetScreen(),
),
Example(
title: 'Create token (legacy)',
builder: (context)=> LegacyTokenScreen(),
)
];
}
4 changes: 2 additions & 2 deletions example/lib/screens/setup_future_payment_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'dart:convert';
import 'dart:developer';

import 'package:flutter/material.dart' hide Card;
import 'package:http/http.dart' as http;
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:http/http.dart' as http;
import 'package:stripe_example/config.dart';
import 'package:stripe_example/widgets/loading_button.dart';
import 'package:stripe_platform_interface/stripe_platform_interface.dart';
Expand Down Expand Up @@ -183,7 +183,7 @@ class _SetupFuturePaymentScreenState extends State<SetupFuturePaymentScreen> {
await Stripe.instance.confirmPaymentMethod(
_retrievedPaymentIntent!.clientSecret,
PaymentMethodParams.cardFromMethodId(
paymentMethodId: _retrievedPaymentIntent!.paymentMethodId),
paymentMethodId: _retrievedPaymentIntent!.paymentMethodId!),
);
}
}
Expand Down
24 changes: 14 additions & 10 deletions example/lib/widgets/loading_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,22 @@ class _LoadingButtonState extends State<LoadingButton> {
setState(() {
_isLoading = true;
});
if (kDebugMode) {

try {
await widget.onPressed!();
} else {
try {
await widget.onPressed!();
} catch (e) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Error $e')));
} catch (e) {
if (kDebugMode) {
rethrow;
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Error $e')));
}
} finally {
setState(() {
_isLoading = false;
});
}
setState(() {
_isLoading = false;
});


}
}
38 changes: 36 additions & 2 deletions packages/stripe/lib/src/stripe.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ class Stripe {
instance.markNeedsSettings();
}

/// Sets the custom url scheme
static set urlScheme(String? value) {
if (value == instance._urlScheme) {
return;
}
instance._urlScheme = value;
instance.markNeedsSettings();
}

/// Retrieves the custom url scheme
static String? get urlScheme {
return instance._urlScheme;
}

/// Retrieves the merchant identifier.
static String? get merchantIdentifier => instance._merchantIdentifier;

Expand All @@ -71,12 +85,13 @@ class Stripe {

/// Reconfigures the Stripe platform by applying the current values for
/// [publishableKey], [merchantIdentifier], [stripeAccountId],
/// [threeDSecureParams]
/// [threeDSecureParams], [urlScheme]
Future<void> applySettings() => _initialise(
publishableKey: publishableKey,
merchantIdentifier: merchantIdentifier,
stripeAccountId: stripeAccountId,
threeDSecureParams: threeDSecureParams,
urlScheme: urlScheme,
);

/// Exposes a [ValueListenable] whether or not Apple pay is supported for this
Expand Down Expand Up @@ -122,6 +137,22 @@ class Stripe {
}
}

/// Creates a single-use token that represents a credit card’s details.
///
/// Tokens are considered legacy, use [PaymentMethod] and [PaymentIntent]
/// instead.
/// /// Throws an [StripeError] in case createToken fails.
Future<TokenData> createToken(CreateTokenParams params) async {
await _awaitForSettings();
try {
final tokenData = await _platform.createToken(params);
return tokenData;
} on StripeError catch (error) {
throw StripeError(message: error.message, code: error.message);
}
}

/// Retrieves a [PaymentIntent] using the provided [clientSecret].
///
/// Throws an [StripeError] in case retrieving the intent fails.
Expand Down Expand Up @@ -290,6 +321,7 @@ class Stripe {
String? _stripeAccountId;
ThreeDSecureConfigurationParams? _threeDSecureParams;
String? _merchantIdentifier;
String? _urlScheme;

static StripePlatform? __platform;

Expand All @@ -311,13 +343,15 @@ class Stripe {
String? stripeAccountId,
ThreeDSecureConfigurationParams? threeDSecureParams,
String? merchantIdentifier,
String? urlScheme,
}) async {
_needsSettings = false;
_needsSettings = false;
await _platform.initialise(
publishableKey: publishableKey,
stripeAccountId: stripeAccountId,
threeDSecureParams: threeDSecureParams,
merchantIdentifier: merchantIdentifier,
urlScheme: urlScheme,
);
}

Expand Down
19 changes: 19 additions & 0 deletions packages/stripe/lib/src/widgets/card_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:stripe_platform_interface/stripe_platform_interface.dart';

/// Customizable form that collects card information.
Expand All @@ -17,6 +18,7 @@ class CardField extends StatefulWidget {
this.enablePostalCode = false,
this.style,
this.autofocus = false,
this.dangerouslyGetFullCardDetails = false,
this.cursorColor,
this.numberHintText,
this.expirationHintText,
Expand Down Expand Up @@ -59,6 +61,15 @@ class CardField extends StatefulWidget {
/// Default is `false`.
final bool autofocus;

/// When true the Full card details will be returned.
///
/// WARNING!!! Only do this if you're certain that you fulfill the necessary
/// PCI compliance requirements. Make sure that you're not mistakenly logging
/// or storing full card details! See the docs for
/// details: https://stripe.com/docs/security/guide#validating-pci-compliance
/// Default is `false`.
final bool dangerouslyGetFullCardDetails;

@override
_CardFieldState createState() => _CardFieldState();
}
Expand Down Expand Up @@ -135,9 +146,15 @@ class _CardFieldState extends State<CardField> {
final fontSize = widget.style?.fontSize ??
Theme.of(context).textTheme.subtitle1?.fontSize ??
kCardFieldDefaultFontSize;

final fontFamily = widget.style?.fontFamily ??
Theme.of(context).textTheme.subtitle1?.fontFamily ??
kCardFieldDefaultFontFamily;

return CardStyle(
textColor: widget.style?.color,
fontSize: fontSize,
fontFamily: fontFamily,
cursorColor: widget.cursorColor,
textErrorColor: decoration.errorStyle?.color,
placeholderColor: decoration.hintStyle?.color,
Expand Down Expand Up @@ -235,6 +252,7 @@ class _MethodChannelCardFieldState extends State<_MethodChannelCardField> {
baseTextStyle?.color ??
kCardFieldDefaultTextColor,
fontSize: baseTextStyle?.fontSize ?? kCardFieldDefaultFontSize,
fontFamily: baseTextStyle?.fontFamily ?? kCardFieldDefaultFontFamily,
textErrorColor:
theme.inputDecorationTheme.errorStyle?.color ?? theme.errorColor,
placeholderColor:
Expand Down Expand Up @@ -469,6 +487,7 @@ class _UiKitCardField extends StatelessWidget {
const kCardFieldDefaultHeight = 48.0;
const kCardFieldDefaultFontSize = 17.0;
const kCardFieldDefaultTextColor = Colors.black;
const kCardFieldDefaultFontFamily = 'Roboto';

typedef CardChangedCallback = void Function(CardFieldInputDetails? details);
typedef CardFocusCallback = void Function(CardFieldName? focusedField);
3 changes: 1 addition & 2 deletions packages/stripe/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
pedantic: ^1.11.0

flutter_lints: ^1.0.3



3 changes: 2 additions & 1 deletion packages/stripe_android/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.stripe:stripe-android:16.8.2'
implementation 'com.stripe:stripe-android:16.10.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ import java.lang.ref.WeakReference

abstract class BaseActivityEventListener : ActivityEventListener, ActivityResultListener {

var pluginInstance: StripeAndroidPlugin? = null

lateinit var activity: WeakReference<Activity>

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
if (pluginInstance != null && pluginInstance?.isInitialized == true) {
onActivityResult(activity.get(), requestCode, resultCode, data)
}
onActivityResult(activity.get(), requestCode, resultCode, data)
return false
}
}
Loading

0 comments on commit a679954

Please sign in to comment.