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

@@ -9,7 +9,6 @@ import '../../events/events.dart';
import '../../generated/l10n.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';
@@ -17,7 +16,6 @@ import '../../store/store.dart';
import '../../utils/http_util.dart';
import '../../utils/util_web.dart' if (dart.library.io) '../../utils/util_io.dart';
import '../../utils/utils.dart';
import '../../widgets/general/payment_verification_code_dialog.dart';
class MobilePayNow extends StatefulWidget {
final Key key;
@@ -36,7 +34,6 @@ class MobilePayNowState extends State<MobilePayNow> {
List<PaymentPlatform> paymentPlatforms;
User _user;
bool nativePay;
@override
Widget build(BuildContext context) {
@@ -56,7 +53,7 @@ class MobilePayNowState extends State<MobilePayNow> {
BuildContext mainContext = context;
ListView listView = ListView.builder(
itemCount: nativePay ? paymentPlatforms.length + 3 : paymentPlatforms.length + 2,
itemCount: paymentPlatforms.length + 1,
itemBuilder: (BuildContext context, int position) {
if (position == 0) {
return Column(
@@ -156,135 +153,7 @@ class MobilePayNowState extends State<MobilePayNow> {
);
}
PaymentPlatform paymentPlatform;
if (position == 1) {
if (_user.stripePaymentMethods.length > 0) {
paymentPlatform = paymentPlatforms[position - 1];
Column column = Column(
children: <Widget>[],
);
column.children.add(
Container(
padding: EdgeInsets.all(16.0),
width: double.infinity,
child: Text(
S.of(context).pay_with_existing_cards,
textAlign: TextAlign.left,
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1,
color: Colors.black26,
),
),
),
),
);
for (StripePaymentMethod stripePaymentMethod in _user.stripePaymentMethods) {
column.children.add(
GestureDetector(
child: Container(
padding: EdgeInsets.only(
top: 16.0, left: 16.0, right: 16.0, bottom: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
stripePaymentMethod.cardBrand == 'visa' ?
Image.asset(
'assets/images/visa.png',
width: 50.0,
height: 50.0,
fit: BoxFit.fill,
) : (stripePaymentMethod.cardBrand == 'mastercard' ?
Image.asset(
'assets/images/master.png',
width: 50.0,
height: 50.0,
fit: BoxFit.fill,
) : Icon(
Icons.credit_card, size: 50.0, color: Colors.black38,)),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20.0, right: 10.0),
child: Text(
'**** ${stripePaymentMethod.cardLast4}',
style: TextStyle(
fontSize: 20.0,
),
),
),
Container(
margin: EdgeInsets.only(left: 20.0, right: 10.0),
child: Text(
S.of(context).expire_token(stripePaymentMethod.cardExpMonth, stripePaymentMethod.cardExpYear),
style: TextStyle(
fontSize: 14.0,
color: Colors.black26,
),
),
),
],
),
),
Icon(
Icons.arrow_forward_ios,
color: Colors.black26,
),
],
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 0.5,
color: Colors.black12,
),
),
),
),
onTap: () {
showDialog(
context: mainContext,
builder: (BuildContext context) {
return PaymentVerificationCodeDialog(_user, () {
Util.goPayment(context, order, paymentPlatform,
stripePaymentMethod: stripePaymentMethod);
}, () {
});
},
);
},
),
);
}
column.children.add(
Container(
width: double.infinity,
child: SizedBox.shrink(),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 10,
color: Colors.black26,
),
),
),
)
);
return column;
} else {
return SizedBox.shrink();
}
}
if (position == 2 && nativePay) {
paymentPlatform = paymentPlatforms[position - 2];
return Util().getNativePay(mainContext, order, paymentPlatform);
}
paymentPlatform = nativePay ? paymentPlatforms[position - 3] : paymentPlatforms[position - 2];
paymentPlatform = paymentPlatforms[position - 1];
return GestureDetector(
child: Container(
padding: EdgeInsets.only(top: 16.0, left: 16.0, right: 16.0, bottom: 16.0),
@@ -354,14 +223,6 @@ class MobilePayNowState extends State<MobilePayNow> {
).then((data) {
paymentPlatforms = (data['payment_platforms'] as List).map((e) =>
PaymentPlatform.fromJson(e)).toList();
PaymentPlatform pp = paymentPlatforms[0];
if (Constants.ENABLE_NATIVE_PAY && pp.publishableKey != null
&& pp.publishableKey.isNotEmpty && pp.merchantId != null
&& pp.merchantId.isNotEmpty) {
nativePay = true;
} else {
nativePay = false;
}
_user = User.fromJson(data['contact']);
store.dispatch(UpdateCurrentUser(_user));
eventBus.fire(OnCurrentUserUpdated());