import * as React from 'react'; import { connect } from "react-redux"; import { TouchableOpacity, View, Text, Image, Switch, StyleSheet, Modal, Alert, TextInput } from 'react-native'; import { WebView } from 'react-native-webview'; import moment from 'moment'; import cardValidator from 'card-validator'; import REQUEST_POST_PAY from '../../components/api/postpayapi'; import CustomHeader from '../../components/header.js'; import Theme from '../../components/theme.style.js'; import Elements from '../../components/elements.js'; import Assets from '../../components/assets.manager.js'; import Cipher from '../../components/cardencrypt/encryptcard'; import DB from '../../components/storage/'; import CustomSafeArea from '../../components/safeArea.component'; import { returnIcon } from '../../utils/card'; class PayatpumpPaymentMethodList extends React.Component { constructor(props) { super(props) } state = { cards: [], cardNumber: null, cardExpiry: null, cardCVV: null, focus_holder: null, focus_expiry: false, focus_cvv: false, enableDefaultCard: false, showModal: false, pubkey: null, verificationUrl: null, cardDetails: null } componentDidMount() { this.getWalletKey() } componentWillUnmount() { } getWalletKey = () => { REQUEST_POST_PAY('getWalletPublicKey', 'get', {}, {}, {}, async (res) => { this.setState({ loading: false }) if(res.success == undefined) { setTimeout(() => { Alert.alert('Error', res.Message) }, 300) } else { if(res.success) { if(res.response.result) { this.setState({ pubkey: res.response.publicKey }) } } else { setTimeout(() => { Alert.alert('Error', 'Failed to get fund. Try again.') }, 300) } } }, (error) => { this.setState({ loading: false }) setTimeout(() => { Alert.alert('Error', 'Failed to get fund. Try again.') }, 300) }) } addCard = async (cardDetails, publicKey, cardHolder, onSuccess, onError) => { Cipher.encryptCard(cardDetails, publicKey) .then(async (encrypted) => { if(encrypted) { let params = { encBlock: { encCardData: encrypted }, paymentType: "CREDIT" } const USER_PROFILE = await DB.profile() REQUEST_POST_PAY('addCreditCard', 'post', { token: USER_PROFILE.data.auth_p97 }, {}, params, (res) => { console.log(res) if(res.success == undefined) { onError(res.Message) } else { if(res.success) { if(res.response.result) { this.addCardProviderData(res.response.referenceNumber, cardHolder, onSuccessResponse => onSuccess(onSuccessResponse), onErrorResponse => onError(onErrorResponse)) } } else { onError('Failed to add new card. Try again.') } } }, (error) => { onError('Error', error) }) } }) } addCardProviderData = async (referenceNumber, cardHolder, onSuccess, onError) => { let params = { referenceNumber: referenceNumber, providerData: { nickName: "Paymaya Visa", firstName: cardHolder } } const USER_PROFILE = await DB.profile() REQUEST_POST_PAY('addCreditCard', 'post', { token: USER_PROFILE.data.auth_p97 }, {}, params, (res) => { if(res.success == undefined) { onError(res.Message) } else { if(res.success) { if(res.response.result) { onSuccess({ referenceNumber: res.response.referenceNumber, verificationUrl: res.response.stepWiseResponsePayload.verificationUrl }) } } else { onError('Failed to add new card. Try again.') } } }, (error) => { onError(error) }) } _handlingCardNumber = (number) => { var value = number.replace(/\s+/g, '').replace(/[^0-9]/gi, '') var matches = value.match(/\d{4,16}/g); var match = matches && matches[0] || '' var parts = [] for (let i = 0, len=match.length; i { if (number.indexOf('.') >= 0 || number.length > 5) return if (number.length === 2 && this.state.cardExpiry.length === 1) number += '/' this.setState({ cardExpiry: number }); } _handlingCVV = (number) => { if (number.indexOf('.') >= 0 || number.length > 3) return this.setState({ cardCVV: number }); } _onAuthenticationSuccess = async (referenceNumber) => { let params = { referenceNumber: referenceNumber, } this.setState({ loading: true }) const USER_PROFILE = await DB.profile() REQUEST_POST_PAY('addCreditCard', 'post', { token: USER_PROFILE.data.auth_p97 }, {}, params, (res) => { if(res.success == undefined) { this.setState({ loading: false }) setTimeout(() => { Alert.alert('Error', res.Message) }, 300) } else { this.setState({ loading: false }) if(res.success) { this.props.route?.params.onAddNewCard({ userPaymentSourceId: res.response.userPaymentSourceId, referenceNumber: res.response.referenceNumber }, this.state.enableDefaultCard) } else { setTimeout(() => { Alert.alert('Error', res.Message) }, 300) } } }, (error) => { this.setState({ loading: false }) setTimeout(() => { Alert.alert('Error', error) }, 300) }) } submitNewAddedCard = () => { if(this.state.cardNumber == null || this.state.cardExpiry == null || this.state.cardCVV == null) { this.setState({ showModal: true }) return } let numberYear = moment(new Date()).format('YYYY').slice(0, 2) //get initial 2 digits of year let cardnumber = this.state.cardNumber.replace(/\s/g, "") let cardExpiry = `${this.state.cardExpiry.split("/")[0]}${numberYear}${this.state.cardExpiry.split("/")[1]}` let cardCvv = this.state.cardCVV console.log(cardnumber.length); if(!cardValidator.number(cardnumber)?.card?.type || cardnumber.length < 16) { Alert.alert('Error', `Invalid card number. Please use different card type.`) return } if(cardValidator.number(cardnumber)?.card?.type === "jcb") { Alert.alert('Error', `${cardValidator.number(cardnumber)?.card?.niceType} is not available. Please use different card type.`) return } if(!cardValidator.expirationDate(cardExpiry).isValid) { Alert.alert('Error', "Invalid expiration date. Please check and try again.") return } if(!cardValidator.cvv(cardCvv).isValid) { Alert.alert('Error', "Invalid cvv number. Please check and try again") return } let cardDetails = { pan: cardnumber, expDate: cardExpiry, cvv: cardCvv } this.setState({ loading: true }) this.addCard(JSON.stringify(cardDetails), this.state.pubkey, cardValidator.number(cardnumber).card.niceType, onSuccess => { setTimeout(() => { this.props.navigation.navigate('VerificationWebview', {...onSuccess, onSuccessAuthentication:(referenceNumber) => this._onAuthenticationSuccess(referenceNumber)}) this.setState({ loading: false }) }, 500); }, error => { Alert.alert('Error', `Something went wrong, please try again later.`) this.setState({ loading: false }) }) } onBackConfirmation = () => { Alert.alert( '', 'Are you sure you want to cancel adding card?', [ { text: 'Cancel', style: 'cancel', }, { text: 'OK', onPress: () => this.props.navigation.goBack(), }, ], {cancelable: true}, ); } onStateChange = (webviewState) => { } renderWebview = () => { return ( this.onStateChange(webViewState)}/> ) } renderErrorModal = () => { return ( {}} style={styles.centeredView}> <> {'Please Fill in the required fields'} this.setState({ showModal: false })} style={{ width: 80, height: 30, backgroundColor: Theme.colors.primary, alignItems: 'center', justifyContent: 'center', borderRadius: 5 }}> Ok ) } renderCardForm = () => { return ( Card Number this.setState({ focus_expiry: true, focus_cvv: false })} onChangeText={(value) => this._handlingCardNumber(value)} style={{ flex: 1, color: this.props.app_theme?.theme.colors.text }} /> this.setState({ focus_expiry: true, focus_cvv: false })} onChangeText={(value) => this._handlingCardExpiry(value)} style={{ flex: 1, color: this.props.app_theme?.theme.colors.text, marginRight: 3 }} /> this.setState({ focus_expiry: true, focus_cvv: false })} onChangeText={(value) => this._handlingCVV(value)} style={{ flex: 1, color: this.props.app_theme?.theme.colors.text, marginLeft: 3 }} /> ) } renderSwitch = () => { return ( Set as primary card this.setState({ enableDefaultCard: !this.state.enableDefaultCard })} /> ) } render() { return ( this.onBackConfirmation()} back={true} menu={false} navigation={this.props.navigation} /> {this.renderErrorModal()} {this.renderCardForm()} {this.renderSwitch()} {this.state.verificationUrl != null && this.renderWebview()} Your card will be charged to ensure that it's valid. Charged amount will be automatically refunded. this.submitNewAddedCard()} style={{ height: 50, marginBottom: 16, backgroundColor: Theme.colors.primary, justifyContent: 'center', alignItems: 'center', borderRadius: 5, marginHorizontal: 35 }}> Save ) } } const mapStateToProps = (state) => { return { app_theme: state.appThemeReducer.theme } } export default connect(mapStateToProps, null)(PayatpumpPaymentMethodList) const styles = StyleSheet.create({ centeredView: { flex: 1, justifyContent: "center", backgroundColor: '#00000090', }, modalView: { margin: 25, backgroundColor: "white", borderRadius: 15, padding: 20, alignItems: "center", shadowColor: "#000", shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 5 }, cardContainer: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', borderBottomWidth: 1, borderBottomColor: Theme.colors.gray, height: 40, borderRadius: 5, marginVertical: 10, marginHorizontal: 16 }, expirationCvvContainer: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', borderBottomWidth: 1, borderBottomColor: Theme.colors.gray, height: 40, borderRadius: 5, marginVertical: 10 } })