// import {
// View,
// Image,
// Text,
// ScrollView,
// AppState,
// Pressable,
// ImageBackground,
// ActivityIndicator,
// Modal,
// Alert,
// TextInput,
// Linking
// } from 'react-native';
// import { SafeAreaView } from 'react-native-safe-area-context';
// import { router } from 'expo-router';
// import { CrossLogoSvg } from '../global/SVG';
// import { useEffect, useRef, useState } from 'react';
// import { walletService } from '../../service/walletService';
// import UnionPayImage from '../../assets/unionpay.png';
// import PayMeImage from '../../assets/payme.png';
// import { formatCouponDate, formatDate } from '../../util/lib';
// import { set } from 'date-fns';
// import { reloadAppAsync } from 'expo';
// const TopUpModal = ({ visible, onClose, onSelect, paymentOptions }) => {
// const getPaymentImage = (key) => {
// switch (key) {
// case 'union_pay_wap_payment':
// return UnionPayImage;
// case 'payme_wap_payment':
// return PayMeImage;
// default:
// return null;
// }
// };
// return (
//
//
//
// 選擇支付方式
//
// {Object.entries(paymentOptions).map(([key, value]) => (
// onSelect(value)}
// style={{
// padding: 10,
// marginBottom: 10,
// borderBottomWidth: 1,
// borderBottomColor: '#eee'
// }}
// >
//
//
//
// {key === 'union_pay_wap_payment' ? 'UnionPay' : 'PayMe'}
//
//
//
// ))}
//
//
// 關閉
//
//
//
//
// );
// };
// const AmountInputModal = ({ visible, onClose, onConfirm }) => {
// const [inputAmount, setInputAmount] = useState('');
// return (
//
//
//
// 輸入增值金額
//
// onConfirm(inputAmount)}
// style={{
// backgroundColor: '#02677D',
// padding: 10,
// borderRadius: 5,
// alignItems: 'center'
// }}
// >
// 確認
//
//
// 取消
//
//
//
//
// );
// };
// export const CouponComponent = ({
// title,
// price,
// detail,
// date
// }: {
// title: string;
// price: string;
// detail: string;
// date: string;
// }) => {
// return (
// console.log('abc')}>
//
//
//
// $
//
// {price}
//
//
//
// {title}
//
//
// {/* //dash line */}
//
//
//
//
//
//
// {title}
// {detail}
//
// 有效期
// {date}
//
//
//
//
// );
// };
// const WalletPageComponent = () => {
// const [walletBalance, setWalletBalance] = useState(null);
// const [loading, setLoading] = useState(false);
// const [modalVisible, setModalVisible] = useState(false);
// const [coupons, setCoupons] = useState([]);
// const [paymentType, setPaymentType] = useState({});
// const [userID, setUserID] = useState('');
// const [selectedPaymentType, setSelectedPaymentType] = useState(null);
// const [amount, setAmount] = useState(0);
// const [amountModalVisible, setAmountModalVisible] = useState(false);
// const [outTradeNo, setOutTradeNo] = useState('');
// const PAYMENT_CHECK_TIMEOUT = 5 * 60 * 1000; // 5 minutes in milliseconds
// const [paymentStatus, setPaymentStatus] = useState(null);
// const [isExpectingPayment, setIsExpectingPayment] = useState(false);
// const appState = useRef(AppState.currentState);
// const paymentInitiatedTime = useRef(null);
// useEffect(() => {
// const subscription = AppState.addEventListener('change', (nextAppState) => {
// if (
// appState.current.match(/inactive|background/) &&
// nextAppState === 'active' &&
// isExpectingPayment &&
// outTradeNo &&
// paymentInitiatedTime.current
// ) {
// const currentTime = new Date().getTime();
// if (currentTime - paymentInitiatedTime.current < PAYMENT_CHECK_TIMEOUT) {
// checkPaymentStatus();
// } else {
// // Payment check timeout reached
// setIsExpectingPayment(false);
// setOutTradeNo('');
// paymentInitiatedTime.current = null;
// Alert.alert(
// 'Payment Timeout',
// 'The payment status check has timed out. Please check your payment history.'
// );
// }
// }
// appState.current = nextAppState;
// });
// return () => {
// subscription.remove();
// };
// }, [outTradeNo, isExpectingPayment]);
// const checkPaymentStatus = async () => {
// try {
// const result = await walletService.checkPaymentStatus(outTradeNo);
// setPaymentStatus(result);
// console.log('checkPaymentStatus from walletPageComponent', result);
// if (result[0].respcd === '0000') {
// console.log(result);
// // Payment successful
// Alert.alert('Success', 'Payment was successful!', [
// {
// text: 'OK',
// onPress: async () => {
// const wallet = await walletService.getWalletBalance();
// setWalletBalance(wallet);
// console.log('new wallet:', wallet);
// }
// }
// ]);
// } else {
// Alert.alert('Payment Failed', 'Payment was not successful. Please try again.');
// }
// setIsExpectingPayment(false);
// setOutTradeNo('');
// paymentInitiatedTime.current = null;
// } catch (error) {
// console.error('Failed to check payment status:', error);
// Alert.alert('Error', 'Failed to check payment status. Please check your payment history.');
// }
// };
// // useEffect(() => {
// // const handleAppStateChange = (nextAppState) => {
// // if (appState.match(/inactive|background/) && nextAppState === 'active') {
// // console.log('App has come to the foreground!');
// // // Check payment status or update UI here
// // console.log('outTradeNo', outTradeNo);
// // }
// // setAppState(nextAppState);
// // };
// // AppState.addEventListener('change', handleAppStateChange);
// // }, [appState]);
// useEffect(() => {
// const fetchData = async () => {
// try {
// setLoading(true);
// const info = await walletService.getCustomerInfo();
// // const coupon = await walletService.getCouponForSpecificUser(info.id);
// const wallet = await walletService.getWalletBalance();
// console.log(wallet);
// setUserID(info.id);
// setWalletBalance(wallet);
// setCoupons(coupon);
// } catch (error) {
// console.log(error);
// } finally {
// setLoading(false);
// }
// };
// fetchData();
// }, []);
// const formatMoney = (amount: any) => {
// if (typeof amount !== 'number') {
// amount = Number(amount);
// }
// return amount.toLocaleString('en-US');
// };
// const filterPaymentOptions = (options, allowedKeys) => {
// return Object.fromEntries(Object.entries(options).filter(([key]) => allowedKeys.includes(key)));
// };
// useEffect(() => {
// const fetchPaymentType = async () => {
// const response = await walletService.selectPaymentType();
// console.log('response', response);
// const filteredPaymentTypes = filterPaymentOptions(response, ['union_pay_wap_payment', 'payme_wap_payment']);
// setPaymentType(filteredPaymentTypes);
// };
// fetchPaymentType();
// }, []);
// const handleTopUp = (selectedValue) => {
// setSelectedPaymentType(selectedValue);
// setModalVisible(false);
// setAmountModalVisible(true);
// };
// const handleAmountConfirm = async (inputAmount) => {
// setAmountModalVisible(false);
// try {
// const numericAmount = parseFloat(inputAmount);
// if (isNaN(numericAmount) || numericAmount <= 0) {
// throw new Error('Invalid amount');
// }
// const response = await walletService.submitPaymentAfterSelectingType(
// numericAmount,
// selectedPaymentType,
// 'test'
// );
// setOutTradeNo(response.out_trade_no);
// console.log('handleAmountConfirm outtradeno here,', response.out_trade_no);
// setIsExpectingPayment(true);
// paymentInitiatedTime.current = new Date().getTime();
// const payUrl = response.pay_url;
// const supported = await Linking.canOpenURL(payUrl);
// if (supported) {
// await Linking.openURL(payUrl);
// } else {
// throw new Error("Can't open payment URL");
// }
// } catch (error) {
// console.error('Top-up failed:', error);
// Alert.alert('Error', 'Failed to process top-up. Please try again.');
// }
// };
// return (
//
//
//
//
// {
// if (router.canGoBack()) {
// router.back();
// } else {
// router.replace('/accountMainPage');
// }
// }}
// >
//
//
// 錢包
//
//
//
//
// 餘額 (HKD)
//
//
// {loading ? (
//
//
//
// ) : (
// <>
// $
// {formatMoney(walletBalance)}
// >
// )}
//
// {
// console.log('增值');
// setModalVisible(true);
// }}
// >
// + 增值
//
//
//
//
//
//
// {
// router.push({
// pathname: '/paymentRecord',
// params: { walletBalance: formatMoney(walletBalance) }
// });
// }}
// >
// 付款記錄
//
//
//
//
//
// 優惠券
// router.push('couponPage')}>
// 顯示所有
//
//
//
// {loading ? (
//
//
//
// ) : (
//
// {coupons
// .filter(
// (coupon) =>
// coupon.is_consumed === false && new Date(coupon.expire_date) > new Date()
// )
// .slice(0, 2)
// .map((coupon, index) => (
//
// ))}
//
// )}
//
//
// setModalVisible(false)}
// onSelect={handleTopUp}
// paymentOptions={paymentType}
// />
// setAmountModalVisible(false)}
// onConfirm={handleAmountConfirm}
// />
//
// );
// };
// export default WalletPageComponent;
//////BELOW uses QFPay 的托管收银台页面 to 增值
//////BELOW uses QFPay 的托管收银台页面 to 增值
//////BELOW uses QFPay 的托管收银台页面 to 增值
//////BELOW uses QFPay 的托管收银台页面 to 增值
//////BELOW uses QFPay 的托管收银台页面 to 增值
import {
View,
Image,
Text,
ScrollView,
AppState,
Pressable,
ImageBackground,
ActivityIndicator,
Modal,
Alert,
TextInput,
Linking,
Dimensions
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { router } from 'expo-router';
import { CrossLogoSvg } from '../global/SVG';
import { useEffect, useRef, useState } from 'react';
import { walletService } from '../../service/walletService';
// import UnionPayImage from '../../assets/unionpay.png';
// import PayMeImage from '../../assets/payme.png';
import { formatCouponDate, formatDate } from '../../util/lib';
import { set } from 'date-fns';
import { reloadAppAsync } from 'expo';
import sha256 from 'crypto-js/sha256';
import { useCallback } from 'react';
import { useChargingStore } from '../../providers/scan_qr_payload_store';
const AmountInputModal = ({ visible, onClose, onConfirm }) => {
const amounts = [
// { amount: 1, percentage: 0 },
{ amount: 200, percentage: 0 },
{ amount: 500, percentage: 5 },
{ amount: 1000, percentage: 10 },
{ amount: 2000, percentage: 15 }
];
const getFontSize = () => {
const { width } = Dimensions.get('window');
if (width < 320) return 8;
if (width < 350) return 10; //super small phones
if (width < 375) return 12; // Smaller phones
if (width < 414) return 14; // Average phones
return 16; // Larger phones
};
return (
選擇增值金額
{amounts.map((amount) => (
onConfirm(amount.amount)}
style={{
backgroundColor: '#02677D',
padding: 10,
borderRadius: 5,
width: '48%',
alignItems: 'center',
marginBottom: 10
}}
>
${amount.amount}
{amount.percentage > 0 ? ` (+${amount.percentage}%) ` : ''}
))}
*括號為回贈比例
取消
);
};
export const IndividualCouponComponent = ({
title,
price,
detail,
date,
setOpacity,
redeem_code,
onCouponClick,
noCircle
}: {
title: string;
price: string;
detail: string;
onCouponClick?: (clickedCoupon: string, clickedCouponDescription: string) => void;
date: string;
setOpacity?: boolean;
redeem_code?: string;
noCircle?: boolean;
}) => {
const { promotion_code } = useChargingStore();
return (
{/* largest container */}
{} : () => onCouponClick(redeem_code)}
>
{/* price column on the left */}
$
{price}
{/* this is a hack for good coupon display */}
{/* detail column on the right */}
{title}
{/* if opacity is true=used coupon= no circle */}
{noCircle ? (
<>>
) : (
{promotion_code?.indexOf(redeem_code) + 1}
)}
{detail}
有效期至 {' '}
{date}
);
};
const WalletPageComponent = () => {
const [walletBalance, setWalletBalance] = useState(null);
const [loading, setLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const [coupons, setCoupons] = useState([]);
const [paymentType, setPaymentType] = useState({});
const [userID, setUserID] = useState('');
const [selectedPaymentType, setSelectedPaymentType] = useState(null);
const [amount, setAmount] = useState(0);
const [amountModalVisible, setAmountModalVisible] = useState(false);
const [outTradeNo, setOutTradeNo] = useState('');
const PAYMENT_CHECK_TIMEOUT = 5 * 60 * 1000; // 5 minutes in milliseconds
const [paymentStatus, setPaymentStatus] = useState(null);
const [isExpectingPayment, setIsExpectingPayment] = useState(false);
const appState = useRef(AppState.currentState);
const paymentInitiatedTime = useRef(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const info = await walletService.getCustomerInfo();
const coupon = await walletService.getCouponForSpecificUser(info.id);
const useableConpon = coupon.filter((couponObj: any) => {
const today = new Date();
if (couponObj.expire_date === null) {
return couponObj.is_consumed === false;
}
const expireDate = new Date(couponObj.expire_date);
return expireDate > today && couponObj.is_consumed === false;
});
setCoupons(useableConpon);
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
//monitor app state
useEffect(() => {
const subscription = AppState.addEventListener('change', (nextAppState) => {
if (
appState.current.match(/inactive|background/) &&
nextAppState === 'active' &&
isExpectingPayment &&
// outTradeNo &&
paymentInitiatedTime.current
) {
const currentTime = new Date().getTime();
if (currentTime - paymentInitiatedTime.current < PAYMENT_CHECK_TIMEOUT) {
checkPaymentStatus();
} else {
// Payment check timeout reached
setIsExpectingPayment(false);
setOutTradeNo('');
paymentInitiatedTime.current = null;
Alert.alert(
'Payment Timeout',
'The payment status check has timed out. Please check your payment history.'
);
}
}
appState.current = nextAppState;
});
return () => {
subscription.remove();
};
}, [outTradeNo, isExpectingPayment]);
//check payment status
const checkPaymentStatus = async () => {
try {
console.log('what is the outTradeNo?? ', outTradeNo);
const result = await walletService.checkPaymentStatus(outTradeNo);
setPaymentStatus(result);
console.log('checkPaymentStatus from walletPageComponent', result);
if (result && !result.some((item) => item.errmsg?.includes('處理中'))) {
// Payment successful
Alert.alert('Success', 'Payment was successful!', [
{
text: '成功',
onPress: async () => {
const wallet = await walletService.getWalletBalance();
setWalletBalance(wallet);
console.log('new wallet:', wallet);
}
}
]);
} else {
Alert.alert('Payment Failed', 'Payment was not successful. Please try again.');
}
setIsExpectingPayment(false);
setOutTradeNo('');
paymentInitiatedTime.current = null;
} catch (error) {
console.error('Failed to check payment status:', error);
Alert.alert('Error', 'Failed to check payment status. Please check your payment history.');
}
};
//fetch customer wallet balance
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const info = await walletService.getCustomerInfo();
const wallet = await walletService.getWalletBalance();
console.log('wallet', wallet);
console.log('type of wallet', typeof wallet);
setUserID(info.id);
setWalletBalance(wallet);
setCoupons(coupon);
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
const formatMoney = (amount: any) => {
if (amount === null || amount === undefined || isNaN(Number(amount))) {
return 'LOADING';
}
if (typeof amount !== 'number') {
amount = Number(amount);
}
// Check if the number is a whole number
if (Number.isInteger(amount)) {
return amount.toLocaleString('en-US');
}
// For decimal numbers, show one decimal place
return Number(amount)
.toFixed(1)
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};
const filterPaymentOptions = (options, allowedKeys) => {
return Object.fromEntries(Object.entries(options).filter(([key]) => allowedKeys.includes(key)));
};
function formatTime(utcTimeString) {
// Parse the UTC time string
const date = new Date(utcTimeString);
// Add 8 hours
date.setHours(date.getHours());
// Format the date
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
// Return the formatted string
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
useEffect(() => {
const fetchPaymentType = async () => {
const response = await walletService.selectPaymentType();
// console.log('response', response);
const filteredPaymentTypes = filterPaymentOptions(response, ['union_pay_wap_payment', 'payme_wap_payment']);
setPaymentType(filteredPaymentTypes);
};
fetchPaymentType();
}, []);
const handleAmountConfirm = async (inputAmount) => {
setAmountModalVisible(false);
try {
const response = await walletService.getOutTradeNo();
console.log('do i have outtrade no??', response);
if (response) {
setOutTradeNo(response);
setIsExpectingPayment(true);
paymentInitiatedTime.current = new Date().getTime();
const now = new Date();
const formattedTime = formatTime(now);
console.log('formattedTime in walletPageComponent', formattedTime);
const out_trade_no = response;
console.log('inputAmount in walletPageComponent', inputAmount);
let amount = inputAmount * 100;
console.log('amount in walletPageComponent', amount);
const origin = 'https://openapi-hk.qfapi.com/checkstand/#/?';
const obj = {
// appcode: '6937EF25DF6D4FA78BB2285441BC05E9',
appcode: '636E234FB30D43598FC8F0140A1A7282',
goods_name: 'Crazy Charge 錢包增值',
out_trade_no: response,
paysource: 'crazycharge_checkout',
return_url: 'https://www.google.com',
failed_url: 'https://www.google.com',
notify_url: 'https://api.crazycharge.com.hk/api/v1/clients/qfpay/webhook',
sign_type: 'sha256',
txamt: amount,
txcurrcd: 'HKD',
txdtm: formattedTime
};
const paramStringify = (json, flag?) => {
let str = '';
let keysArr = Object.keys(json);
keysArr.sort().forEach((val) => {
if (!json[val]) return;
str += `${val}=${flag ? encodeURIComponent(json[val]) : json[val]}&`;
});
return str.slice(0, -1);
};
// const api_key = '8F59E31F6ADF4D2894365F2BB6D2FF2C';
const api_key = '3E2727FBA2DA403EA325E73F36B07824';
const params = paramStringify(obj);
const sign = sha256(`${params}${api_key}`).toString();
const url = `${origin}${paramStringify(obj, true)}&sign=${sign}`;
try {
console.log(url);
const supported = await Linking.canOpenURL(url);
if (supported) {
await Linking.openURL(url);
} else {
Alert.alert('錯誤', '請稍後再試');
}
} catch (error) {
console.error('Top-up failed:', error);
Alert.alert('Error', 'Failed to process top-up. Please try again.');
}
} else {
console.log('no');
}
} catch (error) {
console.log(error);
}
};
// const handleCouponClick = async (clickedCoupon: string) => {
// Alert.alert(
// '立即使用優惠券', // Title
// '按確認打開相機,掃描充電站上的二維碼以使用優惠券', // Message
// [
// {
// text: '取消',
// style: 'cancel'
// },
// {
// text: '確認',
// onPress: () => router.push('scanQrPage')
// }
// ]
// );
// };
const handleCouponClick = async (couponName: string, couponDescription: string) => {
router.push({
pathname: '/couponDetailPage',
params: {
couponName: couponName,
couponDescription: couponDescription
}
});
};
const formattedAmount = formatMoney(walletBalance);
return (
{
if (router.canGoBack()) {
router.back();
} else {
router.replace('/accountMainPage');
}
}}
>
錢包
餘額 (HKD)
{loading ? (
) : (
<>
$
{formattedAmount === 'LOADING' || amount == null ? (
) : (
`${formattedAmount}`
)}
>
)}
{
setAmountModalVisible(true);
}}
>
+ 增值
{
router.push({
pathname: '/paymentRecord',
params: { walletBalance: formatMoney(walletBalance) }
});
}}
>
訂單紀錄
優惠券
router.push('couponPage')}>
顯示所有
{loading ? (
) : (
{coupons
.filter(
(coupon) =>
coupon.is_consumed === false && new Date(coupon.expire_date) > new Date()
)
.slice(0, 2)
.map((coupon, index) => (
handleCouponClick(coupon.coupon.name, coupon.coupon.description)}
/>
))}
)}
{/* setModalVisible(false)}
onSelect={handleTopUp}
paymentOptions={paymentType}
/> */}
setAmountModalVisible(false)}
onConfirm={handleAmountConfirm}
/>
);
};
export default WalletPageComponent;