浏览代码

推送收款微信模板消息

chao 3 年之前
父节点
当前提交
6eaa7a1485

+ 12 - 3
backup.sql

@@ -94,14 +94,21 @@ CREATE TABLE `cm_receipt_user` (
   `del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标记:0未删,其他删除',
   PRIMARY KEY (`id`)
 ) ENGINE=INNODB DEFAULT CHARSET=UTF8MB4 COMMENT='采美收款用户表';
- -- 收款用户权限表
+ -- 收款权限表
+DROP TABLE IF EXISTS `cm_receipt_permission`;
+CREATE TABLE `cm_receipt_permission` (
+  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '收款权限ID',
+  `permission` VARCHAR(100) DEFAULT NULL COMMENT '收款权限描述',
+  PRIMARY KEY (`id`)
+) ENGINE=INNODB DEFAULT CHARSET=UTF8MB4 COMMENT='采美收款权限表';
+ -- 采美收款用户权限关联表
 DROP TABLE IF EXISTS `cm_receipt_user_permission`;
 CREATE TABLE `cm_receipt_user_permission` (
   `id` BIGINT NOT NULL AUTO_INCREMENT,
   `user_id` BIGINT DEFAULT NULL COMMENT '收款用户ID',
-  `permission` BIGINT DEFAULT NULL COMMENT '权限:1录入收款权限,2收款确认权限,3收款审核权限 4返佣管理权限 5供应商退款管理权限',
+  `permission_id` BIGINT DEFAULT NULL COMMENT '收款权限ID',
   PRIMARY KEY (`id`)
-) ENGINE=INNODB DEFAULT CHARSET=UTF8MB4 COMMENT='采美收款用户权限表';
+) ENGINE=INNODB DEFAULT CHARSET=UTF8MB4 COMMENT='采美收款用户权限关联表';
  -- 收款类型表
 DROP TABLE IF EXISTS `cm_receipt_type`;
 CREATE TABLE `cm_receipt_type` (
@@ -110,6 +117,7 @@ CREATE TABLE `cm_receipt_type` (
   PRIMARY KEY (`id`)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='采美收款类型表';
 -- 初始数据
+INSERT  INTO `cm_receipt_permission`(`id`,`permission`) VALUES (1,'收款列表访问'),(2,'收款详情访问'),(3,'收款录入'),(4,'收款关联订单'),(5,'收款关联返佣'),(6,'收款关联供应商退款'),(7,'收款审核');
 INSERT  INTO `cm_receipt_type`(`id`,`type`) VALUES (1,'建设银行-7297'),(2,'广发银行-0115'),(3,'中信银行-7172'),(4,'中信银行-0897'),(5,'中信银行-0897-财付通'),(6,'中信银行-0897-支付宝'),(7,'线上-支付宝'),(8,'线上-微信支付'),(9,'线上-快钱支付'),(10,'口头返佣'),(11,'广发银行-5461'),(12,'企业网银'),(13,'微信支付'),(14,'支付宝'),(15,'微信支付'),(16,'余额抵扣'),(18,'建设银行-1854'),(19,'建设银行-6256');
 
 
@@ -120,3 +128,4 @@ INSERT  INTO `cm_receipt_type`(`id`,`type`) VALUES (1,'建设银行-7297'),(2,'
 
 
 
+

+ 57 - 0
src/main/java/com/caimei365/order/components/WeChatService.java

@@ -36,6 +36,8 @@ public class WeChatService {
     private String appId;
     @Value("${wx.app-secret}")
     private String appSecret;
+    @Value("${wx.message-template-id}")
+    private String messageTemplateId;
     @Value("${wx.mini-app-id}")
     private String miniAppId;
     @Value("${wx.mini-app-secret}")
@@ -337,4 +339,59 @@ public class WeChatService {
         return map;
     }
 
+    /**
+     * 推送收款微信模板消息
+     *
+     * 模板内容:
+     * {{first.DATA}}
+     * 交易金额:{{keyword1.DATA}}
+     * 交易时间:{{keyword2.DATA}}
+     * {{remark.DATA}}
+     * 在发送时,需要将内容中的参数({{.DATA}}内为参数)赋值替换为需要的信息
+     *  @param openid 被推送人的openid
+     * @param title 标题
+     * @param money 金额
+     * @param type 收款类型
+     * @param time 日期时间
+     * @param redirectUrl 跳转链接
+     */
+    public void sendTemplateMsg(String openid, String title, Double money, String type, String time, String redirectUrl) {
+        JSONObject first = new JSONObject();
+        first.put("value", title);
+        first.put("color", "#000000");
+        JSONObject keyword1 = new JSONObject();
+        keyword1.put("value", money.toString());
+        keyword1.put("color", "#FF0000");
+        JSONObject keyword2 = new JSONObject();
+        keyword2.put("value", time);
+        keyword2.put("color", "#c4c400");
+        JSONObject remark = new JSONObject();
+        keyword2.put("value", "收款类型:" + type);
+        keyword2.put("color", "#c4c400");
+
+        JSONObject data = new JSONObject();
+        data.put("first", first);
+        data.put("keyword1", keyword1);
+        data.put("keyword2", keyword2);
+        data.put("remark", remark);
+
+        JSONObject json = new JSONObject();
+        json.put("template_id", messageTemplateId);
+        json.put("topcolor", "#FF0000");
+        json.put("touser", openid);
+        json.put("url", redirectUrl);
+        json.put("data", data);
+        // json 字符串
+        String jsonString = json.toJSONString();
+        log.info(">>>>>>>>推送微信模板消息:" + jsonString);
+        try {
+            // 获取access_token
+            String accessToken = getAccessToken();
+            String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+accessToken;
+            // 发送请求
+            RequestUtil.httpRequest(requestUrl, "POST", jsonString);
+        } catch (Exception e) {
+            log.error("推送微信模板消息失败:", e);
+        }
+    }
 }

+ 29 - 3
src/main/java/com/caimei365/order/controller/ReceiptApi.java

@@ -122,6 +122,7 @@ public class ReceiptApi {
     /**
      * 操作收款信息(作废,设为返佣/普通/供应商退款/非订单款)
      * crm:/api/user/receivables/save
+     *
      * @param receiptDto {
      *                   id:收款Id
      *                   receiptType: 1订单款,2非订单款,3返佣款 4订单款或者非订单款(因财务阶段无法区分订单非订单), 5供应商退款
@@ -279,16 +280,28 @@ public class ReceiptApi {
     /**
      * 确认收款-关联收款信息
      * crm:/api/user/receivables/confirmReceipt
+     *
+     * @param receiptAssociateDto {
+     *                            id: 收款Id
+     *                            orderIds: 关联订单IDS
+     *                            confirmType: 确认订单类型:1小额抹平确认,2大额抹平确认,3大额退款余额,4确认关联
+     *                            noOrderReason: 非订单款说明
+     *                            }
      */
     @ApiOperation("确认收款-关联收款信息")
     @PostMapping("/confirm")
-    public ResponseJson<ReceiptPo> receiptAssociate(ReceiptAssociateDto receiptAssociateDto, @RequestHeader HttpHeaders headers) {
+    public ResponseJson<Void> receiptAssociate(ReceiptAssociateDto receiptAssociateDto, @RequestHeader HttpHeaders headers) {
         return receiptService.receiptAssociate(receiptAssociateDto, headers);
     }
 
     /**
      * 确认收款-关联供应商退款
      * crm:/api/user/shop/relation
+     *
+     * @param receiptAssociateDto {
+     *                            id:          收款Id
+     *                            shopOrderId: 关联供应商退款子订单ID
+     *                            }
      */
     @ApiOperation("确认收款-关联供应商退款")
     @PostMapping("/confirm/refund")
@@ -296,8 +309,21 @@ public class ReceiptApi {
         return receiptService.receiptAssociateRefund(receiptAssociateDto, headers);
     }
 
-
-    // 返佣关联/api/user/rebate/relation
+    /**
+     * 确认收款-关联返佣款
+     * crm:/api/user/rebate/relation
+     *
+     * @param receiptAssociateDto {
+     *                            id:           收款Id
+     *                            shopOrderIds: 关联返佣子订单IDs
+     *                            rebateRemarks:关联返佣备注
+     *                            }
+     */
+    @ApiOperation("确认收款-关联返佣款")
+    @PostMapping("/confirm/rebate")
+    public ResponseJson<ReceiptPo> receiptAssociateRebate(ReceiptAssociateDto receiptAssociateDto, @RequestHeader HttpHeaders headers) {
+        return receiptService.receiptAssociateRebate(receiptAssociateDto, headers);
+    }
 
 }
 

+ 10 - 0
src/main/java/com/caimei365/order/mapper/ReceiptMapper.java

@@ -48,6 +48,7 @@ public interface ReceiptMapper {
      * 获取收款类型
      */
     ReceiptTypeVo getReceiptTypeById(Integer id);
+    String getReceiptTypeStrById(Integer id);
     /**
      * 短信内容Md5加密串 获取收款记录
      */
@@ -145,5 +146,14 @@ public interface ReceiptMapper {
      * 子订单付款类型列表
      */
     List<Integer> getRebatePayTypeList(Integer shopOrderId);
+    /**
+     * 根据用户类型获取用户openid列表
+     */
+    List<String> getOpenidListByUserType(Integer userType);
+    /**
+     * 统计收款金额
+     */
+    double countAssociateAmountById(Integer receiptId);
+
 
 }

+ 8 - 3
src/main/java/com/caimei365/order/model/dto/ReceiptAssociateDto.java

@@ -40,8 +40,13 @@ public class ReceiptAssociateDto implements Serializable {
     @ApiModelProperty("关联供应商退款子订单ID")
     private Integer shopOrderId;
     /**
-     * 微信openid
+     * 关联供应商退款子订单ID
+     */
+    @ApiModelProperty("关联返佣子订单IDs")
+    private String shopOrderIds;
+    /**
+     * 返佣关联备注
      */
-    @ApiModelProperty("微信openid")
-    private String openid;
+    @ApiModelProperty("关联返佣备注")
+    private String rebateRemarks;
 }

+ 0 - 5
src/main/java/com/caimei365/order/model/dto/ReceiptDto.java

@@ -21,11 +21,6 @@ public class ReceiptDto implements Serializable {
      */
     @ApiModelProperty("收款Id")
     private Integer id;
-    /**
-     * 微信openid
-     */
-    @ApiModelProperty("微信openid")
-    private String openid;
     /**
      * 作废标记
      */

+ 28 - 4
src/main/java/com/caimei365/order/service/ReceiptService.java

@@ -115,6 +115,7 @@ public interface ReceiptService {
 
     /**
      * 供应商退款-子订单列表
+     *
      * @param id            收款ID
      * @param confirmedType 0待确认,2已确认子订单
      * @param shopName      供应商名称
@@ -133,22 +134,45 @@ public interface ReceiptService {
 
     /**
      * 返佣款-子订单列表
-     * @param id 返佣收款ID
+     *
+     * @param id       返佣收款ID
      * @param shopName 供应商名称
-     * @param pageNum       页码
-     * @param pageSize      每页数量
+     * @param pageNum  页码
+     * @param pageSize 每页数量
      */
     ResponseJson<PageInfo<ShopOrderVo>> getRebateShopOrderList(Integer id, String shopName, int pageNum, int pageSize, HttpHeaders headers);
 
 
     /**
      * 关联收款信息
+     *
+     * @param receiptAssociateDto {
+     *                            id: 收款Id
+     *                            orderIds: 关联订单IDS
+     *                            confirmType: 确认订单类型:1小额抹平确认,2大额抹平确认,3大额退款余额,4确认关联
+     *                            noOrderReason: 非订单款说明
+     *                            }
      */
-    ResponseJson<ReceiptPo> receiptAssociate(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers);
+    ResponseJson<Void> receiptAssociate(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers);
 
     /**
      * 确认收款-关联供应商退款
+     *
+     * @param receiptAssociateDto {
+     *                            id:          收款Id
+     *                            shopOrderId: 关联供应商退款子订单ID
+     *                            }
      */
     ResponseJson<ReceiptPo> receiptAssociateRefund(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers);
 
+    /**
+     * 确认收款-关联返佣款
+     *
+     * @param receiptAssociateDto {
+     *                            id:           收款Id
+     *                            shopOrderIds: 关联返佣子订单IDs
+     *                            rebateRemarks:关联返佣备注
+     *                            }
+     */
+    ResponseJson<ReceiptPo> receiptAssociateRebate(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers);
 }

+ 58 - 5
src/main/java/com/caimei365/order/service/impl/ReceiptServiceImpl.java

@@ -524,7 +524,7 @@ public class ReceiptServiceImpl implements ReceiptService {
     /**
      * 收款详情(订单/非订单)
      *
-     * @param id     款项Id
+     * @param id 款项Id
      */
     @Override
     public ResponseJson<ReceiptVo> getReceiptDetail(Integer id, HttpHeaders headers) {
@@ -742,6 +742,7 @@ public class ReceiptServiceImpl implements ReceiptService {
 
     /**
      * 供应商退款-子订单列表
+     *
      * @param id            收款ID
      * @param confirmedType 0待确认,2已确认子订单
      * @param shopName      供应商名称
@@ -884,10 +885,17 @@ public class ReceiptServiceImpl implements ReceiptService {
 
     /**
      * 关联收款信息
+     *
+     * @param receiptAssociateDto {
+     *                            id: 收款Id
+     *                            orderIds: 关联订单IDS
+     *                            confirmType: 确认订单类型:1小额抹平确认,2大额抹平确认,3大额退款余额,4确认关联
+     *                            noOrderReason: 非订单款说明
+     *                            }
      */
     @Transactional(rollbackFor = Exception.class)
     @Override
-    public ResponseJson<ReceiptPo> receiptAssociate(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers) {
+    public ResponseJson<Void> receiptAssociate(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers) {
         // 检查收款用户权限
         ReceiptUserVo receiptUser = checkPermissions(1, headers);
         if (null == receiptUser) {
@@ -1062,17 +1070,39 @@ public class ReceiptServiceImpl implements ReceiptService {
         receiptPo.setConfirmUserPermissionId(receiptUser.getId());
         receiptPo.setConfirmDate(time);
         receiptMapper.updateReceipt(receiptPo);
-        return ResponseJson.success(receiptPo);
+        // 关联成功推送模板消息给审核人员
+        List<String> openidList = receiptMapper.getOpenidListByUserType(3);
+        openidList.removeIf(Objects::isNull);
+        double associateAmount = receiptMapper.countAssociateAmountById(receipt.getId());
+        String associateTitle = "收款和订单已确认关联,请及时审核!";
+        String associateDate = receipt.getReceiptDate();
+        String associateType = receiptMapper.getReceiptTypeStrById(receipt.getPayType());
+
+
+        //todo 跳转链接 crm旧链接:/api/user/receivables/toReceivablesPage.rpc?pageName=listToDesc&id=receipt.getId()
+
+
+        String redirectUrl = "";
+        for (String openid : openidList) {
+            // sendTemplateMsg(openid, 标题, 金额, 收款类型, 收款日期, 跳转链接)
+            weChatService.sendTemplateMsg(openid, associateTitle, associateAmount, associateType, associateDate, redirectUrl);
+        }
+        return ResponseJson.success("关联收款信息成功!", null);
     }
 
     /**
      * 确认收款-关联供应商退款
+     *
+     * @param receiptAssociateDto {
+     *                            id:          收款Id
+     *                            shopOrderId: 关联供应商退款子订单ID
+     *                            }
      */
     @Transactional(rollbackFor = Exception.class)
     @Override
     public ResponseJson<ReceiptPo> receiptAssociateRefund(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers) {
         // 检查收款用户权限
-        ReceiptUserVo receiptUser = checkPermissions(1, headers);
+        ReceiptUserVo receiptUser = checkPermissions(5, headers);
         if (null == receiptUser) {
             return ResponseJson.error("无权限操作!", null);
         }
@@ -1088,6 +1118,29 @@ public class ReceiptServiceImpl implements ReceiptService {
 
 
 
+        return null;
+    }
+
+    /**
+     * 确认收款-关联返佣款
+     *
+     * @param receiptAssociateDto {
+     *                            id:           收款Id
+     *                            shopOrderIds: 关联返佣子订单IDs
+     *                            rebateRemarks:关联返佣备注
+     *                            }
+     */
+    @Override
+    public ResponseJson<ReceiptPo> receiptAssociateRebate(ReceiptAssociateDto receiptAssociateDto, HttpHeaders headers) {
+        // 检查收款用户权限
+        ReceiptUserVo receiptUser = checkPermissions(4, headers);
+        if (null == receiptUser) {
+            return ResponseJson.error("无权限操作!", null);
+        }
+
+
+
+
 
 
 
@@ -1137,7 +1190,7 @@ public class ReceiptServiceImpl implements ReceiptService {
             BigDecimal brokerage = BigDecimal.ZERO;
             List<OrderProductVo> orderProductList = orderCommonMapper.getShopOrderProduct(shopOrder.getShopOrderId());
             orderProductList.removeIf(Objects::isNull);
-            for (OrderProductVo orderProduct : orderProductList){
+            for (OrderProductVo orderProduct : orderProductList) {
                 // 已退货数量
                 Integer returnedNum = orderCommonMapper.countReturnedNum(orderProduct.getShopOrderId(), orderProduct.getProductId());
                 returnedNum = null != returnedNum ? returnedNum : 0;

+ 75 - 3
src/main/java/com/caimei365/order/utils/RequestUtil.java

@@ -1,11 +1,16 @@
 package com.caimei365.order.utils;
 
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
+import org.springframework.util.StringUtils;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import java.io.*;
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
 import java.util.List;
 import java.util.Map;
 
@@ -113,4 +118,71 @@ public class RequestUtil {
         return result.toString();
     }
 
+    /**
+     * 向指定 URL 发送请求
+     * @param requestUrl 发送请求的 URL
+     * @param requestMethod 请求方法GET/POST
+     * @param jsonString json字符串参数
+     * @return 远程资源的响应结果
+     */
+    public static String httpRequest(String requestUrl, String requestMethod, String jsonString) {
+        StringBuffer buffer = new StringBuffer();
+        try {
+            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
+            TrustManager[] tm = {
+                    new javax.net.ssl.X509TrustManager(){
+                        @Override
+                        public void checkClientTrusted(X509Certificate[] chain, String authType) {
+                        }
+                        @Override
+                        public void checkServerTrusted(X509Certificate[] chain, String authType) {
+                        }
+                        @Override
+                        public X509Certificate[] getAcceptedIssuers() {
+                            return null;
+                        }
+                    }
+            };
+            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
+            sslContext.init(null, tm, new java.security.SecureRandom());
+            // 从上述SSLContext对象中得到SSLSocketFactory对象
+            SSLSocketFactory ssf = sslContext.getSocketFactory();
+
+            URL url = new URL(requestUrl);
+            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
+            httpUrlConn.setSSLSocketFactory(ssf);
+            httpUrlConn.setDoOutput(true);
+            httpUrlConn.setDoInput(true);
+            httpUrlConn.setUseCaches(false);
+            // 设置请求方式(GET/POST)
+            httpUrlConn.setRequestMethod(requestMethod);
+            if ("GET".equalsIgnoreCase(requestMethod)) {
+                httpUrlConn.connect();
+            }
+            // 当有数据需要提交时
+            if (StringUtils.hasLength(jsonString)) {
+                OutputStream outputStream = httpUrlConn.getOutputStream();
+                // 注意编码格式,防止中文乱码
+                outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8));
+                outputStream.close();
+            }
+
+            // 将返回的输入流转换成字符串
+            InputStream inputStream = httpUrlConn.getInputStream();
+            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
+            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+            String str = null;
+            while ((str = bufferedReader.readLine()) != null) {
+                buffer.append(str);
+            }
+            bufferedReader.close();
+            inputStreamReader.close();
+            // 释放资源
+            inputStream.close();
+            httpUrlConn.disconnect();
+            return buffer.toString();
+        } catch (Exception ignored) {}
+        return null;
+    }
+
 }

+ 8 - 2
src/main/resources/mapper/ReceiptMapper.xml

@@ -441,10 +441,10 @@
         o.rebateFlag,
         o.clauseID AS clauseId,
         o.clauseName,
-        <if test="organizeID == 0 or organizeID == null">
+        <if test="organizeId == 0 or organizeId == null">
             IFNULL(u.userName, u.name) AS userName,
         </if>
-        <if test="organizeID > 0">
+        <if test="organizeId > 0">
             u.name AS "userName",
             IFNULL(u.name, u.userName) AS userName,
         </if>
@@ -750,4 +750,10 @@
         WHERE cror.relationType = '1' AND cror.delFlag = '0'
           AND cror.orderID = #{shopOrderId} and cdr.receiptType = '3'
     </select>
+    <select id="getOpenidListByUserType" resultType="java.lang.String">
+        SELECT DISTINCT openid FROM cm_receipt_user WHERE user_type = #{userType} AND del_flag = 0
+    </select>
+    <select id="countAssociateAmountById" resultType="java.lang.Double">
+        SELECT IFNULL(SUM(associateAmount), 0) FROM cm_receipt_order_relation WHERE receiptID = #{receiptId}
+    </select>
 </mapper>