puzhibing
2023-06-02 9a42cbae72259034a6cbe3a827d168a3a6f65154
新增加司机提现分账逻辑
16个文件已修改
1个文件已删除
30个文件已添加
3121 ■■■■■ 已修改文件
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/api/DriverController.java 100 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/DivisionRecordMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/CashWithdrawalMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/DivisionRecordMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/RechargeRecordMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/CashWithdrawal.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/DivisionRecord.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/RechargeRecord.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/ICashWithdrawalService.java 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDivisionRecordService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDriverService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/CashWithdrawalServiceImpl.java 337 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DivisionRecordServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DriverServiceImpl.java 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DriverWorkServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/OrderPositionServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/OrderServiceImpl.java 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/RevenueServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/Complete.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/PamentOrderUser.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/PaymentOrder.java 293 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/PaymentOrderGood.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/QueryOrder.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/Receive.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/ReceiveGood.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/ReceiveUser.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/Withdraw.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/WeChatUtil.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/AES.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/AesException.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/ByteGroup.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/PKCS7Encoder.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/SHA1.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WXBizMsgCrypt.java 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WXCore.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WeChatUtil.java 415 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WxPKCS7Encoder.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/XMLParse.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/Category.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/Code2Session.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/KeywordEnum.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/MessageTemplate.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/PubTemplateKeywords.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/PubTemplatetitles.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/resources/application.yml 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/resources/redis.properties 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/test/java/com/supersavedriving/driver/GunsApplicationTest.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/api/DriverController.java
@@ -1,5 +1,6 @@
package com.supersavedriving.driver.modular.system.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.supersavedriving.driver.modular.system.model.Driver;
@@ -7,7 +8,9 @@
import com.supersavedriving.driver.modular.system.model.Edition;
import com.supersavedriving.driver.modular.system.model.JoiningRequirements;
import com.supersavedriving.driver.modular.system.service.*;
import com.supersavedriving.driver.modular.system.util.MallBook.model.InterfaceResponse;
import com.supersavedriving.driver.modular.system.util.MallBook.model.Register;
import com.supersavedriving.driver.modular.system.util.MallBook.util.RSASignature;
import com.supersavedriving.driver.modular.system.util.MallBook.util.TrhRequest;
import com.supersavedriving.driver.modular.system.util.PayMoneyUtil;
import com.supersavedriving.driver.modular.system.util.huawei.OBSUtil;
@@ -586,15 +589,16 @@
    @ResponseBody
    @PostMapping("/api/driver/withdrawCash")
//    @ServiceLog(name = "司机提现操作", url = "/api/driver/withdrawCash")
    @ApiOperation(value = "司机提现操作", tags = {"司机端-个人中心"}, notes = "")
    @ApiOperation(value = "司机提现操作【1.1】", tags = {"司机端-个人中心"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "类型(1=余额提现,2=佣金提现)", name = "type", required = true, dataType = "int"),
            @ApiImplicitParam(value = "银行卡id", name = "bankId", required = true, dataType = "int"),
            @ApiImplicitParam(value = "提现金额", name = "money", required = true, dataType = "double"),
            @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResponseWarpper withdrawCash(Integer type, Double money){
        if(null == type){
            return ResponseWarpper.success(ResultUtil.paranErr("type"));
    public ResponseWarpper withdrawCash(Integer type, Integer bankId, Double money){
        if(null == bankId){
            return ResponseWarpper.success(ResultUtil.paranErr("bankId"));
        }
        if(null == money){
            return ResponseWarpper.success(ResultUtil.paranErr("money"));
@@ -604,7 +608,7 @@
            if(null == uid){
                return ResponseWarpper.tokenErr();
            }
            ResultUtil resultUtil = cashWithdrawalService.withdrawCash(uid, type, money);
            ResultUtil resultUtil = cashWithdrawalService.withdrawCash(uid, type, bankId, money);
            return ResponseWarpper.success(resultUtil);
        }catch (Exception e){
            e.printStackTrace();
@@ -673,6 +677,39 @@
    }
    @ResponseBody
    @PostMapping("/base/driver/balanceRecharge1")
//    @ServiceLog(name = "账户余额充值(跳小程序支付)", url = "/api/driver/balanceRecharge")
    @ApiOperation(value = "账户余额充值(跳小程序支付)", tags = {"司机端-个人中心"}, notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "小程序code", name = "jscode", required = true, dataType = "string"),
            @ApiImplicitParam(value = "司机id", name = "driverId", required = true, dataType = "int"),
            @ApiImplicitParam(value = "充值金额", name = "amount", required = true, dataType = "double"),
            @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResponseWarpper balanceRecharge1(String jscode, Integer driverId, Double amount){
        if(null == jscode){
            return ResponseWarpper.success(ResultUtil.paranErr("jscode"));
        }
        if(null == driverId){
            return ResponseWarpper.success(ResultUtil.paranErr("driverId"));
        }
        if(null == amount){
            return ResponseWarpper.success(ResultUtil.paranErr("amount"));
        }
        try {
            ResultUtil resultUtil = driverService.balanceRecharge1(driverId, jscode, amount);
            return ResponseWarpper.success(resultUtil);
        }catch (Exception e){
            e.printStackTrace();
            return new ResponseWarpper(500, e.getMessage());
        }
    }
    /**
     * 账户余额充值支付回调
     * @param request
@@ -680,19 +717,26 @@
     */
    @ResponseBody
    @PostMapping("/base/driver/balanceRechargeCallback")
    public void balanceRechargeCallback(HttpServletRequest request, HttpServletResponse response){
    public void balanceRechargeCallback(@RequestBody InterfaceResponse interfaceResponse, HttpServletResponse response){
        try {
            Map<String, String> map = payMoneyUtil.weixinpayCallback(request);
            if(null != map){
                String out_trade_no = map.get("out_trade_no");
                String transaction_id = map.get("transaction_id");
                String result = map.get("result");
                String orderId = out_trade_no.substring(17);
                driverService.balanceRechargeCallback(out_trade_no, transaction_id);
            // 验签
            boolean verify = RSASignature.validate(interfaceResponse.content(), interfaceResponse.getSign());
            if (verify) {//验签成功业务处理逻辑
                if(!"0000".equals(interfaceResponse.getCode())){
                    System.err.println("充值回调异常:" + interfaceResponse.getMsg());
                    return;
                }
                JSONObject jsonObject = JSON.parseObject(interfaceResponse.getResult());
                String merOrderId = jsonObject.getString("merOrderId");
                String out_trade_no = jsonObject.getString("parameter1");
                driverService.balanceRechargeCallback(out_trade_no, merOrderId);
                response.setStatus(200);
                PrintWriter out = response.getWriter();
                out.print(result);
                out.print("OK");
                out.flush();
                out.close();
            } else {//验签失败业务处理逻辑
                System.err.println("支付回调验签失败");
            }
        }catch (Exception e){
            e.printStackTrace();
@@ -922,6 +966,10 @@
    }
    /**
     * 注册商户回调
     * @param jsonObject
     */
    @ResponseBody
    @PostMapping("/base/driver/microenterpriseCallback")
    public void microenterpriseCallback(@RequestBody JSONObject jsonObject){
@@ -944,7 +992,7 @@
                return ResponseWarpper.tokenErr();
            }
            DriverBank driverId = driverBankService.selectOne(new EntityWrapper<DriverBank>().eq("driverId", uid));
            return ResponseWarpper.success(driverId);
            return ResponseWarpper.success(null == driverId ? new DriverBank() : driverId);
        }catch (Exception e){
            e.printStackTrace();
            return new ResponseWarpper(500, e.getMessage());
@@ -999,4 +1047,26 @@
            return new ResponseWarpper(500, e.getMessage());
        }
    }
    /**
     * 提现分账的回调
     */
    @ResponseBody
    @PostMapping("/base/driver/withdrawCashFZCallback")
    public void withdrawCashFZCallback(@RequestBody InterfaceResponse interfaceResponse){
        cashWithdrawalService.withdrawCashFZCallback(interfaceResponse);
    }
    /**
     * 提现确认收货后的结算回调
     */
    @ResponseBody
    @PostMapping("/base/driver/withdrawCashCallback")
    public void withdrawCashCallback(@RequestBody InterfaceResponse interfaceResponse){
        cashWithdrawalService.withdrawCashCallback(interfaceResponse);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/DivisionRecordMapper.java
New file
@@ -0,0 +1,11 @@
package com.supersavedriving.driver.modular.system.dao;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.supersavedriving.driver.modular.system.model.DivisionRecord;
/**
 * @author zhibing.pu
 * @date 2023/5/6 16:41
 */
public interface DivisionRecordMapper extends BaseMapper<DivisionRecord> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/CashWithdrawalMapper.xml
@@ -9,6 +9,7 @@
        <result column="userDriverId" property="userDriverId"/>
        <result column="code" property="code"/>
        <result column="businessType" property="businessType"/>
        <result column="bankId" property="bankId"/>
        <result column="amount" property="amount"/>
        <result column="state" property="state"/>
        <result column="orderNumber" property="orderNumber"/>
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/DivisionRecordMapper.xml
New file
@@ -0,0 +1,19 @@
<?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.supersavedriving.driver.modular.system.dao.DivisionRecordMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.supersavedriving.driver.modular.system.model.DivisionRecord">
        <id column="id" property="id"/>
        <result column="userType" property="userType"/>
        <result column="userId" property="userId"/>
        <result column="orderId" property="orderId"/>
        <result column="merOrderId" property="merOrderId"/>
        <result column="sourceType" property="sourceType"/>
        <result column="amount" property="amount"/>
        <result column="merchantNumber" property="merchantNumber"/>
        <result column="state" property="state"/>
        <result column="payTime" property="payTime"/>
        <result column="createTime" property="createTime"/>
    </resultMap>
</mapper>
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/dao/mapping/RechargeRecordMapper.xml
@@ -15,5 +15,6 @@
        <result column="orderNumber" property="orderNumber" />
        <result column="createTime" property="createTime" />
        <result column="agentId" property="agentId" />
        <result column="surplusDividedAmount" property="surplusDividedAmount"/>
    </resultMap>
</mapper>
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/CashWithdrawal.java
@@ -42,6 +42,11 @@
    @TableField("businessType")
    private Integer businessType;
    /**
     * 银行卡id
     */
    @TableField("bankId")
    private Integer bankId;
    /**
     * 提现金额
     */
    @TableField("amount")
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/DivisionRecord.java
New file
@@ -0,0 +1,73 @@
package com.supersavedriving.driver.modular.system.model;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;
import java.util.Date;
/**
 * @author zhibing.pu
 * @date 2023/5/6 15:54
 */
@Data
@TableName("t_division_record")
public class DivisionRecord {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 用户类型(1=司机,2=代理商,3=平台)
     */
    @TableField("userType")
    private Integer userType;
    /**
     * 用户id
     */
    @TableField("userId")
    private Integer userId;
    /**
     * 分账业务订单id
     */
    @TableField("orderId")
    private Long orderId;
    /**
     * 第三方分账业务订单id
     */
    @TableField("merOrderId")
    private String merOrderId;
    /**
     * 业务来源(1=订单业务,2=平台充值)
     */
    @TableField("sourceType")
    private Integer sourceType;
    /**
     * 分账金额
     */
    @TableField("amount")
    private Double amount;
    /**
     * 收款商户号
     */
    @TableField("merchantNumber")
    private String merchantNumber;
    /**
     * 分账状态(1=分账中,2=分账成功)
     */
    @TableField("state")
    private Integer state;
    /**
     * 分账时间
     */
    @TableField("payTime")
    private Date payTime;
    /**
     * 添加时间
     */
    @TableField("createTime")
    private Date createTime;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/model/RechargeRecord.java
@@ -9,6 +9,7 @@
import java.util.Date;
/**
 * 系统充值记录
 * @author zhibing.pu
 * @date 2023/3/21 23:08
 */
@@ -71,4 +72,9 @@
     */
    @TableField("agentId")
    private Integer agentId;
    /**
     * 剩余待分账金额
     */
    @TableField("surplusDividedAmount")
    private Double surplusDividedAmount;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/ICashWithdrawalService.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.modular.system.model.CashWithdrawal;
import com.supersavedriving.driver.modular.system.util.MallBook.model.InterfaceResponse;
import com.supersavedriving.driver.modular.system.util.ResultUtil;
@@ -14,10 +15,24 @@
    /**
     * 司机提现申请
     * @param type
     * @param bankId
     * @param money
     * @return
     * @throws Exception
     */
    ResultUtil withdrawCash(Integer driverId, Integer type, Double money) throws Exception;
    ResultUtil withdrawCash(Integer driverId, Integer type, Integer bankId, Double money) throws Exception;
    /**
     * 提现异步回调
     * @param interfaceResponse
     */
    void withdrawCashFZCallback(InterfaceResponse interfaceResponse);
    /**
     * 提现确认收货后的结算回调
     * @param interfaceResponse
     */
    void withdrawCashCallback(InterfaceResponse interfaceResponse);
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDivisionRecordService.java
New file
@@ -0,0 +1,11 @@
package com.supersavedriving.driver.modular.system.service;
import com.baomidou.mybatisplus.service.IService;
import com.supersavedriving.driver.modular.system.model.DivisionRecord;
/**
 * @author zhibing.pu
 * @date 2023/5/6 16:42
 */
public interface IDivisionRecordService extends IService<DivisionRecord> {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/IDriverService.java
@@ -131,6 +131,17 @@
    ResultUtil balanceRecharge(Integer uid, Double amount) throws Exception;
    /**
     * 司机账户余额充值
     * @param driverId
     * @param amount
     * @return
     * @throws Exception
     */
    ResultUtil balanceRecharge1(Integer driverId, String jscode, Double amount) throws Exception;
    /**
     * 支付回调通知处理
     * @param out_trade_no
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/CashWithdrawalServiceImpl.java
@@ -1,22 +1,24 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.dao.CashWithdrawalMapper;
import com.supersavedriving.driver.modular.system.model.AccountChangeDetail;
import com.supersavedriving.driver.modular.system.model.CashWithdrawal;
import com.supersavedriving.driver.modular.system.model.Driver;
import com.supersavedriving.driver.modular.system.service.IAccountChangeDetailService;
import com.supersavedriving.driver.modular.system.service.ICashWithdrawalService;
import com.supersavedriving.driver.modular.system.service.IDriverService;
import com.supersavedriving.driver.modular.system.model.*;
import com.supersavedriving.driver.modular.system.service.*;
import com.supersavedriving.driver.modular.system.util.MallBook.model.*;
import com.supersavedriving.driver.modular.system.util.MallBook.util.TrhRequest;
import com.supersavedriving.driver.modular.system.util.PayMoneyUtil;
import com.supersavedriving.driver.modular.system.util.ResultUtil;
import com.supersavedriving.driver.modular.system.util.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;
/**
 * @author zhibing.pu
@@ -34,6 +36,15 @@
    @Autowired
    private IAccountChangeDetailService accountChangeDetailService;
    @Autowired
    private IRechargeRecordService rechargeRecordService;
    @Autowired
    private IDivisionRecordService divisionRecordService;
    @Value("${callbackPath}")
    private String callbackPath;
@@ -42,26 +53,30 @@
    /**
     * 司机提现操作
     * @param driverId
     * @param type
     * @param bankId
     * @param money
     * @return
     * @throws Exception
     */
    @Override
    public ResultUtil withdrawCash(Integer driverId, Integer type, Double money) throws Exception {
    public ResultUtil withdrawCash(Integer driverId, Integer type, Integer bankId, Double money) throws Exception {
        Driver driver = driverService.selectById(driverId);
        if(type == 1 && (null == driver.getBalance() || driver.getBalance() < money)){
            return ResultUtil.error("账户余额不足");
        if(type == 1 && null == driver.getBalance() || driver.getBalance() < money){
            return ResultUtil.error("余额不足");
        }
        if(type == 2 && (null == driver.getCommission() || driver.getCommission() < money)){
            return ResultUtil.error("佣金余额不足");
        if(type == 2 && null == driver.getCommission() || driver.getCommission() < money){
            return ResultUtil.error("收入余额不足");
        }
        if(ToolUtil.isEmpty(driver.getMerchantNumber())){
            return ResultUtil.error("请先注册商户号");
        }
        CashWithdrawal cashWithdrawal = new CashWithdrawal();
        cashWithdrawal.setType(2);
        cashWithdrawal.setUserDriverId(driverId);
        cashWithdrawal.setCode(System.currentTimeMillis() + UUIDUtil.getNumberRandom(3));
        cashWithdrawal.setBusinessType(type == 1 ? 12 : 11);
        cashWithdrawal.setBusinessType(type == 2 ? 11 : 12);
        cashWithdrawal.setBankId(bankId);
        cashWithdrawal.setAmount(money);
        cashWithdrawal.setState(1);
        cashWithdrawal.setCreateTime(new Date());
@@ -74,32 +89,294 @@
        accountChangeDetail.setUserId(driver.getId());
        accountChangeDetail.setType(1);
        accountChangeDetail.setChangeType(type == 1 ? 4 : 6);
        accountChangeDetail.setOldData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
        if(type == 1){
            accountChangeDetail.setOldData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
            driver.setBalance(driver.getBalance() - money);
            accountChangeDetail.setNewData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
            accountChangeDetail.setExplain("账户余额提现");
        }
        if(type == 2){
            accountChangeDetail.setOldData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
        }else{
            driver.setCommission(driver.getCommission() - money);
            accountChangeDetail.setNewData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
            accountChangeDetail.setExplain("佣金余额提现");
        }
        accountChangeDetail.setNewData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
        accountChangeDetail.setExplain(type == 1 ? "账户余额提现" : "佣金余额提现");
        driverService.updateById(driver);
        accountChangeDetailService.saveData(accountChangeDetail);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String outDetailNo = sdf.format(new Date()) + cashWithdrawal.getId();
        String s = payMoneyUtil.weixinTransferMoney(outDetailNo, money, driver.getOpenid(), driver.getName(), "【超省新代驾】提现付款!");
        if(ToolUtil.isEmpty(s)){
            return ResultUtil.error("提现异常,请联系管理员");
        if(type == 1){//余额提现,调用分账接口 -->确认收货--->提现
            fenzhang(driver, money, cashWithdrawal, 1);
        }else{//佣金提现,调用充值接口数据进行分账
            fenzhang(driver, money, cashWithdrawal, 2);
        }
        cashWithdrawal.setState(2);
        cashWithdrawal.setOrderNumber(s);
        this.updateById(cashWithdrawal);
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
//        String outDetailNo = sdf.format(new Date()) + cashWithdrawal.getId();
//
//        String s = payMoneyUtil.weixinTransferMoney(outDetailNo, money, driver.getOpenid(), driver.getName(), "【超省新代驾】提现付款!");
//        if(ToolUtil.isEmpty(s)){
//            return ResultUtil.error("提现异常,请联系管理员");
//        }
//        cashWithdrawal.setState(2);
//        cashWithdrawal.setOrderNumber(s);
//        this.updateById(cashWithdrawal);
        return ResultUtil.success();
    }
    /**
     * 司机提现,现将支付的订单进行分账
     * @param driver
     * @param amount
     * @param cashWithdrawal
     * @return
     */
    public ResultUtil fenzhang(Driver driver, Double amount, CashWithdrawal cashWithdrawal, Integer payType){
        List<RechargeRecord> rechargeRecords = new ArrayList<>();
        if(payType == 1){//司机充值
            rechargeRecords = rechargeRecordService.selectList(new EntityWrapper<RechargeRecord>().eq("type", 2)
                    .eq("userId", driver.getId()).eq("payType", 1).eq("payStatus", 2).gt("surplusDividedAmount", 0));
        }
        if(payType == 2){//平台充值(补贴金额)
            rechargeRecords = rechargeRecordService.selectList(new EntityWrapper<RechargeRecord>()
                   .eq("payType", 2).eq("payStatus", 2).gt("surplusDividedAmount", 0));
        }
        for (RechargeRecord rechargeRecord : rechargeRecords) {
            Double surplusDividedAmount = rechargeRecord.getSurplusDividedAmount();
            if(surplusDividedAmount.compareTo(amount) >= 0){//够分账
                DivisionRecord divisionRecord = new DivisionRecord();
                divisionRecord.setUserType(1);
                divisionRecord.setUserId(driver.getId());
                divisionRecord.setOrderId(rechargeRecord.getId().longValue());
                divisionRecord.setSourceType(payType == 1 ? 3 : 2);
                divisionRecord.setAmount(surplusDividedAmount);
                divisionRecord.setMerchantNumber(driver.getMerchantNumber());
                divisionRecord.setState(1);
                divisionRecord.setCreateTime(new Date());
                divisionRecordService.insert(divisionRecord);
                Complete complete = new Complete();
                complete.setOriginalMerOrderId(rechargeRecord.getOrderNumber());
                complete.setNotifyUrl(callbackPath + "/base/driver/withdrawCashFZCallback");
                complete.setParameter1(divisionRecord.getId().toString());
                complete.setParameter2(rechargeRecord.getId() + "_" + cashWithdrawal.getId());
                //分账方列表
                List<PamentOrderUser> splitList = new ArrayList<>();
                PamentOrderUser pamentOrderUser = new PamentOrderUser();
                pamentOrderUser.setSplitUserId(driver.getMerchantNumber());
                pamentOrderUser.setSplitAmount(amount.toString());
                pamentOrderUser.setSplitType("1");
                splitList.add(pamentOrderUser);
                complete.setSplitList(splitList);
                TrhRequest<Complete> request = new TrhRequest();
                InterfaceResponse execute = request.execute(complete, Complete.SERVICE_CODE);//分账操作
                if("0000".equals(execute.getCode())){
                    JSONObject jsonObject = JSON.parseObject(execute.getResult());
                    Integer status = jsonObject.getInteger("status");//0:待处理 1:成功 2:失败
                    String merOrderId = jsonObject.getString("merOrderId");
                    if(2 == status){
                        System.err.println("司机提现分账失败:" + execute.getMsg());
                        break;
                    }
                    if(1 == status){
                        divisionRecord.setMerOrderId(merOrderId);
                        divisionRecord.setPayTime(new Date());
                        divisionRecord.setState(2);
                        divisionRecordService.updateById(divisionRecord);
                        //间隔10秒开始调用确认收货后开始提现
                        new Timer().schedule(new TimerTask() {//确认收货和提现
                            @Override
                            public void run() {
                                confirmReceipt(driver, rechargeRecord, divisionRecord, cashWithdrawal);
                            }
                        }, 15000);
                    }
                }else{
                    System.err.println("司机提现分账异常:" + execute.getMsg());
                }
                break;
            }else{//不够分账
                DivisionRecord divisionRecord = new DivisionRecord();
                divisionRecord.setUserType(1);
                divisionRecord.setUserId(driver.getId());
                divisionRecord.setOrderId(rechargeRecord.getId().longValue());
                divisionRecord.setSourceType(payType == 1 ? 3 : 2);
                divisionRecord.setAmount(surplusDividedAmount);
                divisionRecord.setMerchantNumber(driver.getMerchantNumber());
                divisionRecord.setState(1);
                divisionRecord.setCreateTime(new Date());
                divisionRecordService.insert(divisionRecord);
                Complete complete = new Complete();
                complete.setOriginalMerOrderId(rechargeRecord.getOrderNumber());
                complete.setNotifyUrl(callbackPath + "/base/driver/withdrawCashFZCallback");
                complete.setParameter1(divisionRecord.getId().toString());
                //分账方列表
                List<PamentOrderUser> splitList = new ArrayList<>();
                PamentOrderUser pamentOrderUser = new PamentOrderUser();
                pamentOrderUser.setSplitUserId(driver.getMerchantNumber());
                pamentOrderUser.setSplitAmount(surplusDividedAmount.toString());
                pamentOrderUser.setSplitType("1");
                splitList.add(pamentOrderUser);
                complete.setSplitList(splitList);
                TrhRequest<Complete> request = new TrhRequest();
                InterfaceResponse execute = request.execute(complete, Complete.SERVICE_CODE);//分账操作
                if("0000".equals(execute.getCode())){
                    JSONObject jsonObject = JSON.parseObject(execute.getResult());
                    Integer status = jsonObject.getInteger("status");//0:待处理 1:成功 2:失败
                    String merOrderId = jsonObject.getString("merOrderId");
                    if(2 == status){
                        System.err.println("司机提现分账失败:" + execute.getMsg());
                        break;
                    }
                    if(1 == status){
                        divisionRecord.setMerOrderId(merOrderId);
                        divisionRecord.setPayTime(new Date());
                        divisionRecord.setState(2);
                        divisionRecordService.updateById(divisionRecord);
                        //间隔10秒开始调用确认收货后开始提现
                        new Timer().schedule(new TimerTask() {//确认收货和提现
                            @Override
                            public void run() {
                                confirmReceipt(driver, rechargeRecord, divisionRecord, cashWithdrawal);
                            }
                        }, 15000);
                    }
                }else{
                    System.err.println("司机提现分账异常:" + execute.getMsg());
                    break;
                }
                amount -= surplusDividedAmount;
            }
        }
        return ResultUtil.success();
    }
    /**
     * 分账后的确认收货和提现操作
     * @param driver
     * @param rechargeRecord
     * @param divisionRecord
     * @param cashWithdrawal
     */
    public void confirmReceipt(Driver driver, RechargeRecord rechargeRecord, DivisionRecord divisionRecord, CashWithdrawal cashWithdrawal){
        Receive receive = new Receive();
        receive.setOriginalMerOrderId(rechargeRecord.getOrderNumber());
        receive.setAsynMerOrderId(divisionRecord.getMerOrderId());
        receive.setRcvAmount(divisionRecord.getAmount().toString());
        List<ReceiveUser> splitList = new ArrayList<>();
        ReceiveUser receiveUser = new ReceiveUser();
        receiveUser.setSplitUserId(driver.getMerchantNumber());
        receiveUser.setRcvSplitAmount(divisionRecord.getAmount().toString());
        splitList.add(receiveUser);
        receive.setSplitList(splitList);
        TrhRequest<Receive> request = new TrhRequest();
        InterfaceResponse execute1 = request.execute(receive, Receive.SERVICE_CODE);//确认收货
        if("0000".equals(execute1.getCode())){
            JSONObject jsonObject = JSON.parseObject(execute1.getResult());
            String merOrderId = jsonObject.getString("merOrderId");
            if(ToolUtil.isNotEmpty(merOrderId)){
                Withdraw withdraw = new Withdraw();
                withdraw.setUserId(driver.getMerchantNumber());
                withdraw.setAmount(divisionRecord.getAmount().toString());
                withdraw.setOrderName("账户余额提现");
                withdraw.setRemark("账户余额提现");
                withdraw.setNotifyUrl(callbackPath + "/base/driver/withdrawCashCallback");
                withdraw.setParameter1(cashWithdrawal.getId().toString());
                TrhRequest<Withdraw> request1 = new TrhRequest();
                InterfaceResponse execute = request1.execute(withdraw, Withdraw.SERVICE_CODE);//结算(提现)
                if("0000".equals(execute.getCode())){
                    JSONObject jsonObject1 = JSON.parseObject(execute.getResult());
                    String merOrderId1 = jsonObject1.getString("merOrderId");
                    Integer status = jsonObject1.getInteger("status");//0:待处理;1:成功;2:失败
                    if(1 == status){
                        cashWithdrawal.setOrderNumber(merOrderId1);
                        cashWithdrawal.setState(2);
                        this.updateById(cashWithdrawal);
                    }
                    if(2 == status){
                        System.err.println("结算接口异常【提现】:" + jsonObject1.getString("statusMsg"));
                    }
                }else{
                    System.err.println("结算接口异常【提现】:" + execute.getMsg());
                }
            }
        }else{
            System.err.println("分账确认收货异常【提现】:" + execute1.getMsg());
        }
    }
    /**
     * 提现分账的异步回调
     * @param interfaceResponse
     */
    @Override
    public void withdrawCashFZCallback(InterfaceResponse interfaceResponse) {
        if("0000".equals(interfaceResponse.getCode())){
            JSONObject jsonObject = JSON.parseObject(interfaceResponse.getResult());
            Integer status = jsonObject.getInteger("status");//0:待处理 1:成功 2:失败
            String merOrderId = jsonObject.getString("merOrderId");
            if(2 == status){
                System.err.println("司机提现分账失败:" + interfaceResponse.getMsg());
                return;
            }
            if(1 == status){
                String parameter1 = jsonObject.getString("parameter1");
                String parameter2 = jsonObject.getString("parameter2");
                DivisionRecord divisionRecord = divisionRecordService.selectById(parameter1);
                divisionRecord.setMerOrderId(merOrderId);
                divisionRecord.setPayTime(new Date());
                divisionRecord.setState(2);
                divisionRecordService.updateById(divisionRecord);
                Driver driver = driverService.selectById(divisionRecord.getUserId());
                String[] s = parameter2.split("_");
                RechargeRecord rechargeRecord = rechargeRecordService.selectById(s[0]);
                CashWithdrawal cashWithdrawal = this.selectById(s[1]);
                //间隔10秒开始调用确认收货后开始提现
                new Timer().schedule(new TimerTask() {//确认收货和提现
                    @Override
                    public void run() {
                        confirmReceipt(driver, rechargeRecord, divisionRecord, cashWithdrawal);
                    }
                }, 15000);
            }
        }else{
            System.err.println("司机提现分账异常:" + interfaceResponse.getMsg());
        }
    }
    /**
     * 提现确认收货后的结算回调
     * @param interfaceResponse
     */
    @Override
    public void withdrawCashCallback(InterfaceResponse interfaceResponse) {
        if("0000".equals(interfaceResponse.getCode())){
            JSONObject jsonObject1 = JSON.parseObject(interfaceResponse.getResult());
            String merOrderId1 = jsonObject1.getString("merOrderId");
            Integer status = jsonObject1.getInteger("status");//0:待处理;1:成功;2:失败
            if(1 == status){
                String parameter1 = jsonObject1.getString("parameter1");
                CashWithdrawal cashWithdrawal = this.selectById(parameter1);
                cashWithdrawal.setOrderNumber(merOrderId1);
                cashWithdrawal.setState(2);
                this.updateById(cashWithdrawal);
            }
            if(2 == status){
                System.err.println("结算接口异常【提现】:" + jsonObject1.getString("statusMsg"));
            }
        }else{
            System.err.println("结算接口异常【提现】:" + interfaceResponse.getMsg());
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DivisionRecordServiceImpl.java
New file
@@ -0,0 +1,15 @@
package com.supersavedriving.driver.modular.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.supersavedriving.driver.modular.system.dao.DivisionRecordMapper;
import com.supersavedriving.driver.modular.system.model.DivisionRecord;
import com.supersavedriving.driver.modular.system.service.IDivisionRecordService;
import org.springframework.stereotype.Service;
/**
 * @author zhibing.pu
 * @date 2023/5/6 16:42
 */
@Service
public class DivisionRecordServiceImpl extends ServiceImpl<DivisionRecordMapper, DivisionRecord> implements IDivisionRecordService {
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DriverServiceImpl.java
@@ -13,11 +13,12 @@
import com.supersavedriving.driver.modular.system.service.*;
import com.supersavedriving.driver.modular.system.dao.DriverMapper;
import com.supersavedriving.driver.modular.system.util.*;
import com.supersavedriving.driver.modular.system.util.MallBook.model.InterfaceResponse;
import com.supersavedriving.driver.modular.system.util.MallBook.model.Register;
import com.supersavedriving.driver.modular.system.util.MallBook.model.*;
import com.supersavedriving.driver.modular.system.util.MallBook.util.TrhRequest;
import com.supersavedriving.driver.modular.system.util.mongodb.model.Location;
import com.supersavedriving.driver.modular.system.util.rongyun.RongYunUtil;
import com.supersavedriving.driver.modular.system.util.weChat.WeChatUtil;
import com.supersavedriving.driver.modular.system.util.weChat.model.Code2Session;
import com.supersavedriving.driver.modular.system.warpper.*;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
@@ -40,6 +41,7 @@
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -101,8 +103,17 @@
    @Autowired
    private PushUtil pushUtil;
    @Autowired
    private WeChatUtil weChatUtil;
    @Value("${callbackPath}")
    private String callbackPath;
    @Value("${wx.appletsAppid}")
    private String appletsAppid;
    @Value("${alipay.appid}")
    private String appid;
@@ -678,84 +689,131 @@
        rechargeRecord.setAgentId(driver.getAgentId());
        rechargeRecordService.insert(rechargeRecord);
        PaymentOrder paymentOrder = new PaymentOrder();
        paymentOrder.setBizOrderId(out_trade_no);
        paymentOrder.setAmount(String.valueOf(Double.valueOf(amount * 100).intValue()));
        paymentOrder.setOrderName("账户充值");
        paymentOrder.setPayType("WX_MINI");
        paymentOrder.setTransferType("0");
        paymentOrder.setAsynSplitFlag("1");
        paymentOrder.setAppid(appletsAppid);
        paymentOrder.setOpenid(driver.getOpenid());
        paymentOrder.setTerminalIp(InetAddress.getLocalHost().getHostAddress());
        List<PaymentOrderGood> goodsDetail = new ArrayList<>();
        PaymentOrderGood paymentOrderGood = new PaymentOrderGood();
        paymentOrderGood.setGoodsName("充值");
        goodsDetail.add(paymentOrderGood);
        paymentOrder.setGoodsDetail(goodsDetail);
        paymentOrder.setFrontUrl("http://www.baidu.com");//前端回调地址
        paymentOrder.setNotifyUrl(callbackPath + "/base/driver/balanceRechargeCallback");
        paymentOrder.setParameter1(out_trade_no);
        ResultUtil weixinpay = payMoneyUtil.weixinpay("余额充值", "", out_trade_no, amount.toString(), "/base/driver/balanceRechargeCallback", "APP");
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    int num = 1;
                    int wait = 0;
                    while (num <= 10){
                        int min = 5000;
                        wait += (min * num);
                        RechargeRecord rechargeRecord1 = rechargeRecordService.selectOne(new EntityWrapper<RechargeRecord>().eq("code", out_trade_no));
                        if(rechargeRecord1.getPayStatus() != 1){
                            return;
                        }
                        /**
                         * SUCCESS--支付成功
                         * REFUND--转入退款
                         * NOTPAY--未支付
                         * CLOSED--已关闭
                         * REVOKED--已撤销(刷卡支付)
                         * USERPAYING--用户支付中
                         * PAYERROR--支付失败(其他原因,如银行返回失败)
                         * ACCEPT--已接收,等待扣款
                         */
                        ResultUtil<Map<String, String>> resultUtil = payMoneyUtil.queryWXOrder(out_trade_no, "");
                        if(resultUtil.getCode() == 200){
                            Map<String, String> map = resultUtil.getData();
                            String trade_type = map.get("trade_type");
                            String trade_state = map.get("trade_state");
                            String transaction_id = map.get("transaction_id");
                            if("REFUND".equals(trade_state) || "NOTPAY".equals(trade_state) || "CLOSED".equals(trade_state) || "REVOKED".equals(trade_state) || "PAYERROR".equals(trade_state)){
                                rechargeRecordService.deleteById(rechargeRecord1.getId());
        TrhRequest<PaymentOrder> request = new TrhRequest();
        InterfaceResponse execute = request.execute(paymentOrder, PaymentOrder.SERVICE_CODE);
        if(!"0000".equals(execute.getCode())){
            return ResultUtil.error(execute.getMsg());
        }
        JSONObject jsonObject = JSON.parseObject(execute.getResult());
        String status = jsonObject.getString("status");
        if("2".equals(status)){
            return ResultUtil.error("失败");
        }
        String payCode = jsonObject.getString("payCode");
        if(ToolUtil.isNotEmpty(payCode)){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        int num = 1;
                        int wait = 0;
                        while (num <= 10){
                            int min = 5000;
                            wait += (min * num);
                            RechargeRecord rechargeRecord1 = rechargeRecordService.selectOne(new EntityWrapper<RechargeRecord>().eq("code", out_trade_no));
                            if(rechargeRecord1.getPayStatus() != 1){
                                return;
                            }
                            if("SUCCESS".equals(trade_state)){
                                Driver driver1 = DriverServiceImpl.this.selectById(uid);
                                AccountChangeDetail accountChangeDetail = new AccountChangeDetail();
                                accountChangeDetail.setUserType(2);
                                accountChangeDetail.setUserId(uid);
                                accountChangeDetail.setCode(System.currentTimeMillis() + UUIDUtil.getNumberRandom(3));
                                accountChangeDetail.setChangeType(3);
                                accountChangeDetail.setType(1);
                                accountChangeDetail.setCreateTime(new Date());
                                accountChangeDetail.setExplain("余额充值");
                                accountChangeDetail.setOldData(driver1.getBalance() + driver1.getBackgroundBalance() + driver1.getCouponBalance() + driver1.getCommission());
                                driver1.setBalance(driver1.getBalance() + amount);
                                accountChangeDetail.setNewData(driver1.getBalance() + driver1.getBackgroundBalance() + driver1.getCouponBalance() + driver1.getCommission());
                                DriverServiceImpl.this.updateById(driver1);
                                accountChangeDetailService.saveData(accountChangeDetail);
                            QueryOrder queryOrder = new QueryOrder();
                            /**
                             * 原请求订单号(必填)  字段长度最长:32位
                             */
                            queryOrder.setOriginalMerOrderId(out_trade_no);
                            /**
                             * 1:支付查询 2:退款查询 3:确认收货查询 4:结算查询 5:充值查询 6:转账查询 7:异步分账查询(必填)  字段长度最长:1位
                             */
                            queryOrder.setQueryType("1");
                            TrhRequest<QueryOrder> request = new TrhRequest();
                            InterfaceResponse execute1 = request.execute(queryOrder, QueryOrder.SERVICE_CODE);
                            if("0000".equals(execute1.getCode())){
                                JSONObject jsonObject1 = JSON.parseObject(execute1.getResult());
                                String status1 = jsonObject1.getString("status");
                                if("0".equals(status1)){//待处理
                                    Thread.sleep(wait);
                                    num++;
                                }
                                if("1".equals(status1)){//成功
                                    String merOrderId = jsonObject1.getString("merOrderId");
                                    Driver driver1 = DriverServiceImpl.this.selectById(rechargeRecord1.getUserId());
                                    AccountChangeDetail accountChangeDetail = new AccountChangeDetail();
                                    accountChangeDetail.setUserType(2);
                                    accountChangeDetail.setUserId(driver1.getId());
                                    accountChangeDetail.setCode(System.currentTimeMillis() + UUIDUtil.getNumberRandom(3));
                                    accountChangeDetail.setChangeType(3);
                                    accountChangeDetail.setType(1);
                                    accountChangeDetail.setCreateTime(new Date());
                                    accountChangeDetail.setExplain("账户充值");
                                    accountChangeDetail.setOldData(driver1.getBalance() + driver1.getBackgroundBalance() + driver1.getCouponBalance() + driver1.getCommission());
                                    driver1.setBalance(driver1.getBalance() + rechargeRecord1.getAmount());
                                    accountChangeDetail.setNewData(driver1.getBalance() + driver1.getBackgroundBalance() + driver1.getCouponBalance() + driver1.getCommission());
                                    DriverServiceImpl.this.updateById(driver1);
                                    accountChangeDetailService.saveData(accountChangeDetail);
                                rechargeRecord1.setPayTime(new Date());
                                rechargeRecord1.setPayStatus(2);
                                rechargeRecord1.setOrderNumber(transaction_id);
                                rechargeRecordService.updateById(rechargeRecord1);
                                return;
                            }
                            if("USERPAYING".equals(trade_state) || "ACCEPT".equals(trade_state)){
                                    rechargeRecord1.setPayTime(new Date());
                                    rechargeRecord1.setPayStatus(2);
                                    rechargeRecord1.setOrderNumber(merOrderId);
                                    rechargeRecord1.setSurplusDividedAmount(rechargeRecord1.getAmount());
                                    rechargeRecordService.updateById(rechargeRecord1);
                                    break;
                                }
                                if("2".equals(status1) || 10 == num){//失败
                                    rechargeRecordService.deleteById(rechargeRecord1.getId());
                                    break;
                                }
                            }else{
                                Thread.sleep(wait);
                                num++;
                            }
                        }else{
                            Thread.sleep(wait);
                            num++;
                        }
                        if(10 == num){
                            rechargeRecordService.deleteById(rechargeRecord1.getId());
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
        return weixinpay;
            }).start();
        }
        return ResultUtil.success(payCode);
    }
    /**
     * 司机端跳小程序支付
     * @param driverId
     * @param jscode
     * @param amount
     * @return
     * @throws Exception
     */
    @Override
    public ResultUtil balanceRecharge1(Integer driverId, String jscode, Double amount) throws Exception {
        Code2Session code2Session = weChatUtil.code2Session(jscode);
        if(null != code2Session.getErrcode() && code2Session.getErrcode() != 0){
            return ResultUtil.error(code2Session.getErrmsg());
        }
        String openid = code2Session.getOpenid();
        Driver driver = this.selectById(driverId);
        driver.setOpenid(openid);
        this.updateById(driver);
        return balanceRecharge(driverId, amount);
    }
    /**
     * 充值回调通知逻辑处理
@@ -776,7 +834,7 @@
        accountChangeDetail.setChangeType(3);
        accountChangeDetail.setType(1);
        accountChangeDetail.setCreateTime(new Date());
        accountChangeDetail.setExplain("余额充值");
        accountChangeDetail.setExplain("账户充值");
        accountChangeDetail.setOldData(driver1.getBalance() + driver1.getBackgroundBalance() + driver1.getCouponBalance() + driver1.getCommission());
        driver1.setBalance(driver1.getBalance() + rechargeRecord1.getAmount());
        accountChangeDetail.setNewData(driver1.getBalance() + driver1.getBackgroundBalance() + driver1.getCouponBalance() + driver1.getCommission());
@@ -786,6 +844,7 @@
        rechargeRecord1.setPayTime(new Date());
        rechargeRecord1.setPayStatus(2);
        rechargeRecord1.setOrderNumber(transaction_id);
        rechargeRecord1.setSurplusDividedAmount(rechargeRecord1.getAmount());
        rechargeRecordService.updateById(rechargeRecord1);
    }
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/DriverWorkServiceImpl.java
@@ -53,6 +53,9 @@
    @Override
    public ResultUtil driverWork(Integer driverId) throws Exception {
        Driver driver = driverService.selectById(driverId);
        if(ToolUtil.isEmpty(driver.getMerchantNumber())){
            return ResultUtil.error("请先注册商户号");
        }
        SystemConfig systemConfig = systemConfigService.selectOne(new EntityWrapper<SystemConfig>().eq("type", 6));
        Double num1 = JSON.parseObject(systemConfig.getContent()).getDouble("num1");
        if(driver.getBalance() == null || driver.getBalance().compareTo(num1) < 0){
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/OrderPositionServiceImpl.java
@@ -48,6 +48,10 @@
    @Override
    public void saveOrderPosition(DriverPositionWarpper driverPositionWarpper) throws Exception {
        Integer orderId = driverPositionWarpper.getOrderId();
        Order order = orderService.selectById(orderId);
        if(order.getState() != 105){
            return;
        }
        Integer orderType = driverPositionWarpper.getOrderType();
        File file = new File(filePath + orderId + ".json");
        if(!file.exists()){
@@ -59,14 +63,14 @@
            OrderPositionWarpper orderPositionWarpper = orderPositionWarppers.get(orderPositionWarppers.size() - 1);
            saveOrderMileage(driverPositionWarpper, orderPositionWarpper);
        }
        //大于50米才存储有效定位数据
        //大于100米才存储有效定位数据
        if(orderPositionWarppers.size() > 0){
            OrderPositionWarpper orderPositionWarpper1 = orderPositionWarppers.get(orderPositionWarppers.size() - 1);
            String fromLonLat = driverPositionWarpper.getLon() + "," + driverPositionWarpper.getLat();
            String toLonLat = orderPositionWarpper1.getLon() + "," + orderPositionWarpper1.getLat();
            Map<String, Double> distance = GeodesyUtil.getDistance(fromLonLat, toLonLat);
            Double wgs84 = distance.get("WGS84");
            if(wgs84 >= 50){
            if(wgs84 >= 100){
                OrderPositionWarpper orderPositionWarpper = new OrderPositionWarpper();
                BeanUtils.copyProperties(driverPositionWarpper, orderPositionWarpper);
                orderPositionWarpper.setInsertTime(new Date());
@@ -99,7 +103,7 @@
        Order order = orderService.selectById(driverPositionWarpper.getOrderId());
        Double wgs84 = distance.get("WGS84");
        Integer num = map.get(order.getId().toString());
        if(50 < wgs84){
        if(100 < wgs84){
            order.setActualMileage(order.getActualMileage() + wgs84.intValue());
            orderService.updateById(order);
            map.put(order.getId().toString(), 0);
@@ -115,7 +119,7 @@
                }
            }
        }
        if(50 >= wgs84 && 12 <= (null == num ? 0 : num)){//1分钟(5秒上传一次数据)
        if(100 >= wgs84 && 12 <= (null == num ? 0 : num)){//1分钟(5秒上传一次数据)
            Integer integer = map.get(order.getId().toString());
            map.put(order.getId().toString(), null == integer ? 0 : integer++);
            //进入等待状态
@@ -128,7 +132,7 @@
                e.printStackTrace();
            }
        }
        if(50 >= wgs84 && 12 > (null == num ? 0 : num)){
        if(100 >= wgs84 && 12 > (null == num ? 0 : num)){
            Integer integer = map.get(order.getId().toString());
            map.put(order.getId().toString(), null == integer ? 0 : integer++);
        }
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/OrderServiceImpl.java
@@ -1158,6 +1158,8 @@
                order.setCouponId(coupon.getId());
                order.setDiscountAmount(coupon.getCouponPreferentialAmount());
                order.setPayMoney(order.getOrderMoney() - coupon.getCouponPreferentialAmount());
            }else{
                order.setPayMoney(order.getOrderMoney());
            }
        }
@@ -1169,9 +1171,6 @@
                    userToCoupon.setValidCount(userToCoupon.getValidCount() - 1);
                    userToCouponService.updateById(userToCoupon);
                    Coupon coupon = couponService.selectById(userToCoupon.getCouponId());
                    order.setPayMoney(order.getPayMoney() - coupon.getCouponPreferentialAmount());
                    order.setCouponId(coupon.getId());
                    order.setDiscountedPrice(coupon.getCouponPreferentialAmount());
                    Driver driver = driverService.selectById(order.getDriverId());
                    AccountChangeDetail accountChangeDetail = new AccountChangeDetail();
@@ -1193,7 +1192,7 @@
        }
        this.updateById(order);
        if(state == 108){//计算抽成
        if(payType == 2 && state == 108){//计算抽成
            saveRevenue(order);
        }
@@ -1628,6 +1627,40 @@
     */
    @Override
    public void completeCollection() {
        this.baseMapper.completeCollection();
        List<Order> orders = this.selectList(new EntityWrapper<Order>().eq("state", 107).eq("status", 1).eq("payType", 3));
        for (Order order : orders) {
            order.setPayTime(new Date());
            if(null != order.getCouponId()){
                UserToCoupon userToCoupon = userToCouponService.selectById(order.getCouponId());
                if(userToCoupon.getValidCount() > 0){
                    userToCoupon.setValidCount(userToCoupon.getValidCount() - 1);
                    userToCouponService.updateById(userToCoupon);
                    Coupon coupon = couponService.selectById(userToCoupon.getCouponId());
                    Driver driver = driverService.selectById(order.getDriverId());
                    AccountChangeDetail accountChangeDetail = new AccountChangeDetail();
                    accountChangeDetail.setCode(System.currentTimeMillis() + UUIDUtil.getNumberRandom(3));
                    accountChangeDetail.setUserType(2);
                    accountChangeDetail.setUserId(order.getDriverId());
                    accountChangeDetail.setCreateTime(new Date());
                    accountChangeDetail.setOldData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
                    accountChangeDetail.setType(1);
                    accountChangeDetail.setChangeType(7);
                    accountChangeDetail.setOrderId(order.getId());
                    accountChangeDetail.setExplain("优惠券收入");
                    driver.setCouponBalance(driver.getCouponBalance() + coupon.getCouponPreferentialAmount());
                    accountChangeDetail.setNewData(driver.getBalance() + driver.getBackgroundBalance() + driver.getCouponBalance() + driver.getCommission());
                    driverService.updateById(driver);
                    accountChangeDetailService.insert(accountChangeDetail);
                }
            }
            this.updateById(order);
            try {
                saveRevenue(order);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/service/impl/RevenueServiceImpl.java
@@ -66,6 +66,7 @@
            CommissionListWarpper commissionListWarpper = new CommissionListWarpper();
            commissionListWarpper.setCreateTime(revenue.getCreateTime().getTime());
            commissionListWarpper.setAmount(revenue.getAmount());
            commissionListWarpper.setUserType(2);
            Order order = orderService.selectById(revenue.getOrderId());
            if(null != order.getUserId()){
                AppUser appUser = appUserService.selectById(order.getUserId());
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/Complete.java
New file
@@ -0,0 +1,58 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
import java.util.List;
public class Complete {
    /**业务类型编号,必须和接口文档一致*/
    public static String SERVICE_CODE = "complete";
    //原支付请求订单号
    private String originalMerOrderId;
    //分账方列表
    private List<PamentOrderUser> splitList;
    //后台回调地址
    private String notifyUrl;
    //自定义参数1
    private String parameter1;
    //自定义参数2
    private String parameter2;
    public String getOriginalMerOrderId() {
        return originalMerOrderId;
    }
    public void setOriginalMerOrderId(String originalMerOrderId) {
        this.originalMerOrderId = originalMerOrderId;
    }
    public List<PamentOrderUser> getSplitList() {
        return splitList;
    }
    public void setSplitList(List<PamentOrderUser> splitList) {
        this.splitList = splitList;
    }
    public String getNotifyUrl() {
        return notifyUrl;
    }
    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }
    public String getParameter1() {
        return parameter1;
    }
    public void setParameter1(String parameter1) {
        this.parameter1 = parameter1;
    }
    public String getParameter2() {
        return parameter2;
    }
    public void setParameter2(String parameter2) {
        this.parameter2 = parameter2;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/PamentOrderUser.java
New file
@@ -0,0 +1,46 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
public class PamentOrderUser {
    /**
     * 分账方会员ID(必填)
     */
    private  String splitUserId;
    /**
     * 分账金额(必填)
     */
    private String splitAmount;
    /**
     * 分账类型(必填)
     * 0:收单金额(收款人)
     * 1:分账金额
     * 2:佣金
     */
    private String splitType;
    public String getSplitUserId() {
        return splitUserId;
    }
    public void setSplitUserId(String splitUserId) {
        this.splitUserId = splitUserId;
    }
    public String getSplitAmount() {
        return splitAmount;
    }
    public void setSplitAmount(String splitAmount) {
        this.splitAmount = splitAmount;
    }
    public String getSplitType() {
        return splitType;
    }
    public void setSplitType(String splitType) {
        this.splitType = splitType;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/PaymentOrder.java
New file
@@ -0,0 +1,293 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
import java.util.List;
public class PaymentOrder {
    /**业务类型编号,必须和接口文档一致*/
    public static String SERVICE_CODE = "paymentOrder";
    /**
     * 业务订单号(必填)
     */
    private String bizOrderId;
    /**
     * 交易金额(必填)
     */
    private String amount;
    /**
     * 付款人
     */
    private String payerUserName;
    /**
     * 收款人会员ID(必填)
     */
    private String payeeUserId;
    /**
     * 订单名称(必填)
     */
    private String orderName;
    /**
     * 支付类型(必填)
     */
    private String payType;
    /**
     * 交易类型(必填)
     */
    private String transferType;
    /**
     * 订单过期时间
     */
    private String expire;
    /**
     * 微信或支付宝的appid
     */
    private String appid;
    /**
     * 微信或支付宝用户id
     */
    private String openid;
    /**
     * 终端IP(必填)
     */
    private String terminalIp;
    /**
     * 分账方列表(必填)
     */
    private List<PamentOrderUser> splitList;
    /**
     * 商品列表(必填)
     */
    private List<PaymentOrderGood> goodsDetail;
    /**
     * 前台回调地址(必填)
     */
    private String frontUrl;
    /**
     * 后台回调地址(必填)
     */
    private String notifyUrl;
    /**
     * 自定义参数1
     */
    private String parameter1;
    /**
     * 自定义参数2
     */
    private String parameter2;
    /*
     * 是否异步分账
     */
    private String asynSplitFlag;
    /**
     * 付款方子商户编号
     */
    private String payerUserId;
    /**
     * 银行编码
     */
    private String bankCode;
    /**
     * 银行卡类型
     */
    private String cardType;
    /**
     * 快捷卡唯一标识
     */
    private String tokenNo;
    public String getPayerUserId() {
        return payerUserId;
    }
    public void setPayerUserId(String payerUserId) {
        this.payerUserId = payerUserId;
    }
    public String getBankCode() {
        return bankCode;
    }
    public void setBankCode(String bankCode) {
        this.bankCode = bankCode;
    }
    public String getCardType() {
        return cardType;
    }
    public void setCardType(String cardType) {
        this.cardType = cardType;
    }
    public String getTokenNo() {
        return tokenNo;
    }
    public void setTokenNo(String tokenNo) {
        this.tokenNo = tokenNo;
    }
    public String getAsynSplitFlag() {
        return asynSplitFlag;
    }
    public void setAsynSplitFlag(String asynSplitFlag) {
        this.asynSplitFlag = asynSplitFlag;
    }
    public String getBizOrderId() {
        return bizOrderId;
    }
    public void setBizOrderId(String bizOrderId) {
        this.bizOrderId = bizOrderId;
    }
    public String getAmount() {
        return amount;
    }
    public void setAmount(String amount) {
        this.amount = amount;
    }
    public String getPayerUserName() {
        return payerUserName;
    }
    public void setPayerUserName(String payerUserName) {
        this.payerUserName = payerUserName;
    }
    public String getPayeeUserId() {
        return payeeUserId;
    }
    public void setPayeeUserId(String payeeUserId) {
        this.payeeUserId = payeeUserId;
    }
    public String getOrderName() {
        return orderName;
    }
    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }
    public String getPayType() {
        return payType;
    }
    public void setPayType(String payType) {
        this.payType = payType;
    }
    public String getTransferType() {
        return transferType;
    }
    public void setTransferType(String transferType) {
        this.transferType = transferType;
    }
    public String getExpire() {
        return expire;
    }
    public void setExpire(String expire) {
        this.expire = expire;
    }
    public String getAppid() {
        return appid;
    }
    public void setAppid(String appid) {
        this.appid = appid;
    }
    public String getOpenid() {
        return openid;
    }
    public void setOpenid(String openid) {
        this.openid = openid;
    }
    public String getTerminalIp() {
        return terminalIp;
    }
    public void setTerminalIp(String terminalIp) {
        this.terminalIp = terminalIp;
    }
    public List<PamentOrderUser> getSplitList() {
        return splitList;
    }
    public void setSplitList(List<PamentOrderUser> splitList) {
        this.splitList = splitList;
    }
    public List<PaymentOrderGood> getGoodsDetail() {
        return goodsDetail;
    }
    public void setGoodsDetail(List<PaymentOrderGood> goodsDetail) {
        this.goodsDetail = goodsDetail;
    }
    public String getFrontUrl() {
        return frontUrl;
    }
    public void setFrontUrl(String frontUrl) {
        this.frontUrl = frontUrl;
    }
    public String getNotifyUrl() {
        return notifyUrl;
    }
    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }
    public String getParameter1() {
        return parameter1;
    }
    public void setParameter1(String parameter1) {
        this.parameter1 = parameter1;
    }
    public String getParameter2() {
        return parameter2;
    }
    public void setParameter2(String parameter2) {
        this.parameter2 = parameter2;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/PaymentOrderGood.java
New file
@@ -0,0 +1,48 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
public class PaymentOrderGood {
    /** 商品编号 */
    private String goodsId;
    /** 商品名称,必填 */
    private String goodsName;
    /** 商品数量 */
    private String quantity;
    /** 商品价格 */
    private String price;
    public String getGoodsId() {
        return goodsId;
    }
    public void setGoodsId(String goodsId) {
        this.goodsId = goodsId;
    }
    public String getGoodsName() {
        return goodsName;
    }
    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }
    public String getQuantity() {
        return quantity;
    }
    public void setQuantity(String quantity) {
        this.quantity = quantity;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/QueryOrder.java
New file
@@ -0,0 +1,31 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
public class QueryOrder {
    /**业务类型编号,必须和接口文档一致*/
    public static String SERVICE_CODE = "queryOrder";
    /**
     * 原请求订单号
     */
    private String originalMerOrderId;
    /**
     * 查询类型
     */
    private String queryType;
    public String getOriginalMerOrderId() {
        return originalMerOrderId;
    }
    public void setOriginalMerOrderId(String originalMerOrderId) {
        this.originalMerOrderId = originalMerOrderId;
    }
    public String getQueryType() {
        return queryType;
    }
    public void setQueryType(String queryType) {
        this.queryType = queryType;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/Receive.java
New file
@@ -0,0 +1,102 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
import java.util.List;
/**
 * 确认收货信息参数
 */
public class Receive {
    /**业务类型编号,必须和接口文档一致*/
    public static String SERVICE_CODE = "receive";
    /**
     * 原支付请求订单号(必填)
     */
    private String originalMerOrderId;
    /**
     * 异步分账订单号(多次异步确认订单进行确认收货时必传)
     */
    private String asynMerOrderId;
    /**
     * 确认收货总额(必填)
     * 必须大于0
     * 确认收货总额=总确认分账金额
     */
    private String rcvAmount;
    /**
     * 分账方列表(必填)
     */
    private List<ReceiveUser> splitList;
    /**
     * 商品列表
     */
    private List<ReceiveGood> goodsDetail;
    /**
     * 自定义参数1
     */
    private String parameter1;
    /**
     * 自定义参数2
     */
    private String parameter2;
    public String getOriginalMerOrderId() {
        return originalMerOrderId;
    }
    public void setOriginalMerOrderId(String originalMerOrderId) {
        this.originalMerOrderId = originalMerOrderId;
    }
    public String getAsynMerOrderId() {
        return asynMerOrderId;
    }
    public void setAsynMerOrderId(String asynMerOrderId) {
        this.asynMerOrderId = asynMerOrderId;
    }
    public String getRcvAmount() {
        return rcvAmount;
    }
    public void setRcvAmount(String rcvAmount) {
        this.rcvAmount = rcvAmount;
    }
    public List<ReceiveUser> getSplitList() {
        return splitList;
    }
    public void setSplitList(List<ReceiveUser> splitList) {
        this.splitList = splitList;
    }
    public List<ReceiveGood> getGoodsDetail() {
        return goodsDetail;
    }
    public void setGoodsDetail(List<ReceiveGood> goodsDetail) {
        this.goodsDetail = goodsDetail;
    }
    public String getParameter1() {
        return parameter1;
    }
    public void setParameter1(String parameter1) {
        this.parameter1 = parameter1;
    }
    public String getParameter2() {
        return parameter2;
    }
    public void setParameter2(String parameter2) {
        this.parameter2 = parameter2;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/ReceiveGood.java
New file
@@ -0,0 +1,48 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
public class ReceiveGood {
    /** 商品编号 */
    private String goodsId;
    /** 商品名称,必填 */
    private String goodsName;
    /** 商品数量 */
    private String quantity;
    /** 商品价格 */
    private String price;
    public String getGoodsId() {
        return goodsId;
    }
    public void setGoodsId(String goodsId) {
        this.goodsId = goodsId;
    }
    public String getGoodsName() {
        return goodsName;
    }
    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }
    public String getQuantity() {
        return quantity;
    }
    public void setQuantity(String quantity) {
        this.quantity = quantity;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/ReceiveUser.java
New file
@@ -0,0 +1,27 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
public class ReceiveUser {
    /** 分账方会员ID,必填 */
    private String splitUserId;
    /** 确认分账金额,必填 */
    private String rcvSplitAmount;
    public String getSplitUserId() {
        return splitUserId;
    }
    public void setSplitUserId(String splitUserId) {
        this.splitUserId = splitUserId;
    }
    public String getRcvSplitAmount() {
        return rcvSplitAmount;
    }
    public void setRcvSplitAmount(String rcvSplitAmount) {
        this.rcvSplitAmount = rcvSplitAmount;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/MallBook/model/Withdraw.java
New file
@@ -0,0 +1,96 @@
package com.supersavedriving.driver.modular.system.util.MallBook.model;
public class Withdraw {
    /**业务类型编号,必须和接口文档一致*/
    public static String SERVICE_CODE = "withdraw";
    /**
     * 子商户编号(必填)
     */
    private String userId;
    /**
     * 结算金额(必填)
     */
    private String amount;
    /**
     * 订单名称
     */
    private String orderName;
    /**
     * 备注
     */
    private String remark;
    /**
     * 后台回调地址(必填)
     */
    private String notifyUrl;
    /**
     * 自定义参数1
     */
    private String parameter1;
    /**
     * 自定义参数2
     */
    private String parameter2;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getAmount() {
        return amount;
    }
    public void setAmount(String amount) {
        this.amount = amount;
    }
    public String getOrderName() {
        return orderName;
    }
    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public String getNotifyUrl() {
        return notifyUrl;
    }
    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }
    public String getParameter1() {
        return parameter1;
    }
    public void setParameter1(String parameter1) {
        this.parameter1 = parameter1;
    }
    public String getParameter2() {
        return parameter2;
    }
    public void setParameter2(String parameter2) {
        this.parameter2 = parameter2;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/WeChatUtil.java
File was deleted
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/AES.java
New file
@@ -0,0 +1,72 @@
package com.supersavedriving.driver.modular.system.util.weChat;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
/**
* AES加密
* @author pzb
* @Date 2021/12/3 15:43
*/
public class AES {
    public static boolean initialized = false;
    /**
     * AES解密
     *
     * @param content
     *            密文
     * @return
     * @throws InvalidAlgorithmParameterException
     * @throws NoSuchProviderException
     */
    public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            Key sKeySpec = new SecretKeySpec(keyByte, "AES");
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    public static void initialize() {
        if (initialized)
            return;
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }
    // 生成iv
    public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(iv));
        return params;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/AesException.java
New file
@@ -0,0 +1,59 @@
package com.supersavedriving.driver.modular.system.util.weChat;
@SuppressWarnings("serial")
public class AesException extends Exception {
    public final static int OK = 0;
    public final static int ValidateSignatureError = -40001;
    public final static int ParseXmlError = -40002;
    public final static int ComputeSignatureError = -40003;
    public final static int IllegalAesKey = -40004;
    public final static int ValidateAppidError = -40005;
    public final static int EncryptAESError = -40006;
    public final static int DecryptAESError = -40007;
    public final static int IllegalBuffer = -40008;
    //public final static int EncodeBase64Error = -40009;
    //public final static int DecodeBase64Error = -40010;
    //public final static int GenReturnXmlError = -40011;
    private int code;
    private static String getMessage(int code) {
        switch (code) {
        case ValidateSignatureError:
            return "签名验证错误";
        case ParseXmlError:
            return "xml解析失败";
        case ComputeSignatureError:
            return "sha加密生成签名失败";
        case IllegalAesKey:
            return "SymmetricKey非法";
        case ValidateAppidError:
            return "appid校验失败";
        case EncryptAESError:
            return "aes加密失败";
        case DecryptAESError:
            return "aes解密失败";
        case IllegalBuffer:
            return "解密后得到的buffer非法";
//        case EncodeBase64Error:
//            return "base64加密错误";
//        case DecodeBase64Error:
//            return "base64解密错误";
//        case GenReturnXmlError:
//            return "xml生成失败";
        default:
            return null; // cannot be
        }
    }
    public int getCode() {
        return code;
    }
    AesException(int code) {
        super(getMessage(code));
        this.code = code;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/ByteGroup.java
New file
@@ -0,0 +1,26 @@
package com.supersavedriving.driver.modular.system.util.weChat;
import java.util.ArrayList;
class ByteGroup {
    ArrayList<Byte> byteContainer = new ArrayList<Byte>();
    public byte[] toBytes() {
        byte[] bytes = new byte[byteContainer.size()];
        for (int i = 0; i < byteContainer.size(); i++) {
            bytes[i] = byteContainer.get(i);
        }
        return bytes;
    }
    public ByteGroup addBytes(byte[] bytes) {
        for (byte b : bytes) {
            byteContainer.add(b);
        }
        return this;
    }
    public int size() {
        return byteContainer.size();
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/PKCS7Encoder.java
New file
@@ -0,0 +1,67 @@
/**
 * 对公众平台发送给公众账号的消息加解密示例代码.
 *
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */
// ------------------------------------------------------------------------
package com.supersavedriving.driver.modular.system.util.weChat;
import java.nio.charset.Charset;
import java.util.Arrays;
/**
 * 提供基于PKCS7算法的加解密接口.
 */
class PKCS7Encoder {
    static Charset CHARSET = Charset.forName("utf-8");
    static int BLOCK_SIZE = 32;
    /**
     * 获得对明文进行补位填充的字节.
     *
     * @param count 需要进行填充补位操作的明文字节个数
     * @return 补齐用的字节数组
     */
    static byte[] encode(int count) {
        // 计算需要填充的位数
        int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
        if (amountToPad == 0) {
            amountToPad = BLOCK_SIZE;
        }
        // 获得补位所用的字符
        char padChr = chr(amountToPad);
        String tmp = new String();
        for (int index = 0; index < amountToPad; index++) {
            tmp += padChr;
        }
        return tmp.getBytes(CHARSET);
    }
    /**
     * 删除解密后明文的补位字符
     *
     * @param decrypted 解密后的明文
     * @return 删除补位字符后的明文
     */
    static byte[] decode(byte[] decrypted) {
        int pad = (int) decrypted[decrypted.length - 1];
        if (pad < 1 || pad > 32) {
            pad = 0;
        }
        return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
    }
    /**
     * 将数字转化成ASCII码对应的字符,用于对明文进行补码
     *
     * @param a 需要转化的数字
     * @return 转化得到的字符
     */
    static char chr(int a) {
        byte target = (byte) (a & 0xFF);
        return (char) target;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/SHA1.java
New file
@@ -0,0 +1,61 @@
/**
 * 对公众平台发送给公众账号的消息加解密示例代码.
 *
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */
// ------------------------------------------------------------------------
package com.supersavedriving.driver.modular.system.util.weChat;
import java.security.MessageDigest;
import java.util.Arrays;
/**
 * SHA1 class
 *
 * 计算公众平台的消息签名接口.
 */
public class SHA1 {
    /**
     * 用SHA1算法生成安全签名
     * @param token 票据
     * @param timestamp 时间戳
     * @param nonce 随机字符串
     * @param encrypt 密文
     * @return 安全签名
     * @throws AesException
     */
    public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException
              {
        try {
            String[] array = new String[] { token, timestamp, nonce, encrypt };
            StringBuffer sb = new StringBuffer();
            // 字符串排序
            Arrays.sort(array);
            for (int i = 0; i < 4; i++) {
                sb.append(array[i]);
            }
            String str = sb.toString();
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();
            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.ComputeSignatureError);
        }
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WXBizMsgCrypt.java
New file
@@ -0,0 +1,288 @@
/**
 * 对公众平台发送给公众账号的消息加解密示例代码.
 *
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */
// ------------------------------------------------------------------------
/**
 * 针对org.apache.commons.codec.binary.Base64,
 * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
 * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
 */
package com.supersavedriving.driver.modular.system.util.weChat;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Random;
/**
 * 提供接收和推送给公众平台消息的加解密接口(UTF8编码的字符串).
 * <ol>
 *     <li>第三方回复加密消息给公众平台</li>
 *     <li>第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。</li>
 * </ol>
 * 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案
 * <ol>
 *     <li>在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:
 *      http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html</li>
 *     <li>下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt</li>
 *     <li>如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件</li>
 *     <li>如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件</li>
 * </ol>
 */
public class WXBizMsgCrypt {
    static Charset CHARSET = Charset.forName("utf-8");
    Base64 base64 = new Base64();
    byte[] aesKey;
    String token;
    String appId;
    /**
     * 构造函数
     * @param token 公众平台上,开发者设置的token
     * @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey
     * @param appId 公众平台appid
     *
     * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
     */
    public WXBizMsgCrypt(String token, String encodingAesKey, String appId) throws AesException {
        if (encodingAesKey.length() != 43) {
            throw new AesException(AesException.IllegalAesKey);
        }
        this.token = token;
        this.appId = appId;
        aesKey = Base64.decodeBase64(encodingAesKey + "=");
    }
    // 生成4个字节的网络字节序
    byte[] getNetworkBytesOrder(int sourceNumber) {
        byte[] orderBytes = new byte[4];
        orderBytes[3] = (byte) (sourceNumber & 0xFF);
        orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF);
        orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF);
        orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF);
        return orderBytes;
    }
    // 还原4个字节的网络字节序
    int recoverNetworkBytesOrder(byte[] orderBytes) {
        int sourceNumber = 0;
        for (int i = 0; i < 4; i++) {
            sourceNumber <<= 8;
            sourceNumber |= orderBytes[i] & 0xff;
        }
        return sourceNumber;
    }
    // 随机生成16位字符串
    String getRandomStr() {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 16; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
    /**
     * 对明文进行加密.
     *
     * @param text 需要加密的明文
     * @return 加密后base64编码的字符串
     * @throws AesException aes加密失败
     */
    String encrypt(String randomStr, String text) throws AesException {
        ByteGroup byteCollector = new ByteGroup();
        byte[] randomStrBytes = randomStr.getBytes(CHARSET);
        byte[] textBytes = text.getBytes(CHARSET);
        byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length);
        byte[] appidBytes = appId.getBytes(CHARSET);
        // randomStr + networkBytesOrder + text + appid
        byteCollector.addBytes(randomStrBytes);
        byteCollector.addBytes(networkBytesOrder);
        byteCollector.addBytes(textBytes);
        byteCollector.addBytes(appidBytes);
        // ... + pad: 使用自定义的填充方式对明文进行补位填充
        byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
        byteCollector.addBytes(padBytes);
        // 获得最终的字节流, 未加密
        byte[] unencrypted = byteCollector.toBytes();
        try {
            // 设置加密模式为AES的CBC模式
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
            IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
            // 加密
            byte[] encrypted = cipher.doFinal(unencrypted);
            // 使用BASE64对加密后的字符串进行编码
            String base64Encrypted = base64.encodeToString(encrypted);
            return base64Encrypted;
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.EncryptAESError);
        }
    }
    /**
     * 对密文进行解密.
     *
     * @param text 需要解密的密文
     * @return 解密得到的明文
     * @throws AesException aes解密失败
     */
    String decrypt(String text) throws AesException {
        byte[] original;
        try {
            // 设置解密模式为AES的CBC模式
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
            cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
            // 使用BASE64对密文进行解码
            byte[] encrypted = Base64.decodeBase64(text);
            // 解密
            original = cipher.doFinal(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.DecryptAESError);
        }
        String xmlContent, from_appid;
        try {
            // 去除补位字符
            byte[] bytes = PKCS7Encoder.decode(original);
            // 分离16位随机字符串,网络字节序和AppId
            byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
            int xmlLength = recoverNetworkBytesOrder(networkOrder);
            xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
            from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),
                    CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.IllegalBuffer);
        }
        // appid不相同的情况
        if (!from_appid.equals(appId)) {
            throw new AesException(AesException.ValidateAppidError);
        }
        return xmlContent;
    }
    /**
     * 将公众平台回复用户的消息加密打包.
     * <ol>
     *     <li>对要发送的消息进行AES-CBC加密</li>
     *     <li>生成安全签名</li>
     *     <li>将消息密文和安全签名打包成xml格式</li>
     * </ol>
     *
     * @param replyMsg 公众平台待回复用户的消息,xml格式的字符串
     * @param timeStamp 时间戳,可以自己生成,也可以用URL参数的timestamp
     * @param nonce 随机串,可以自己生成,也可以用URL参数的nonce
     *
     * @return 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串
     * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
     */
    public String encryptMsg(String replyMsg, String timeStamp, String nonce) throws AesException {
        // 加密
        String encrypt = encrypt(getRandomStr(), replyMsg);
        // 生成安全签名
        if (timeStamp == "") {
            timeStamp = Long.toString(System.currentTimeMillis());
        }
        String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt);
        // System.out.println("发送给平台的签名是: " + signature[1].toString());
        // 生成发送的xml
        String result = XMLParse.generate(encrypt, signature, timeStamp, nonce);
        return result;
    }
    /**
     * 检验消息的真实性,并且获取解密后的明文.
     * <ol>
     *     <li>利用收到的密文生成安全签名,进行签名验证</li>
     *     <li>若验证通过,则提取xml中的加密消息</li>
     *     <li>对消息进行解密</li>
     * </ol>
     *
     * @param msgSignature 签名串,对应URL参数的msg_signature
     * @param timeStamp 时间戳,对应URL参数的timestamp
     * @param nonce 随机串,对应URL参数的nonce
     * @param postData 密文,对应POST请求的数据
     *
     * @return 解密后的原文
     * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
     */
    public String decryptMsg(String msgSignature, String timeStamp, String nonce, String postData)
            throws AesException {
        // 密钥,公众账号的app secret
        // 提取密文
        Object[] encrypt = XMLParse.extract(postData);
        // 验证安全签名
        String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString());
        // 和URL中的签名比较是否相等
        // System.out.println("第三方收到URL中的签名:" + msg_sign);
        // System.out.println("第三方校验签名:" + signature);
        if (!signature.equals(msgSignature)) {
            throw new AesException(AesException.ValidateSignatureError);
        }
        // 解密
        String result = decrypt(encrypt[1].toString());
        return result;
    }
    /**
     * 验证URL
     * @param msgSignature 签名串,对应URL参数的msg_signature
     * @param timeStamp 时间戳,对应URL参数的timestamp
     * @param nonce 随机串,对应URL参数的nonce
     * @param echoStr 随机串,对应URL参数的echostr
     *
     * @return 解密之后的echostr
     * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
     */
    public String verifyUrl(String msgSignature, String timeStamp, String nonce, String echoStr)
            throws AesException {
        String signature = SHA1.getSHA1(token, timeStamp, nonce, "");
        if (!signature.equals(msgSignature)) {
            throw new AesException(AesException.ValidateSignatureError);
        }
        String result = decrypt(echoStr);
        return result;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WXCore.java
New file
@@ -0,0 +1,52 @@
package com.supersavedriving.driver.modular.system.util.weChat;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
public class WXCore {
    private static Logger logger = LoggerFactory.getLogger(WXCore.class);
    private static final String WATERMARK = "watermark";
    @Value("${wx.appletsAppid}")
    private static String appid ;
    /**
     * 解密数据
     * @return
     * @throws Exception
     */
    public static String decrypt(String encryptedData, String sessionKey, String iv){
        String result = "";
        try {
            AES aes = new AES();
            byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
            if(null != resultByte && resultByte.length > 0){
                result = new String(WxPKCS7Encoder.decode(resultByte), "UTF-8");
//                JSONObject jsonObject = JSON.parseObject(result);
//                String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString("appid");
//                if(!appid.equals(decryptAppid)){
//                    result = "";
//                }
            }
        } catch (Exception e) {
            result = "";
            e.printStackTrace();
        }
        return result;
    }
    public static void main(String[] args) throws Exception{
        String appId = "wx4f4bc4dec97d474b";
        String encryptedData = "ajhisfk0EhWCBcoxt/5QJA3bKPTygQXANbCSev92MyqIqGxRhzZFS1SlQrIWAo3tx8YfsB+VlScZNOlRyfnXKqPUl9h+PDeKsTkTst9V4pq4mUbI+r3AautXBffVk/rpyjMfanVsWeOlxkupdv2U9U4BrueR/Rak+TCmHTWUUf8eDLoi6nioL/Pft/rYaO3JD54hgpcY0Ef/k7Boyap4E0/uKVowY1ANO7KVydSXE6S7OKzXuzmDTbV38v+7ryMHtglUzoKzF1gL8y9OZRwkaesfHN1kfItjpsAibjSgkIiiW6ZEHLT2n1UDkJtfUqg63je2cJAH7gzeUm9TCDDftdhLU+NuPk3j/LXyFQ05pJ8B19+kIXF3dcmHOH7lFvi7yGmVuAD/9AnetGWgId3TZDS/OjbiVUM30RogeziAw98VpAyAAq1r2ULFwi8e928m";
        String sessionKey = "CdxFGwXIluQFZ+qD+NSFKQ==";
        String iv = "3FD8r1Spwlf7LG8YEq41+Q==";
        logger.debug(decrypt(encryptedData, sessionKey, iv));
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WeChatUtil.java
New file
@@ -0,0 +1,415 @@
package com.supersavedriving.driver.modular.system.util.weChat;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.supersavedriving.driver.core.util.ToolUtil;
import com.supersavedriving.driver.modular.system.util.RedisUtil;
import com.supersavedriving.driver.modular.system.util.UUIDUtil;
import com.supersavedriving.driver.modular.system.util.httpClinet.HttpClientUtil;
import com.supersavedriving.driver.modular.system.util.httpClinet.HttpResult;
import com.supersavedriving.driver.modular.system.util.weChat.model.Code2Session;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
/**
 * 微信工具类
 */
@Component
public class WeChatUtil {
    private static Logger logger = LoggerFactory.getLogger(WeChatUtil.class);
    @Value("${wx.appletsAppid}")
    private String wxAppletsAppid;
    @Value("${wx.appletsAppSecret}")
    private String wxAppletsAppSecret;
    @Value("${wx.officialAccountAppid}")
    private String officialAccountAppid;
    @Value("{wx.officialAccountAppSecret}")
    private String officialAccountAppSecret;
    @Value("${wx.appid}")
    private String webAppId;
    @Value("${wx.appSecret}")
    private String webAppSecret;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RedisUtil redisUtil;
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(30000);
                    new Timer().schedule(new TimerTask() {
                        @Override
                        public void run() {
                            try {
                                String wxAppletsAccessToken = getWxAppletsAccessToken();
                                if(ToolUtil.isEmpty(wxAppletsAccessToken)){
                                    System.err.println("获取微信小程序access_token失败");
                                    return;
                                }
                                redisUtil.setStrValue("wxAppletsAccessToken", wxAppletsAccessToken, 7000);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }, 0, 7000000);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }
    /**
     * 小程序使用jscode获取openid
     * @param jscode
     * @return
     */
    public Code2Session code2Session(String jscode) throws Exception{
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxAppletsAppid + "&secret=" + wxAppletsAppSecret
                + "&js_code=" + jscode + "&grant_type=authorization_code";
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(null == httpResult || httpResult.getCode() != 200){
            return null;
        }
        Code2Session code2Session = JSON.parseObject(httpResult.getData(), Code2Session.class);
        return code2Session;
    }
    /**
     * 获取微信小程序token
     * @return
     */
    public String getWxAppletsAccessToken() throws Exception{
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + wxAppletsAppid + "&secret=" + wxAppletsAppSecret;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return "";
        }
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        return jsonObject.getString("access_token");
    }
    /***
     * 获取jsapiTicket(小程序)
     * 来源 www.vxzsk.com
     * @return
     */
    public String getWxAppletsJSApiTicket() throws Exception{
        String wxAppletsAccessToken = redisUtil.getValue("wxAppletsAccessToken");
        String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + wxAppletsAccessToken + "&type=jsapi";
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", urlStr, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
        logger.debug(httpResult.getData());
        String ticket = JSONObject.parseObject(httpResult.getData()).getString("ticket");
        return  ticket;
    }
    /**
     * 通过config接口注入权限验证配置(小程序)
     * 附录1-JS-SDK使用权限签名算法,
     * @return
     */
    public Map<String,Object> getWxAppletsSignatureConfig(String url) throws Exception{
        //获取token
        try {
            url = URLDecoder.decode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String ticket = getWxAppletsJSApiTicket();
        String noncestr = UUIDUtil.getRandomCode();
        Long timestamp = System.currentTimeMillis();
        String content = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        String signature = DigestUtils.sha1Hex(content);
        Map<String,Object> map=new HashMap<>();
        map.put("appId", wxAppletsAppid);
        map.put("timestamp", timestamp);
        map.put("nonceStr", noncestr);
        map.put("signature", signature);
        return  map;
    }
    /**
     * 网站应用登录
     * @param code
     * @return
     */
    public Map<String, String> webAccessToken(String code) throws Exception{
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + webAppId + "&secret=" + webAppSecret + "&code=" + code + "&grant_type=authorization_code";
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        int errcode = jsonObject.getIntValue("errcode");
        Map<String, String> map = new HashMap<>();
        if(errcode == 0){//成功
            map.put("access_token", jsonObject.getString("access_token"));
            map.put("openid", jsonObject.getString("openid"));
            map.put("refresh_token", jsonObject.getString("refresh_token"));
            map.put("unionid", jsonObject.getString("unionid"));
            return map;
        }
        if(errcode == -1){//系统繁忙,此时请开发者稍候再试
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        if(errcode == 40029){//code 无效
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        if(errcode == 45011){//频率限制,每个用户每分钟100次
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        return map;
    }
    /**
     * 获取微信个人信息
     * @param access_token
     * @param openid
     * @return
     */
    public Map<String, Object> getUserInfo(String access_token, String openid) throws Exception{
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(httpResult.getData());
        int errcode = jsonObject.getIntValue("errcode");
        Map<String, Object> map = new HashMap<>();
        if(errcode == 0){//成功
            map.put("nickname", jsonObject.getString("nickname"));
            map.put("openid", jsonObject.getString("openid"));
            map.put("sex", jsonObject.getString("sex"));
            map.put("headimgurl", jsonObject.getString("headimgurl"));
            return map;
        }
        if(errcode == -1){//系统繁忙,此时请开发者稍候再试
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        if(errcode == 40029){//code 无效
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        if(errcode == 45011){//频率限制,每个用户每分钟100次
            map.put("msg", jsonObject.getString("errmsg"));
            return map;
        }
        return map;
    }
    /**
     * 公众号获取openid
     * @param code
     * @return
     */
    public Map<String,Object> getOpenId(String code) throws Exception{
        if (code == null || code.length() == 0) {
            return null;
        }
        String grantType = "authorization_code";
        String params = "appid=" + officialAccountAppid + "&secret=" + officialAccountAppSecret + "&code=" + code + "&grant_type=" + grantType;
        logger.debug("sssss"+params);
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", "https://api.weixin.qq.com/sns/oauth2/access_token?" + params, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
        JSONObject json = JSON.parseObject(httpResult.getData());
        logger.debug(json.toJSONString());
        String openId = json.get("openid").toString();
        String accessToken = json.get("access_token").toString();
        Integer expiresIn = json.getInteger("expires_in");
        String refresh_token = json.getString("refresh_token");
        String unionid = json.getString("unionid");
        Map<String,Object> map=new HashMap<>();
        map.put("openId",openId);
        map.put("accessToken",accessToken);
        map.put("expiresIn", expiresIn);
        map.put("refreshToken", refresh_token);
        map.put("unionid", unionid);
        return map;
    }
    /***
     * 获取acess_token (公众号)
     * 来源www.vxzsk.com
     * @return
     */
    public String getAccessToken() throws Exception{
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + officialAccountAppid
                + "&secret=" + officialAccountAppSecret;
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
        String accessToken = JSONObject.parseObject(httpResult.getData()).getString("access_token");
        return accessToken;
    }
    /***
     * 获取jsapiTicket(公众号)
     * 来源 www.vxzsk.com
     * @return
     */
    public String getJSApiTicket() throws Exception{
        //获取token
        String acess_token = redisUtil.getValue("acess_token");
        String urlStr = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + acess_token + "&type=jsapi";
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", urlStr, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
        logger.debug(httpResult.getData());
        String ticket = JSONObject.parseObject(httpResult.getData()).getString("ticket");
        return  ticket;
    }
    /**
     * 通过config接口注入权限验证配置(公众号)
     * 附录1-JS-SDK使用权限签名算法,
     * @return
     */
    public Map<String,Object> getSignatureConfig(String url) throws Exception{
        //获取token
        try {
            url = URLDecoder.decode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String ticket = getJSApiTicket();
        String noncestr = UUIDUtil.getRandomCode();
        Long timestamp = System.currentTimeMillis();
        String content = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        String signature = DigestUtils.sha1Hex(content);
        Map<String,Object> map=new HashMap<>();
        map.put("appId", officialAccountAppid);
        map.put("timestamp", timestamp);
        map.put("nonceStr", noncestr);
        map.put("signature", signature);
        return  map;
    }
    /**
     * 公众号获取用户个人信息
     * @param access_token
     * @param openid
     * @return
     */
    public Map<String, Object> queryUserInfo(String access_token, String openid) throws Exception{
        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid + "&lang=zh_CN";
        HttpResult httpResult = HttpClientUtil.pushHttpRequset("GET", url, null, null, "form");
        if(httpResult.getCode() != 200){
            return null;
        }
        logger.debug(httpResult.getData());
        JSONObject j = JSON.parseObject(httpResult.getData());
        Map<String, Object> map = new HashMap<>();
        map.put("nickname", j.getString("nickname"));
        map.put("sex", j.getInteger("sex"));
        map.put("headimgurl", j.getString("headimgurl"));
        map.put("unionid", j.getString("unionid"));
        return map;
    }
    /**
     * 获取小程序二维码
     * @param page      跳转页 例如 pages/index/index
     * @param scene     参数 a=1&b=2
     */
    public InputStream getwxacodeunlimit(String page, String scene, String envVersion) throws Exception{
        try {
            String wxAppletsAccessToken = redisUtil.getValue("wxAppletsAccessToken");
            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + wxAppletsAccessToken;
            Map<String, Object> param = new HashMap<>();
            param.put("scene", scene);
            param.put("page", page);
            param.put("env_version", envVersion);
            HttpHeaders httpHeaders = new HttpHeaders();
            MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
            httpHeaders.setContentType(type);
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(param, httpHeaders);
            ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class, new Object[0]);
            String body1 = exchange.getBody();
//            System.err.println(body1);
            ResponseEntity<byte[]> entity  = restTemplate.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
            byte[] body = entity.getBody();
//            System.err.println(Base64.encodeBase64String(body));
            return new ByteArrayInputStream(body);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取小程序urlscheme码
     * @return
     */
    public String getUrlscheme(String path) throws Exception{
        String wxAppletsAccessToken = redisUtil.getValue("wxAppletsAccessToken");
        String url = "https://api.weixin.qq.com/wxa/generatescheme?access_token=" + wxAppletsAccessToken;
        Map<String, Object> param = new HashMap<>();
        param.put("is_expire", true);
        param.put("expire_type", 1);
        param.put("expire_interval", 180);
        Map<String, Object> map1 = new HashMap<>();
        map1.put("path", path);
        map1.put("query", "");
        map1.put("env_version", "release");
        param.put("jump_wxa", map1);
        HttpHeaders httpHeaders = new HttpHeaders();
        MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
        httpHeaders.setContentType(type);
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(param, httpHeaders);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        String body1 = exchange.getBody();
        return body1;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/WxPKCS7Encoder.java
New file
@@ -0,0 +1,63 @@
package com.supersavedriving.driver.modular.system.util.weChat;
import java.nio.charset.Charset;
import java.util.Arrays;
/**
* 微信小程序加解密
* @author pzb
* @Date 2021/12/3 15:43
*/
public class WxPKCS7Encoder {
    private static final Charset CHARSET = Charset.forName("utf-8");
    private static final int BLOCK_SIZE = 32;
    /**
     * 获得对明文进行补位填充的字节.
     *
     * @param count
     *            需要进行填充补位操作的明文字节个数
     * @return 补齐用的字节数组
     */
    public static byte[] encode(int count) {
        // 计算需要填充的位数
        int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
        if (amountToPad == 0) {
            amountToPad = BLOCK_SIZE;
        }
        // 获得补位所用的字符
        char padChr = chr(amountToPad);
        String tmp = new String();
        for (int index = 0; index < amountToPad; index++) {
            tmp += padChr;
        }
        return tmp.getBytes(CHARSET);
    }
    /**
     * 删除解密后明文的补位字符
     *
     * @param decrypted
     *            解密后的明文
     * @return 删除补位字符后的明文
     */
    public static byte[] decode(byte[] decrypted) {
        int pad = decrypted[decrypted.length - 1];
        if (pad < 1 || pad > 32) {
            pad = 0;
        }
        return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
    }
    /**
     * 将数字转化成ASCII码对应的字符,用于对明文进行补码
     *
     * @param a
     *            需要转化的数字
     * @return 转化得到的字符
     */
    public static char chr(int a) {
        byte target = (byte) (a & 0xFF);
        return (char) target;
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/XMLParse.java
New file
@@ -0,0 +1,71 @@
/**
 * 对公众平台发送给公众账号的消息加解密示例代码.
 *
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */
// ------------------------------------------------------------------------
package com.supersavedriving.driver.modular.system.util.weChat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
/**
 * XMLParse class
 *
 * 提供提取消息格式中的密文及生成回复消息格式的接口.
 */
class XMLParse {
    /**
     * 提取出xml数据包中的加密消息
     * @param xmltext 待提取的xml字符串
     * @return 提取出的加密消息字符串
     * @throws AesException
     */
    public static Object[] extract(String xmltext) throws AesException     {
        Object[] result = new Object[3];
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            StringReader sr = new StringReader(xmltext);
            InputSource is = new InputSource(sr);
            Document document = db.parse(is);
            Element root = document.getDocumentElement();
            NodeList nodelist1 = root.getElementsByTagName("Encrypt");
            NodeList nodelist2 = root.getElementsByTagName("ToUserName");
            result[0] = 0;
            result[1] = nodelist1.item(0).getTextContent();
            result[2] = nodelist2.item(0).getTextContent();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.ParseXmlError);
        }
    }
    /**
     * 生成xml消息
     * @param encrypt 加密后的消息密文
     * @param signature 安全签名
     * @param timestamp 时间戳
     * @param nonce 随机字符串
     * @return 生成的xml字符串
     */
    public static String generate(String encrypt, String signature, String timestamp, String nonce) {
        String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n"
                + "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n"
                + "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n" + "</xml>";
        return String.format(format, encrypt, signature, timestamp, nonce);
    }
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/Category.java
New file
@@ -0,0 +1,18 @@
package com.supersavedriving.driver.modular.system.util.weChat.model;
import lombok.Data;
/**
 * 订阅消息类目
 */
@Data
public class Category {
    /**
     * 类目id
     */
    private String id;
    /**
     * 类目名称
     */
    private String name;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/Code2Session.java
New file
@@ -0,0 +1,33 @@
package com.supersavedriving.driver.modular.system.util.weChat.model;
import lombok.Data;
/**
 * TODO
 *
 * @author 39373
 * @date 2023/2/26 19:42
 */
@Data
public class Code2Session {
    /**
     * 状态码(-1=系统繁忙,0=成功,40029=code无效,45011=频率限制,每个用户每分钟100次,40226=高风险等级用户,小程序登录拦截 )
     */
    private Integer errcode;
    /**
     * 状态说明
     */
    private String errmsg;
    /**
     * openid
     */
    private String openid;
    /**
     * sessionKey
     */
    private String session_key;
    /**
     * unionid
     */
    private String unionid;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/KeywordEnum.java
New file
@@ -0,0 +1,17 @@
package com.supersavedriving.driver.modular.system.util.weChat.model;
import lombok.Data;
import java.util.List;
@Data
public class KeywordEnum {
    /**
     * 枚举参数的 key
     */
    private String keywordCode;
    /**
     * 枚举参数值范围列表
     */
    private List<String> enumValueList;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/MessageTemplate.java
New file
@@ -0,0 +1,36 @@
package com.supersavedriving.driver.modular.system.util.weChat.model;
import lombok.Data;
import java.util.List;
/**
 * 消息模板
 */
@Data
public class MessageTemplate {
    /**
     * 添加至帐号下的模板 id,发送小程序订阅消息时所需
     */
    private String priTmplId;
    /**
     * 模版标题
     */
    private String title;
    /**
     * 模版内容
     */
    private String content;
    /**
     * 模板内容示例
     */
    private String example;
    /**
     * 模版类型,2 为一次性订阅,3 为长期订阅
     */
    private Integer type;
    /**
     * 枚举参数值范围
     */
    private List<KeywordEnum> keywordEnumValueList;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/PubTemplateKeywords.java
New file
@@ -0,0 +1,26 @@
package com.supersavedriving.driver.modular.system.util.weChat.model;
import lombok.Data;
/**
 * 公共消息模板关键字
 */
@Data
public class PubTemplateKeywords {
    /**
     * 关键词 id,选用模板时需要
     */
    private Integer kid;
    /**
     * 关键词内容
     */
    private String name;
    /**
     * 关键词内容对应的示例
     */
    private String example;
    /**
     * 参数类型
     */
    private String rule;
}
driver/guns-admin/src/main/java/com/supersavedriving/driver/modular/system/util/weChat/model/PubTemplatetitles.java
New file
@@ -0,0 +1,26 @@
package com.supersavedriving.driver.modular.system.util.weChat.model;
import lombok.Data;
/**
 * 功能模板
 */
@Data
public class PubTemplatetitles {
    /**
     * 模版标题 id
     */
    private Integer tid;
    /**
     * 模版标题
     */
    private String title;
    /**
     * 模版类型,2 为一次性订阅,3 为长期订阅
     */
    private Integer type;
    /**
     * 模版所属类目 id
     */
    private Integer categoryId;
}
driver/guns-admin/src/main/resources/application.yml
@@ -79,8 +79,12 @@
  grantType: authorization_code #填authorization_code
  appid: wx8a9af3889395d0e1 #应用唯一标识,在微信开放平台提交应用审核通过后获得
  appSecret: 95a34f114973298cce4297a20bb59bc3 #应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
  appletsAppid: 1 #小程序APPid
  appletsAppSecret: 1 #
  appletsAppid: wx8ae6c610563f2fe6 #小程序APPid
  appletsAppSecret: 8b2c93b0be4f017350050f1e660680fe #
  officialAccountAppid: 11111
  officialAccountAppSecret: 1111
  webAppId: 111
  webAppSecret: 11
  mchId: 1636941942 #微信支付分配的商户号
  key: Eri2GR2SB3b6iIhaoD7k3KQ8X0wf1Ybh #key为商户平台设置的密钥key:
  apiv3: AKJ51Z4nhSqYBxmOXgUyCKA1vLP0J5Aj #key为商户平台设置的密钥key:
@@ -88,10 +92,10 @@
---
alipay:
  appid: 2021001161600393  #应用程序唯一标识
  appPrivateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCEbTcG2wz+kaYDo2YxflpHE59MvKc3rbl6RlBgO6i5GzgphzeRTv5kRWUpSVkKCsbxFvAYLcgFPmm5nY2fz5hCTKiRcYfpUjH/OougUbzYU3ilUc9JqMbmvy7KN+Kv7+kQYCGLvMqlyYPiJ7LrmJLpE/FUcNLDwo6xUmwJSxaF7M4TbD3ZQZdddki1iJp9GihlqehZCMWOBeotEXvPKDEzSEkYlnvHPQaaspVgeesGmlHDuOiZUokENutxpjo7klWe97NA49hXEtI+xlczNGJKdBr0keBX/kSMsnx8kMxYDjh4QTySBaR6zlO4RYPFekWv9QZ2CrfiKCS7AHUpZYZ5AgMBAAECggEAXjCoUPIBHhhOcowIJe/vGlr0lUohzdJ8+GGGzcvhSDf6DF+mwG3lN0C8oU8QS7o6okRkZW46tLAd1u4fS6oGbDHGPBz6RJQ4B4eGxHMe1OcaCsxTmdq4DmuxRhfV3rnPldwqQA/6O01HxtXhxvzwkWOj5SGSZ7a8c5diTIHh9ULd6neUI/rIFC97mH1TeW0uDIxAtyvswz0pIfDhAR+lsOyTg/8qzsIXjpBFG4gAVxhUeUqQA5HzbsFglC08V7ViDk1OEoWi3yIj1CmNdtntJI4cxqLgTK7MNB9udhbN2I9YasuIpZvlAcvPi5R9cYT8vvFBCFGM+i22wtcsQmxdAQKBgQDaD9y6WNmsp+IaAUG3FqbJC8SqwreGIiEflWwVjrd+LuN6yhyr45CobOmhbTz0de8gRJEZKgJZEJcywL1ScrPIC4n1JaG688lk5aR+0Lik5fy1+L6G/CydJoJqlh6KKdwPJmDGpVu/geLJcLkWcYOwL56IL7GK2JI1p607R0x6iQKBgQCbd0n4xG9GkpvW4LDAJiMEhwPu9QcCKIT0mXVXCgMFdWel9bY3+8RSZoziWutaofm9tRHFAqwjbRyOZ+EdckkNsWVkkTnkKGtAhYKgM0GaOwdMFxmvME5WYJ74a5t1jiezDmR3obUBtS2nyQ8CFPUnlimoTR9F6APrth3h8uvwcQKBgFWaCn1AqdrEYNbyjViRVNHxg7fBDohiV3xtjOt9hfzL7VLjipPTlpL3hlNvbZFNxpx1LjyhqCBMif5LeUanbnnmRbbtmeqpDvNDzupVh1Z8TlMlHa4hymW6m1G6MqzsN83es/jnKvgnxd5sGMx9rUN5vhMaHekykVrswu1VVOl5AoGAMDljh7gfMEv/7TqLeT8bM6dR8AivoNrCy0Di5hnj8AiIGzHJ0TnWnxzSbNB5GwcNeew109/NV7vb1MyiRskRoh657eUiiQSEqGIBsAHWQqo2zEKKJA6e7ipQhYyTj3aGGAPJ5FYT2LDDtb0nW6T2ms34pA0wOzYKKU63nEQHLfECgYEAgbbpZJRtPxWB1M/Dg7loguT5O/VUsKefS0JrSD+tJIqYkumH5mejvYW5YEeDdelkvBhAEFUW9JOkzL+1w1g3wz2QQ2aPV/r55cJE3EfOzbwgw6GsO+8UuyiavbFhS3pFZNI0pR5M3u1+SIcLqQCnYLbO11vnEXglB6wjw9/oxPE= #开发者应用私钥
  alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhG03BtsM/pGmA6NmMX5aRxOfTLynN625ekZQYDuouRs4KYc3kU7+ZEVlKUlZCgrG8RbwGC3IBT5puZ2Nn8+YQkyokXGH6VIx/zqLoFG82FN4pVHPSajG5r8uyjfir+/pEGAhi7zKpcmD4iey65iS6RPxVHDSw8KOsVJsCUsWhezOE2w92UGXXXZItYiafRooZanoWQjFjgXqLRF7zygxM0hJGJZ7xz0GmrKVYHnrBppRw7jomVKJBDbrcaY6O5JVnvezQOPYVxLSPsZXMzRiSnQa9JHgV/5EjLJ8fJDMWA44eEE8kgWkes5TuEWDxXpFr/UGdgq34igkuwB1KWWGeQIDAQAB #应用公钥
  alipay_public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzmDrvcNvhexu3KkxVS9bemdSn6pyQUFmpyOGMDOirGR+RbmldpH2N9bPegzZynb5+bmRHii4ib31XeoXc7M7r6UsPhmPeLoSBNwpC+Uig0VxPa0hmvHjAl6StArhB3eMib6Zo40nM6eCYZLLZ1kKpI5Ad/APov9uLrbSnoeZsgeRibQix07arvTEsZq6pJavNlA+UBjp65o6Bv0+kfQ65pMTpbu+jRtTzkTj1hoW9PjwlWrY21F1FvN67zDWkTB2LjGFsqan0Qoe4/X8nK3VsDvkjIm/ZQsnQr8ZzfcuTzQPrcZpo3h9DPZoHeiToEfXtyk7E0bQHEmYVpmrvk/IJwIDAQAB #支付宝公钥
  appid: 111  #应用程序唯一标识
  appPrivateKey: 111 #开发者应用私钥
  alipayPublicKey: 111 #应用公钥
  alipay_public_key: 111 #支付宝公钥
---
@@ -129,17 +133,15 @@
#  mallbook 调起接口参数配置
mallbook:
  # pay_url:mallbook接口地址    测试环境: https://uat.mallbook.cn/api   生产环境:https://cloudpay.mallbook.cn/api
  pay_url: https://uat.mallbook.cn/api
  pay_url: https://cloudpay.mallbook.cn/api
  # merchant_no 业务系统商户平台编号,需替换为mallbook工作人员提供的商户编号
  merchant_no: HF2023041901
  merchant_no: MBH23056
  # version 接口版本号
  version: 1.0.0
  # channel_type 渠道类型 HF:汇付
  channel_type: HF
  # merchant_private_key 商户平台私钥,需要替换成商户平台自己生成的私钥
  merchant_private_key: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIDGadl1oxP7EJg+/o32vpAMa8cwFevD6xu3FjIh04TOuVTpC9hbAwiyX/9OKQi3nHEISyrtnF6Y49tkmb7X8nDwOahvsyOjgNYp+NtSLAdgPAbd6lv2DPC1lVYYu5IkMz7PRifntROFH6OvE5fpj6GinaFY3TYBjyDcC2VVbq/LAgMBAAECgYATdmlvDWF9Vpe2eubcK+u3N7leXH0jqfOxt6UqJISkcN3/4E0DARZfTR5HJtf60k1ZpAhAT7MvdOoTMYwvFNI2WEFRwND5wBl+OdEN/lyWeISjjg1EnnTLj/azGLgE8Z2q/FodGikqrGrc2tSNIy75afeW2gUTF3DHiwcG76SYeQJBAPOyIzpT3yMfM7iVhjaPfmyxvDXq0cLwiAF0eUbrebPO0EevI+PKYhmN2oRMis6wSJbv+sbkElOXQzDefjw0ieUCQQCHRuFlX9JQYUOoyyirKxpu30uys+ygZqmo4PiKgIaaJJPm2p2o7vzZJANGmkmdwFf2LLzij70InKGvqGTEnvfvAkEAnJOMRuG0sOBPXv3TaiLwW+4mu43QkKvy9txbP9H0NC9ha22AZc+XEEwwZmi3lu109mXifv/zNnot1axe91facQJALExcwQqo32OKeXrVvX+m70m2CzX6NeiIhGHvYcOG0HFL8ZwDZu+j4yN04yjhFISJCXdK/1Icj/ZiyBf3r59zBwJACl7Sya9BcqRo5XJ/A7+T2E3VQT2nIopy0hPRLKWFaOzrCIsn3gcC58KSACXl2QMiG5kp1192QOC26b3o57ZecA==
  merchant_private_key: MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALHmyTrxPYcAwABnX+3VW9vxUftm57zBpnbfOT4vizMnKdpfCkIgtdbfdnSCtt637yWM2fxnZfItnhTeQA2lL8f4SXgZt/bVXfmAWi4IxQ+HJy0Qs8nNy2nnjICPBPcpWzHwUxQ/THHqU0a7b9B91J5DFcbQb25BHeRpHwkBw6A/AgMBAAECgYAmcWq2s/7Jt53F+JDAQkTRaHqAyyH0phwkv+QMzhVUfngK2lLLK2pf/nYIg16lDjY9dQx+AJIFHVp1w/kveayzOz3BIqPoznyIVYPolRGZCWPo+2vdp0CIdBh7zahST5g5Gem4cU47wO5hPYs1kXKPG4mUPtaIAMHFxhyLvIagAQJBAOS63AIZrRrldeNCVVNXbpAT52JuWLCgravM9coOh6scmG6UQwxxcott8hneHr9fazk2LHbHMxlG8F+dQPA0+D8CQQDHHJN7Dnske8oJ+1sq4uhQP3HMsmNIgth+ZcaZpiPcxnNKYVGhzAwTVV2ruFJle5ajebo6zfWuqJhtZGRNh1gBAkA/lRoXk1+lfGfa9tOVSVa4wm+t0xLgdqoQefdRZdyc2mQdSSWiTd8Tl0qXmkFd3X6G9uJBWnp/6lJjoektXOwtAkBsZTQsw99qJzIAaSRinpDWTxPG2j6OlR0DAqkxsG7JnAfbsEteh9TzGYAbIgdJVBTX/kbSCJn9ca85rnOkeVABAkAUbDfU3Z702z20NtwAxc1IkrtQ1lKuqSpj9/LuR1/6KRkYQsUWnUiOO9hu5YDWIcflFrnCenF8j8OnvGghltxT
  # mall_book_public_key mallbook测试环境公钥 不需要替换
  mall_book_public_key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0L2DaHOO8ekhktB6RoHxIcki/0v7OUeOn9tX9VBE+jv6PRjqlZRWL3Qezxz5ADtHEyLv+RFFaceXSep6rWyoQ6DRlvLv5CySUAxAM42LLVe4DI3l/0ccEAIuU5NCpwAAj1zkm2X01DwUCZwymLjlqbDlBvQhpq+1fddtTtA/QLQIDAQAB
  # mall_book_public_key mallbook生产环境公钥  不需要替换
  # mall_book_public_key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq6OLZKgUHH5wOk9xSBgN7yC17r3PQwMlY9/IorqrOlaIqrU0eAVZ5+dWrJD/3bdu7Ctq8n8trTm/IUYs7wtMg5SKwyX4/N+KQc2N7LL4yCq4vNl41q9sYgrtA0QnZoucIZcq1mwyu7RTDC8Wp7LGddnlkJsmL8masgMxA6cc9NwIDAQAB
  mall_book_public_key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq6OLZKgUHH5wOk9xSBgN7yC17r3PQwMlY9/IorqrOlaIqrU0eAVZ5+dWrJD/3bdu7Ctq8n8trTm/IUYs7wtMg5SKwyX4/N+KQc2N7LL4yCq4vNl41q9sYgrtA0QnZoucIZcq1mwyu7RTDC8Wp7LGddnlkJsmL8masgMxA6cc9NwIDAQAB
driver/guns-admin/src/main/resources/redis.properties
@@ -3,18 +3,18 @@
spring.redis.database=0
# Redis·þÎñÆ÷µØÖ·
spring.redis.host=127.0.0.1
# Redis·þÎñÆ÷Á¬½Ó¶Ë¿Ú
spring.redis.port=16379
# Redis·þÎñÆ÷Á¬½ÓÃÜÂ루ĬÈÏΪ¿Õ£©
spring.redis.password=cKsEeyffDXG5PzNg8CIbrWxFluXrCprZ
## Redis·þÎñÆ÷µØÖ·
#spring.redis.host=127.0.0.1
## Redis·þÎñÆ÷Á¬½Ó¶Ë¿Ú
#spring.redis.port=6379
#spring.redis.port=16379
## Redis·þÎñÆ÷Á¬½ÓÃÜÂ루ĬÈÏΪ¿Õ£©
#spring.redis.password=123456
#spring.redis.password=cKsEeyffDXG5PzNg8CIbrWxFluXrCprZ
## Redis·þÎñÆ÷µØÖ·
spring.redis.host=127.0.0.1
# Redis·þÎñÆ÷Á¬½Ó¶Ë¿Ú
spring.redis.port=6379
# Redis·þÎñÆ÷Á¬½ÓÃÜÂ루ĬÈÏΪ¿Õ£©
spring.redis.password=123456
# Á¬½Ó³Ø×î´óÁ¬½ÓÊý£¨Ê¹ÓøºÖµ±íʾûÓÐÏÞÖÆ£©
spring.redis.jedis.pool.max-active=1024
driver/guns-admin/src/test/java/com/supersavedriving/driver/GunsApplicationTest.java
@@ -42,8 +42,15 @@
//        System.err.println(JSON.toJSONString(driverId));
        ResultUtil resultUtil = driverBankService.addDriverBank(1, "蒲芝兵", "15828353127"
                , "510823198911154858", "6212264402094114687");
//        ResultUtil resultUtil = driverBankService.addDriverBank(1, "蒲芝兵", "15828353127"
//                , "510823198911154858", "6212264402094114687");
//        System.err.println(JSON.toJSONString(resultUtil));
//        ResultUtil resultUtil1 = driverBankService.delDriverBank(1, 1);
//        System.err.println(JSON.toJSONString(resultUtil1));
        ResultUtil resultUtil = driverService.balanceRecharge(1, 1D);
        System.err.println(JSON.toJSONString(resultUtil));
    }
}