|
|
@@ -2,20 +2,23 @@ import { Image } from 'expo-image';
|
|
|
import { useRouter } from 'expo-router';
|
|
|
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
|
|
import {
|
|
|
- ActivityIndicator,
|
|
|
- Alert,
|
|
|
- Dimensions,
|
|
|
- Modal,
|
|
|
- ScrollView,
|
|
|
- StyleSheet,
|
|
|
- Text,
|
|
|
- TouchableOpacity,
|
|
|
- View
|
|
|
+ ActivityIndicator,
|
|
|
+ Alert,
|
|
|
+ Dimensions,
|
|
|
+ Modal,
|
|
|
+ ScrollView,
|
|
|
+ StyleSheet,
|
|
|
+ Text,
|
|
|
+ TouchableOpacity,
|
|
|
+ View
|
|
|
} from 'react-native';
|
|
|
|
|
|
import { applyOrder, getApplyResult, previewOrder } from '@/services/award';
|
|
|
+import Alipay from 'expo-native-alipay';
|
|
|
import { LotteryResultModal, LotteryResultModalRef } from './LotteryResultModal';
|
|
|
|
|
|
+
|
|
|
+
|
|
|
const { width: SCREEN_WIDTH } = Dimensions.get('window');
|
|
|
|
|
|
// 等级配置
|
|
|
@@ -95,6 +98,13 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ // ... (Imports handled via separate edit or assume existing)
|
|
|
+
|
|
|
+ const [payConfig, setPayConfig] = useState<any>(null);
|
|
|
+ const [paymentMethod, setPaymentMethod] = useState<'ALIPAY' | 'WXPAY'>('ALIPAY');
|
|
|
+
|
|
|
+ // ...
|
|
|
+
|
|
|
useImperativeHandle(ref, () => ({
|
|
|
show: (n: number, previewData: any = {}, bNum?: string, seats?: number[], pack?: boolean) => {
|
|
|
setNum(n);
|
|
|
@@ -103,6 +113,7 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
setPackFlag(pack || undefined);
|
|
|
setPreviewData(previewData);
|
|
|
setVisible(true);
|
|
|
+ fetchPayConfig();
|
|
|
},
|
|
|
showFreedom: () => {
|
|
|
setFreedomNum(10);
|
|
|
@@ -125,6 +136,7 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
setFreedomNum(selectedNum);
|
|
|
setPreviewData(preview);
|
|
|
setVisible(true);
|
|
|
+ fetchPayConfig();
|
|
|
}
|
|
|
} catch (error: any) {
|
|
|
Alert.alert('提示', error?.message || '获取订单信息失败');
|
|
|
@@ -144,7 +156,19 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
onSuccess({ tradeNo: '', num });
|
|
|
};
|
|
|
|
|
|
- // 支付
|
|
|
+ const fetchPayConfig = async () => {
|
|
|
+ try {
|
|
|
+ const res = await import('@/services/user').then(m => m.getParamConfig('wxpay_alipay'));
|
|
|
+ if (res && res.data) {
|
|
|
+ setPayConfig(JSON.parse(res.data));
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log('Fetch Pay Config Error', e);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // ...
|
|
|
+
|
|
|
const pay = async () => {
|
|
|
if (loading) return;
|
|
|
if (!checked) {
|
|
|
@@ -154,25 +178,48 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
|
|
|
setLoading(true);
|
|
|
try {
|
|
|
- const paymentType = 'WALLET';
|
|
|
+ let paymentType = '';
|
|
|
+
|
|
|
+ // Prioritize Wallet if checked
|
|
|
+ if (cashChecked) {
|
|
|
+ paymentType = 'WALLET';
|
|
|
+ } else if (paymentMethod === 'ALIPAY') {
|
|
|
+ // APP端固定使用 ALIPAY_APP,忽略后端配置的 CUSTOMER_SERVICE_LINK
|
|
|
+ paymentType = 'ALIPAY_APP';
|
|
|
+ } else {
|
|
|
+ // 微信支付也固定使用 WXPAY_APP
|
|
|
+ paymentType = 'WXPAY_APP';
|
|
|
+ }
|
|
|
+
|
|
|
const payNum = packFlag ? 1 : num;
|
|
|
|
|
|
+ console.log('Submit Order Params:', {
|
|
|
+ poolId,
|
|
|
+ quantity: payNum,
|
|
|
+ paymentType,
|
|
|
+ boxNum,
|
|
|
+ seatNumbers,
|
|
|
+ packFlag,
|
|
|
+ payConfig
|
|
|
+ });
|
|
|
+
|
|
|
const res = await applyOrder(poolId, payNum, paymentType, boxNum, seatNumbers, packFlag);
|
|
|
+
|
|
|
+ console.log('Apply Order Result:', res);
|
|
|
|
|
|
- if (res?.paySuccess || res?.bizTradeNo || res?.tradeNo) {
|
|
|
- const tradeNo = res.bizTradeNo || res.tradeNo;
|
|
|
- setVisible(false);
|
|
|
-
|
|
|
- // Navigation to Lottery Animation
|
|
|
- router.push({
|
|
|
- pathname: '/lottery' as any,
|
|
|
- params: { tradeNo, num, poolId }
|
|
|
- });
|
|
|
-
|
|
|
- // Trigger success callback (e.g. to refresh pool data)
|
|
|
- onSuccess({ tradeNo, num });
|
|
|
+ if (!res) {
|
|
|
+ Alert.alert('提示', '订单创建失败');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.paySuccess) {
|
|
|
+ // Direct Success (Wallet)
|
|
|
+ handleSuccess(res.bizTradeNo || res.tradeNo);
|
|
|
+ } else if (res.payInfo) {
|
|
|
+ // Handle Native Payment
|
|
|
+ handleNativePay(res.payInfo, paymentType, res.bizTradeNo || res.tradeNo);
|
|
|
} else {
|
|
|
- Alert.alert('提示', res?.message || '支付失败,请重试');
|
|
|
+ Alert.alert('提示', res?.message || '支付失败,请重试');
|
|
|
}
|
|
|
} catch (error: any) {
|
|
|
Alert.alert('支付失败', error?.message || '请稍后重试');
|
|
|
@@ -181,6 +228,45 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ const handleSuccess = (tradeNo: string) => {
|
|
|
+ setVisible(false);
|
|
|
+ router.push({
|
|
|
+ pathname: '/lottery' as any,
|
|
|
+ params: { tradeNo, num, poolId }
|
|
|
+ });
|
|
|
+ onSuccess({ tradeNo, num });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleNativePay = async (payInfo: string, type: string, tradeNo: string) => {
|
|
|
+ if (type === 'ALIPAY' || type.includes('ALIPAY')) {
|
|
|
+ try {
|
|
|
+ // 设置支付宝 URL Scheme(用于支付完成后返回APP)
|
|
|
+ Alipay.setAlipayScheme('alipay2021004126636720');
|
|
|
+
|
|
|
+ // 使用 expo-native-alipay 调用支付宝
|
|
|
+ const result = await Alipay.pay(payInfo);
|
|
|
+ console.log('Alipay Result:', result);
|
|
|
+
|
|
|
+ // resultStatus: '9000' 表示支付成功
|
|
|
+ const status = result?.resultStatus;
|
|
|
+
|
|
|
+ if (status === '9000') {
|
|
|
+ // 支付成功,跳转到抽奖页面
|
|
|
+ handleSuccess(tradeNo);
|
|
|
+ } else if (status === '6001') {
|
|
|
+ Alert.alert('提示', '用户取消支付');
|
|
|
+ } else {
|
|
|
+ Alert.alert('支付中断', `状态码: ${status}`);
|
|
|
+ }
|
|
|
+ } catch (e: any) {
|
|
|
+ console.log('Alipay Error:', e);
|
|
|
+ Alert.alert('支付异常', e.message || '调用支付宝失败');
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Alert.alert('提示', '微信支付暂未实现');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
// 获取抽奖结果(10发以下用弹窗)
|
|
|
const fetchLotteryResult = async (tradeNo: string) => {
|
|
|
setResultLoading(true);
|
|
|
@@ -202,9 +288,7 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
setTimeout(poll, 1000);
|
|
|
} else {
|
|
|
setResultLoading(false);
|
|
|
- if (typeof window !== 'undefined') {
|
|
|
- window.alert('获取结果超时,请在仓库中查看');
|
|
|
- }
|
|
|
+ Alert.alert('提示', '获取结果超时,请在仓库中查看');
|
|
|
}
|
|
|
} catch {
|
|
|
if (attempts < maxAttempts) {
|
|
|
@@ -212,9 +296,7 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
setTimeout(poll, 1000);
|
|
|
} else {
|
|
|
setResultLoading(false);
|
|
|
- if (typeof window !== 'undefined') {
|
|
|
- window.alert('获取结果失败,请在仓库中查看');
|
|
|
- }
|
|
|
+ Alert.alert('提示', '获取结果失败,请在仓库中查看');
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
@@ -331,6 +413,41 @@ export const CheckoutModal = forwardRef<CheckoutModalRef, CheckoutModalProps>(
|
|
|
</TouchableOpacity>
|
|
|
</View>
|
|
|
)}
|
|
|
+
|
|
|
+ {/* Payment Methods Section */}
|
|
|
+ {(!cashChecked || (cash && cash.balance < (lastPrice || (data?.price || 0) * num))) && payConfig ? (
|
|
|
+ <View style={styles.paymentSection}>
|
|
|
+ <Text style={styles.sectionTitle}>支付方式</Text>
|
|
|
+
|
|
|
+ {payConfig?.alipay?.enabled ? (
|
|
|
+ <TouchableOpacity
|
|
|
+ style={styles.payOption}
|
|
|
+ onPress={() => setPaymentMethod('ALIPAY')}
|
|
|
+ >
|
|
|
+ <View style={styles.rowLeft}>
|
|
|
+ <Text style={styles.payLabel}>支付宝支付</Text>
|
|
|
+ </View>
|
|
|
+ <View style={[styles.radio, paymentMethod === 'ALIPAY' && styles.radioChecked]}>
|
|
|
+ {paymentMethod === 'ALIPAY' ? <View style={styles.radioInner} /> : null}
|
|
|
+ </View>
|
|
|
+ </TouchableOpacity>
|
|
|
+ ) : null}
|
|
|
+
|
|
|
+ {payConfig?.wxpay?.enabled ? (
|
|
|
+ <TouchableOpacity
|
|
|
+ style={styles.payOption}
|
|
|
+ onPress={() => setPaymentMethod('WXPAY')}
|
|
|
+ >
|
|
|
+ <View style={styles.rowLeft}>
|
|
|
+ <Text style={styles.payLabel}>微信支付</Text>
|
|
|
+ </View>
|
|
|
+ <View style={[styles.radio, paymentMethod === 'WXPAY' && styles.radioChecked]}>
|
|
|
+ {paymentMethod === 'WXPAY' ? <View style={styles.radioInner} /> : null}
|
|
|
+ </View>
|
|
|
+ </TouchableOpacity>
|
|
|
+ ) : null}
|
|
|
+ </View>
|
|
|
+ ) : null}
|
|
|
|
|
|
<View style={styles.agreementRow}>
|
|
|
<View style={styles.agreementLeft}>
|
|
|
@@ -658,4 +775,29 @@ const styles = StyleSheet.create({
|
|
|
fontSize: 16,
|
|
|
fontWeight: '600',
|
|
|
},
|
|
|
+ paymentSection: {
|
|
|
+ marginTop: 20,
|
|
|
+ borderTopWidth: 1,
|
|
|
+ borderTopColor: '#f0f0f0',
|
|
|
+ paddingTop: 10,
|
|
|
+ },
|
|
|
+ sectionTitle: {
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ marginBottom: 10,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ payOption: {
|
|
|
+ flexDirection: 'row',
|
|
|
+ justifyContent: 'space-between',
|
|
|
+ alignItems: 'center',
|
|
|
+ paddingVertical: 12,
|
|
|
+ borderBottomWidth: 1,
|
|
|
+ borderBottomColor: '#f9f9f9',
|
|
|
+ },
|
|
|
+ payLabel: {
|
|
|
+ fontSize: 14,
|
|
|
+ color: '#333',
|
|
|
+ marginLeft: 10,
|
|
|
+ },
|
|
|
});
|