feat: Phase 1 — remove Stripe, switch to e-Transfer

- Drop stripe_payment + stripe_sdk deps; delete stripe pay pages/widgets
- New ETransferPay widget: shows payment@wisetronic.com + R#<orderId> remark
- goPayment stripe/native branches now route to e-Transfer
- pay_now widgets: strip saved-cards section & dead nativePay logic
- my_cards pages rewritten as e-Transfer info (route kept)
- models/utils/constants cleaned of stripe; env constraint -> Dart 3

See UPGRADE_NOTES.md. (Null-safety migration is Phase 3; deps upgrade Phase 2.)
This commit is contained in:
2026-07-24 02:47:13 +08:00
parent f8a90ad305
commit 7ffcc848d0
17 changed files with 371 additions and 1548 deletions

View File

@@ -15,7 +15,6 @@ import 'package:hive/hive.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:stripe_payment/stripe_payment.dart';
import '../constants.dart';
import '../events/eventbus.dart';
@@ -24,12 +23,11 @@ import '../generated/l10n.dart';
import '../models/comment.dart';
import '../models/order.dart';
import '../models/payment_platform.dart';
import '../models/stripe_payment_method.dart';
import '../models/user.dart';
import '../routes.dart';
import '../store/actions.dart';
import '../store/store.dart';
import '../widgets/general/stripe_pay.dart';
import '../widgets/general/e_transfer_pay.dart';
import 'http_util.dart';
import 'utils.dart';
@@ -507,62 +505,14 @@ class Util {
}
Widget getNativePay(BuildContext context, Order order, PaymentPlatform paymentPlatform) {
return GestureDetector(
child: Container(
padding: EdgeInsets.only(top: 16.0, left: 16.0, right: 16.0, bottom: 16.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 6.0),
child: Text(
Platform.isAndroid ? S.of(context).pay_with : S.of(context).pay_with,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: EdgeInsets.only(right: 10.0),
child: Platform.isAndroid ? Image.asset(
'assets/images/google_pay.png',
height: 22.0,
fit: BoxFit.fitHeight,
) : Image.asset(
'assets/images/apple_pay.png',
height: 22.0,
fit: BoxFit.fitHeight,
),
),
],
),
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 10,
color: Colors.black26,
),
),
),
),
onTap: () {
print(paymentPlatform);
PaymentPlatform newPaymentPlatform = PaymentPlatform.fromJson(json.decode(json.encode(paymentPlatform)));
newPaymentPlatform.code = Constants.PAYMENT_METHOD_NATIVE_PAY;
goPayment(context, order, newPaymentPlatform);
},
);
// Native (Apple/Google) pay removed with Stripe. Web uses e-Transfer.
return SizedBox.shrink();
}
static void goPayment(BuildContext context, Order order,
PaymentPlatform paymentPlatform, {
bool googlePay=false,
bool applePay=false,
StripePaymentMethod stripePaymentMethod,
}) {
switch(paymentPlatform.code) {
case Constants.PAYMENT_METHOD_CODE_SQUARE:
@@ -584,102 +534,23 @@ class Util {
break;
case Constants.PAYMENT_METHOD_NATIVE_PAY:
StripePayment.setOptions(
StripeOptions(publishableKey: paymentPlatform.publishableKey,
merchantId: paymentPlatform.merchantId,
androidPayMode: paymentPlatform.publishableKey.contains('_test_')
? 'test'
: 'production'
)
);
StripePayment.paymentRequestWithNativePay(
androidPayOptions: AndroidPayPaymentRequest(
totalPrice: order.totalPrice.toStringAsFixed(2),
currencyCode: order.businessInfo.currency,
),
applePayOptions: ApplePayPaymentOptions(
currencyCode: order.businessInfo.currency,
countryCode: order.businessInfo.address.country,
items: [
ApplePayItem(
label: order.businessInfo.name,
amount: order.totalPrice.toStringAsFixed(2),
),
],
),
).then((token) {
print('return native token: ${token.tokenId}');
processNativePay(context, token, order);
}).catchError((error) {
print('native pay error: $error');
});
// Native (Apple/Google) pay removed with Stripe; route to e-Transfer.
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (BuildContext context) {
return ETransferPay(order: order);
}
));
break;
case Constants.PAYMENT_METHOD_CODE_STRIPE:
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (BuildContext context) {
return StripePay(order, paymentPlatform, stripePaymentMethod: stripePaymentMethod,);
return ETransferPay(order: order);
}
));
break;
}
}
static void processNativePay(BuildContext context, Token token, Order order) async {
PaymentMethod paymentMethod = await StripePayment.createPaymentMethod(
PaymentMethodRequest(
card: CreditCard(
token: token.tokenId,
),
),
);
if (paymentMethod != null) {
Utils.stripePaymentIntent(order, null, paymentMethod.id, paymentMethod.type, (response) {
if (response.data['status'] == Constants.STRIPE_STATUS_REQUIRES_CONFIRMATION) {
StripePayment.confirmPaymentIntent(
PaymentIntent(
clientSecret: response.data[Constants.STRIPE_CLIENT_SECRET],
paymentMethodId: response.data['payment_method'],
),
).then((paymentIntentResult) {
if (paymentIntentResult.status == Constants.STRIPE_STATUS_SUCCEDED) {
Utils.stripeChargedSuccess(order,
paymentMethod.id,
paymentIntentResult.paymentIntentId,
(response) {
StripePayment.completeNativePayRequest().then((_) {
eventBus.fire(OnOrderUpdated());
Routes.router.navigateTo(context, '/orderdetail/${order.id}', replace: true);
}).catchError((error) {
Utils.showMessageDialog(context, error, onOk: () {
Navigator.of(context).pop();
});
});
},
(error) {
Utils.showMessageDialog(context, error, onOk: () {
Navigator.of(context).pop();
});
}
);
} else {
Utils.showMessageDialog(context, Exception('Unknown error'));
}
}).catchError((error) {
Utils.showMessageDialog(context, error, onOk: () {
Navigator.of(context).pop();
});
});
}
}, (error) {
Utils.showMessageDialog(context, error, onOk: () {
Navigator.of(context).pop();
});
});
} else {
}
}
static Future<Uint8List> getBytesFromAsset(String path, int width) async {
ByteData data = await rootBundle.load(path);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);

View File

@@ -16,11 +16,10 @@ import '../generated/l10n.dart';
import '../models/comment.dart' as mComment;
import '../models/order.dart';
import '../models/payment_platform.dart';
import '../models/stripe_payment_method.dart';
import '../models/user.dart';
import '../store/actions.dart';
import '../store/store.dart';
import '../pages/stripe_pay_web.dart';
import '../widgets/general/e_transfer_pay.dart';
import 'http_util.dart';
import 'utils.dart';
@@ -252,7 +251,6 @@ class Util {
PaymentPlatform paymentPlatform, {
bool googlePay=false,
bool applePay=false,
StripePaymentMethod stripePaymentMethod,
}) {
switch(paymentPlatform.code) {
case Constants.PAYMENT_METHOD_CODE_SQUARE:
@@ -276,7 +274,7 @@ class Util {
case Constants.PAYMENT_METHOD_CODE_STRIPE:
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (BuildContext context) {
return StripePayWeb(order, paymentPlatform, stripePaymentMethod: stripePaymentMethod,);
return ETransferPay(order: order);
}
));
break;

View File

@@ -291,39 +291,6 @@ class Utils {
return amount.toStringAsFixed(decimalPlace);
}
static void createOrUpdateStripePaymentMethod(
String paymentMethodId,
String cardBrand,
String paymentMethodType,
String cardCountry,
int cardExpMonth,
int cardExpYear,
String cardFunding,
String cardLast4,
) {
HttpUtil.httpPost(
'v1/create-update-stripe-payment-method',
(response) {
if (response.statusCode == 200) {
print(
'create or update customer stripe payment method success. ${response.data}');
}
},
body: {
'payment_method_id': paymentMethodId,
'card_brand': cardBrand,
'payment_method_type': paymentMethodType,
'card_country': cardCountry,
'card_exp_month': cardExpMonth,
'card_exp_year': cardExpYear,
'card_funding': cardFunding,
'card_last4': cardLast4,
},
isFormData: true,
).catchError((error) {
print('Error: ${error}');
});
}
static showSubmitDialog(BuildContext context) {
showDialog(
@@ -900,48 +867,7 @@ class Utils {
}
}
static void stripePaymentIntent(Order order, String customerId, String paymentMethodId, String cardType,
OnSuccess onSuccess, OnError onError,
{
String cardBrand,
String cardCountry,
int cardExpMonth,
int cardExpYear,
String cardFunding,
String cardLast4,
}) {
HttpUtil.httpPost('v1/stripe-payment-intent',
onSuccess,
body: {
'order_id': order.id,
'pay_amount': order.totalPrice,
'customer_id': customerId == null ? '' : customerId,
'payment_method_id': paymentMethodId,
'payment_method_type': cardType,
'card_brand': cardBrand,
'card_country': cardCountry,
'card_exp_month': cardExpMonth,
'card_exp_year': cardExpYear,
'card_funding': cardFunding,
'card_last4': cardLast4,
},
isFormData: true,
).catchError(onError);
}
static void stripeChargedSuccess(Order order, String paymentMethodId,
String paymentIntentId, OnSuccess onSuccess, OnError onError) {
HttpUtil.httpPost('v1/stripe-charged-success',
onSuccess,
isFormData: true,
body: {
'order_id': order.id,
'payment_method_id': paymentMethodId,
'payment_intent_id': paymentIntentId,
}
).catchError(onError);
}
static int getProductLineInOrder(CartInfo cartInfo) {
int qty = 0;