unioil-loyalty-rn-app/app/screens/payatpump/pumppaymentmethod.js

484 lines
19 KiB
JavaScript

import * as React from 'react';
import { connect } from "react-redux";
import {
SafeAreaView,
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/';
class PayatpumpPaymentMethodList extends React.Component {
constructor(props) {
super(props)
}
state = {
cards: [],
cardNumber: null,
cardHolder: null,
cardExpiry: null,
cardCVV: null,
focus_holder: null,
focus_expiry: false,
focus_cvv: false,
enableDefaultCard: false,
showModal: false,
pubkey: null,
verificationUrl: 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.')
}
}
// if(res.success == undefined) {
// onError(res.Message)
// } else {
// if(res.success) {
// if(res.response.result) {
// onSuccess({ userPaymentSourceId: res.response.userPaymentSourceId, referenceNumber: res.response.referenceNumber })
// }
// } else {
// onError('Error', 'Failed to get fund. 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) => {
console.log(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<len; i+=4) {
parts.push(match.substring(i, i+4))
}
var cardnumber = parts.length ? parts.join(' ') : number
this.setState({ cardNumber: cardnumber });
}
_handlingCardHolder = (name) => {
this.setState({ cardHolder: name })
}
_handlingCardExpiry = (number) => {
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) => {
console.log(res)
if(res.success == undefined) {
this.setState({ loading: false })
setTimeout(() => {
Alert.alert('Error', res.Message)
}, 300)
} else {
this.setState({ loading: false })
if(res.success) {
setTimeout(() => {
this.props.route?.params.onAddNewCard({ userPaymentSourceId: res.response.userPaymentSourceId, referenceNumber: res.response.referenceNumber }, this.state.enableDefaultCard)
this.props.navigation.goBack()
}, 500);
} 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.state.cardHolder == 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 cardHolder = this.state.cardHolder
let cardExpiry = `${this.state.cardExpiry.split("/")[0]}${numberYear}${this.state.cardExpiry.split("/")[1]}`
let cardCvv = this.state.cardCVV
if(cardValidator.number(cardnumber)?.card?.type != undefined && cardValidator.number(cardnumber)?.card?.type !== "visa") {
Alert.alert('Error', `${cardValidator.number(cardnumber)?.card?.type.slice(0,1).toUpperCase() + cardValidator.number(cardnumber).card.type.slice(1, cardValidator.number(cardnumber).card.type.length)} in not available. Please use different card type.`)
return
} else {
if(cardValidator.number(cardnumber)?.card?.type == undefined) {
Alert.alert('Error', "Invalid card number. Please check and try again.")
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, cardHolder, onSuccess => {
this.setState({ loading: false })
setTimeout(() => {
this.props.navigation.navigate('VerificationWebview', {...onSuccess, onSuccessAuthentication:(referenceNumber) => this._onAuthenticationSuccess(referenceNumber)})
}, 500);
},
error => {
this.setState({ loading: false })
setTimeout(() => {
Alert.alert('Error', error)
}, 300)
})
}
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) => {
console.log(webviewState)
}
renderWebview = () => {
return (
<WebView
originWhitelist={['*']}
source={{ uri: this.state.data ? this.state.data?.redirectUrl : '' }}
style={{
backgroundColor: 'transparent',
width: Theme.screen.w,
height: Theme.screen.h,
padding: 15
}}
onNavigationStateChange={(webViewState) => this.onStateChange(webViewState)}/>
)
}
renderErrorModal = () => {
return (
<Modal
animationType="none"
transparent={true}
visible={this.state.showModal}>
<TouchableOpacity activeOpacity={1} onPress={() => {}} style={styles.centeredView}>
<View style={[styles.modalView, { backgroundColor: this.props.app_theme?.theme.colors.border }]}>
<>
<Image source={Assets.icons.points_balance} style={{ width: 85, height: 85, resizeMode: 'contain' }} />
<Text style={{ fontSize: 18, color: this.props.app_theme?.theme.colors.text, marginVertical: 30 }}>{'Please Fill in the required fields'}</Text>
<TouchableOpacity onPress={() => this.setState({ showModal: false })} style={{ width: 80, height: 30, backgroundColor: Theme.colors.primary, alignItems: 'center', justifyContent: 'center', borderRadius: 5 }}>
<Text style={{ fontSize: 18, color: Theme.colors.white, textAlign: 'center' }}>Ok</Text>
</TouchableOpacity>
</>
</View>
</TouchableOpacity>
</Modal>
)
}
renderCardForm = () => {
return (
<>
<View style={{ flex: 0.2, justifyContent: 'center' }}>
<Text style={{ fontSize: 20, color: Theme.colors.primary, textAlign: 'center' }}>Enroll Your Payment Card</Text>
</View>
<View style={{ flex: 0.1 }} />
<View style={{ flex: 0.3 }}>
<View style={{ flexDirection: 'row', marginHorizontal: 16 }}>
<Text style={{ color: this.props.app_theme?.theme.colors.text }}>Enroll Your Payment Card</Text>
</View>
<View style={styles.cardContainer}>
<TextInput
keyboardType="numeric"
returnKeyType={'done'}
placeholder="This card will be used for pay at pump"
placeholderTextColor={Theme.colors.gray}
value={this.state.cardNumber}
onFocus={() => this.setState({ focus_expiry: true, focus_cvv: false })}
onChangeText={(value) => this._handlingCardNumber(value)}
style={{ flex: 1, color: this.props.app_theme?.theme.colors.text, fontStyle: 'italic' }}
/>
<Image source={Assets.icons.stpunlabeled} style={{ width: 30, height: 30, resizeMode: 'contain' }} />
</View>
</View>
<View style={{ flex: 0.3 }}>
<View style={{ flexDirection: 'row', marginHorizontal: 16 }}>
<Text style={{ color: this.props.app_theme?.theme.colors.text }}>Name on Card</Text>
</View>
<View style={styles.cardContainer}>
<TextInput
keyboardType="ascii-capable"
returnKeyType={'done'}
value={this.state.cardHolder}
onFocus={() => this.setState({ focus_expiry: true, focus_cvv: false })}
onChangeText={(value) => this._handlingCardHolder(value)}
style={{ flex: 1, color: this.props.app_theme?.theme.colors.text }}
/>
</View>
</View>
<View style={{ flex: 0.3 }}>
<View style={{ flexDirection: 'row', marginHorizontal: 16 }}>
<Text style={{ color: this.props.app_theme?.theme.colors.text, flex: 1 }}>Expiration (MM/YY)</Text>
<Text style={{ color: this.props.app_theme?.theme.colors.text, flex: 0.5 }}>CVV</Text>
</View>
<View style={{ flex: 0.3, flexDirection: 'row' }}>
<View style={[styles.expirationCvvContainer, { flex: 1, marginLeft: 16, marginRight: 5 }]}>
<TextInput
keyboardType="numeric"
returnKeyType={'done'}
value={this.state.cardExpiry}
onFocus={() => 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 }}
/>
</View>
<View style={[styles.expirationCvvContainer, { flex: 0.55, marginRight: 16, marginLeft: 5 }]}>
<TextInput
keyboardType="numeric"
returnKeyType={'done'}
value={this.state.cardCVV}
onFocus={() => 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 }}
/>
</View>
</View>
</View>
</>
)
}
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<CustomHeader
title={"Add Card"}
onBackPress={() => this.onBackConfirmation()}
back={true}
menu={false}
navigation={this.props.navigation}
/>
<Elements.loaderView
title="Validating"
message="Please wait..."
isDarkMode={this.props.app_theme?.theme.dark}
backgroundColor={this.props.app_theme?.theme.colors.border}
color={this.props.app_theme?.theme.colors.text}
visible={this.state.loading} />
{this.renderErrorModal()}
{this.renderCardForm()}
{this.state.verificationUrl != null && this.renderWebview()}
<View style={{ flex: 1 }} />
<View>
<Text style={{ textAlign: 'center', fontStyle: 'italic', color: this.props.app_theme?.theme.colors.text }}>Your card will be changed to ensure that it's valid.</Text>
<Text style={{ textAlign: 'center', fontStyle: 'italic', color: this.props.app_theme?.theme.colors.text }}>Charge amount will be automatically refunded.</Text>
<View style={{ marginBottom: 5 }} />
<TouchableOpacity onPress={() => this.submitNewAddedCard()}
style={{ height: 55, marginBottom: 16, backgroundColor: Theme.colors.primary, justifyContent: 'center', alignItems: 'center', borderRadius: 5, marginHorizontal: 16 }}>
<Text style={{ fontSize: 18, color: Theme.colors.white, textAlign: 'center', fontWeight: 'bold' }}>Save</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
)
}
}
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
}
})