Skip to content

Commit 08b7a1e

Browse files
authored
Add web plugin for beta release (#476)
* add web support * feat: prepare release for web * fix: analyzer problems * fix: address changes requested * fix: format and update readme
1 parent d439026 commit 08b7a1e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+21260
-315
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ This is caused by the Stripe SDK requires the use of the AppCompat theme for the
5555

5656
Compatible with apps targeting iOS 11 or above.
5757

58+
#### Web (Experimental)
59+
60+
Now you can use Stripe with Flutter web! Notice right now it is highly experimental and only a subset of features is implemented.
61+
62+
Check the steps needed [here](https://github.com/flutter-stripe/flutter_stripe/tree/main/packages/stripe_web)
63+
64+
5865
## Usage example
5966

6067
```dart

example/assets/android.png

149 KB
Loading

example/assets/apple.png

20.5 KB
Loading

example/assets/web.png

29.8 KB
Loading

example/ios/Podfile.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
PODS:
22
- Flutter (1.0.0)
3+
- integration_test (0.0.1):
4+
- Flutter
35
- pay_ios (0.0.1):
46
- Flutter
57
- Stripe (21.9.0):
@@ -15,11 +17,15 @@ PODS:
1517
- StripeCore (21.9.0)
1618
- StripeUICore (21.9.0):
1719
- StripeCore (= 21.9.0)
20+
- webview_flutter_wkwebview (0.0.1):
21+
- Flutter
1822

1923
DEPENDENCIES:
2024
- Flutter (from `Flutter`)
25+
- integration_test (from `.symlinks/plugins/integration_test/ios`)
2126
- pay_ios (from `.symlinks/plugins/pay_ios/ios`)
2227
- stripe_ios (from `.symlinks/plugins/stripe_ios/ios`)
28+
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
2329

2430
SPEC REPOS:
2531
trunk:
@@ -30,18 +36,24 @@ SPEC REPOS:
3036
EXTERNAL SOURCES:
3137
Flutter:
3238
:path: Flutter
39+
integration_test:
40+
:path: ".symlinks/plugins/integration_test/ios"
3341
pay_ios:
3442
:path: ".symlinks/plugins/pay_ios/ios"
3543
stripe_ios:
3644
:path: ".symlinks/plugins/stripe_ios/ios"
45+
webview_flutter_wkwebview:
46+
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
3747

3848
SPEC CHECKSUMS:
3949
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
50+
integration_test: 7db6d89f336f671dcbc7563ee27a5b08f6f8aee1
4051
pay_ios: 8c7beb9c61d885f3f51b61f75f8793023fc8843a
4152
Stripe: 41c3d261501e1dc84755b1bdabdaae50ebf92b53
4253
stripe_ios: fce03ba840e641cc31ff5bdb67f5d5b9c938b897
4354
StripeCore: 2ea9531e863ef20f191a0d61f00dedb7f061baef
4455
StripeUICore: a0f9e40520823d34c63baec0782fc4a0c7fb7484
56+
webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162
4557

4658
PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048
4759

example/lib/main.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_stripe/flutter_stripe.dart';
33
import 'package:stripe_example/.env.dart';
4-
4+
import 'screens/checkout/checkout_screen.dart';
55
import 'screens/screens.dart';
66
import 'widgets/dismiss_focus_overlay.dart';
77

@@ -22,7 +22,16 @@ class App extends StatelessWidget {
2222
return DismissFocusOverlay(
2323
child: MaterialApp(
2424
theme: exampleAppTheme,
25-
home: HomePage(),
25+
routes: {...CheckoutScreenExample.routes},
26+
onGenerateInitialRoutes: (settings) {
27+
print(settings);
28+
return [
29+
MaterialPageRoute(builder: (context) {
30+
return HomePage();
31+
})
32+
];
33+
},
34+
navigatorObservers: [],
2635
),
2736
);
2837
}
@@ -57,7 +66,9 @@ class _HomePageState extends State<HomePage> {
5766

5867
final exampleAppTheme = ThemeData(
5968
colorScheme: ColorScheme.light(
60-
primary: Color(0xff6058F7), secondary: Color(0xff6058F7)),
69+
primary: Color(0xff6058F7),
70+
secondary: Color(0xff6058F7),
71+
),
6172
primaryColor: Colors.white,
6273
appBarTheme: AppBarTheme(elevation: 1),
6374
);
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import 'dart:convert';
2+
import 'dart:developer';
3+
import 'package:stripe_example/.env.dart';
4+
import 'platforms/stripe_checkout.dart'
5+
if (dart.library.js) 'platforms/stripe_checkout_web.dart';
6+
import 'package:flutter/foundation.dart';
7+
import 'package:flutter/material.dart';
8+
9+
import 'package:stripe_checkout/stripe_checkout.dart';
10+
import 'package:http/http.dart' as http;
11+
12+
final kApiUrl = defaultTargetPlatform == TargetPlatform.android
13+
? 'http://10.0.2.2:4242'
14+
: 'http://localhost:4242';
15+
16+
class CheckoutScreenExample extends StatefulWidget {
17+
CheckoutScreenExample({Key? key, this.title, this.snackBarText})
18+
: super(key: key);
19+
20+
final String? title;
21+
22+
final String? snackBarText;
23+
24+
static final routes = {
25+
// For Flutter web
26+
'/success': (c) => CheckoutScreenExample(
27+
title: 'Checkout - Done',
28+
snackBarText: 'Paid succesfully',
29+
),
30+
'/canceled': (c) => CheckoutScreenExample(
31+
title: 'Checkout - Canceled',
32+
snackBarText: 'Checkout canceled',
33+
),
34+
};
35+
36+
@override
37+
_CheckoutScreenExample createState() => _CheckoutScreenExample();
38+
}
39+
40+
class _CheckoutScreenExample extends State<CheckoutScreenExample> {
41+
@override
42+
void initState() {
43+
if (widget.snackBarText != null) {
44+
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
45+
ScaffoldMessenger.of(context).showSnackBar(
46+
SnackBar(content: Text(widget.snackBarText!)),
47+
);
48+
});
49+
}
50+
super.initState();
51+
}
52+
53+
@override
54+
Widget build(BuildContext context) {
55+
return Scaffold(
56+
appBar: AppBar(
57+
title: Text(widget.title ?? 'Checkout Example'),
58+
),
59+
body: Center(
60+
child: Column(
61+
mainAxisAlignment: MainAxisAlignment.center,
62+
children: <Widget>[
63+
ElevatedButton(
64+
onPressed: getCheckout,
65+
child: Text('Open Checkout'),
66+
)
67+
],
68+
),
69+
),
70+
);
71+
}
72+
73+
Future<void> getCheckout() async {
74+
final String sessionId = await _createCheckoutSession();
75+
final result = await redirectToCheckout(
76+
context: context,
77+
sessionId: sessionId,
78+
publishableKey: stripePublishableKey,
79+
);
80+
81+
if (mounted) {
82+
final text = result.when(
83+
success: () => 'Paid succesfully',
84+
canceled: () => 'Checkout canceled',
85+
error: (e) => 'Error $e');
86+
ScaffoldMessenger.of(context).showSnackBar(
87+
SnackBar(content: Text(text)),
88+
);
89+
}
90+
}
91+
92+
Future<String> _createCheckoutSession() async {
93+
final url = Uri.parse('$kApiUrl/create-checkout-session');
94+
final response = await http.post(
95+
url,
96+
headers: {
97+
'Content-Type': 'application/json',
98+
},
99+
body: json.encode({
100+
if (kIsWeb) 'port': getUrlPort(),
101+
}),
102+
);
103+
final Map<String, dynamic> bodyResponse = json.decode(response.body);
104+
final id = bodyResponse['id'] as String;
105+
log('Checkout session id $id');
106+
return id;
107+
}
108+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//@dart= 2.12
2+
String getUrlPort() {
3+
throw 'Not implemented';
4+
}
5+
6+
String getReturnUrl() {
7+
return 'Not implemented';
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'dart:html' as html;
2+
3+
String getUrlPort() => html.window.location.port;
4+
5+
String getReturnUrl() => html.window.location.href;

example/lib/screens/regional_payment_methods/ideal_screen.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:convert';
22

3+
import 'package:flutter/foundation.dart';
34
import 'package:flutter/material.dart';
45
import 'package:flutter_stripe/flutter_stripe.dart';
56
import 'package:http/http.dart' as http;
@@ -41,7 +42,7 @@ class IdealScreen extends StatelessWidget {
4142
try {
4243
await Stripe.instance.confirmPayment(
4344
clientSecret,
44-
PaymentMethodParams.ideal(),
45+
PaymentMethodParams.ideal(bankName: kIsWeb ? 'revolut' : null),
4546
);
4647

4748
ScaffoldMessenger.of(context).showSnackBar(

0 commit comments

Comments
 (0)