import React, { Component } from 'react'; import { StyleSheet, View, Text, Image, AppState, Linking } from 'react-native'; import BottomSheet from '../BottomSheet'; import LColors from '@assets/Strings/LColors'; import { bottomSpace, scaleSize, screenHeight } from '@utils/layout'; import { UIActivityIndicator } from 'react-native-indicators'; import { getList, doPayment, checkPay } from '@api/Order'; import ACTION_TYPE from '../Order/OrderAction'; import LTouchableOpacity from '../TouchAble/LTouchableOpacity'; import { aliPay, wxPay } from '@utils/native'; import TimerText from './TimerText'; import { Base64 } from 'js-base64'; import DialogContainer from '@common/UIComponents/Dialog/DialogContainer'; import { track } from '@utils/dataAnalytics'; import IconFont from '@assets/iconfont'; import LNumberText from 'imou-rn/dist/components/LNumberText'; import LToast from 'imou-rn/dist/components/LToast'; import { getImageUrlForPath } from '@utils/layout'; import LNetImage from '../LNetImage'; import { log, toast } from '@common/Utils/LogUtil';

export default class PayModal extends Component { constructor(props) { super(props); this.state = { data: null, selPayWayIndex: 0, time: '', isLoading: true, isNetError: false, leftTime: 10000, confirmModalVisible: true, appState: AppState.currentState, paymentId: '', }; this.isGoToSuccess = false; this.onBack = this._handleBack.bind(this); }

componentDidMount() { AppState.addEventListener('change', this._handleAppStateChange); }

componentWillUnmount() { AppState.removeEventListener('change', this._handleAppStateChange); }

_handleAppStateChange = (nextAppState) => { if ( this.state.appState && this.state.appState.match(/inactive|background/) && nextAppState === 'active' ) { this.doWhileGetPayResult(); } this.setState({ appState: nextAppState }); };

doWhileGetPayResult() { const { paying, visible } = this.state; if (!paying || this.isChecking || !visible) return; this.isChecking = true; LToast.loading('加载中', 0); let times = 0; const interval = setInterval(() => { if (times === 6) { LToast.removeAll(); clearInterval(interval); this.isChecking = false; return; } this._checkPay(interval); times++; }, 500); }

_checkPay(interval) { const { paymentId, visible } = this.state; if (!visible) return; console.log('_checkPay2222'); if (!paymentId) { this._fetchData(); return; } const json = { paymentId: paymentId, }; checkPay(json) .then((res) => { const { code, data, desc } = res; this.isChecking = false;

    if (code === 10000) {
      const { payStatus, promotionType, preparePayType } = data || {};
      if (
        payStatus === '1' ||
        (promotionType === 'prepare' && payStatus === '3' && preparePayType === 'deposit')
      ) {
        if (interval) {
          LToast.removeAll();
          interval && clearInterval(interval);
          AppState.removeEventListener('change', (state) => {
            // this._handleAppStateChange(state);
          });
        }
        this.isGoToSuccess = true;
        const from = this.props.from;
        this.timerText && this.timerText.stop();

        if (from && from === 'orderList') {
          this.updateCallback && this.updateCallback(ACTION_TYPE.PAY);
          this.setState(
            {
              visible: false,
            },
            () => {
              this.props.navigation &&
                this.props.navigation.navigate('PaySuccessScreen', {
                  data: { orderInfo: data },
                });
              this.updateCallback = null;
            },
          );
          return;
        }
        this.setState(
          {
            visible: false,
          },
          () => {
            this.props.navigation &&
              this.props.navigation.replace('PaySuccessScreen', {
                data: { orderInfo: data },
              });
          },
        );
      } else {
        this._fetchData();
      }
    } else {
      LToast.removeAll();
      interval && clearInterval(interval);
      this.isChecking = false;
      toast('服务器开小差啦~');
    }
  })
  .catch(() => {
    LToast.removeAll();
    interval && clearInterval(interval);
    AppState.removeEventListener('change', (state) => {
      this._handleAppStateChange(state);
    });
    this.isChecking = false;
    toast('服务器开小差啦~');
  });

} _handleBack() { this._handleOnClose(); if (this.props.from === 'confirm') { const { data } = this.state; this.props.navigation && this.props.navigation.replace('OrderDtlScreen', { orderID: data?.orderId, }); } else if (this.props.from === 'orderDtl') { this.props.onRefresh && this.props.onRefresh(); } track('$AppClick', 'PayScreen', { $element_id: 'click_cancel_pay', }); } _handleOnClose() { AppState.removeEventListener('change', (state) => { this._handleAppStateChange(state); }); this.props.onClose && this.props.onClose(); if (this.props.from === 'orderList') { this.updateCallback && this.updateCallback(ACTION_TYPE.PAY); } this.timerText && this.timerText.stop(); this.isGoToSuccess = false; this.setState({ visible: false, isLoading: false, paying: false, }); } show(data) { if (!data) return; AppState.addEventListener('change', (state) => { this._handleAppStateChange(state); }); this.isGoToSuccess = false; this.setState( { visible: true, data: data, isLoading: true, paying: true, paymentId: '', }, () => { this.updateCallback = data.updateCallback; this._fetchData(); }, ); } _fetchData() { if (!this.state.data) return; const { orderId } = this.state.data || {}; const json = { orderId: orderId, endPay: 0, platform: 'appnative', version: '5.5.0', }; getList(json) .then((data) => { if (data.code === 10000) { this._handleNetResult(data); } else { toast('服务器开小差啦~'); this.setState({ data: { orderId: orderId }, }); } }) .catch(() => { toast('服务器开小差啦~'); }); } _handleNetResult(result) { console.log('this.isGoToSuccess', this.isGoToSuccess); if (this.isGoToSuccess) return; const data = result?.data; if (data?.payStatus == 1) { this.comfirmModal && this.comfirmModal.hide(); this.isGoToSuccess = true; const from = this.props.from; this.timerText && this.timerText.stop(); if (from && from === 'orderList') { console.log('this.state.data.updateCallback', this.updateCallback); this.updateCallback && this.updateCallback(ACTION_TYPE.PAY); this.setState( { visible: false, }, () => { this.props.navigation && this.props.navigation.navigate('PaySuccessScreen', { data: data }); this.updateCallback = null; }, ); return; } this.setState( { visible: false, }, () => { this.props.navigation && this.props.navigation.replace('PaySuccessScreen', { data: data }); }, ); return; } this.timerText && this.timerText.stop(); this.setState({ isLoading: false, isNetError: false, data: data, leftTime: data?.leftTime, }); this.timerText && this.timerText.start(data?.leftTime); }

_handlePayResult(result) { const code = result?.code; if (JSON.stringify(result) === '{}' || !result) { this.doWhileGetPayResult(); return; } else if (code === 6001) { const timer = setTimeout(() => { clearTimeout(timer); this._fetchData(); }, 500);

  toast('取消支付');
} else if (code === -1) {
  const timer = setTimeout(() => {
    clearTimeout(timer);
    this._fetchData();
  }, 500);
  toast('其他错误');
} else if (code === 8000) {
  const timer = setTimeout(() => {
    clearTimeout(timer);
    this._fetchData();
  }, 500);

  return;
}
this.comfirmModal && this.comfirmModal.hide();

} _renderPayWayRow({ title, appId, index }) { const { data } = this.state; return ( {index > 0 ? ( <View style={{ height: StyleSheet.hairlineWidth, backgroundColor: LColors.N5, }} /> ) : null} <LTouchableOpacity disabled={data?.payable !== '1'} trackInfo={{ screenName: 'PayScreen', elementInfo: { $element_id: click_pay_${appId}, }, }} sensorsDataParams={{ $element_id: m_orderDtl_payWayBy${appId}_rpckn }} onPress={() => { this._doPayment({ appId }); }}> <IconFont name={appId === 'alipayapp' ? 'checkPay_Alipay' : 'checkPay_wepay'} size={32} /> {title} <IconFont size={10} name={'goodDetail_MoreArrow1'} /> ); } async _doPayment(infoItem) { const { data } = this.state; const { orderId, payMoney } = data; if (infoItem?.appId === 'wxpayapp') { const canOpenWX = await Linking.canOpenURL('weixin://'); if (!canOpenWX) { this.alertModal && this.alertModal.show(); return; } } const req = { orderId: orderId, payMoney: payMoney, payAppId: infoItem?.appId, };

doPayment(req)
  .then(async (res) => {
    const { code, desc } = res;
    if (code === 10000) {
      const html = res.data?.html;
      this.setState({
        paymentId: res.data?.paymentId,
      });
      if (!html) return;
      const base64Str = Base64.encode(html, false);

      if (infoItem?.appId === 'alipayapp') {
        const canOpenAlipay = await Linking.canOpenURL('alipays://');
        log('canOpenAlipay', canOpenAlipay);
        aliPay(base64Str)
          .then((data) => {
            this._handlePayResult(data);
          })
          .catch((e) => {
            this._handlePayResult(e);
          });
        if (canOpenAlipay) {
          this.comfirmModal && this.comfirmModal.show();
        }
      } else if (infoItem?.appId === 'wxpayapp') {
        wxPay(base64Str)
          .then((data) => {
            this._handlePayResult(data);
          })
          .catch((e) => {
            this._handlePayResult(e);
          });
        this.comfirmModal && this.comfirmModal.show();
      }
    } else if (code === 20001) {
      toast('请勿重复支付');

      this._fetchData();
    } else if (code === 21000) {
      toast(desc);
    } else {
      toast('服务器开小差啦~');
    }
  })
  .catch((e) => {
    toast(e);
  });

}

render() { const { visible, data, leftTime, isLoading } = this.state; return ( <BottomSheet modalVisible={visible} maxHeight={screenHeight * 0.4} title={'确认付款'} onClose={() => { if (leftTime > 0) { this.backAlert && this.backAlert.show(); } else { AppState.removeEventListener('change', (state) => { this._handleAppStateChange(state); }); this._handleBack(); } }}> {!visible ? null : isLoading ? ( ) : ( {leftTime > 0 ? ( ¥ {data?.payMoney} ) : null} {leftTime > 0 ? ( <TimerText ref={(ref) => (this.timerText = ref)} style={styles.timerText} onEndTimeHandle={() => { this._fetchData(); }} /> ) : ( <LNetImage style={styles.outBigImg} resizeMode={'contain'} source={{ uri: getImageUrlForPath('/comment/Ask_EmptyState@3x.png') }} /> 支付超时,请重新下单 )} {leftTime > 0 ? ( {data?.payInfo && data?.payInfo.map((item, index) => { const { appId } = item; const title = appId === 'alipayapp' ? '支付宝' : '微信支付'; return ( {this._renderPayWayRow({ title, index, appId })} ); })} ) : null} )} <DialogContainer ref={(ref) => (this.alertModal = ref)} visible={false} title={'您尚未安装微信或者微信版本过低,建议升级至最新版后重试'} mainBtnTitle={'知道了'} mainAction={() => {}} /> <DialogContainer ref={(ref) => (this.backAlert = ref)} visible={false} title={'是否放弃本次付款?'} mainBtnTitle={'继续支付'} secondaryBtnTitle={'放弃支付'} mainAction={() => {}} secAction={this.onBack} /> ); } }

const styles = StyleSheet.create({ container: { position: 'relative', paddingBottom: bottomSpace + 180, }, rowBack: { alignItems: 'stretch', }, row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', height: 60, }, payWarp: { marginTop: 16, }, priceLarge: { textAlign: 'center', fontSize: 32, color: LColors.C2, lineHeight: 35, }, rowRight: { flexDirection: 'row', alignItems: 'center' }, payName: { marginLeft: 17, fontSize: 18, color: LColors.N1 }, timerText: { marginTop: 5, textAlign: 'center', marginRight: 12, fontSize: 15, color: LColors.N1, }, outBigImg: { width: scaleSize(90), height: scaleSize(112), }, loading: { justifyContent: 'center', alignItems: 'center', height: 255 }, priceSmall: { fontSize: 12, fontWeight: 'bold' }, outTimeText: { fontSize: 15, color: LColors.N15, lineHeight: 21, marginTop: 15, textAlign: 'center', }, outWarp: { alignItems: 'center' }, });


原文地址: https://www.cveoy.top/t/topic/f3DR 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录