zoukankan      html  css  js  c++  java
  • Java生鲜电商平台-生鲜电商中售后退款流程整理与架构实现(小程序/APP)

    Java生鲜电商平台-生鲜电商中售后退款流程整理与架构实现(小程序/APP)

    说明:任何一个生鲜电商系统,无论是小程序还是APP都无法避免的会出现退货,退款等售后问题,那么根据我这边的经验,本文分享下,在做售后的系统设计的

    过程中,我们以为如何进行设计,如何进行退款,如何进行审批与操作呢?

    目录

    1. 售后系统的流程设计。

    2. 售后系统的数据库设计。

    3. 售后系统的代码实现。

    4. 售后系统的运营统计。

    5. 售后系统的复盘.

    1. 售后系统的流程设计。

      说明:售后系统的流程设计指的是如何进行售后系统的步骤设计,理论上是存在以下几个步骤的,我先简单的画个图。工具用Visio

             

              

                    我们根据上面画的流程图,我们分析下有以下几个步骤

                   1. 用户通过某一个订单中的具体商品进行申请售后,比如说:买的土豆烂了一半。

                   2. 客服人员根据用户的申请进行审批,审批存在审批通过与审批不通过的情况,通过则打款,不通过则退回,可再次申请。

                   3. 审批通过后,系统记录申请打款的记录表,然后自动打款。出现异常,则走异常监控,人工干预。

                  4. 最后根据日或者周为单位进行整个系统的运营复盘,这样才更加的高效与减少售后问题,这里有个疑问,为什么不用避免售后问题呢?而要采用减少呢?

                       根据我这6年来的生鲜电商的经验,这个售后问题无法避免与消除,不管是精细化做得多么的好的企业,都一定存在这个情况,只是比率比较小而已.

    2. 售后系统的数据库设计。

                   

          说明:根据整个业务的流程与整理,我们发现需要有以下几张表来记录。(Mysql数据库为例)

                    1. 售后记录基础信息表。(aftersales)

                    2. 售后审批日志表 。(aftersales_approve)

                    3.售后问题分类信息表  (aftersales_classify)

                    4. 售后问题分类明细表  (aftersales_classify_item)

                    5.  售后退款金额记录表  (aftersales_refund)

    3. 售后系统的代码实现。

                  说明:根据整个业务场景,我们发现,用户在生鲜电商小程序或者APP上提交售后申请。客服人员进行售后的审批。系统自动打款,运营复盘。

                   这里面有些基础的东西,都是CRUD,我就不贴代码了,我贴一些核心的代码

                    1. 系统自动打款

                         说明:系统去扫描售后退款金额记录表,把需要打款的信息进行提交给微信,用的是定时器来操作。

                         

    @Scheduled(cron = "0 */5 * * * ?")
        public void aftersalesRefundExecute()
        {
            log.info("[AftersalesRefundJob][aftersalesRefundExecute]系统开启任务检查:需要打款的售后列表");
    
            List<AftersalesRefund>  list= this.aftersalesRefundService.getAftersalesRefundList();
    
            if(CollectionUtils.isEmpty(list))
            {
                log.info("未查询到需要打款的售后列表");
                return;
            }
    
            for (AftersalesRefund refund:list)
            {
    
                //获取订单
                String orderSn=aftersalesRefundService.getOrderSnByAftersalesRefund(refund.getAftersalesId());
    
                //获取订单对象
                Order order=this.orderService.getOrderByOrderNumber(orderSn);
    
                try
                {
                    //申请退款
                    WxPayRefundRequest refundInfo = WxPayRefundRequest.newBuilder()
                            .outTradeNo(orderSn)
                            //退款订单号
                            .outRefundNo(refund.getRefundOrderNumber())
                            //金额,单位为:分
                            .totalFee(order.getActualPrice().multiply(BigDecimal.valueOf(100)).intValue())
                            //退款金额,单位为:分
                            .refundFee(refund.getRefundAmount().multiply(BigDecimal.valueOf(100)).intValue())
                            .notifyUrl("https://wx-api.xxx.com/refund/refundNotify")
                            .build();
                    WxPayRefundResult wxPayRefundResult;
                    try
                    {
                        wxPayRefundResult = wxPayService.refund(refundInfo);
                        //判断退款信息是否正确
                        if (REFUND_SUCCESS.equals(wxPayRefundResult.getReturnCode()) && REFUND_SUCCESS.equals(wxPayRefundResult.getResultCode()))
                        {
                            log.info("正在退款中....");
                        }else
                        {
                            log.info("退款失败,请联系管理员...");
                        }
                    } catch (WxPayException e) {
    
                        //组织对象
                        refund.setRefundStatus(3);
                        refund.setRefundRemarks(e.getXmlString());
                        //更新错误信息
                        this.aftersalesRefundService.updateAftersalesRefundException(refund);
                        log.error("微信退款接口错误信息= {}", e);
                    }
                  Thread.sleep(1500);
                }catch (Exception ex)
                {
                    log.error("[AftersalesRefundJob][aftersalesRefundExecute] exception",ex);
                }
            }
        }
    

                         2. 系统自动打款成功后,微信会服务端进行回调来通知。

                              说明:微信服务端回调,我们一般需要做什么几个步骤呢?(注意,在同一个事务里面完成,如果失败,就直接让微信返回FAIL)

                                      1. 验证签名

                                      2. 更新申请记录表状态

                                      3.  增加售后日志记录

                                      4.  更新售后主表状态

    public Object orderRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
            //解析xml的结果
            String xmlResult = null;
            try {
                xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            } catch (IOException e) {
                log.error("[OrderRefundServiceImpl][orderRefund] [xmlResult]exception",e);
                return WxPayNotifyResponse.fail(e.getMessage());
            }
    
            log.info("[OrderRefundServiceImpl][orderRefund] xmlResult 的数据为{}",xmlResult);
            WxPayRefundNotifyResult result = null;
            try
            {
                //解析并验证,返回WxPayRefundNotifyResult对象
                result = wxPayService.parseRefundNotifyResult(xmlResult);
                log.info("微信退款通知xml解析转result结果为{}",result);
            } catch (WxPayException e) {
                log.error("[OrderRefundServiceImpl][orderRefund] [WxPayRefundNotifyResult]exception",e);
                return WxPayNotifyResponse.fail(e.getMessage());
            }
    
            log.info("处理腾讯支付平台的订单支付");
            log.info("微信退款通知--->result:{}",result);
            log.info("微信退款通知解密信息--->result:{}",result.getReqInfo().toString());
    
            //获取退款的状态
            String refundStatus=result.getReqInfo().getRefundStatus();
    
            //比对状态,成功才处理
            if(!WxPayConstants.ResultCode.SUCCESS.equals(refundStatus)){
                log.error(refundStatus);
                throw new WxPayException("微信退款通知状态不为成功!refundStatus:{}"+refundStatus);
            }
    
            //微信退款单号
            String refundId = result.getReqInfo().getRefundId();
    
            //商户退款订单号
            String outRefundNo = result.getReqInfo().getOutRefundNo();
    
            // 分转化成元
            String totalFee = BaseWxPayResult.fenToYuan(result.getReqInfo().getRefundFee());
    
            //获取售后退款对象
            AftersalesRefund aftersalesRefund=this.aftersalesRefundMapper.getAftersalesRefundByRefundOrderNumber(outRefundNo);
    
            log.info("aftersalesRefund对象为:{}",aftersalesRefund);
    
            if (aftersalesRefund == null)
            {
                log.error("AftersalesRefund is not found");
                throw new WxPayException("微信退款售后对象找不到");
            }
    
            //比对退款金额跟申请金额
            if (!totalFee.equals(aftersalesRefund.getRefundAmount().toString())) {
                return WxPayNotifyResponse.fail(aftersalesRefund.getRefundOrderNumber() + " : 支付金额不符合 totalFee=" + totalFee);
            }
    
            //比对状态,如果退款状态,0为初始化申请,1为进行中,2为退款成功,3为退款失败'
            //幂等操作,如果是2表示退款已经处理,则不用处理
            if(aftersalesRefund.getRefundStatus().intValue()==2)
            {
                return WxPayNotifyResponse.success("处理成功!");
            }
    
            ////////////////////////////////3.更新申请记录表状态/////////////////////////////////
            //退款成功
            aftersalesRefund.setRefundStatus(2);
            //微信订单号
            aftersalesRefund.setWeixinOrderNumber(refundId);
            //微信通知时间
            aftersalesRefund.setWeixinNotifyTime(new Date());
            //更新状态
            aftersalesRefundMapper.updateAftersalesRefund(aftersalesRefund);
    
            /////////////////////////////4. 记录时间轴
            AftersalesApprove aftersalesApprove=new AftersalesApprove();
            aftersalesApprove.setAftersalesId(aftersalesRefund.getAftersalesId());
            //'审批的状态,默认为0,0表示初始化创建,待审核,1为审核未通过,2为审核通过,3,退款中,4,退款成功',
            aftersalesApprove.setApproveStatus(4);
            aftersalesApprove.setApproveContent("退款成功");
            aftersalesApprove.setCreateBy("服务器回调处理");
            aftersalesApprove.setCreateTime(new Date());
            aftersalesApproveMapper.insertAftersalesApprove(aftersalesApprove);
    
            ///////////////////////////////5.更新售后状态//////////////////////
            Aftersales aftersales=new Aftersales();
            aftersales.setAftersalesId(aftersalesRefund.getAftersalesId());
            //4表示退款成功
            aftersales.setAftersalesStatus(4);
            aftersalesMapper.updateAftersalesMapperAftersalesStatus(aftersales);
    
            return WxPayNotifyResponse.success("处理成功!");
        }

    5. 售后系统的复盘.

          说明:为什么有售后系统的复盘呢?原因只有一个,就是通过复盘来获取与统计整个运营系统中发现的问题,进行及时的纠正,最终达到提高客户满意度以及整个公司的成本降低,口碑做好,越做越好的目的.

           在此,文章写完了,当然整个售后过程中是有很多的细节需要注意与检查的,本文只是起到一个抛砖引玉的作用,如果有什么疑问,请在下面进行评论与留言,我会一一答复.

  • 相关阅读:
    九度 1363 欢乐斗地主
    九度 1377 缓变序列
    九度 1376 最近零子序列
    转几篇关于linux下AT&T汇编的帖子
    九度 1358 陈博的平均主义
    九度 1394 五连击数组
    HDU 2817 A sequence of numbers
    HDU 1867 A + B for you again
    HDU 1753 大明A+B
    HDU 1715 大菲波数
  • 原文地址:https://www.cnblogs.com/jurendage/p/12880664.html
Copyright © 2011-2022 走看看