import React, { Component } from 'react' import { Checkbox, Flex, List, Radio, Toast, WhiteSpace, WingBlank } from 'antd-mobile' import { browser, getParam, http, is_weixin } from '@/utils' import { HeaderBar } from '@common/index' import VlistBase from '@/common/v-list-base' import './index.scss' import { WithFullSize } from '@/HOCs' import { Link } from "react-router-dom" import app from "@/utils/app" const RadioItem = Radio.RadioItem const Item = Flex.Item function OrderList({courses, toggleSelectedCourse}) { return ( <Flex wrap={'wrap'}> {courses.length && courses.map(course => { const {image_name: img, course_id, coupon_desc, coupon_num} = course const info = ( <div className="info"> <div className="title">{course.course_title}</div> <div className="des"> <div className={'deposit-discount'}> 定金折扣:<span className={'price'}>-¥{course.deduction_amount}</span> </div> { course.coupon_amount != 0 && <div className={'coupon-amount'}> 使用优惠券:<span className={'price'}>-¥{course.coupon_amount}</span> </div> } </div> <div className="prices"> <span className={'sale-price price'}>¥{course.sale_price}</span> <span className={'former-price'}>¥{course.price1}</span> </div> </div> ) return ( <React.Fragment key={course.course_id}> <Item className={'order-item'}> <Flex className="select-bar" justify={'between'}> <Item> <Checkbox defaultChecked onChange={() => { toggleSelectedCourse(course) }}/> </Item> <Item className={'final-payment-hint'}> 待付尾款 </Item> </Flex> <VlistBase img={img} handleClick={() => { }} info={info} /> </Item> <div className="order-prefer"> <List key={course_id}> <List.Item arrow="horizontal" onClick={() => { }} > <Link to={{ pathname: `/coupons`, search: `?id=${course_id}`, state: { from: '/order' } }}> <Flex justify='between'> <span style={{ color: '#333', fontSize: '15px' }} >优惠券</span> <span style={{ fontSize: '14px', color: '#999999' }} > {!coupon_desc ? (coupon_num === 0 ? '无' : `${coupon_num}张可用`) : (coupon_desc)} </span> </Flex> </Link> </List.Item> </List> </div> </React.Fragment> ) })} </Flex> ) } let mockData = [] if (browser.isWeixin) { mockData = [ {value: 1, label: '微信支付', icon: 'iconweixinzhifu'} ] } else { mockData = [ {value: 1, label: '微信支付', icon: 'iconweixinzhifu'}, {value: 0, label: '支付宝', icon: 'iconalipay'}, ] } class FinalDepositOrder extends Component { constructor(props) { super(props) this.state = { pay_amount: 0, payType: 1, stageNumber: 0, orderId: getParam('oid'), categoryList: [], selectedCourses: [], salePrice: '', user_account: '', useBalance: false, info: false, order_id: '', moneyOffRules: [], finalEndTime: '', offset: 0, appliedMoneyOffRule: {} } } onChange = (value) => { this.setState({ payType: value, checkPeriod: false, }) if (value === 2) { this.setState({ huabei: true, }) } } // 确定购买 pay = () => { const {payType, order_id} = this.state if (payType === 0) { this.alipayPay(order_id) } else if (payType === 1) { this.weixinPay(order_id) } } //提交 submit = () => { this.createOrder().then(res => { if (res.data.errno == 200) { this.setState({ order_id: res.data.data.order_id }, () => { if (res.data.data.pay_jump === 1) { this.props.history.push('/purchased') } else { this.pay() } }) } else { Toast.info(res.data.msg) } }) } //创建订单 createOrder = () => { const {selectedCourses, salePrice, useBalance, user_account, appliedMoneyOffRule} = this.state return http.post(`${API["base-api"]}/m/deposit/final/create`, { course_ids: selectedCourses.map(item => item.course_id), cut_amount: appliedMoneyOffRule.cut_amount || 0, pay_amount: salePrice, is_deduction: useBalance ? 1 : 0, deduction_amount: useBalance ? this.getBalanceOffset() : 0, plat_form: 5, source: getParam('source') }) } // 微信支付 weixinPay = (orderId) => { // 微信内部-支付 if (is_weixin()) { window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(window.location.href + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect" } else { // 微信外部-支付 http.get(`${API['base-api']}/pay/wxpay/wap_charge/oid/${orderId}`).then((res) => { if (res.data.errno === 0) { window.location.href = res.data.data.url + "&redirect_url=" + encodeURIComponent(window.location.href + "&weixinpay=1").toLowerCase() } else { Toast.info(res.data.msg, 2) } }) } } // 微信内部支付 isweixinPay = () => { let _this = this let weixin_code = getParam('code') if (weixin_code) { if (getParam('oid') === undefined) { return } else { http.get(`${API['base-api']}/pay/wxpay/pub_charge/oid/${getParam('oid')}/code/${weixin_code}`).then((res) => { if (res.data.errno === 0) { let data = res.data.data function onBridgeReady() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { appId: data.appId, //公众号名称,由商户传入 timeStamp: data.timeStamp, //时间戳,自1970年以来的秒数 nonceStr: data.nonceStr, //随机串 package: data.package, signType: data.signType, //微信签名方式: paySign: data.paySign //微信签名 }, function (res) { if (res.err_msg == "get_brand_wcpay_request:ok") { Toast.info('支付成功', 2) _this.intervalPayStatus = setInterval(function () { http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => { if (res.data.errno === 401) { clearInterval(_this.intervalPayStatus) _this.intervalPayStatus = null _this.props.history.replace(`/expand/callback?order_id=${getParam('oid')}`) } }) }, 1000) } else { alert('支付失败') } } ) } if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false) } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady) document.attachEvent('onWeixinJSBridgeReady', onBridgeReady) } } else { onBridgeReady() } } else { Toast.info(res.data.msg, 2) } }) } } } // 支付完成之后获取状态 payCallback = () => { const _this = this // 支付回调 // 定时器轮训获取订单状态 _this.intervalPayStatus = setInterval(function () { http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => { if (res.data.errno === 401) { clearInterval(_this.intervalPayStatus) _this.intervalPayStatus = null window.location.href = '/expand/callback?order_id=' + getParam('oid') } }) }, 1000) } // 支付宝支付 alipayPay = (orderId) => { http.get(`${API['base-api']}/pay/alipay/wap_charge_new/oid/${orderId}`).then((res) => { if (res.data.errno === 0) { this.payCallback() window.location = res.data.data.url } else { Toast.info(res.data.msg, 2) } }) } componentDidMount() { if (getParam('weixinpay')) { this.payCallback() } if (browser.isWeixin) { this.isweixinPay(getParam('oid')) } http.get(`${API["base-api"]}/m/deposit/final/preorder`) .then(res => { const {data} = res if (data.errno == 200) { this.setState({ categoryList: [...data.data.courses], salePrice: this.getTotalPrice({ courses: [...data.data.courses], moneyOffRules: data.data['full_rule'] }), selectedCourses: [...data.data.courses], user_account: data.data.user_account, moneyOffRules: data.data['full_rule'], finalEndTime: data.data['final_end_time'] }) } else { Toast.info(data.msg) } }) } // 展示余额抵扣规则 showInfo = () => { this.setState((prevState) => ({ info: !prevState.info })) } toggleSelectedCourse = course => { this.setState(prevState => { const {selectedCourses} = prevState let index = prevState.selectedCourses.findIndex(item => item.course_id == course.course_id) if (index == -1) { selectedCourses.push(course) } else { selectedCourses.splice(index, 1) } let totalPrice = this.getTotalPrice(selectedCourses) return {selectedCourses, salePrice: totalPrice, offset: this.getBalanceOffset(totalPrice)} }) } //获取支付价格 getTotalPrice = ( { courses = this.state.selectedCourses, useBalance = this.state.useBalance, moneyOffRules = this.state.moneyOffRules } = {} ) => { let totalPrice = this.getOriginTotalPrice({courses}) totalPrice = this.moneyOff(totalPrice, moneyOffRules) if (useBalance) { totalPrice -= parseFloat(this.state.user_account) } return totalPrice < 0 ? 0 : totalPrice.toFixed(2) } //满减计算 moneyOff = (totalPrice, moneyOffRules = this.state.moneyOffRules) => { let rules = moneyOffRules.sort((a, b) => b.full_amount - a.full_amount) let result = parseFloat(totalPrice) for (let i = 0; i < rules.length; i++) { let rule = rules[i] if (result >= rule.full_amount) { this.setState({ appliedMoneyOffRule: rule }) return result - parseFloat(rule.cut_amount) } } return result } //使用余额 useBalance = () => { this.setState(prevState => { const useBalance = !prevState.useBalance let totalPrice = this.getTotalPrice({useBalance}) return { useBalance, salePrice: totalPrice, offset: this.getBalanceOffset(totalPrice) } }) } getOriginTotalPrice = ({courses = this.state.selectedCourses} = {}) => { return courses.reduce((accu, item) => { return accu + parseFloat(item['sale_price']) }, 0) } getBalanceOffset = () => { let originalTotalPrice = this.getOriginTotalPrice() let currentPrice = this.moneyOff(originalTotalPrice) let offset = parseFloat(this.state.user_account) - parseFloat(currentPrice) offset = offset >= 0 ? currentPrice : this.state.user_account return offset } render() { const { orderId, salePrice, payType, categoryList, user_account, useBalance, info, finalEndTime, offset, appliedMoneyOffRule } = this.state return ( <div className='deposit-pay-order'> <HeaderBar title='课程报名' arrow={true}></HeaderBar> <WhiteSpace size='sm' /> {/*<div className='order-number'> <WingBlank> <Flex justify='between' align='center' style={{height: '44px'}}> <span>订单号</span> <span className='number'>{orderId}</span> </Flex> </WingBlank> </div>*/} <WhiteSpace size='md' /> <div className={'order-list'}> <OrderList courses={categoryList} toggleSelectedCourse={this.toggleSelectedCourse} /> </div> <div className="order-balance"> <List> <Item className="order-prefer-text"> <Flex justify='between'> <Flex align='center'> <span>余额抵扣</span> <span className="order-balanceprice"> (余额: <i className="order-money">{`${user_account}元`}</i> ) </span> <i className="iconfont iconiconfront-22 question-mark" onClick={this.showInfo}></i> </Flex> <Flex> { useBalance ? ( <> <span style={{ color: '#FF2121', fontSize: '15px', marginRight: "6px" }}>{`-¥${offset}`}</span> <i className={`iconfont icondanseshixintubiao-5 balance-used`} onClick={this.useBalance} /> </> ) : ( <i className='circle-icon' onClick={this.useBalance}></i> ) } </Flex> </Flex> </Item> </List> </div> <WhiteSpace size='md'></WhiteSpace> <div className='order-number'> <WingBlank> <Flex justify='between' align='center' style={{height: '44px'}}> <span>支付金额</span> <span className='money'>{`¥${salePrice}`}</span> </Flex> </WingBlank> </div> <WhiteSpace/> { appliedMoneyOffRule.full_amount && <div className="money-off"> <WingBlank> <Flex justify='end' align='center' style={{height: '44px'}}> <span>满{appliedMoneyOffRule.full_amount}减{appliedMoneyOffRule.cut_amount}:</span> <span className='money'>{`-¥${appliedMoneyOffRule.cut_amount}`}</span> </Flex> </WingBlank> </div> } <WhiteSpace size='md'></WhiteSpace> <List renderHeader={() => '支付方式'} className='pay-type-list'> {mockData.map(i => ( <RadioItem thumb={<i className={`iconfont ${i.icon} ${payType === i.value ? 'checked' : ''}`}></i>} key={i.value} checked={payType === i.value} onChange={() => this.onChange(i.value)}> {i.label} </RadioItem> ))} </List> <div className='pay-tip'>{`${finalEndTime}结束支付尾款`}</div> <div className='pay-button' onClick={this.submit}>确认支付</div> { info ? ( <div style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.8)', zIndex: '99' }}> <div style={{ padding: '20px', backgroundColor: '#FFF', width: '300px', height: '170px', margin: '0 auto', position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%, -50%)' }}> <Flex direction='column' justify='between' align='center' style={{height: '100%'}}> <p style={{fontSize: '16px', color: '#333333'}}>余额抵扣说明</p> <p style={{ lineHeight: '20px', fontSize: '13px', color: '#666666' }}>分销课程或者参与七月在线的相关活动,可获得资金奖励。账户资金可直接提现,也可抵扣课程费用。</p> <div onClick={this.showInfo} style={{ width: '260px', height: '30px', lineHeight: '30px', textAlign: 'center', borderRadius: '3px', border: '1px solid #0099FF', color: '#0099FF', fontSize: '15px' }}>知道了 </div> </Flex> </div> </div> ) : null } </div> ) } } export default WithFullSize(FinalDepositOrder)