Authored by 张文文

添加身份证上传及身份证绑定接口调试

... ... @@ -39,8 +39,9 @@ export default class Mine extends Component {
let imageUrl = YH_Image.getSlicedUrl(ico, 50, 50, 2);
let nickname = this.props.profile.nickname;
let uploadStyle = bindStatus ? {color: '#444444'} : {color: '#D0021B'};
let isUpload = bindStatus ? '已上传' : '未上传';
let uploadStatus = this.props.identityCardInfo.data;
let uploadStyle = uploadStatus ? {color: '#444444'} : {color: '#D0021B'};
let isUpload = uploadStatus ? '已上传' : '未上传';
//当前粉丝数空值判断
let fansAmount = this.props.shareTotalInfo.shareTotalInfoData.fans;
... ...
/**
* Created by misty on 2019/06/05.
*/
'use strict';
import React, {Component} from "react";
import ReactNative ,{
Dimensions,
StyleSheet,
Text,
View,
TouchableOpacity,
TextInput,
ScrollView,
Platform,
Image,
InteractionManager,
} from "react-native";
import Prompt from "../../common/components/Prompt";
import YH_Image from "../../common/components/YH_Image";
import YH_ActionSheet from "../../common/components/YH_ActionSheet";
import ImagePicker from 'react-native-image-picker';
import LoadingIndicator from '../../common/components/LoadingIndicator';
export default class NameAuthen extends Component {
constructor(props) {
super(props);
this.state = {
isBack: false,
backIDCardImageUri: '',
frontIDCardImageUri: '',
}
// this.renderCell = this.renderCell.bind(this)
this.renderHeader = this.renderHeader.bind(this)
this.renderMeritCell = this.renderMeritCell.bind(this)
this.renderIDCardAddDetailCell = this.renderIDCardAddDetailCell.bind(this)
this.actionsheetItemClick = this.actionsheetItemClick.bind(this)
}
renderHeader(title) {
return <View style={styles.headerDetailContainer}>
<Text style={styles.headerTitle} numberOfLines={1}>{title}</Text>
</View>
}
renderMeritCell(title) {
return <View style={styles.meritCell}>
<View style={styles.meritAnnotation}/>
<Text style={styles.headerDetailTitle}>{title}</Text>
</View>
}
renderIDCardAddDetailCell() {
return (
<View style={styles.renderIDCardAddDetailCell}>
{this.renderIDCardAddCellImage(false)}
{this.renderIDCardAddCellImage(true)}
</View>
)
}
renderIDCardAddCellImage(isBack) {
let title = isBack ? '反面照片' : '正面照片';
let image = isBack ? require('../images/cardBack.png') : require('../images/cardFront.png');
let imageUrl = isBack ? this.state.backIDCardImageUri : this.state.frontIDCardImageUri;
let hasImage = imageUrl.length > 0 ? true : false;
return (
<View style={styles.renderIDCardAddCellImage}>
<TouchableOpacity
activeOpacity={1.0}
onPress={() => {
if(!hasImage){
this.setState({
isBack,
})
this.refs.YH_ActionSheet.showModal();
}
}}>
{hasImage ?
<YH_Image resizeMode="contain" url={imageUrl} style={[styles.viewImage, {backgroundColor: 'transparent', borderWidth: 0,}]}/>
:
<View style={styles.viewImage}>
<Image style={styles.addImage} resizeMode={'contain'} source={require('../images/addID.png')}/>
<Text style={[styles.imageText, {marginTop: 13}]}>{title}</Text>
</View>
}
</TouchableOpacity>
<TouchableOpacity
activeOpacity={1.0}
style={styles.addImageClose}
onPress={() => {
if(isBack){
this.setState({
backIDCardImageUri: '',
})
}else {
this.setState({
frontIDCardImageUri: '',
})
}
}}>
{hasImage ?
<Image style={{height: 16,width: 16}} source={require('../images/imageShareClose.png')}/>
: null}
</TouchableOpacity>
<View style={styles.renderIDCardSampleCellImage}>
<Image style={styles.cardImage} source={image}/>
<Text style={styles.cardImageEGtip}>(示例)</Text>
</View>
</View>
)
}
actionsheetItemClick(id){
this.props.showLoading && this.props.showLoading(true);
let that = this;
if(id == 1){
ReactNative.NativeModules.YH_MarketHelper.goUFOIDCardCameraVC(this.state.isBack).then(data => {
InteractionManager.runAfterInteractions(() => {
that.refs.YH_ActionSheet.cancelModal();
if(that.state.isBack){
that.setState({
backIDCardImageUri: data,
})
}else {
that.setState({
frontIDCardImageUri: data,
})
}
that.props.showLoading && that.props.showLoading(false);
});
})
.catch(error => {
that.refs.YH_ActionSheet.cancelModal();
that.props.showLoading && that.props.showLoading(false);
});
}else if(id == 2){
if(Platform.OS == 'ios'){
let options = {
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.launchImageLibrary(options, (response) => {
InteractionManager.runAfterInteractions(() => {
console.log(response);
that.refs.YH_ActionSheet.cancelModal();
let uri = response ? response.uri : '';
if(uri){
if(that.state.isBack){
that.setState({
backIDCardImageUri: uri,
})
}else {
that.setState({
frontIDCardImageUri: uri,
})
}
}
that.props.showLoading && that.props.showLoading(false);
});
});
}
else{
ReactNative.NativeModules.YH_MarketHelper.goPhotoVC().then(data => {
InteractionManager.runAfterInteractions(() => {
that.refs.YH_ActionSheet.cancelModal();
if(that.state.isBack){
that.setState({
backIDCardImageUri: data,
})
}else {
that.setState({
frontIDCardImageUri: data,
})
}
that.props.showLoading && that.props.showLoading(false);
});
})
.catch(error => {
});
}
}
}
render() {
let buttonDisabled = this.state.backIDCardImageUri.length == 0 || this.state.frontIDCardImageUri.length == 0
let isShowToast = this.props.isShowToast;
let toastMessage = this.props.toastMessage;
return <View style={styles.mainContainer}>
<ScrollView style={styles.mainContainer}
keyboardShouldPersistTaps={'handled'}>
{this.renderHeader('请上传身份证照片')}
{this.renderMeritCell('请上传原始比例清晰的身份证正反面。请勿进行裁剪涂改,否则无法通过审核。')}
{this.renderMeritCell('照片格式支持jpg、jpeg、png。')}
{this.renderMeritCell('身份证照片信息将加密处理,仅用于提现财务用途。')}
{this.renderMeritCell('身份证信息需与提现银行卡信息匹配,否则无法正常提现成功。')}
{this.renderIDCardAddDetailCell()}
</ScrollView>
<TouchableOpacity style={[styles.submitButton, buttonDisabled ? styles.disabledButton : {}]}
disabled={buttonDisabled}
onPress={()=> {
if (this.state.backIDCardImageUri.length > 0 && this.state.frontIDCardImageUri.length > 0) {
this.props.bindIdentityCard && this.props.bindIdentityCard(this.state.frontIDCardImageUri, this.state.backIDCardImageUri);
}
}}>
<Text style={styles.buttonText}>{'提交'}</Text>
</TouchableOpacity>
{isShowToast ? <Prompt
text={toastMessage}
duration={1500}
onPromptHidden={this.props.hideToastMessage}
/> : null}
<YH_ActionSheet
ref="YH_ActionSheet"
items={[{title:'拍照',id:'1'},{title:'从相册中选择',id:'2'}]}
actionsheetItemClick={this.actionsheetItemClick}
modalTitle={""} />
<LoadingIndicator
isVisible={this.props.isShowLoading}
/>
</View>
}
}
const { width } = Dimensions.get('window');
let styles = StyleSheet.create({
mainContainer: {
flex: 1,
backgroundColor: 'white',
},
headerDetailContainer: {
backgroundColor: 'white',
},
headerTitle: {
marginLeft: 15,
marginTop: 20,
fontFamily: 'PingFang-SC-Medium',
fontSize: 17,
color: '#444444',
letterSpacing: 0,
},
meritCell: {
marginTop: 10,
flexDirection: 'row',
paddingLeft: 15,
paddingRight: 10,
},
meritAnnotation: {
width: 3,
height: 3,
borderRadius: 1.5,
backgroundColor: '#B0B0B0',
marginTop: 8,
},
headerDetailTitle: {
fontFamily: 'PingFang-SC-Regular',
fontSize: 14,
color: '#B0B0B0',
letterSpacing: 0,
marginLeft: 5,
},
cell: {
height: 50,
alignItems: 'center',
flexDirection: 'row',
paddingLeft: 15,
paddingRight: 15,
},
cellTitle: {
fontSize: 14,
fontFamily: 'PingFang-SC-Regular',
color: '#444444',
},
textInput: {
fontSize: 14,
marginLeft: 22,
fontFamily: 'PingFang-SC-Regular',
color: '#B0B0B0',
},
imageText: {
fontFamily: 'PingFang-SC-Regular',
color: '#B0B0B0',
fontSize: 14,
},
buttonText: {
color: 'white',
fontSize: 14,
fontWeight: 'bold',
},
submitButton: {
marginLeft: 15,
marginRight: 15,
marginBottom: 33,
height: 44,
backgroundColor: '#002B47',
alignItems: 'center',
justifyContent: 'center',
},
disabledButton: {
backgroundColor: '#CCCCCC'
},
line: {backgroundColor: '#EEEEEE', left: 20, right: 20, bottom: 0, height: 1, position: 'absolute'},
renderIDCardAddDetailCell: {
flexDirection: 'row',
marginTop: 20,
marginLeft: 15,
marginRight: 15,
justifyContent: 'space-between',
alignItems: 'center',
},
renderIDCardAddCellImage: {
width: (width - 50)/2,
},
viewImage: {
height: 101,
width: (width - 50)/2,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 2,
borderWidth: 1,
borderStyle: 'dashed',
borderColor: '#f0f0f0',
},
addImage: {
height: 30,
width: 30,
},
addImageClose: {
position: 'absolute',
height: 16,
width: 16,
top: -4,
left: (width - 50)/2-10,
},
renderIDCardSampleCellImage: {
width: 80,
marginTop: 30,
marginLeft: ((width-50)/2-80)/2,
},
cardImage: {
width: 80,
height: 50,
},
cardImageEGtip: {
height: 13,
width: 80,
marginTop: 4,
fontFamily: 'PingFang-SC-Regular',
fontSize: 9,
color: '#999999',
letterSpacing: 0,
textAlign: 'center',
},
})
... ...
... ... @@ -163,4 +163,16 @@ export default keyMirror({
SHOW_TIP_MESSAGE: null,
HIDDEN_TIP_MESSAGE: null,
IDENTITY_CARD_INFO_REQUEST: null,
IDENTITY_CARD_INFO_SUCCESS: null,
IDENTITY_CARD_INFO_FAILURE: null,
BIND_IDENTITY_CARD_REQUEST: null,
BIND_IDENTITY_CARD_SUCCESS: null,
BIND_IDENTITY_CARD_FAILURE: null,
SHOW_TOAST: null,
HIDE_TOAST: null,
SHOW_LOADING: null,
});
... ...
... ... @@ -44,6 +44,7 @@ class MineContainer extends Component {
componentDidMount() {
this.props.actions.getMineUserInfo();
this.props.actions.getSettlementInfo();
this.props.actions.getIdentityCardInfo();
this.props.actions.getMineResourceInfo();
this.props.actions.getShareTotalInfo();
}
... ... @@ -75,6 +76,7 @@ class MineContainer extends Component {
settlementInfo,
mineResourceInfo,
shareTotalInfo,
identityCardInfo,
} = this.props.alliance;
let isFetching = settlementInfo.isFetching;
return (
... ... @@ -84,6 +86,7 @@ class MineContainer extends Component {
settlementInfo={settlementInfo}
mineResourceInfo={mineResourceInfo}
shareTotalInfo={shareTotalInfo}
identityCardInfo={identityCardInfo}
jumpWithUrl={this._jumpWithUrl}
resourceJumpWithUrl={this._resourceJumpWithUrl}
refreshSettlementInfo={this._refreshSettlementInfo}
... ...
... ... @@ -8,6 +8,9 @@ import {Map} from "immutable";
import * as allianceActions from '../reducers/alliance/allianceActions';
import NameAuthen from "../components/NameAuthen";
import AllianceService from '../services/AllianceService';
const actions = [
allianceActions
];
... ... @@ -34,6 +37,10 @@ function mapDispatchToProps(dispatch) {
class NameAuthenContainer extends Component {
constructor(props) {
super(props);
this.bindIdentityCard = this.bindIdentityCard.bind(this);
this.showLoading = this.showLoading.bind(this);
this.hideToastMessage = this.hideToastMessage.bind(this);
}
componentDidMount() {
... ... @@ -44,10 +51,60 @@ class NameAuthenContainer extends Component {
}
showLoading(show){
this.props.actions.showLoading(show);
}
hideToastMessage(){
this.props.actions.hideToastMessage();
}
bindIdentityCard(frontIDCardImageUri, backIDCardImageUri) {
this.showLoading(true);
console.log(backIDCardImageUri);
console.log(frontIDCardImageUri);
let param = [{code: 0,imageUri:frontIDCardImageUri.replace('file://','')},{code: 1,imageUri:backIDCardImageUri.replace('file://','')}];
NativeModules.YH_MarketHelper && NativeModules.YH_MarketHelper.postIDCardImage(param).then(data => {
let list = data;
let cardFrontUrl = '';
let cardBackUrl = '';
for (let i = 0; i < list.length; i++) {
const element = list[i];
if(element.code == 0){
cardFrontUrl = element.result;
}else if(element.code == 1){
cardBackUrl = element.result;
}
}
this.showLoading(false);
if(cardFrontUrl.length <= 0 || cardBackUrl.length <= 0){
this.props.actions.showToastMessage('图片上传失败!请重试!');
return;
}
this.props.actions.bindIdentityCard(cardFrontUrl, cardBackUrl, function(json) {
});
})
.catch(error => {
this.showLoading(false);
this.props.actions.showToastMessage(error.message || '网络请求错误');
});
}
render() {
return (
<View style={styles.container}>
<NameAuthen
bindIdentityCard={this.bindIdentityCard}
showLoading={this.showLoading}
isShowLoading={this.props.alliance.isShowLoading}
isShowToast={this.props.alliance.isShowToast}
toastMessage={this.props.alliance.toastMessage}
hideToastMessage={this.hideToastMessage}/>
</View>
);
}
... ...
... ... @@ -112,6 +112,19 @@ const {
SHOW_BANK_TIPS_ALERT,
DISMISS_BANK_TIPS_ALERT,
IDENTITY_CARD_INFO_REQUEST,
IDENTITY_CARD_INFO_SUCCESS,
IDENTITY_CARD_INFO_FAILURE,
BIND_IDENTITY_CARD_REQUEST,
BIND_IDENTITY_CARD_SUCCESS,
BIND_IDENTITY_CARD_FAILURE,
SHOW_TOAST,
HIDE_TOAST,
SHOW_LOADING,
} = require('../../constants/actionTypes').default;
export function showTipsAlertDialog() {
... ... @@ -629,6 +642,66 @@ export function invitedFriendsFailue(error) {
}
}
export function identityCardInfoRequest() {
return {
type: IDENTITY_CARD_INFO_REQUEST,
};
}
export function identityCardInfoSuccess(json) {
return {
type: IDENTITY_CARD_INFO_SUCCESS,
payload: json
};
}
export function identityCardInfoFailure(error) {
return {
type: IDENTITY_CARD_INFO_FAILURE,
payload: error
};
}
export function bindIdentityCardRequest() {
return {
type: BIND_IDENTITY_CARD_REQUEST,
};
}
export function bindIdentityCardSuccess(json) {
return {
type: BIND_IDENTITY_CARD_SUCCESS,
payload: json
};
}
export function bindIdentityCardFailure(error) {
return {
type: BIND_IDENTITY_CARD_FAILURE,
payload: error
};
}
export function showLoading(show) {
return {
type: SHOW_LOADING,
payload: show
};
}
export function showToastMessage(value) {
return {
type: SHOW_TOAST,
payload: value
};
}
export function hideToastMessage() {
return {
type: HIDE_TOAST,
};
}
export function getSettlementInfo() {
return (dispatch, getState) => {
let {app} = getState();
... ... @@ -1275,3 +1348,58 @@ function exposeProductListData(json) {
res.product_list = list;
return res;
}
export function bindIdentityCard(cardFrontUrl, cardBackUrl, callback) {
return (dispatch, getState) => {
let {app, alliance} = getState();
let funBindIdentityCard = (uid) => {
dispatch(bindIdentityCardRequest());
return new AllianceService(app.host).bindIdentityCard(uid, cardFrontUrl, cardBackUrl)
.then(json => {
dispatch(bindIdentityCardSuccess(json));
callback && typeof callback === 'function' && callback(json)
})
.catch(error => {
dispatch(bindIdentityCardFailure(error));
dispatch(showToastMessage(error.message));
});
};
let uid = 0;
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
funBindIdentityCard(uid)
})
.catch(error => {
funBindIdentityCard(uid)
});
};
}
export function getIdentityCardInfo() {
return (dispatch, getState) => {
let {app} = getState();
let fetchIdentityCardInfo = (uid) => {
dispatch(identityCardInfoRequest());
return new AllianceService(app.host).fetchIdentityCardInfo(uid)
.then(json => {
dispatch(identityCardInfoSuccess(json));
})
.catch(error => {
dispatch(identityCardInfoFailure(error));
});
};
let uid = 0;
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
fetchIdentityCardInfo(uid)
})
.catch(error => {
fetchIdentityCardInfo(uid)
});
};
}
... ...
... ... @@ -195,6 +195,22 @@ let InitialState = Record({
username: '',
})),
bindIdentityCardResult: new (Record({
isFetching: false,
error: null,
})),
identityCardInfo: new (Record({
isFetching: false,
error: null,
data: null,
})),
isShowToast: false,
toastMessage: '',
isShowLoading: false,
});
export default InitialState;
... ...
... ... @@ -111,6 +111,18 @@ const {
INVITED_FRIENDS_SUCCESS,
INVITED_FRIENDS_FAILURE,
IDENTITY_CARD_INFO_REQUEST,
IDENTITY_CARD_INFO_SUCCESS,
IDENTITY_CARD_INFO_FAILURE,
BIND_IDENTITY_CARD_REQUEST,
BIND_IDENTITY_CARD_SUCCESS,
BIND_IDENTITY_CARD_FAILURE,
SHOW_TOAST,
HIDE_TOAST,
SHOW_LOADING,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -621,6 +633,39 @@ export default function couponReducer(state = initialState, action) {
return state.set('tipMessage', '');
}
case IDENTITY_CARD_INFO_REQUEST: {
return state.setIn(['identityCardInfo', 'isFetching'], true)
.setIn(['identityCardInfo', 'error'], null);
}
case IDENTITY_CARD_INFO_SUCCESS: {
return state.setIn(['identityCardInfo', 'isFetching'], false)
.setIn(['identityCardInfo', 'data'], action.payload)
.setIn(['identityCardInfo', 'error'], null);
}
case IDENTITY_CARD_INFO_FAILURE: {
return state.setIn(['identityCardInfo', 'isFetching'], false)
.setIn(['identityCardInfo', 'error'], action.payload);
}
case BIND_BANK_CARD_REQUEST:
return state.setIn(['bindIdentityCardResult', 'isFetching'], true);
case BIND_BANK_CARD_SUCCESS:
return state.setIn(['bindIdentityCardResult', 'isFetching'], false);
case BIND_BANK_CARD_FAILURE:
return state.setIn(['bindIdentityCardResult', 'isFetching'], false)
.setIn(['bindIdentityCardResult', 'error'], action.payload);
case SHOW_LOADING:
return state.set('isShowLoading', action.payload);
case SHOW_TOAST:
return state.set('isShowToast', true).set('toastMessage', action.payload);
case HIDE_TOAST:
return state.set('isShowToast', false).set('toastMessage', '');
}
return state;
}
... ...
... ... @@ -417,4 +417,42 @@ export default class AllianceService {
});
}
//(查询是否绑定身份证)
async fetchIdentityCardInfo(uid) {
return await this.api.get({
url: '',
body: {
uid,
method: 'app.union.shareOrder.getIdentityCard',
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
// 绑定身份证信息
async bindIdentityCard(uid, cardFrontUrl, cardBackUrl) {
return await this.api.get({
url: '',
body: {
method: 'app.union.shareOrder.bindIdentityCard',
uid,
cardFrontUrl,
cardBackUrl,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...
import React from 'react';
import PropTypes from 'prop-types';
import {
View,
StyleSheet,
Text,
Modal,
TouchableOpacity,
Dimensions
} from 'react-native'
const {width,height} =Dimensions.get('window')
export default class YH_ActionSheet extends React.Component {
constructor(props){
super(props)
this.state = {
modalVisible:false,
}
}
static propTypes={
items:PropTypes.array,
itemStyle:PropTypes.object,
actionTitleStyle:PropTypes.object,
itemTitleStyle:PropTypes.object,
modalTitle:PropTypes.string,
}
static defaultProps={
items:[],
itemStyle:{},
actionTitleStyle:{},
itemTitleStyle:{},
modalTitle:''
}
showModal(){
this.setState({modalVisible:true})
}
cancelModal(){
this.setState({modalVisible:false})
}
clickItem(id){
this.props.actionsheetItemClick(id);
}
render(){
let actionSheets = this.props.items.map((item,i)=>{
return(
<TouchableOpacity
key={i}
style={[styles.actionItem,this.props.itemStyle]}
onPress={()=>this.clickItem(item.id)}>
<Text style={[styles.actionItemTitle,this.props.itemTitleStyle]}
>{item.title}</Text>
</TouchableOpacity>
)
})
return <Modal animationType="fade" //slide
visible={this.state.modalVisible}
transparent={true}
onRequestClose={()=>this.setState({modalVisible:false})}>
<View style={styles.modalStyle}>
<View style={styles.subView}>
<View style={styles.itemContainer}>
{this.props.modalTitle ? <View style={[styles.itemContainer,{height:55,marginTop:5}]}>
<Text style={[styles.actionTitle,this.props.actionTitleStyle]}
>{this.props.modalTitle}</Text>
</View> : null}
{actionSheets}
</View>
<View style={[styles.itemContainer]}>
<TouchableOpacity
style={[styles.actionItem,this.props.itemStyle,{height:70,marginBottom:-5,backgroundColor:'white'}]}
onPress={()=>this.setState({modalVisible:false})}>
<Text style={[styles.actionItemTitle,this.props.itemTitleStyle,{color:'#999999',}]}>取消</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
}
}
const styles = StyleSheet.create({
modalStyle:{
justifyContent:'flex-end',
alignItems:'center',
flex:1,
backgroundColor:'rgba(0,0,0,0.2)',
},
subView:{
justifyContent:'flex-end',
alignItems:'center',
alignSelf:'stretch',
width:width,
backgroundColor:'white',
},
itemContainer:{
marginLeft:15,
marginRight:15,
marginBottom:0.5,
backgroundColor:'#fff',
justifyContent:'center',
alignItems:'center',
},
actionItem:{
width:width,
height:70,
alignItems:'center',
justifyContent:'center',
borderTopColor:'#EEEEEE',
borderTopWidth:0.5,
},
actionTitle:{
fontSize:14,
color:'#9EA3AD',
textAlign:'center',
},
actionItemTitle:{
fontSize:16,
color:'#000000',
textAlign:'center',
},
})
... ...
... ... @@ -50,6 +50,7 @@
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0",
"stacktrace-js": "^2.0.0",
"react-native-image-picker": "^0.28.1",
"timeago.js": "^3.0.2"
},
"devDependencies": {
... ...