中景合天部分工作内容摘要

1.提交代码git截图

差一周不到三个月时间提交代码不少于130次,不算合并代码。

 2. 统计相关的代码部分实现

controller的实现

package com.zjht.shoplineserver.controller.bigdata;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zjht.shoplineserver.dao.mapper.SalesDataAnalysisMapper;
import com.zjht.shoplineserver.model.vo.MsgEnum;
import com.zjht.shoplineserver.model.vo.ResultInfo;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@RequestMapping("/sales/analysis")
@RestController
public class SalesDataAnalysisController {
    @Resource
    private SalesDataAnalysisMapper salesDataAnalysisMapper;
    List<String> types = new ArrayList<String>(){
        {
            this.add("官网");
            this.add("公众号");
            this.add("小程序");
        }
    };
    @RequestMapping("/channel")
    public ResultInfo channel(@RequestBody JSONObject args) {

        ResultInfo resultInfo = new ResultInfo();
        try {
            String type = args.getString("type");
            if(StringUtils.isEmpty(type))
                type = "1";
            String beginTm = getBeginTm(type);
            String endTm = LocalDate.now().plusDays(1l).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00";
            List<Map<String, Object>> stats = salesDataAnalysisMapper.channel(beginTm , endTm);
            List<Map<String, Object>> newStats = new ArrayList<>();
            if(stats.size() < types.size()) {

                Map<String, BigDecimal> maps = new HashMap<>();
                for (Map<String, Object> one : stats) {
                    maps.put(one.get("ItemKey").toString(), (BigDecimal) one.get("ItemValue"));
                }
                for (String t : types) {
                    Map<String, Object> newMap = new HashMap<>();
                    newMap.put("ItemKey", t);
                    BigDecimal d = maps.get(t);
                    if (d != null) {
                        newMap.put("ItemValue", d);
                    } else {
                        newMap.put("ItemValue", BigDecimal.ZERO);
                    }
                    newStats.add(newMap);
                }
            } else {
                newStats = stats;
            }
            resultInfo.setData(newStats);
        } catch (Exception e) {
            resultInfo.setCode(MsgEnum.EXISTS_ERROR.getCode());
            resultInfo.setMsg(e.getMessage());
        }

        return resultInfo;
    }
    private String getBeginTm(String type) throws Exception {

        String beginTm = "";

        if(type.equals("1")) {
            beginTm =  LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00";
        } else if(type.equals("2")) {
            beginTm =  LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"))+"-01 00:00:00";
        } else if(type.equals("3")) {
            beginTm =  LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"))+"-01-01 00:00:00";
        } else {
            throw new Exception("type类型参数不对!");
        }
        return beginTm;
    }

    @RequestMapping("/salesType")
    public ResultInfo salesType(@RequestBody JSONObject args) {
        ResultInfo resultInfo = new ResultInfo();
        try {
            String type = args.getString("type");
            if(StringUtils.isEmpty(type))
                type = "1";
            String beginTm = getBeginTm(type);
            String endTm = LocalDate.now().plusDays(1l).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00";
            List<Map<String, Object>> stats = salesDataAnalysisMapper.salesType(beginTm , endTm);
            Map<String, List<Map>> map = stats.stream().collect(Collectors.groupingBy(
                    (Map m) -> (String)m.get("type"))
            );

            List<Object> data = new ArrayList<>();
            Map<String, Object> newMapResult = null;
            List<Map> newList = null;
            for(Map.Entry<String, List<Map>> entry : map.entrySet()) {
                newMapResult = new HashMap<>();
                newList = new ArrayList<>();
                List<Map> oldMap =  entry.getValue();
                Map nm = null;
                for(Map om : oldMap) {
                    nm = new HashMap();
                    nm.put("ItemValue", om.get("ItemValue"));
                    nm.put("ItemKey", om.get("ItemKey"));
                    newList.add(nm);
                }
                newMapResult.put("type", entry.getKey());
                newMapResult.put("value", newList);
                data.add(newMapResult);
                resultInfo.setData(data);
            }

        }catch (Exception e) {
            resultInfo.setCode(MsgEnum.EXISTS_ERROR.getCode());
            resultInfo.setMsg(e.getMessage());
        }
        return resultInfo;
    }

    @RequestMapping("/salesAmountTop10") // 商铺
    public ResultInfo salesAmountTop10(@RequestBody JSONObject args) {
        ResultInfo resultInfo = new ResultInfo();
        try {
            List<Map<String, Object>> stats = this.returnStats(args, 0);
            resultInfo.setData(stats);
        }catch (Exception e) {
            resultInfo.setCode(MsgEnum.EXISTS_ERROR.getCode());
            resultInfo.setMsg(e.getMessage());
        }
        return resultInfo;
    }

    @RequestMapping("/orderAmountTop10")
    public ResultInfo orderAmountTop10(@RequestBody JSONObject args) {
        ResultInfo resultInfo = new ResultInfo();
        try {

            List<Map<String, Object>> stats = this.returnStats(args, 100);
            resultInfo.setData(stats);
        }catch (Exception e) {
            resultInfo.setCode(MsgEnum.EXISTS_ERROR.getCode());
            resultInfo.setMsg(e.getMessage());
        }
        return resultInfo;
    }

    private List<Map<String, Object>> returnStats(JSONObject args, int opt) throws Exception {
        List<Map<String, Object>> stats = null;
        try {
            String type = args.getString("type");
            if(StringUtils.isEmpty(type))
                type = "1";
            String beginTm = "";
            String endTm = "";
            if(type.equals("4")) {
                beginTm = args.getString("startTime") + " 00:00:00";;
                endTm = args.getString("endTime") + " 00:00:00";;
            } else {
                beginTm = getBeginTm(type);
                endTm = LocalDate.now().plusDays(1l).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00";
            }
            if(opt == 0)
                stats = salesDataAnalysisMapper.salesAmountTop10(beginTm , endTm);
            else
                stats = salesDataAnalysisMapper.orderAmountTop10(beginTm , endTm);
        }catch (Exception e) {
            throw new Exception("统计失败,失败原因:"+e);
        }
        return stats;
    }

    @RequestMapping("/processSatisfy")
    public ResultInfo processSatisfy(@RequestBody JSONObject args) {
        ResultInfo resultInfo = new ResultInfo();
        try {
            String type = args.getString("type");
            if(StringUtils.isEmpty(type))
                type = "1";
            String beginTm = getBeginTm(type);
            String endTm = LocalDate.now().plusDays(1l).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00";
            List<Map<String, Object>> stats = salesDataAnalysisMapper.processSatisfy(beginTm, endTm);
            resultInfo.setData(stats);
        }catch (Exception e) {
            resultInfo.setCode(MsgEnum.EXISTS_ERROR.getCode());
            resultInfo.setMsg(e.getMessage());
        }
        return resultInfo;
    }

    private List<String> dics = new ArrayList<String>(){
        {
            this.add("curDayDayCount");
            this.add("lastDayDayCount");
            this.add("curMonthMonthCount");
            this.add("lastMonthMonthCount");
            this.add("curYearYearCount");
            this.add("lastYearYearCount");
        }
    };

    @RequestMapping("/qoqSatisfy")
    public ResultInfo qoqSatisfy() {
        ResultInfo resultInfo = new ResultInfo();
        try {
            Map<String, String> args = new HashMap<>();
            // 当日的开始 结束时间
            String curDtBeginTm =  LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00";
            String curDtEndTm = LocalDate.now().plusDays(1l).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00";
            args.put("curDtBeginTm", curDtBeginTm);
            args.put("curDtEndTm", curDtEndTm);
            // 昨天的开始和结束时间
            String preDtBeginTm = LocalDate.now().minusDays(1l).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00";
            String preDtEndTm = curDtBeginTm;
            args.put("preDtBeginTm", preDtBeginTm);
            args.put("preDtEndTm", preDtEndTm);
            // 当月开始和结束时间
            String curMonthBeginTm =  LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"))+"-01 00:00:00";
            String curMonthEndTm = curDtEndTm;
            args.put("curMonthBeginTm", curMonthBeginTm);
            args.put("curMonthEndTm", curMonthEndTm);
            // 上一个月开始和结束时间
            String preMonthBeginTm = LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM"))+"-01 00:00:00";
            String preMonthEndTm = curMonthBeginTm;
            args.put("preMonthBeginTm", preMonthBeginTm);
            args.put("preMonthEndTm", preMonthEndTm);
            // 当年的开始和结束时间
            String curYearBeginTm = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"))+"-01-01 00:00:00";
            String curYearEndTm = curDtEndTm;
            args.put("curYearBeginTm", curYearBeginTm);
            args.put("curYearEndTm", curYearEndTm);
            // 上一年的开始和结束时间
            String preYearBeginTm = LocalDate.now().minusYears(1l).format(DateTimeFormatter.ofPattern("yyyy"))+"-01-01 00:00:00";
            String preYearEndTm = curYearBeginTm;
            args.put("preYearBeginTm", preYearBeginTm);
            args.put("preYearEndTm", preYearEndTm);

            List<Integer> stats = salesDataAnalysisMapper.qoqSatisfy(args);
            Map<String, Object> dataMap = new HashMap<>();
            int i = 0;
            for(Integer x : stats) {
                dataMap.put(dics.get(i++), x);
            }

            resultInfo.setData(new ArrayList<Map>(){{this.add(dataMap);}});
        }catch (Exception e) {
            resultInfo.setCode(MsgEnum.EXISTS_ERROR.getCode());
            resultInfo.setMsg(e.getMessage());
        }
        return resultInfo;
    }

}

 mapper实现

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zjht.shoplineserver.dao.mapper.SalesDataAnalysisMapper">
    <select id="channel"  resultType="java.util.HashMap">
          SELECT sum(amount)  as ItemValue ,
          CASE platform
            WHEN 3 THEN '官网'
            WHEN 4 THEN '公众号'
            ELSE '小程序' END as ItemKey
          FROM s_online_order WHERE 1=1
          and completedate BETWEEN #{beginTm} and #{endTm}
          and `status` = 9
          GROUP BY platform
    </select>

    <select id="salesType"  resultType="java.util.HashMap">
        SELECT sum(amount) as ItemValue,
                   CASE platform
            WHEN 3 THEN '官网'
            WHEN 4 THEN '公众号'
            ELSE '小程序' END as ItemKey,
                   CASE type
                  WHEN 1 THEN '门票'
            WHEN 2 THEN '美食'
            WHEN 3 THEN '酒店'
                  WHEN 4 THEN '特产'
            ELSE '跟团游' END as type

                   FROM s_online_order WHERE 1=1
and completedate BETWEEN #{beginTm} and #{endTm}
and `status` = 9
GROUP BY type,platform

    </select>

    <select id="salesAmountTop10" resultType="java.util.HashMap">
        SELECT
        sum(amount) as ItemValue,
        shopname as ItemKey
        FROM s_online_order
        WHERE 1=1
         and completedate BETWEEN  #{beginTm} and #{endTm}
         and `status`= 9
        GROUP BY shopname order by ItemValue desc limit 10
    </select>

    <select id="orderAmountTop10" resultType="java.util.HashMap">
        SELECT
        sum(quantity) as ItemValue,
        shopname as ItemKey
        FROM s_online_order
        WHERE 1=1
         and completedate BETWEEN  #{beginTm} and #{endTm}
         and `status`= 9
        GROUP BY shopname order by ItemValue desc limit 10
    </select>

    <select id="processSatisfy" resultType="java.util.HashMap">
        SELECT count(*) as counts, '满意' as ItemKey FROM s_member_commercial_suggest WHERE `status` &lt; 4
        and createdate BETWEEN  #{beginTm} and #{endTm}
        union
        SELECT count(*) as counts, '不满意' as ItemKey FROM s_member_commercial_suggest WHERE `status` &gt; 3
        and createdate BETWEEN  #{beginTm} and #{endTm}
    </select>
    <select id="qoqSatisfy" resultType="java.lang.Integer">
        SELECT count(*) as count FROM s_member_commercial_suggest
        WHERE createdate BETWEEN #{curDtBeginTm} and #{curDtEndTm}
        union all
        SELECT count(*) as count FROM s_member_commercial_suggest
        WHERE createdate BETWEEN #{preDtBeginTm} and #{preDtEndTm}
        union all
        SELECT count(*) as count FROM s_member_commercial_suggest
        WHERE createdate BETWEEN #{curMonthBeginTm} and #{curMonthEndTm}
        union all
        SELECT count(*) FROM s_member_commercial_suggest
        WHERE createdate BETWEEN #{preMonthBeginTm} and #{preMonthEndTm}
        union all
        SELECT count(*) FROM s_member_commercial_suggest
        WHERE createdate BETWEEN #{curYearBeginTm} and #{curYearEndTm}
        union all
        SELECT count(*) FROM s_member_commercial_suggest
        WHERE createdate BETWEEN #{preYearBeginTm} and #{preYearEndTm}
    </select>

</mapper>

 3.排序代码实现

代码样例 做成模板,其他调用处模板化调用

package com.zjht.currentserver.model.zyb;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.persistence.Table;
import java.util.*;
import java.util.stream.Collectors;

/***
 * 重排序的工具类
 */
@Component
public class ReOrderUtils {
    Logger log = LoggerFactory.getLogger(ReOrderUtils.class);
    @Autowired
    JdbcTemplate jdbcTemplate;

    private static final String COMMON_ID_SORT_QUERY_TEMPLATE = "select id, #{sortColumn} from  #{tabName} where #{argsSql} order by #{sortColumn}" ;
    private static final String COMMON_ID_SORT_QUERY_TEMPLATE_NO_WHERE = "select id, #{sortColumn} from  #{tabName} order by #{sortColumn}" ;
    private static final String COMMON_ID_SORT_UPDATE_TEMPLATE = "update #{tabName} set #{sortColumn} = #{newSort} where id = #{id}";

    /***
     * 对clazz类型的参数字段相关的数据重新编号
     * @param clazz
     * @param argsColumns
     * @param argsVals
     * @param sortColumn
     * @throws Exception
     */
    public void realignOrder(Class clazz, String[] argsColumns, Object[] argsVals, String sortColumn) throws Exception{
        this.realignOrder(clazz, argsColumns, argsVals, sortColumn, new HashSet<>());
    }

    public void realignOrder(Class clazz, String sortColumn) throws Exception{
        this.realignOrder(clazz, null, new Object[]{}, sortColumn, new HashSet<>());
    }

    public void realignOrder(Class clazz,  String sortColumn, Set<Integer> deleteIds) throws Exception{
        this.realignOrder(clazz, null, new Object[]{}, sortColumn, deleteIds);
    }
    /**
     *
     * @param clazz
     * @param argsColumns
     * @param argsVals
     * @param sortColumn
     * @param deleteIds
     * @throws Exception
     */
    public void realignOrder(Class clazz, String[] argsColumns, Object[] argsVals, String sortColumn, Set<Integer> deleteIds) throws Exception{
        try {
            Table table = (Table)clazz.getAnnotation(Table.class);
            String tabName = table.name();
            String argsSql = "";
            if(argsColumns != null)
                argsSql = this.whereSql(argsColumns, argsVals);
            String sql = ReOrderUtils.COMMON_ID_SORT_QUERY_TEMPLATE
                    .replace("#{tabName}", tabName)
                    .replace("#{argsSql}", argsSql)
                    .replace("#{sortColumn}", sortColumn);
            if(argsColumns == null) {
                sql = ReOrderUtils.COMMON_ID_SORT_QUERY_TEMPLATE_NO_WHERE
                        .replace("#{tabName}", tabName)
                        .replace("#{sortColumn}", sortColumn);
            }
            Map<Integer, Integer> origOnes = jdbcTemplate.queryForList(sql, argsVals).stream().collect(Collectors.toMap(s->(Integer)s.get("id"), s -> (Integer)s.get(sortColumn)));
            // 原来的排序
            Map<Integer, Integer> originalOrderOnes = origOnes.entrySet().stream()
                    .sorted(Map.Entry.comparingByValue())
                    .collect(
                            Collectors.toMap(
                                    Map.Entry::getKey,
                                    Map.Entry::getValue,
                                    (oldVal, newVal) -> oldVal,
                                    LinkedHashMap::new
                            )
                    );

            this.executeUpdateSortNo(origOnes, originalOrderOnes, deleteIds, tabName, sortColumn);

        } catch (Exception e) {
            log.info("重排序号失败,原因:{}", e);
            throw e;
        }
    }
    private void executeUpdateSortNo(Map<Integer, Integer> origOnes, Map<Integer, Integer> originalOrderOnes, Set<Integer> deleteIds, String tabName, String sortColumn) {
        String sql = "";
        int newNo = 1;
        int newSort = 0;    // 新顺序号
        int oldSort = 0;    // 老顺序号
        for (Map.Entry<Integer, Integer> entry : originalOrderOnes.entrySet()) {
            if(deleteIds.contains(entry.getKey())) continue;
            newSort = newNo++;
            oldSort = origOnes.get(entry.getKey());
            if (newSort == oldSort) continue;
            sql = COMMON_ID_SORT_UPDATE_TEMPLATE
                    .replace("#{tabName}", tabName)
                    .replace("#{sortColumn}", sortColumn)
                    .replace("#{newSort}", newSort+"")
                    .replace("#{id}", entry.getKey()+"");
            jdbcTemplate.execute(sql);
        }
    }

    public void realignOrder(Class clazz, String argsSql, String sortColumn, Set<Integer> deleteIds) throws Exception{
        try {
            Table table = (Table)clazz.getAnnotation(Table.class);
            String tabName = table.name();

            String sql = ReOrderUtils.COMMON_ID_SORT_QUERY_TEMPLATE
                    .replace("#{tabName}", tabName)
                    .replace("#{argsSql}", argsSql)
                    .replace("#{sortColumn}", sortColumn);
            Object[] args = new Object[]{};
            Map<Integer, Integer> origOnes = jdbcTemplate.queryForList(sql, args).stream().collect(Collectors.toMap(s->(Integer)s.get("id"), s -> (Integer)s.get(sortColumn)));
            // 原来的排序
            Map<Integer, Integer> originalOrderOnes = origOnes.entrySet().stream()
                    .sorted(Map.Entry.comparingByValue())
                    .collect(
                            Collectors.toMap(
                                    Map.Entry::getKey,
                                    Map.Entry::getValue,
                                    (oldVal, newVal) -> oldVal,
                                    LinkedHashMap::new
                            )
                    );

            this.executeUpdateSortNo(origOnes, originalOrderOnes, deleteIds, tabName, sortColumn);
        } catch (Exception e) {
            log.info("重排序号失败,原因:{}", e);
            throw e;
        }
    }

    /**
     * 前后的记录要更新新的顺序编号
     * @param sqlTemplate   sql 模板
     * @param id             主键
     * @param newSort       新的顺序号
     * @param oldSort       旧的顺序号
     * @param type          类型
     * @param up            是否向上
     * @throws Exception
     */
    public void changeUpDownOrder(String sqlTemplate,int id, int newSort, int oldSort, String type, boolean up) throws Exception{
        this.changeUpDownOrder(sqlTemplate, id, newSort, oldSort, type, up, new HashMap<>());
    }

    public void changeUpDownOrder(String sqlTemplate,int id, int newSort, int oldSort,  boolean up) throws Exception{
        this.changeUpDownOrder(sqlTemplate, id, newSort, oldSort, "", up, new HashMap<>());
    }
    /**
     *
     * @param sqlTemplate   sql 模板
     * @param id             主键
     * @param newSort       新的顺序号
     * @param oldSort       旧的顺序号
     * @param type          类型
     * @param up            是否向上
     * @param exts          扩展的判断字段及值
     * @throws Exception
     */
    public void changeUpDownOrder(String sqlTemplate,int id, int newSort, int oldSort, String type, boolean up, Map<String,String> exts) throws Exception{
        String updateSql = sqlTemplate.replace("#{newSort}", newSort+"")
                .replace("#{oldSort}", oldSort+"")
                .replace("#{type}", type);
        for(Map.Entry<String, String> entry : exts.entrySet()) {
            updateSql = updateSql.replace(entry.getKey(), entry.getValue());
        }
        String upStr = up? "上":"下";
        try {
            jdbcTemplate.execute(updateSql);
        }catch (Exception e) {
            log.info("id为{}的{}一条数据的编号从{}变到{}失败!", id,upStr, oldSort, newSort);
            throw new Exception("id为"+id+"的" + upStr + "一条数据的编号从"+oldSort+"变到"+newSort+"失败!");
        }
    }

    /***
     * 拼接where 子句
     * @param argsColumns   参数字段数组
     * @param argsVals      参数字段对应值数组
     * @return
     */
    private String whereSql(String[] argsColumns,Object[] argsVals){
        String sqlSnippet = "";
        int i = 0;
        int length = argsColumns.length;
        for(String argsColumn : argsColumns) {
            if(argsVals[i] == null) {
                i++;
                continue;
                //sqlSnippet += argsColumn + " is null ";
            } else {
                sqlSnippet += argsColumn + "=? ";
            }
            if(i++ < length-1){
                sqlSnippet += " and ";
            }

        }
        return sqlSnippet;
    }

}

上下移操作的函数调用

@Autowired
ReOrderUtils reOrderUtils;

@Autowired
JdbcTemplate jdbcTemplate;
@Transactional(rollbackFor = Exception.class)
@Override
public ResultInfo upordownmoveindex(int id, String type,String sceniccategoryid) throws Exception{
    reOrderUtils.realignOrder(SResourceScenic.class, "sortindex");
    // 当前编号的数据
    SResourceScenic curNeedChanged = null;
    Optional<SResourceScenic> byId = scenicDao.findById(id);
    if (byId.isPresent()) {
        curNeedChanged = byId.get();
    } else {
        logger.info("未获取id为{}的数据!", id);
        throw  new Exception("未获取id为"+id+"的数据!");
    }
    Map<String, Object> map = new HashMap<>();
    int currNeedSort  = curNeedChanged.getSortindex();
    if (type.equals("up")) {

        if(currNeedSort > 1) {
            int nowPrevSort = currNeedSort - 1;
            reOrderUtils.changeUpDownOrder(ScenicDao.UPDATE_SORT_SQL,id, currNeedSort, nowPrevSort, type.equals("up"));
            // 当前节点上移一个编号
            curNeedChanged.setSortindex(nowPrevSort);
        } else {
            logger.info("id为{}的数据已经是置顶数据!", id);
        }

    } else if (type.equals("down")) {
        int maxNo = jdbcTemplate.queryForObject(ScenicDao.COUNT_SQL, Integer.class);

        if(currNeedSort < maxNo) {
            int nowNextSort = currNeedSort + 1;
            reOrderUtils.changeUpDownOrder(ScenicDao.UPDATE_SORT_SQL,id, currNeedSort, nowNextSort, type.equals("up"));
            // 当前节点下移一个编号
            curNeedChanged.setSortindex(nowNextSort);
        } else {
            logger.info("id为{}的数据已经是最后一个序号的数据!", id);
        }

    } else if (type.equals("stick")) {

        if(currNeedSort > 1) {
            scenicDao.findAllBySortIndexAndType(curNeedChanged.getSortindex()).stream()
                    .filter(Objects::nonNull)
                    .forEach(o-> o.setSortindex(o.getSortindex() + 1));
            // 当前节点置顶
            curNeedChanged.setSortindex(1);
        } else {
            logger.info("id为{}的数据已经是置顶数据!", id);
        }
    }
    return new ResultInfo(ServerMsgEnum.SUCCESS.getServerCode(), ServerMsgEnum.SUCCESS.getServerMsg(), map);
}

删除操作

public void deleteByIds(String ids,  String sceniccategoryid ) throws Exception{
    if( StringUtils.isEmpty( ids)) {
        logger.info("删除的主键不能为空!");
        throw new Exception("删除的主键不能为空!");
    }

    /*if(StringUtils.isEmpty(sceniccategoryid)) {
        logger.info("景区景点的类型不能为空!");
        throw new Exception("景区景点的类型不能为空!");
    }*/
    String[] idStr = ids.split(",");
    Arrays.stream(idStr).filter(StringUtils::isNotEmpty).map(Integer::valueOf).forEach(o->scenicDao.deleteById(o));
    Set<Integer> deleteIds = Arrays.stream(idStr).filter(StringUtils::isNotEmpty).map(Integer::valueOf).collect(Collectors.toSet());
    // 删除后进行该类型的重新排序
    reOrderUtils.realignOrder(SResourceScenic.class, "sortindex", deleteIds);
}

4.支付代码

封装调用支付网关的接口

package com.zjht.currentserver.model.zyb;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zjht.currentserver.model.po.YNCredit.BaseInputVo;
import com.zjht.currentserver.model.po.YNCredit.Constants;
import com.zjht.currentserver.model.zyb.ynrcpay.YNCreditSignUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Component
public class HttpUtils {
    private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
    @Resource
    RestTemplate restTemplate;

    /***
     *
     * @param inputVo
     * @return
     * @throws Exception
     */
    public String postYNCreditGateWay(BaseInputVo inputVo) throws Exception{
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("request", inputVo);

        /***开始设置头信息*/
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        // 设置证书
        headers.add("ynrcc-cert",Constants.gzh_ynrcc_cert);
        // 设置签名
        // 签名串
        String signTxt = YNCreditSignUtils.sign(Constants.My_priKey, JSON.toJSONString(requestBody));
        logger.info("请求签名串:{}",signTxt);
        headers.add("ynrcc-sign",signTxt);

        restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));

        HttpEntity<String> formEntity = new HttpEntity<String>(JSON.toJSONString(requestBody), headers);
        /***结束设置头信息*/

        /**开始调用微信小程序支付接口**/
        logger.info("云南农信小程序公众号支付网关地址{}", Constants.Yunnan_Rural_Credit_url_with_sign);
        String payResult = null;
        HttpHeaders responseHeaders = null;
        try {
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(Constants.Yunnan_Rural_Credit_url_with_sign, formEntity, String.class);
            responseHeaders = responseEntity.getHeaders();
            payResult = responseEntity.getBody();
        }catch (Exception e) {
            logger.error("调用云南农信支付网关地址{}失败,原因{}",Constants.Yunnan_Rural_Credit_url_with_sign, e);
        }
        /**结束调用微信小程序支付接口**/
        if(responseHeaders == null) {
            logger.error("调用云南农信支付网关地址{}失败,响应报文头不能为空!",Constants.Yunnan_Rural_Credit_url_with_sign);
            throw new Exception("调用云南农信支付网关地址"+ Constants.Yunnan_Rural_Credit_url_with_sign+"失败,响应报文头不能为空!");
        }
        String responseSign = responseHeaders.getFirst("ynrcc-sign");
        // 验签测试
        if(Constants.LOCAL_CHECK_TEST) {
            char s = responseSign.charAt(0);
            char replace = '0';
            if(s == '0') {
                replace = '1';
            }
            String last = responseSign.substring(1);
            responseSign =  replace + last;
        }
        if(StringUtils.isEmpty(responseSign)) {
            logger.error("调用云南农信支付网关地址{}失败,响应报文头签名不能为空!",Constants.Yunnan_Rural_Credit_url_with_sign);
            throw new Exception("调用云南农信支付网关地址"+ Constants.Yunnan_Rural_Credit_url_with_sign+"失败,响应报文头签名不能为空!");
        }
        boolean checkResponse = YNCreditSignUtils.verifySign(Constants.Yunnan_Rural_Credit_pubKey, payResult, responseSign);
        if(!checkResponse) {
            logger.error("调用云南农信支付网关地址{}失败,响应报文验签失败!",Constants.Yunnan_Rural_Credit_url_with_sign);
            throw new Exception("调用云南农信支付网关地址"+ Constants.Yunnan_Rural_Credit_url_with_sign+"失败,响应报文验签失败!");
        }

        /**开始解析微信小程序支付接口报文**/
        Throwable t = null;
        if(StringUtils.isEmpty(payResult)) {
            logger.error("调用云南农信支付网关响应报文不能为空!");
            throw new Exception("调用云南农信支付网关响应报文不能为空!");
        }
        JSONObject jsonObject = null;
        try {
            jsonObject = JSONObject.parseObject(payResult);
        }catch (Exception e) {
            t = e;
        }

        if(jsonObject == null) {
            logger.error("响应报文反序列化失败!原因:{}", t);
            throw new Exception("响应报文反序列化失败!原因"+t);
        }

        String resText = jsonObject.getString("response");
        if(StringUtils.isEmpty(resText)) {
            logger.error("报文信息有误,没有一级response节点信息");
            throw new Exception("报文信息有误,没有一级response节点信息");
        }

        return resText;
    }

}

 某行微信预付款的代码实现

package com.zjht.payserver.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.zjht.currentserver.model.po.YNCredit.*;
import com.zjht.currentserver.model.zyb.HttpUtils;
import com.zjht.currentserver.model.zyb.StringUtil;
import com.zjht.currentserver.model.zyb.ynrcpay.SeqNoGenerator;
import com.zjht.currentserver.model.zyb.ynrcpay.YNCreditSignUtils;
import com.zjht.payserver.feign.FeignOrderService;
import com.zjht.payserver.mapper.PayInfoMapper;
import com.zjht.payserver.service.YNCreditPayService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class YNCreditPayServiceImpl implements YNCreditPayService {
    private Logger logger = LoggerFactory.getLogger(YNCreditPayServiceImpl.class);
    @Resource
    RestTemplate restTemplate;
    @Resource
    FeignOrderService feignOrderService;
    @Resource
    HttpUtils httpUtils;

    @Autowired
    private ValueOperations<String,Object> valueOperations;

    @Override
    public String wxPay(JSONObject json, String pConf) throws Exception{
        // 参数校验
        if(StringUtils.isEmpty(pConf)) {
            throw new Exception("支付配置信息不能为空!");
        }
        JSONObject wxconf = JSONObject.parseObject(pConf);
        String notifyUrl = wxconf.getString("notify_url");      // 回调地址
        String mchId = wxconf.getString("mch_id");              // 商户号
        String appId = wxconf.getString("appid");               //"wx6be77239f2397ff4";//
        String openid = json.getString("openid");               // openid
        if(StringUtils.isEmpty(openid))
            throw new Exception("openid不能为空!");
        String tradeNo = json.getString("out_trade_no");
        if(StringUtils.isEmpty(tradeNo)) {
            throw new Exception("tradeNo不能为空!");
        }
        // 预付单再缓存中则 从缓存返回
        Object preOrderInfo = valueOperations.get(tradeNo);
        if(preOrderInfo!= null){
            return preOrderInfo.toString();
        }

        //存入attach信息
        String attach = wxconf.getString("attach");
        if(StringUtils.isNotBlank(attach)){
            valueOperations.set("yn_attach_"+tradeNo,attach,1, TimeUnit.DAYS);
        }

        // 查询订单数量
        String  totalNum = json.getString("totalNum");
       if(StringUtils.isEmpty(totalNum)) {
            totalNum = "1";
        }

        String totalAmt = json.getString("total_fee");
        if(StringUtils.isEmpty(totalAmt) ) {
            throw new Exception("交易金额不能为空!");
        }

        // 组装请求报文
        String orderDesc = json.getString("body");
        PayInputVo payInputVo =PayInputVo.builder()
                .tranCode(PayInputVo.TRANCODE)
                .merId(Constants.gzh_merId)                       // 商户id
                .temId(Constants.gzh_temId)                  // 终端id
                .seqNo(SeqNoGenerator.generate())
                .tradeNo(tradeNo)
                .txnTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))                     // 取当前时间
                .totalNum(totalNum)
                .totalAmt(totalAmt)                 // 交易金额
                .orderDesc(orderDesc)
                .subOpenId(openid)
                .subAppId(appId)
                .notifyUrl(notifyUrl)               // 我们定义写死的
                .build();
        String payResult = httpUtils.postYNCreditGateWay(payInputVo);


        String result = this.parseResponseExeResult(payResult, json, pConf);
        if(StringUtils.isEmpty(result)) {
            logger.error("返回解析的三级微信支付信息错误!");
            throw new Exception("返回解析的三级微信支付信息错误!");
        }

        return result;
    }

    @Override
    public String queryOrder(JSONObject json, String pConf) throws Exception {
        // 参数校验
        if(StringUtils.isEmpty(pConf)) {
            throw new Exception("支付配置信息不能为空!");
        }
        String tradeNo = json.getString("out_trade_no");
        if(StringUtils.isEmpty(tradeNo)) {
            throw new Exception("tradeNo不能为空!");
        }
        // 组装请求报文
        QueryOrderInputVo payInputVo =QueryOrderInputVo.builder()
                .merId(Constants.gzh_merId)                       // 商户id
                .temId(Constants.gzh_temId)                  // 终端id
                .seqNo(SeqNoGenerator.generate())
                // 商品信息
                .tradeNo(tradeNo)
                .txnTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))                     // 取当前时间
                .build();
        String resText = httpUtils.postYNCreditGateWay(payInputVo);
        JSONObject jsonResult = JSON.parseObject(resText);
        if(jsonResult == null) {
            logger.error("返回数据二级json序列化对象不能为空!");
            throw new Exception("返回数据二级json序列化对象不能为空!");
        }

        String state = jsonResult.getString("state");
        String code = jsonResult.getString("code");
        String returnTradeNo = jsonResult.getString("tradeNo");
        if(StringUtils.isEmpty(state) || StringUtils.isEmpty("code") || !returnTradeNo.equals(tradeNo)) {
            logger.error("返回解析对象参数state、code、tradeNo错误!");
            throw new Exception("返回解析对象参数state、code、tradeNo错误!");
        }
        String result = "FAIL";
        if( code.equals("000000") && returnTradeNo.equals(tradeNo)) {
            result = "SUCCESS";
        }
        /**结束解析微信小程序支付接口报文**/
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String closeOrder(JSONObject json, String pConf) throws Exception {

        // 查询订单状态,如果未支付状态 则关闭,否则不予处理
        // 参数校验
        if(StringUtils.isEmpty(pConf)) {
            throw new Exception("支付配置信息不能为空!");
        }
        JSONObject wxconf = JSONObject.parseObject(pConf);
        String tradeNo = json.getString("out_trade_no");
        if(StringUtils.isEmpty(tradeNo)) {
            throw new Exception("tradeNo不能为空!");
        }

        String totalAmt = json.getString("total_fee");
        if(StringUtils.isEmpty(totalAmt) ) {
            throw new Exception("交易金额不能为空!");
        }

        CloseOrderInputVo payInputVo =CloseOrderInputVo.builder()
                .merId(Constants.gzh_merId)                       // 商户id
                .temId(Constants.gzh_temId)                  // 终端id
                .seqNo(SeqNoGenerator.generate())
                .tradeNo(tradeNo+"01")
                .originTradeNo(tradeNo)
                .txnTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))                     // 取当前时间
                .totalAmt(totalAmt)                 // 交易金额
                .build();
        String processResult = httpUtils.postYNCreditGateWay(payInputVo);


        JSONObject result = JSONObject.parseObject(processResult);

        if(result == null) {
            logger.error("response节点信息反序列化对象不能为空!");
            throw new Exception("response节点信息反序列化对象不能为空!");
        }
        String code = result .getString("code");
        String state = result.getString("state");
        if(StringUtils.isEmpty(code) || StringUtils.isEmpty(state)) {
            logger.error("response节点信息反序列化对象code 或 state不能为空!");
            throw new Exception("response节点信息反序列化对象code 或 state不能为空!");
        }
        String returnResult = "FAIL";
        if(code .equals("000000") && state.equals("0")) {
            returnResult = "SUCCESS";
            valueOperations.getOperations().delete(tradeNo);
        }


        return returnResult;
    }

//    @Resource
//    MQSender mqSender;
    /***
     *
     * @param resText
     * @return
     * @throws Exception
     */
    private String parseResponseExeResult(String resText, JSONObject originalArgs , String pConf) throws Exception {

        PayOutputVo payOutputVo = null;
        Throwable t = null;
        String result = "";
        logger.info("响应报文response节点二级字符串内容{}", resText);
        try {
            payOutputVo = JSON.parseObject(resText, PayOutputVo.class);
        } catch (Exception e) {
            t = e;
        }
        if(payOutputVo == null) {
            logger.error("响应报文response节点二级字符串反序列化失败!原因:{}", t);
            return null;
        }
        String state = payOutputVo.getState();
        String code = payOutputVo.getCode();
        if(StringUtils.isEmpty(state)) {
            logger.info("响应报文二级状态信息有误!");
            return null;
        }
        if(StringUtils.isEmpty(code)) {
            logger.info("响应报文二级订单执行成功失败码信息有误!");
            return null;
        }

        Map<String, String> payInfos =  payOutputVo.getWxPayData();
        if(CollectionUtils.isEmpty(payInfos)) {
            logger.info("响应报文三级微信信息不能为空!");
            return null;
        }
        try {
            JSONObject request = new JSONObject();
            request.put("ordertradelogsn", payOutputVo.getWxPayData().get("tradeNo"));
            request.put("orderno", payOutputVo.getWxPayData().get("orderId"));
            feignOrderService.updateTransIdByOrderno(request);
        }catch (Exception e) {
            //logger.error("跨服务更新order表失败,原因:", e);
        }

        // 返回微信支付需要的签名内容
        Map appMap = new HashMap();
        appMap.put("appId", payInfos.get("appId")); //
        appMap.put("timeStamp", payInfos.get("timeStamp"));
        appMap.put("nonceStr", payInfos.get("nonceStr"));
        appMap.put("package", payInfos.get("package"));
        appMap.put("signType", payInfos.get("signType"));
        appMap.put("sign", payInfos.get("paySign"));
        logger.info("签名内容log-----" + JSONObject.toJSONString(appMap));
        // 待支付放在缓存中 从缓存中删除
        valueOperations.set(payOutputVo.getTradeNo(), JSONObject.toJSONString(appMap), 2l, TimeUnit.HOURS);
        // 用延迟队列处理延迟未支付的订单
        //mqSender.sendLazy(originalArgs.toJSONString());


        return JSONObject.toJSONString(appMap);
    }


}

退款接口 

package com.zjht.shoplineserver.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zjht.currentserver.model.ResultInfo;
import com.zjht.currentserver.model.po.SOnlineOrder;
import com.zjht.currentserver.model.po.SOnlineOrderLog;
import com.zjht.currentserver.model.po.SOnlineRefund;
import com.zjht.currentserver.model.po.YNCredit.Constants;
import com.zjht.currentserver.model.po.YNCredit.PayInputVo;
import com.zjht.currentserver.model.po.YNCredit.RefundInputVo;
import com.zjht.currentserver.model.po.YNCredit.RefundOutputVo;
import com.zjht.currentserver.model.zyb.ynrcpay.SeqNoGenerator;
import com.zjht.currentserver.model.zyb.ynrcpay.YNCreditSignUtils;
import com.zjht.shoplineserver.dao.SOnlineOrderLogDao;
import com.zjht.shoplineserver.dao.order.OrderDao;
import com.zjht.shoplineserver.dao.order.SOnlineOrderDao;
import com.zjht.shoplineserver.dao.order.SOnlineRefundsDao;
import com.zjht.shoplineserver.model.enums.OrderServerStatus;
import com.zjht.shoplineserver.model.enums.OrderTechanStatus;
import com.zjht.shoplineserver.model.enums.RefundTechanStatus;
import com.zjht.shoplineserver.service.order.SOnlineOrderService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
// 农行退款接口
@Component
public class YNCreditRefundUtil {
    private static final Logger logger = LoggerFactory.getLogger(YNCreditRefundUtil.class);
    @Resource
    com.zjht.currentserver.model.zyb.HttpUtils httpUtils;

    public String postRefund(JSONObject json, String pConf) throws Exception{

        // 参数校验
        if(StringUtils.isEmpty(pConf)) {
            throw new Exception("支付配置信息不能为空!");
        }
        JSONObject wxconf = JSONObject.parseObject(pConf);
        String notifyUrl = wxconf.getString("notify_url");      // 回调地址
        String mchId = wxconf.getString("mch_id");              // 商户号
        String tradeNo = json.getString("out_trade_no");
        if(StringUtils.isEmpty(tradeNo)) {
            throw new Exception("tradeNo不能为空!");
        }
        // 查询订单数量
        String  totalNum = json.getString("totalNum");
        if(StringUtils.isEmpty(totalNum)) {
            totalNum = "1";
        }

        String totalAmt = json.getString("total_fee");
        if(StringUtils.isEmpty(totalAmt) ) {
            throw new Exception("交易金额不能为空!");
        }

        RefundInputVo refundInputVo =RefundInputVo.builder()
                 .merId(mchId)
                .temId(Constants.gzh_temId)
                .seqNo(SeqNoGenerator.generate())
                .tradeNo(tradeNo+"00")
                .originTradeNo(tradeNo)
                .txnTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
                .totalNum(totalNum)
                .totalAmt(totalAmt)
                .notifyUrl(notifyUrl)
                .build();
        String resText = httpUtils.postYNCreditGateWay(refundInputVo);
        RefundOutputVo refundOutputVo = null;
        try {
            refundOutputVo = JSON.parseObject(resText, RefundOutputVo.class);
        }catch (Exception e) {
            logger.error("农信行退款响应报文反序列化失败,原因:", e);
            throw new Exception("农信行退款响应报文反序列化失败,原因:"+e);
        }
        if(refundOutputVo == null) {
            logger.error("农信行退款响应报文反序列化对象为空,执行退款失败!");
            throw new Exception("农信行退款响应报文反序列化对象为空,执行退款失败!");
        }
        if( StringUtils.isEmpty(refundOutputVo.getState())) {
            logger.error("农信行退款失败,退款结果状态不能为空!");
            throw new Exception("农信行退款失败,退款结果状态不能为空!");
        }
        String resultStr = "SUCCESS";
        if(refundOutputVo.getState().equals("1")) {
            resultStr =  "FAIL";
        }
        /**结束解析微信小程序支付接口报文**/
        return resultStr;
    }
}

退款流程调用处的接口调用代码

if(sOnlineOrder.getPaymethod() == 4) { // TODO 农信行退款
    //
    JSONObject obj = new JSONObject();
    obj.put("out_trade_no", sOnlineOrder.getOrderno());
    obj.put("totalNum", sOnlineOrder.getQuantity()+"");
    obj.put("total_fee", getMoney(sOnlineOrder.getAmount()));
    obj.put("body", sOnlineOrder.getGoodname());
    JSONObject redisConfig = new JSONObject();
    redisConfig.put("mch_id", Constants.gzh_merId);
    redisConfig.put("notify_url", "https://www.xxxx.cn/ab/pay/callback/xx");
    try {
        String result =  ynCreditRefundUtil.postRefund(obj, redisConfig.toJSONString());
        if(StringUtils.isNotEmpty(result) && result.equals("SUCCESS")) {
            ynCreditRefundUtil.changeOrderStatus(sOnlineOrder, sOnlineRefund);
        }

    } catch (Exception e) {
        logger.error("退款失败,原因", e);
    }
}

5. 原项目代码冗余啰嗦250行代码改为25行

修改的项目为老项目,代码冗余且不满足需求,阅读起来费解,只好手刃重写!不支持java stream否则2~5行最多不超过10行就搞定了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值