UNPKG

react-native-paysofter

Version:

This is a React Native package for integrating Paysofter payment gateway into your React Native application.

348 lines (329 loc) 10.2 kB
// VerifyAccountFundPromiseOtp.js import React, { useState, useEffect, useCallback } from "react"; import { View, Text, TextInput, Button, StyleSheet, TouchableOpacity, ScrollView, } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; import ConfirmPaysofterPromise from "./ConfirmPaysofterPromise"; import Message from "./Message"; import { Card } from "react-native-paper"; import MessageFixed from "./MessageFixed"; import Loader from "./Loader"; import { PAYSOFTER_API_URL } from "./config/apiConfig"; import axios from "axios"; const VerifyAccountFundPromiseOtp = ({ email, amount, paysofterPublicKey, qty, productName, referenceId, currency, duration, onSuccess, formattedPayerEmail, securityCode, accountId, }) => { const [otp, setOtp] = useState(""); const [resendDisabled, setResendDisabled] = useState(false); const [resendLoading, setResendLoading] = useState(false); const [resendMessage, setResendMessage] = useState(""); const [countdown, setCountdown] = useState(60); const [showSuccessMessage, setShowSuccessMessage] = useState(false); const [sendOtpData, setSendOtpData] = useState(null); const [showConfirmPaysofterPromise, setShowConfirmPaysofterPromise] = useState(false); const [hasHandledSuccess, setHasHandledSuccess] = useState(false); const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); const [error, setError] = useState(""); const [promiseLoading, setPromiseLoading] = useState(false); const [promiseSuccess, setPromiseSuccess] = useState(false); const [promiseError, setPromiseError] = useState(""); useEffect(() => { const fetchSendOtpData = async () => { try { const data = await AsyncStorage.getItem("debitAccountData"); setSendOtpData(data ? JSON.parse(data) : {}); } catch (e) { console.error("Error fetching data from AsyncStorage:", e); } }; fetchSendOtpData(); }, []); const createdAt = new Date().toLocaleString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: true, timeZoneName: "short", }); const paymentMethod = "Paysofter Promise"; const otpData = sendOtpData ? { otp: otp, account_id: sendOtpData?.account_id, amount: amount, currency: currency, public_api_key: paysofterPublicKey, created_at: createdAt, } : {}; const debitAccountData = sendOtpData ? { account_id: sendOtpData?.account_id, security_code: sendOtpData?.security_code, amount: amount, public_api_key: paysofterPublicKey, qty: qty, product_name: productName, reference_id: referenceId, created_at: createdAt, } : {}; const handleVerifyEmailOtp = async () => { setLoading(true); setError(""); try { const { data } = await axios.post( `${PAYSOFTER_API_URL}/api/verify-otp/`, otpData ); console.log(data); setSuccess(true); } catch (error) { setError( error.response && error.response.data.detail ? error.response.data.detail : error.message ); } finally { setLoading(false); } }; const handleResendEmailOtp = async () => { setResendLoading(true); setResendMessage(""); try { await axios.post( `${PAYSOFTER_API_URL}/api/send-debit-fund-account-otp/`, debitAccountData ); setResendMessage(`OTP resent to ${formattedPayerEmail} successfully.`); setResendDisabled(true); } catch (error) { setResendMessage("Error resending OTP. Please try again."); } finally { setResendLoading(false); } }; useEffect(() => { let timer; if (countdown > 0 && resendDisabled) { timer = setTimeout(() => setCountdown(countdown - 1), 1000); } else if (countdown === 0 && resendDisabled) { setResendDisabled(false); } else if (!resendDisabled) { setCountdown(60); } return () => { clearTimeout(timer); }; }, [countdown, resendDisabled]); const handleOnSuccess = useCallback(() => { onSuccess(); }, [onSuccess]); useEffect(() => { if (success && !hasHandledSuccess) { const createPaysofterPromise = async () => { setPromiseLoading(true); setPromiseError(""); try { const paysofterPromiseData = { buyer_email: sendOtpData?.email, amount: sendOtpData?.amount, currency: sendOtpData?.currency, account_id: sendOtpData?.account_id, public_api_key: sendOtpData?.public_api_key, qty: qty, product_name: productName, reference_id: referenceId, duration: duration, created_at: createdAt, payment_method: paymentMethod, }; // console.log("paysofterPromiseData:", paysofterPromiseData); const { data } = await axios.post( `${PAYSOFTER_API_URL}/api/create-promise/`, paysofterPromiseData ); console.log(data); setPromiseSuccess(true); setHasHandledSuccess(true); setShowSuccessMessage(true); handleOnSuccess(); setTimeout(() => { setShowConfirmPaysofterPromise(true); setShowSuccessMessage(false); AsyncStorage.removeItem("debitAccountData"); }, 3000); } catch (error) { setPromiseError( error.response && error.response.data.message ? error.response.data.message : error.message ); } finally { setPromiseLoading(false); } }; createPaysofterPromise(); } }, [success, hasHandledSuccess]); useEffect(() => { if (promiseSuccess && !hasHandledSuccess) { setHasHandledSuccess(true); setShowSuccessMessage(true); setTimeout(() => { setShowConfirmPaysofterPromise(true); setShowSuccessMessage(false); AsyncStorage.removeItem("debitAccountData"); }, 3000); } }, [promiseSuccess, hasHandledSuccess]); return ( <ScrollView contentContainerStyle={styles.container}> <Card style={styles.card}> <Card.Content> {showConfirmPaysofterPromise ? ( <ConfirmPaysofterPromise /> ) : ( <View style={styles.content}> <Text style={styles.title}>Verify OTP ({currency})</Text> {showSuccessMessage && ( <Message variant="success">Promise sent successfully!</Message> )} {loading && <Loader />} {error && <Message variant="danger">{error}</Message>} {promiseLoading && <Loader />} {promiseError && ( <Message variant="danger">{promiseError}</Message> )} {resendMessage && ( <Message variant={resendLoading ? "info" : "success"}> {resendMessage} </Message> )} <TextInput style={styles.input} value={otp} onChangeText={(text) => setOtp(text)} placeholder="Enter OTP" required /> <Button title="Verify OTP" onPress={handleVerifyEmailOtp} disabled={otp === "" || loading || success} color="#28a745" /> <Text style={styles.infoText}> OTP has been sent to your email {formattedPayerEmail} for Paysofter Account ID: {sendOtpData?.account_id} and expires in 10 minutes. It might take a few seconds to deliver. </Text> <TouchableOpacity onPress={handleResendEmailOtp} disabled={resendDisabled || resendLoading} > <Text style={styles.resendText}> {resendLoading ? "Resending OTP..." : resendDisabled ? `Resend OTP (${countdown}sec)` : "Resend OTP"} </Text> </TouchableOpacity> </View> )} <View style={styles.errorContainer}> {error && <MessageFixed variant="danger">{error}</MessageFixed>} </View> </Card.Content> </Card> </ScrollView> ); }; const styles = StyleSheet.create({ container: { padding: 5, }, content: { marginVertical: 20, padding: 20, borderWidth: 1, borderRadius: 10, borderColor: "#ddd", alignItems: "center", }, title: { fontSize: 24, fontWeight: "bold", marginBottom: 20, }, input: { height: 40, borderColor: "gray", borderWidth: 1, padding: 10, width: "100%", marginBottom: 20, }, infoText: { textAlign: "center", marginVertical: 20, }, resendText: { color: "blue", textDecorationLine: "underline", textAlign: "center", }, errorContainer: { padding: 10, }, roundedPrimaryBtn: { backgroundColor: "#007bff", color: "#fff", padding: 10, borderRadius: 25, justifyContent: "center", alignItems: "center", textAlign: "center", }, roundedDisabledBtn: { backgroundColor: "#d3d3d3", color: "#fff", padding: 10, borderRadius: 25, justifyContent: "center", alignItems: "center", textAlign: "center", }, btnText: { color: "#fff", fontSize: 14, fontWeight: "bold", }, }); export default VerifyAccountFundPromiseOtp;