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]系统开启任务检查:需要打款的售后列表"); Listlist= 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. 售后系统的复盘.
说明:为什么有售后系统的复盘呢?原因只有一个,就是通过复盘来获取与统计整个运营系统中发现的问题,进行及时的纠正,最终达到提高客户满意度以及整个公司的成本降低,口碑做好,越做越好的目的.
在此,文章写完了,当然整个售后过程中是有很多的细节需要注意与检查的,本文只是起到一个抛砖引玉的作用,如果有什么疑问,请在下面进行评论与留言,我会一一答复.