-
Notifications
You must be signed in to change notification settings - Fork 570
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stripe connect (payments rework) (#1746)
closes #1597 - [x] Setup stripe connect onboarding flow on backend and app - [x] Paypal details flow on backend and app - [x] Link app payments to connected accounts through destination charges - [x] Handle all onboarding flow cases in app - [x] Separate payments page like Shopify - [x] Cleanup and test all cases - [x] Fix minor issues Points to note: - ~New payment links will have to be created for current paid apps to add destination charge~ - ~I set transfer type to destination charge instead of direct charge (in case of direct charge, the user will need to provide a lot more stuff for identity verification). In destination charge we will have to pay the stripe fees (hence I set the marketplace fee as 10% to cover the stripe fees), whereas in direct charge the stripe fee is deducted from the amount (alongside the marketplace fee which we define) and then the remaining amount is transferred to connected account.~ - ~With this PR, it will be mandatory to connect stripe to be able to make paid apps~ - We (Omi Team) will be bearing the stripe fees and there will be no fee for creators https://github.com/user-attachments/assets/0bc62c35-5c1d-49c0-b248-9c57a10c6b7f
- Loading branch information
Showing
21 changed files
with
1,803 additions
and
27 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import 'dart:convert'; | ||
|
||
import 'package:friend_private/backend/http/shared.dart'; | ||
import 'package:friend_private/env/env.dart'; | ||
import 'package:friend_private/pages/payments/models/payment_method_config.dart'; | ||
import 'package:friend_private/utils/logger.dart'; | ||
|
||
Future<Map<String, dynamic>?> getStripeAccountLink() async { | ||
try { | ||
var response = await makeApiCall( | ||
url: '${Env.apiBaseUrl}v1/stripe/connect-accounts', | ||
headers: {}, | ||
body: '', | ||
method: 'POST', | ||
); | ||
if (response == null || response.statusCode != 200) { | ||
return null; | ||
} | ||
return jsonDecode(response.body); | ||
} catch (e) { | ||
Logger.error(e); | ||
return null; | ||
} | ||
} | ||
|
||
Future<bool> isStripeOnboardingComplete() async { | ||
try { | ||
var response = await makeApiCall( | ||
url: '${Env.apiBaseUrl}v1/stripe/onboarded', | ||
headers: {}, | ||
body: '', | ||
method: 'GET', | ||
); | ||
if (response == null || response.statusCode != 200) { | ||
return false; | ||
} | ||
return jsonDecode(response.body)['onboarding_complete']; | ||
} catch (e) { | ||
Logger.error(e); | ||
return false; | ||
} | ||
} | ||
|
||
Future<bool> savePayPalDetails(String email, String link) async { | ||
try { | ||
var response = await makeApiCall( | ||
url: '${Env.apiBaseUrl}v1/paypal/payment-details', | ||
headers: {}, | ||
body: jsonEncode({'email': email, 'paypalme_url': link}), | ||
method: 'POST', | ||
); | ||
if (response == null || response.statusCode != 200) { | ||
return false; | ||
} | ||
return true; | ||
} catch (e) { | ||
Logger.error(e); | ||
return false; | ||
} | ||
} | ||
|
||
Future<Map<String, dynamic>?> fetchPaymentMethodsStatus() async { | ||
try { | ||
var response = await makeApiCall( | ||
url: '${Env.apiBaseUrl}v1/payment-methods/status', | ||
headers: {}, | ||
body: '', | ||
method: 'GET', | ||
); | ||
if (response == null || response.statusCode != 200) { | ||
return null; | ||
} | ||
return jsonDecode(response.body); | ||
} catch (e) { | ||
Logger.error(e); | ||
return null; | ||
} | ||
} | ||
|
||
Future<PayPalDetails?> fetchPayPalDetails() async { | ||
try { | ||
var response = await makeApiCall( | ||
url: '${Env.apiBaseUrl}v1/paypal/payment-details', | ||
headers: {}, | ||
body: '', | ||
method: 'GET', | ||
); | ||
if (response == null || response.statusCode != 200) { | ||
return null; | ||
} | ||
return PayPalDetails.fromJson(jsonDecode(response.body)); | ||
} catch (e) { | ||
Logger.error(e); | ||
return null; | ||
} | ||
} | ||
|
||
Future<bool> setDefaultPaymentMethod(String method) async { | ||
try { | ||
var response = await makeApiCall( | ||
url: '${Env.apiBaseUrl}v1/payment-methods/default', | ||
headers: {}, | ||
body: jsonEncode({'method': method}), | ||
method: 'POST', | ||
); | ||
if (response == null || response.statusCode != 200) { | ||
return false; | ||
} | ||
return true; | ||
} catch (e) { | ||
Logger.error(e); | ||
return false; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_svg/svg.dart'; | ||
import 'package:friend_private/gen/assets.gen.dart'; | ||
|
||
class PaymentMethodConfig { | ||
final String title; | ||
final Widget icon; | ||
final Color backgroundColor; | ||
final VoidCallback onManageTap; | ||
final VoidCallback? onSetActiveTap; | ||
final bool isActive; | ||
final bool isConnected; | ||
|
||
const PaymentMethodConfig({ | ||
required this.title, | ||
required this.icon, | ||
required this.backgroundColor, | ||
required this.onManageTap, | ||
this.onSetActiveTap, | ||
this.isActive = false, | ||
this.isConnected = false, | ||
}); | ||
|
||
String get subtitle => isActive ? 'Active' : (isConnected ? 'Connected' : 'Not Connected'); | ||
|
||
static PaymentMethodConfig stripe({ | ||
required VoidCallback onManageTap, | ||
VoidCallback? onSetActiveTap, | ||
bool isActive = false, | ||
bool isConnected = false, | ||
}) { | ||
return PaymentMethodConfig( | ||
title: 'Stripe', | ||
icon: SvgPicture.asset( | ||
Assets.images.stripeLogo, | ||
width: 80, | ||
color: Colors.white, | ||
), | ||
backgroundColor: isActive ? const Color(0xFF635BFF) : Colors.grey.shade800, | ||
onManageTap: onManageTap, | ||
onSetActiveTap: onSetActiveTap, | ||
isActive: isActive, | ||
isConnected: isConnected, | ||
); | ||
} | ||
|
||
static PaymentMethodConfig paypal({ | ||
required VoidCallback onManageTap, | ||
VoidCallback? onSetActiveTap, | ||
bool isActive = false, | ||
bool isConnected = false, | ||
}) { | ||
return PaymentMethodConfig( | ||
title: 'PayPal', | ||
icon: const Icon( | ||
Icons.paypal, | ||
size: 32, | ||
color: Colors.white, | ||
), | ||
backgroundColor: isActive ? const Color(0xFF003087) : Colors.grey.shade800, | ||
onManageTap: onManageTap, | ||
onSetActiveTap: onSetActiveTap, | ||
isActive: isActive, | ||
isConnected: isConnected, | ||
); | ||
} | ||
} | ||
|
||
class PayPalDetails { | ||
final String email; | ||
final String link; | ||
|
||
PayPalDetails({required this.email, required this.link}); | ||
|
||
Map<String, dynamic> toJson() { | ||
return { | ||
'email': email, | ||
'paypalme_url': link, | ||
}; | ||
} | ||
|
||
factory PayPalDetails.fromJson(Map<String, dynamic> json) { | ||
return PayPalDetails( | ||
email: json['email'], | ||
link: json['paypalme_url'], | ||
); | ||
} | ||
} |
Oops, something went wrong.