// 支付组件
import React , { useState , useEffect , useCallback } from "react" ;
import {
View ,
Text ,
StyleSheet ,
ScrollView ,
Image ,
TouchableOpacity ,
SafeAreaView ,
ActivityIndicator ,
Alert ,
TextInput ,
Linking ,
Platform ,
Clipboard ,
} from "react-native" ;
import fontSize from "../utils/fontsizeUtils" ;
import widthUtils from "../utils/widthUtils" ;
import CircleOutlineIcon from "../components/CircleOutlineIcon" ;
import CloseIcon from "../components/CloseIcon" ;
import CheckIcon from "../components/CheckIcon" ;
import BackIcon from "../components/BackIcon" ;
// 添加导航相关导入
import { useNavigation } from '@react-navigation/native' ;
import { navigationRef } from "../navigation/RootNavigation" ;
// 添加API服务
import { payApi } from "../services/api/payApi" ;
interface RechargeScreenProps {
onClose : ( ) = > void ;
}
const RechargeScreen = ( { onClose } : RechargeScreenProps ) = > {
const [ selectedPrice , setSelectedPrice ] = useState ( "500,000" ) ;
const [ selectedOperator , setSelectedOperator ] = useState < string | null > ( null ) ;
const [ activeTab , setActiveTab ] = useState ( 0 ) ;
const [ showBlankPage , setShowBlankPage ] = useState ( false ) ;
// 添加货币转换相关状态
const [ isConverting , setIsConverting ] = useState ( false ) ;
// 指定导航类型为any
const navigation = useNavigation < any > ( ) ;
const [ convertedAmount , setConvertedAmount ] = useState < {
converted_amount : number ;
item_key : string ;
original_amount : number ;
} [ ] > ( [ ] ) ;
const [ currentCurrency , setCurrentCurrency ] = useState ( "USD" ) ;
const [ phoneNumber , setPhoneNumber ] = useState ( '22660962235' ) ;
const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
const [ paymentParams , setPaymentParams ] = useState < {
originalAmount : number ;
amount : number ;
currency : string ;
payment_method : string ;
selectedPriceLabel : string ;
} | null > ( null ) ;
const handlePriceSelect = ( price : string ) = > {
setSelectedPrice ( price ) ;
// 如果当前已选择了货币转换,则重新计算转换后的金额
if ( selectedOperator === "currency" && currentCurrency !== "FCFA" ) {
handleCurrencyConversion ( price , currentCurrency ) ;
}
} ;
const handleOperatorSelect = ( operator : string ) = > {
setSelectedOperator ( operator === selectedOperator ? null : operator ) ;
// 如果选择了货币支付方式,立即进行货币转换
if ( operator === "currency" && operator !== selectedOperator ) {
// 触发货币转换,使用默认的USD
handleCurrencySelect ( "USD" ) ;
}
} ;
const handleBackButton = ( ) = > {
setShowBlankPage ( false ) ;
} ;
const handleButtonClick = ( ) = > {
if ( selectedOperator ) {
// 准备支付参数,方便后续发送
const params = {
originalAmount : parseFloat ( selectedPrice . replace ( /,/g , '' ) ) ,
amount : parseFloat ( selectedPrice . replace ( /,/g , '' ) ) ,
currency : "FCFA" ,
payment_method : "" ,
selectedPriceLabel : selectedPrice + " FCFA" // 选择的充值面额
} ;
// 根据selectedOperator确定支付方式
if ( selectedOperator === "orange" ) {
params . payment_method = "Orange Money" ;
} else if ( selectedOperator === "mtn" ) {
params . payment_method = "MTN MoMo" ;
} else if ( selectedOperator === "balance" ) {
params . payment_method = "Balance" ;
} else if ( selectedOperator === "currency" ) {
// 当选择了货币转换时
params . payment_method = "paypal" ;
params . currency = currentCurrency ; // 使用选择的货币
// 使用转换后的金额,如果有
if ( convertedAmount . length > 0 ) {
const convertedTotal = convertedAmount . find ( item = > item . item_key === 'total_amount' ) ;
if ( convertedTotal ) {
params . amount = convertedTotal . converted_amount ;
}
}
}
// 保存支付参数
setPaymentParams ( params ) ;
// 打印支付信息
console . log ( "Payment Information:" ) ;
console . log ( "Selected Recharge Amount:" , params . selectedPriceLabel ) ;
console . log ( "Original Amount:" , params . originalAmount , "FCFA" ) ;
console . log ( "Converted Amount:" , params . amount ) ;
console . log ( "Currency:" , params . currency ) ;
console . log ( "Payment Method:" , params . payment_method ) ;
setShowBlankPage ( true ) ;
}
} ;
// 提取一个专门用于货币转换的函数
const handleCurrencyConversion = ( price : string , currency : string ) = > {
setIsConverting ( true ) ;
// 格式化金额,去除逗号
const amount = parseFloat ( price . replace ( /,/g , '' ) ) ;
// 如果金额为0或无效,则不进行转换
if ( ! amount || isNaN ( amount ) ) {
console . warn ( "Invalid amount for currency conversion" ) ;
setIsConverting ( false ) ;
return ;
}
console . log ( ` Converting ${ amount } FCFA to ${ currency } ... ` ) ;
// 调用货币转换API
const data = {
from_currency : 'FCFA' ,
to_currency : currency ,
amounts : {
total_amount : amount ,
domestic_shipping_fee : 0 ,
shipping_fee : 0 ,
} ,
} ;
payApi . convertCurrency ( data )
. then ( ( res ) = > {
if ( res && res . converted_amounts_list && res . converted_amounts_list . length > 0 ) {
console . log ( "Conversion successful:" , res . converted_amounts_list ) ;
setConvertedAmount ( res . converted_amounts_list ) ;
} else {
console . error ( "Conversion response invalid:" , res ) ;
// 使用近似汇率作为备用
const fallbackRate = currency === "USD" ? 580.0 : 655.96 ; // 1 USD = 580 FCFA, 1 EUR = 655.96 FCFA
const convertedValue = amount / fallbackRate ;
setConvertedAmount ( [ {
converted_amount : convertedValue ,
item_key : 'total_amount' ,
original_amount : amount
} ] ) ;
if ( Platform . OS === 'web' ) {
console . warn ( "Using fallback conversion rate due to API error" ) ;
} else {
Alert . alert ( "Info" , "Taux de conversion approximatif utilisé" ) ;
}
}
} )
. catch ( ( error ) = > {
console . error ( "Currency conversion failed:" , error ) ;
// 使用近似汇率作为备用
const fallbackRate = currency === "USD" ? 580.0 : 655.96 ;
const convertedValue = amount / fallbackRate ;
setConvertedAmount ( [ {
converted_amount : convertedValue ,
item_key : 'total_amount' ,
original_amount : amount
} ] ) ;
if ( Platform . OS === 'web' ) {
console . warn ( "Using fallback conversion rate due to API error" ) ;
} else {
Alert . alert ( "Info" , "Taux de conversion approximatif utilisé" ) ;
}
} )
. finally ( ( ) = > {
setIsConverting ( false ) ;
} ) ;
} ;
// 修改货币选择函数,调用通用的转换函数
const handleCurrencySelect = ( currency : string ) = > {
setCurrentCurrency ( currency ) ;
handleCurrencyConversion ( selectedPrice , currency ) ;
} ;
// 更新处理支付提交的函数
const handlePaySubmit = async ( ) = > {
if ( ! paymentParams ) {
if ( Platform . OS === 'web' ) {
alert ( "Veuillez sélectionner un mode de paiement" ) ;
} else {
Alert . alert ( "Erreur" , "Veuillez sélectionner un mode de paiement" ) ;
}
return ;
}
// 验证电话号码(添加更严格的验证)
if ( ! phoneNumber || phoneNumber . length < 8 ) {
if ( Platform . OS === 'web' ) {
alert ( "Veuillez entrer un numéro de téléphone valide (au moins 8 chiffres)" ) ;
} else {
Alert . alert ( "Erreur" , "Veuillez entrer un numéro de téléphone valide (au moins 8 chiffres)" ) ;
}
return ;
}
// 显示提交中状态
setIsSubmitting ( true ) ;
try {
// 准备请求数据,添加电话号码
const rechargeData = {
amount : paymentParams.amount ,
currency : paymentParams.currency ,
payment_method : paymentParams.payment_method ,
phone : phoneNumber // 注意:如果后端API不支持此参数,可能需要调整
} ;
console . log ( "Submitting recharge request:" , rechargeData ) ;
// 调用充值接口(使用可选链避免错误)
const response = await payApi . initiateRecharge ( rechargeData ) ;
console . log ( "Recharge response:" , response ) ;
if ( response && response . success ) {
const paymentInfo = response . payment ;
// 存储交易ID,以便后续查询
if ( Platform . OS === 'web' ) {
sessionStorage . setItem ( 'recharge_transaction_id' , paymentInfo . transaction_id || '' ) ;
sessionStorage . setItem ( 'recharge_id' , response . recharge_id ? . toString ( ) || '' ) ;
}
// 检查是否有支付URL
if ( paymentInfo && paymentInfo . payment_url ) {
// 记录重要信息到控制台
console . log ( "Transaction ID:" , paymentInfo . transaction_id ) ;
console . log ( "Recharge ID:" , response . recharge_id ) ;
console . log ( "Payment URL:" , paymentInfo . payment_url ) ;
// 打开支付页面
navigation . navigate ( "Pay" , {
payUrl : paymentInfo.payment_url ,
} ) ;
// Web平台添加额外提示,因为可能会被浏览器拦截
if ( Platform . OS === 'web' ) {
setTimeout ( ( ) = > {
alert ( ` Si la page de paiement ne s'ouvre pas automatiquement, veuillez cliquer sur le bouton "Continuer" pour procéder au paiement. Vous pouvez également copier ce lien: ${ paymentInfo . payment_url } ` ) ;
} , 1500 ) ;
}
} else {
// 没有支付URL但交易成功的情况
if ( Platform . OS === 'web' ) {
alert ( "Votre recharge a été traitée avec succès!" ) ;
onClose ( ) ; // 关闭充值页面
} else {
Alert . alert (
"Succès" ,
"Votre recharge a été traitée avec succès!" ,
[ { text : "OK" , onPress : onClose } ]
) ;
}
}
} else {
// 处理失败情况,显示错误消息
const errorMessage = response ? . msg || "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer." ;
if ( Platform . OS === 'web' ) {
alert ( errorMessage ) ;
} else {
Alert . alert ( "Erreur" , errorMessage ) ;
}
}
} catch ( error ) {
// 处理异常
console . error ( "Recharge error:" , error ) ;
let errorMessage = "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer." ;
// 尝试从错误对象中提取更具体的错误信息
if ( error instanceof Error ) {
errorMessage = error . message || errorMessage ;
}
if ( Platform . OS === 'web' ) {
alert ( errorMessage ) ;
} else {
Alert . alert ( "Erreur" , errorMessage ) ;
}
} finally {
// 无论成功失败,都取消提交状态
setIsSubmitting ( false ) ;
}
} ;
return (
< SafeAreaView style = { styles . safeArea } >
< View style = { showBlankPage ? styles.mainContainer1 : styles.mainContainer } >
< View style = { styles . header } >
< Text style = { styles . title } > Recharger < / Text >
{ ! showBlankPage && (
< TouchableOpacity onPress = { onClose } style = { styles . closeButton } >
< CloseIcon size = { fontSize ( 15 ) } / >
< / TouchableOpacity >
) }
{ showBlankPage && (
< TouchableOpacity onPress = { handleBackButton } style = { styles . backButton } >
< Text style = { styles . backButtonText } >
< BackIcon size = { fontSize ( 18 ) } / >
< / Text >
< / TouchableOpacity >
) }
< / View >
{ ! showBlankPage ? (
< >
< ScrollView contentContainerStyle = { styles . scrollContent } >
< View style = { styles . container2 } >
< View style = { styles . amountRechargeContainer } >
< Text style = { styles . rechargePromptTextStyle } >
Choisissez ou entrez le montant à recharger
< / Text >
< / View >
< / View >
{ /* 金额选择 */ }
< View style = { styles . priceGroup } >
< View style = { styles . row } >
< TouchableOpacity
style = { [
styles . priceBoxBlue ,
selectedPrice === "500,000"
? styles . priceBoxSelected
: styles . priceBoxUnselected ,
] }
onPress = { ( ) = > handlePriceSelect ( "500,000" ) }
>
< Text
style = { [
styles . priceTextBlue ,
selectedPrice === "500,000"
? styles . priceTextSelected
: styles . priceTextUnselected ,
] }
>
500 , 000
< / Text >
< Text
style = { [
styles . currencyTextBlue ,
selectedPrice === "500,000"
? styles . currencyTextSelected
: styles . currencyTextUnselected ,
] }
>
FCFA
< / Text >
< / TouchableOpacity >
< TouchableOpacity
style = { [
styles . priceBoxWhite ,
selectedPrice === "1000,000"
? styles . priceBoxSelected
: styles . priceBoxUnselected ,
] }
onPress = { ( ) = > handlePriceSelect ( "1000,000" ) }
>
< Text
style = { [
styles . priceText ,
selectedPrice === "1000,000"
? styles . priceTextSelected
: styles . priceTextUnselected ,
] }
>
1000 , 000
< / Text >
< Text
style = { [
styles . currencyText ,
selectedPrice === "1000,000"
? styles . currencyTextSelected
: styles . currencyTextUnselected ,
] }
>
FCFA
< / Text >
< / TouchableOpacity >
< TouchableOpacity
style = { [
styles . priceBoxWhite ,
selectedPrice === "2000,000"
? styles . priceBoxSelected
: styles . priceBoxUnselected ,
] }
onPress = { ( ) = > handlePriceSelect ( "2000,000" ) }
>
< Text
style = { [
styles . priceText ,
selectedPrice === "2000,000"
? styles . priceTextSelected
: styles . priceTextUnselected ,
] }
>
2000 , 000
< / Text >
< Text
style = { [
styles . currencyText ,
selectedPrice === "2000,000"
? styles . currencyTextSelected
: styles . currencyTextUnselected ,
] }
>
FCFA
< / Text >
< / TouchableOpacity >
< / View >
< View style = { styles . row } >
< TouchableOpacity
style = { [
styles . priceBoxWhite ,
selectedPrice === "3000,000"
? styles . priceBoxSelected
: styles . priceBoxUnselected ,
] }
onPress = { ( ) = > handlePriceSelect ( "3000,000" ) }
>
< Text
style = { [
styles . priceText ,
selectedPrice === "3000,000"
? styles . priceTextSelected
: styles . priceTextUnselected ,
] }
>
3000 , 000
< / Text >
< Text
style = { [
styles . currencyText ,
selectedPrice === "3000,000"
? styles . currencyTextSelected
: styles . currencyTextUnselected ,
] }
>
FCFA
< / Text >
< / TouchableOpacity >
< TouchableOpacity
style = { [
styles . priceBoxWhite ,
selectedPrice === "5000,000"
? styles . priceBoxSelected
: styles . priceBoxUnselected ,
] }
onPress = { ( ) = > handlePriceSelect ( "5000,000" ) }
>
< Text
style = { [
styles . priceText ,
selectedPrice === "5000,000"
? styles . priceTextSelected
: styles . priceTextUnselected ,
] }
>
5000 , 000
< / Text >
< Text
style = { [
styles . currencyText ,
selectedPrice === "5000,000"
? styles . currencyTextSelected
: styles . currencyTextUnselected ,
] }
>
FCFA
< / Text >
< / TouchableOpacity >
< / View >
< / View >
{ /* 支付方式标题 */ }
< View style = { styles . section } >
< Text style = { styles . subtitle } > Choisissez votre mode de paiement < / Text >
< / View >
{ /* Tab Bar */ }
< View style = { styles . tabContainer } >
< TouchableOpacity
style = { [ styles . tab , activeTab === 0 && styles . activeTab ] }
onPress = { ( ) = > setActiveTab ( 0 ) }
>
< Text style = { [ styles . tabText , activeTab === 0 && styles . activeTabText ] } >
Mode de paiement
< / Text >
< / TouchableOpacity >
< TouchableOpacity
style = { [ styles . tab , activeTab === 1 && styles . activeTab ] }
onPress = { ( ) = > setActiveTab ( 1 ) }
>
< Text style = { [ styles . tabText , activeTab === 1 && styles . activeTabText ] } >
Autre
< / Text >
< / TouchableOpacity >
< / View >
{ /* Tab Content */ }
{ activeTab === 0 ? (
< >
< View style = { styles . operatorCard } >
< View
style = { {
flexDirection : "row" ,
alignItems : "center" ,
justifyContent : "space-between" ,
} }
>
< View style = { { flexDirection : "row" , alignItems : "center" } } >
< Image
source = { require ( "../../assets/img/image_cb840273.png" ) }
style = { styles . operatorImage }
/ >
< Text style = { styles . orangeText } >
Nous ne supportons que { "\n" } les opérateurs affichés .
< / Text >
< / View >
< TouchableOpacity onPress = { ( ) = > handleOperatorSelect ( "orange" ) } >
< View style = { styles . checkboxContainer } >
< CircleOutlineIcon
size = { fontSize ( 24 ) }
strokeColor = {
selectedOperator === "orange" ? "#007efa" : undefined
}
fillColor = {
selectedOperator === "orange" ? "#007efa" : undefined
}
/ >
{ selectedOperator === "orange" && (
< View style = { styles . checkmarkContainer } >
< CheckIcon size = { fontSize ( 12 ) } color = "#FFFFFF" / >
< / View >
) }
< / View >
< / TouchableOpacity >
< / View >
< View style = { styles . iconRow } >
< Image
source = { require ( "../../assets/img/image_7337a807.png" ) }
style = { styles . operatorIcon }
/ >
< Image
source = { require ( "../../assets/img/image_96b927ad.png" ) }
style = { styles . operatorIcon }
/ >
< Image
source = { require ( "../../assets/img/image_1fee7e8b.png" ) }
style = { styles . operatorIcon }
/ >
< / View >
< / View >
< View style = { styles . cardContainer } >
< View style = { styles . iconRow } >
< Image
source = { require ( "../../assets/img/image_13d56c9.png" ) }
style = { styles . operatorImage }
/ >
< / View >
{ /* 右侧圆圈图标 */ }
< TouchableOpacity onPress = { ( ) = > handleOperatorSelect ( "mtn" ) } >
< View style = { styles . checkboxContainer } >
< CircleOutlineIcon
size = { fontSize ( 24 ) }
strokeColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
fillColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
/ >
{ selectedOperator === "mtn" && (
< View style = { styles . checkmarkContainer } >
< CheckIcon size = { fontSize ( 12 ) } color = "#FFFFFF" / >
< / View >
) }
< / View >
< / TouchableOpacity >
< / View >
< View style = { styles . balanceInfoContainer } >
< View style = { styles . leftInfo } >
< View style = { styles . blueBox } >
{ /* 圆形图标(左边) */ }
< Image
source = { require ( "../../assets/img/余额 icon.png" ) }
style = { styles . operatorImage }
/ >
< / View >
< Text style = { styles . balanceText } >
Vous avez encore un solde { "\n" } de 650 , 000 FCFA
< / Text >
< / View >
{ /* 圆形图标(右边) */ }
< TouchableOpacity onPress = { ( ) = > handleOperatorSelect ( "balance" ) } >
< View style = { styles . checkboxContainer } >
< CircleOutlineIcon
size = { fontSize ( 24 ) }
strokeColor = {
selectedOperator === "balance" ? "#007efa" : undefined
}
fillColor = { selectedOperator === "balance" ? "#007efa" : undefined }
/ >
{ selectedOperator === "balance" && (
< View style = { styles . checkmarkContainer } >
< CheckIcon size = { fontSize ( 12 ) } color = "#FFFFFF" / >
< / View >
) }
< / View >
< / TouchableOpacity >
< / View >
< View style = { styles . currencyContainer } >
< View style = { styles . currencyRow } >
< Image
source = { require ( "../../assets/img/image_8786995c.png" ) }
style = { styles . currencyImage }
/ >
< TouchableOpacity onPress = { ( ) = > handleOperatorSelect ( "currency" ) } >
< View style = { styles . checkboxContainer } >
< CircleOutlineIcon
size = { fontSize ( 24 ) }
strokeColor = {
selectedOperator === "currency" ? "#007efa" : undefined
}
fillColor = {
selectedOperator === "currency" ? "#007efa" : undefined
}
/ >
{ selectedOperator === "currency" && (
< View style = { styles . checkmarkContainer } >
< CheckIcon size = { fontSize ( 12 ) } color = "#FFFFFF" / >
< / View >
) }
< / View >
< / TouchableOpacity >
< / View >
{ selectedOperator === "currency" && (
< >
< Text style = { styles . subtitle } > Choisissez la devise < / Text >
< View style = { styles . row } >
< TouchableOpacity
style = { currentCurrency === "USD" ? styles.currencyButtonActive : styles.currencyButtonInactive }
onPress = { ( ) = > handleCurrencySelect ( "USD" ) }
>
< Text style = { currentCurrency === "USD" ? styles.buttonTextWhite : styles.buttonTextDark } > USD < / Text >
< / TouchableOpacity >
< TouchableOpacity
style = { currentCurrency === "EUR" ? styles.currencyButtonActive : styles.currencyButtonInactive }
onPress = { ( ) = > handleCurrencySelect ( "EUR" ) }
>
< Text style = { currentCurrency === "EUR" ? styles.buttonTextWhite : styles.buttonTextDark } > EUR < / Text >
< / TouchableOpacity >
< / View >
{ isConverting ? (
< View style = { { flexDirection : 'row' , alignItems : 'center' , marginTop : 16 } } >
< ActivityIndicator size = "small" color = "#ff5100" / >
< Text style = { { . . . styles . totalText , marginLeft : 10 } } > Converting . . . < / Text >
< / View >
) : (
< Text style = { styles . totalText } >
Total : { convertedAmount . length > 0
? ` ${ currentCurrency === "USD" ? "$" : "€" } ${ convertedAmount . find ( item = > item . item_key === 'total_amount' ) ? . converted_amount . toFixed ( 2 ) || '0.00' } `
: ` $ ${ ( parseFloat ( selectedPrice . replace ( /,/g , '' ) ) / 580 ) . toFixed ( 2 ) } ` }
< / Text >
) }
< / >
) }
< / View >
< View style = { styles . cardContainer } >
< View style = { styles . iconRow } >
< Image
source = { require ( "../../assets/img/image_4e72f054.png" ) }
style = { styles . operatorImage1 }
/ >
< / View >
{ /* 右侧圆圈图标 */ }
< TouchableOpacity onPress = { ( ) = > handleOperatorSelect ( "mtn" ) } >
< View style = { styles . checkboxContainer } >
< CircleOutlineIcon
size = { fontSize ( 24 ) }
strokeColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
fillColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
/ >
{ selectedOperator === "mtn" && (
< View style = { styles . checkmarkContainer } >
< CheckIcon size = { fontSize ( 12 ) } color = "#FFFFFF" / >
< / View >
) }
< / View >
< / TouchableOpacity >
< / View >
< / >
) : (
< View style = { styles . outerContainer } >
< View style = { styles . flexContainer } >
< View style = { styles . imageContainer } >
< Image
source = { require ( '../../assets/img/image_c6aa9539.png' ) }
style = { styles . imageStyle }
resizeMode = "cover"
/ >
< / View >
< View style = { styles . verticalAlignEndContent } >
< View style = { styles . svgContainer } >
< TouchableOpacity onPress = { ( ) = > handleOperatorSelect ( "mtn" ) } >
< View style = { styles . checkboxContainer } >
< CircleOutlineIcon
size = { fontSize ( 24 ) }
strokeColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
fillColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
/ >
{ selectedOperator === "mtn" && (
< View style = { styles . checkmarkContainer } >
< CheckIcon size = { fontSize ( 12 ) } color = "#FFFFFF" / >
< / View >
) }
< / View >
< / TouchableOpacity >
< / View >
< / View >
< / View >
< View style = { styles . flexContainer } >
< View style = { styles . imageContainer } >
< Image
source = { require ( '../../assets/img/Global 1.png' ) }
style = { styles . imageStyle }
resizeMode = "cover"
/ >
< / View >
< View style = { styles . verticalAlignEndContent } >
< View style = { styles . svgContainer } >
< TouchableOpacity onPress = { ( ) = > handleOperatorSelect ( "mtn" ) } >
< View style = { styles . checkboxContainer } >
< CircleOutlineIcon
size = { fontSize ( 24 ) }
strokeColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
fillColor = { selectedOperator === "mtn" ? "#007efa" : undefined }
/ >
{ selectedOperator === "mtn" && (
< View style = { styles . checkmarkContainer } >
< CheckIcon size = { fontSize ( 12 ) } color = "#FFFFFF" / >
< / View >
) }
< / View >
< / TouchableOpacity >
< / View >
< / View >
< / View >
< / View >
) }
< / ScrollView >
{ /* 操作按钮 - 固定在底部 */ }
< View style = { styles . actionButtonsContainer } >
< View style = { styles . actionButtons } >
< TouchableOpacity style = { styles . cancelButton } onPress = { onClose } >
< Text style = { styles . buttonTextDark } > Annuler < / Text >
< / TouchableOpacity >
< TouchableOpacity style = { styles . confirmButton } onPress = { handleButtonClick } >
< Text style = { styles . buttonTextWhite } > Confirmer < / Text >
< / TouchableOpacity >
< / View >
< / View >
< / >
) : (
< View style = { styles . paymentConfirmContainer } >
{ /* 充值金额信息 */ }
< View style = { styles . paymentSummaryCard } >
< Text style = { styles . paymentSummaryTitle } > Résumé de la recharge < / Text >
< View style = { styles . paymentSummaryRow } >
< Text style = { styles . paymentSummaryLabel } > Montant : < / Text >
< Text style = { styles . paymentSummaryValue } >
{ paymentParams ? . selectedPriceLabel || selectedPrice + " FCFA" }
< / Text >
< / View >
{ paymentParams ? . currency !== "FCFA" && (
< View style = { styles . paymentSummaryRow } >
< Text style = { styles . paymentSummaryLabel } > Montant converti : < / Text >
< Text style = { styles . paymentSummaryValueHighlight } >
{ paymentParams ? . currency === "USD" ? "$" : "€" }
{ paymentParams ? . amount . toFixed ( 2 ) || "0.00" }
< / Text >
< / View >
) }
< View style = { styles . paymentSummaryRow } >
< Text style = { styles . paymentSummaryLabel } > Méthode de paiement : < / Text >
< Text style = { styles . paymentSummaryValue } >
{ paymentParams ? . payment_method || "Non sélectionné" }
< / Text >
< / View >
< / View >
{ /* 电话号码输入 */ }
< View style = { styles . phoneInputContainer } >
< Text style = { styles . phoneInputLabel } > Numéro de téléphone < / Text >
< View style = { styles . phoneInputWrapper } >
< View style = { styles . countryCodeContainer } >
< Text style = { styles . countryCodeText } > + 89 < / Text >
< / View >
< TextInput
style = { styles . phoneInput }
value = { phoneNumber }
onChangeText = { setPhoneNumber }
keyboardType = "phone-pad"
placeholder = "Entrez votre numéro"
placeholderTextColor = "#999"
/ >
< / View >
< / View >
{ /* 支持的运营商 */ }
< View style = { styles . supportedOperatorsContainer } >
< Text style = { styles . supportedOperatorsTitle } > Opérateurs pris en charge < / Text >
< View style = { styles . operatorsRow } >
< Image
source = { require ( "../../assets/img/image_7337a807.png" ) }
style = { styles . operatorSmallIcon }
/ >
< Image
source = { require ( "../../assets/img/image_96b927ad.png" ) }
style = { styles . operatorSmallIcon }
/ >
< Image
source = { require ( "../../assets/img/image_1fee7e8b.png" ) }
style = { styles . operatorSmallIcon }
/ >
< / View >
< / View >
{ /* 支付按钮 */ }
< TouchableOpacity
style = { [ styles . payButton , isSubmitting && styles . payButtonDisabled ] }
onPress = { handlePaySubmit }
disabled = { isSubmitting }
>
{ isSubmitting ? (
< ActivityIndicator size = "small" color = "#fff" / >
) : (
< Text style = { styles . payButtonText } >
PAYER { paymentParams ? . currency === "FCFA"
? paymentParams . originalAmount . toLocaleString ( ) + " " + paymentParams . currency
: ( paymentParams ? . currency === "USD"
? "$" + paymentParams ? . amount . toFixed ( 2 )
: paymentParams ? . amount . toFixed ( 2 ) + " €" )
}
< / Text >
) }
< / TouchableOpacity >
< / View >
) }
< / View >
< / SafeAreaView >
) ;
} ;
const styles = StyleSheet . create ( {
safeArea : {
flex : 1 ,
backgroundColor : "#f0f0f0" ,
} ,
mainContainer : {
flex : 1 ,
backgroundColor : "#f0f0f0" ,
borderTopLeftRadius : 10 ,
borderTopRightRadius : 10 ,
} ,
mainContainer1 : {
flex : 1 ,
backgroundColor : "#fff" ,
borderTopLeftRadius : 10 ,
borderTopRightRadius : 10 ,
} ,
header : {
flexDirection : "row" ,
justifyContent : "center" ,
alignItems : "center" ,
padding : 24 ,
paddingBottom : 0 ,
position : "relative" ,
marginTop : 20 ,
marginBottom : 20 ,
} ,
scrollContent : {
padding : 24 ,
paddingTop : 0 ,
} ,
container : {
padding : 24 ,
backgroundColor : "#f0f0f0" ,
borderTopLeftRadius : 10 ,
borderTopRightRadius : 10 ,
} ,
title : {
fontSize : 24 ,
fontWeight : "700" ,
textTransform : "capitalize" ,
color : "black" ,
position : "absolute" ,
left : 0 ,
right : 0 ,
textAlign : "center" ,
} ,
section : {
marginTop : 44 ,
} ,
subtitle : {
fontSize : 16 ,
fontWeight : "700" ,
color : "black" ,
textTransform : "capitalize" ,
marginBottom : 12 ,
} ,
priceGroup : {
marginTop : 10 ,
} ,
row : {
flexDirection : "row" ,
justifyContent : "flex-start" ,
marginTop : 15 ,
} ,
priceBoxBlue : {
width : "30%" ,
backgroundColor : "#edf2fa" ,
borderColor : "#002fa7" ,
borderWidth : 1 ,
borderRadius : 5 ,
paddingVertical : 9 ,
paddingHorizontal : 22 ,
alignItems : "center" ,
marginRight : "5%" ,
} ,
priceBoxWhite : {
width : "30%" ,
backgroundColor : "white" ,
borderRadius : 5 ,
paddingVertical : 9 ,
paddingHorizontal : 22 ,
alignItems : "center" ,
marginRight : "5%" ,
} ,
priceTextBlue : {
fontSize : fontSize ( 16 ) ,
fontWeight : "700" ,
color : "#002fa7" ,
} ,
currencyTextBlue : {
fontSize : fontSize ( 10 ) ,
color : "#002fa7" ,
marginTop : 1 ,
} ,
priceText : {
fontSize : fontSize ( 16 ) ,
fontWeight : "700" ,
color : "#333" ,
} ,
currencyText : {
fontSize : fontSize ( 10 ) ,
color : "#7f7e7e" ,
marginTop : 1 ,
} ,
operatorCard : {
backgroundColor : "white" ,
padding : 16 ,
borderRadius : 5 ,
marginTop : 18 ,
} ,
operatorImage : {
width : 80 ,
height : 30 ,
resizeMode : "contain" ,
} ,
operatorImage1 : {
width : 228 ,
height : 30 ,
resizeMode : "contain" ,
} ,
orangeText : {
color : "#ff5100" ,
fontSize : fontSize ( 12 ) ,
fontWeight : "500" ,
marginLeft : 12 ,
} ,
iconRow : {
flexDirection : "row" ,
gap : 10 ,
} ,
operatorIcon : {
width : 60 ,
height : 22 ,
resizeMode : "contain" ,
} ,
currencyContainer : {
backgroundColor : "white" ,
padding : 10 ,
borderRadius : 5 ,
marginTop : 20 ,
} ,
currencyRow : {
flexDirection : "row" ,
alignItems : "center" ,
justifyContent : "space-between" ,
paddingRight :6
} ,
currencyImage : {
width : 80 ,
height : 30 ,
resizeMode : "contain" ,
} ,
radioCircle : {
width : 24 ,
height : 24 ,
borderRadius : 12 ,
borderWidth : 2 ,
borderColor : "#007AFF" ,
} ,
currencyButtonActive : {
backgroundColor : "#002fa7" ,
borderRadius : 18 ,
width : widthUtils ( 36 , 100 ) . width ,
height : widthUtils ( 36 , 100 ) . height ,
justifyContent : "center" ,
alignItems : "center" ,
} ,
currencyButtonInactive : {
backgroundColor : "#eeeeee" ,
borderRadius : 18 ,
width : widthUtils ( 36 , 100 ) . width ,
height : widthUtils ( 36 , 100 ) . height ,
justifyContent : "center" ,
alignItems : "center" ,
marginLeft : 10 ,
} ,
buttonTextWhite : {
color : "white" ,
fontWeight : "600" ,
} ,
buttonTextDark : {
color : "black" ,
fontWeight : "500" ,
} ,
totalText : {
marginTop : 16 ,
fontWeight : "900" ,
fontSize : fontSize ( 16 ) ,
color : "#ff5100" ,
} ,
actionButtonsContainer : {
padding : 24 ,
paddingTop : 0 ,
backgroundColor : "#f0f0f0" ,
} ,
actionButtons : {
flexDirection : "row" ,
justifyContent : "space-between" ,
padding : 10 ,
} ,
cancelButton : {
backgroundColor : "white" ,
borderRadius : 25 ,
width : widthUtils ( 50 , 160 ) . width ,
height : widthUtils ( 50 , 160 ) . height ,
justifyContent : "center" ,
alignItems : "center" ,
borderColor : "#ccc" ,
borderWidth : 1 ,
} ,
confirmButton : {
backgroundColor : "#002fa7" ,
borderRadius : 25 ,
width : widthUtils ( 50 , 160 ) . width ,
height : widthUtils ( 50 , 160 ) . height ,
justifyContent : "center" ,
alignItems : "center" ,
} ,
balanceInfoContainer : {
flexDirection : "row" ,
backgroundColor : "white" ,
borderRadius : 5 ,
paddingHorizontal : 16 ,
height : 50 ,
alignItems : "center" ,
justifyContent : "space-between" ,
marginTop : 14 ,
} ,
leftInfo : {
flexDirection : "row" ,
alignItems : "center" ,
flex : 1 ,
} ,
blueBox : {
flexDirection : "row" ,
backgroundColor : "#3955f6" ,
paddingHorizontal : 7 ,
paddingLeft : 6 ,
alignItems : "center" ,
borderRadius : 4 ,
} ,
saleText : {
fontSize : 16 ,
fontFamily : "Timmana" ,
color : "white" ,
marginLeft : 4 ,
} ,
balanceText : {
marginLeft : 17 ,
fontSize : fontSize ( 11 ) ,
lineHeight : 14 ,
fontWeight : "500" ,
color : "#333333" ,
} ,
cardContainer : {
flexDirection : "row" ,
alignItems : "center" ,
justifyContent : "space-between" ,
backgroundColor : "white" ,
borderRadius : 5 ,
paddingHorizontal : 16 ,
height : 50 ,
marginTop : 15 ,
} ,
imageSmall : {
width : widthUtils ( 30 , 24 ) . width ,
height : widthUtils ( 30 , 24 ) . height ,
resizeMode : "contain" ,
} ,
imageLarge : {
width : widthUtils ( 26 , 44 ) . width ,
height : widthUtils ( 26 , 44 ) . height ,
resizeMode : "contain" ,
} ,
emptyBox : {
backgroundColor : "transparent" ,
borderWidth : 0 ,
} ,
container1 : {
flexDirection : "row" ,
gap : 10 ,
alignItems : "center" ,
marginTop : 10 ,
} ,
button : {
width : widthUtils ( 36 , 190 ) . width ,
height : widthUtils ( 36 , 190 ) . height ,
borderRadius : 18 ,
justifyContent : "center" ,
alignItems : "center" ,
} ,
buttonActive : {
backgroundColor : "#002fa7" ,
} ,
buttonInactive : {
backgroundColor : "#fdfefe" ,
} ,
textActive : {
color : "white" ,
fontWeight : "600" ,
fontSize : fontSize ( 15 ) ,
} ,
textInactive : {
color : "black" ,
fontSize : fontSize ( 15 ) ,
} ,
priceBoxSelected : {
backgroundColor : "#edf2fa" ,
borderColor : "#002fa7" ,
borderWidth : 1 ,
} ,
priceBoxUnselected : {
backgroundColor : "white" ,
borderColor : "#dddddd" ,
borderWidth : 1 ,
} ,
priceTextSelected : {
color : "#002fa7" ,
} ,
priceTextUnselected : {
color : "#333" ,
} ,
currencyTextSelected : {
color : "#002fa7" ,
} ,
currencyTextUnselected : {
color : "#7f7e7e" ,
} ,
closeButton : {
padding : 5 ,
position : "absolute" ,
right : 24 ,
zIndex : 1 ,
} ,
checkboxContainer : {
position : "relative" ,
width : fontSize ( 24 ) ,
height : fontSize ( 24 ) ,
} ,
checkmarkContainer : {
position : "absolute" ,
top : 0 ,
left : 0 ,
right : 0 ,
bottom : 0 ,
justifyContent : "center" ,
alignItems : "center" ,
} ,
container2 : {
width : '100%' ,
marginTop : 20 ,
} ,
amountRechargeContainer : {
display : 'flex' ,
flexDirection : 'column' ,
alignItems : 'center' ,
justifyContent : 'center' ,
width : '100%' ,
height : 60 ,
backgroundColor : 'white' ,
borderRadius : 5 ,
} ,
rechargePromptTextStyle : {
flex : 0 ,
padding : 0 ,
margin : 0 ,
fontSize : 14 ,
lineHeight : 14 ,
color : '#747474' ,
// Note: PingFang SC font might not be available by default in React Native
// You may need to load custom fonts using expo-font or other methods
} ,
tabContainer : {
flexDirection : 'row' ,
backgroundColor : 'white' ,
borderRadius : 5 ,
marginTop : 10 ,
padding : 5 ,
} ,
tab : {
flex : 1 ,
paddingVertical : 10 ,
alignItems : 'center' ,
borderRadius : 5 ,
} ,
activeTab : {
backgroundColor : '#002fa7' ,
} ,
tabText : {
fontSize : fontSize ( 14 ) ,
color : '#333' ,
fontWeight : '500' ,
} ,
activeTabText : {
color : 'white' ,
fontWeight : '600' ,
} ,
emptyTab : {
backgroundColor : 'white' ,
borderRadius : 5 ,
padding : 20 ,
marginTop : 10 ,
alignItems : 'center' ,
justifyContent : 'center' ,
height : 200 ,
} ,
emptyTabText : {
color : '#666' ,
fontSize : fontSize ( 14 ) ,
} ,
outerContainer : {
width : '100%' ,
} ,
flexContainer : {
flexDirection : 'row' ,
alignItems : 'center' ,
justifyContent : 'flex-start' ,
height : 50 ,
paddingRight : 16 ,
paddingLeft : 16 ,
backgroundColor : 'white' ,
borderRadius : 5 ,
marginTop : 18 ,
} ,
imageContainer : {
width : '26.54%' ,
} ,
imageStyle : {
width : 80 ,
height : 30 ,
borderWidth : 0 ,
} ,
verticalAlignEndContent : {
flexDirection : 'column' ,
alignItems : 'flex-end' ,
width : '73.46%' ,
} ,
svgContainer : {
width : 24 ,
height : 24 ,
} ,
backButton : {
position : "absolute" ,
left : 24 ,
zIndex : 1 ,
} ,
backButtonText : {
fontSize : fontSize ( 14 ) ,
color : "#007AFF" ,
fontWeight : "500" ,
} ,
blankPage : {
flex : 1 ,
justifyContent : "center" ,
alignItems : "center" ,
backgroundColor : "#f0f0f0" ,
} ,
blankPageText : {
fontSize : fontSize ( 16 ) ,
color : "#666" ,
} ,
paymentSection2 : {
paddingTop : 24 ,
paddingRight : 20 ,
paddingBottom : 333 ,
paddingLeft : 20 ,
backgroundColor : 'white' ,
borderTopLeftRadius : 10 ,
borderTopRightRadius : 10 ,
} ,
paymentSectionContainer : {
flexDirection : 'row' ,
alignItems : 'center' ,
justifyContent : 'flex-start' ,
width : '100%' ,
} ,
paymentSection : {
width : '8.48%' ,
paddingRight : 15 ,
} ,
svgContainer1 : {
width : 18 ,
height : 18 ,
} ,
paymentSection1 : {
flexDirection : 'column' ,
alignItems : 'center' ,
justifyContent : 'flex-start' ,
width : '91.52%' ,
paddingRight : 33 ,
} ,
paymentHeadingStyle : {
padding : 0 ,
margin : 0 ,
fontSize : 24 ,
lineHeight : 22 ,
color : 'black' ,
textTransform : 'capitalize' ,
fontFamily : 'Montserrat-Bold' ,
} ,
transactionSummaryContainer1 : {
width : '100%' ,
} ,
transactionSummaryContainer : {
width : '100%' ,
paddingRight : 15 ,
paddingLeft : 15 ,
backgroundColor : 'linear-gradient(90deg, rgba(206, 229, 255, 1) 0%, rgba(238, 244, 255, 1) 100%' ,
borderRadius : 5 ,
} ,
flexContainerWithImages : {
flexDirection : 'row' ,
alignItems : 'flex-start' ,
justifyContent : 'flex-start' ,
} ,
imageContainerStyled : {
width : 99 ,
height : 36 ,
borderWidth : 0 ,
} ,
imageContainerWithBorder : {
width : 135 ,
height : 140 ,
marginLeft : 141 ,
borderWidth : 0 ,
} ,
amountContainer : {
width : '100%' ,
paddingTop : 8 ,
paddingRight : 11 ,
paddingBottom : 10 ,
paddingLeft : 11 ,
marginTop : - 83 ,
backgroundColor : 'white' ,
borderWidth : 1 ,
borderRadius : 5 ,
} ,
amountLabel : {
padding : 0 ,
margin : 0 ,
fontSize : 12 ,
color : '#7f7e7e' ,
fontFamily : 'PingFangSC-Medium' ,
} ,
amountContainer1 : {
flexDirection : 'row' ,
alignItems : 'flex-start' ,
justifyContent : 'flex-start' ,
marginTop : 1 ,
} ,
priceHeading : {
padding : 0 ,
paddingBottom : 5 ,
margin : 0 ,
fontSize : 24 ,
lineHeight : 22 ,
color : '#161616' ,
fontFamily : 'Montserrat-Bold' ,
} ,
priceLabel : {
padding : 0 ,
paddingTop : 5 ,
margin : 0 ,
marginLeft : 3 ,
fontSize : 12 ,
color : '#7f7e7e' ,
fontFamily : 'PingFangSC-Medium' ,
} ,
mobileInfoSection : {
width : '100%' ,
marginTop : 30 ,
} ,
mobileNumberSection : {
width : '100%' ,
} ,
mobileNumberLabel : {
padding : 0 ,
margin : 0 ,
fontSize : 14 ,
lineHeight : 18 ,
color : 'black' ,
fontFamily : 'PingFangSC-Regular' ,
} ,
infoCard : {
flexDirection : 'row' ,
alignItems : 'center' ,
justifyContent : 'flex-start' ,
width : '100%' ,
height : 50 ,
paddingRight : 12 ,
paddingLeft : 12 ,
marginTop : 12 ,
borderWidth : 1 ,
borderColor : '#d8d8d8' ,
borderRadius : 25 ,
} ,
flexRowWithIcon : {
flexDirection : 'row' ,
alignItems : 'center' ,
justifyContent : 'flex-start' ,
} ,
maskedImageWithText : {
width : 20 ,
height : 12 ,
borderWidth : 0 ,
} ,
highlightText : {
padding : 0 ,
margin : 0 ,
marginLeft : 3 ,
fontSize : 16 ,
lineHeight : 22 ,
color : '#1c284e' ,
fontFamily : 'PingFangSC-Semibold' ,
} ,
svgContainer2 : {
width : 12 ,
height : 12 ,
marginLeft : 12 ,
} ,
verticalDivider : {
width : 1 ,
height : 30 ,
marginLeft : 8.5 ,
borderLeftWidth : 1 ,
borderColor : '#b1b1b1' ,
} ,
statisticText : {
padding : 0 ,
margin : 0 ,
marginLeft : 19.5 ,
fontSize : 16 ,
lineHeight : 22 ,
color : '#1c284e' ,
fontFamily : 'PingFangSC-Semibold' ,
} ,
mobileOperatorsContainer : {
width : '100%' ,
marginTop : 20 ,
} ,
operatorSupportContainer : {
flexDirection : 'row' ,
gap : 10 ,
alignItems : 'center' ,
justifyContent : 'flex-start' ,
marginTop : 12 ,
} ,
imageContainerWithBorder1 : {
width : 70 ,
height : 26 ,
borderWidth : 0 ,
} ,
blueBoxContainer : {
flexDirection : 'column' ,
alignItems : 'center' ,
justifyContent : 'flex-start' ,
width : '100%' ,
marginTop : 50 ,
backgroundColor : '#002fa7' ,
borderRadius : 25 ,
} ,
paymentNotice1 : {
flexDirection : 'column' ,
alignItems : 'center' ,
justifyContent : 'center' ,
height : 50 ,
} ,
paymentNotice : {
padding : 0 ,
margin : 0 ,
fontSize : 16 ,
color : 'white' ,
fontFamily : 'Montserrat-Bold' ,
} ,
paymentConfirmContainer : {
flex : 1 ,
padding : 20 ,
backgroundColor : "#fff" ,
} ,
paymentSummaryCard : {
backgroundColor : "#f5f9ff" ,
borderRadius : 10 ,
padding : 20 ,
marginBottom : 20 ,
} ,
paymentSummaryTitle : {
fontSize : fontSize ( 18 ) ,
fontWeight : "700" ,
marginBottom : 15 ,
color : "#333" ,
} ,
paymentSummaryRow : {
flexDirection : "row" ,
justifyContent : "space-between" ,
marginBottom : 10 ,
} ,
paymentSummaryLabel : {
fontSize : fontSize ( 14 ) ,
color : "#666" ,
} ,
paymentSummaryValue : {
fontSize : fontSize ( 14 ) ,
fontWeight : "500" ,
color : "#333" ,
} ,
paymentSummaryValueHighlight : {
fontSize : fontSize ( 14 ) ,
fontWeight : "600" ,
color : "#ff5100" ,
} ,
phoneInputContainer : {
marginBottom : 20 ,
} ,
phoneInputLabel : {
fontSize : fontSize ( 16 ) ,
fontWeight : "500" ,
marginBottom : 10 ,
color : "#333" ,
} ,
phoneInputWrapper : {
flexDirection : "row" ,
borderWidth : 1 ,
borderColor : "#ddd" ,
borderRadius : 25 ,
overflow : "hidden" ,
} ,
countryCodeContainer : {
backgroundColor : "#f5f5f5" ,
paddingHorizontal : 15 ,
justifyContent : "center" ,
borderRightWidth : 1 ,
borderRightColor : "#ddd" ,
} ,
countryCodeText : {
fontSize : fontSize ( 16 ) ,
color : "#333" ,
} ,
phoneInput : {
flex : 1 ,
height : 50 ,
paddingHorizontal : 15 ,
fontSize : fontSize ( 16 ) ,
color : "#333" ,
} ,
supportedOperatorsContainer : {
marginBottom : 30 ,
} ,
supportedOperatorsTitle : {
fontSize : fontSize ( 16 ) ,
fontWeight : "500" ,
marginBottom : 10 ,
color : "#333" ,
} ,
operatorsRow : {
flexDirection : "row" ,
alignItems : "center" ,
} ,
operatorSmallIcon : {
width : 70 ,
height : 26 ,
resizeMode : "contain" ,
marginRight : 15 ,
} ,
payButton : {
backgroundColor : "#002fa7" ,
borderRadius : 25 ,
height : 50 ,
justifyContent : "center" ,
alignItems : "center" ,
marginTop : 20 ,
} ,
payButtonDisabled : {
backgroundColor : "#8da0d4" ,
opacity : 0.7 ,
} ,
payButtonText : {
color : "white" ,
fontSize : fontSize ( 16 ) ,
fontWeight : "700" ,
} ,
} ) ;
export default RechargeScreen ;