puzhibing
2026-04-16 088fc4587e0124ed156dd82113f104a4d5bedf76
新增加小程序接口
19个文件已添加
5个文件已修改
768 ■■■■■ 已修改文件
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/UserSubscribeMessageController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/UserSubscribeMessageMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IUserSubscribeMessageService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/UserSubscribeMessageServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/vo/UserSubscribeMessageVo.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/resources/mapper/account/UserSubscribeMessageMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/account/UserSubscribeMessageClientFallbackFactory.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/pushMessage/SubscribeMessageClientFallbackFactory.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/account/UserSubscribeMessageClient.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/pushMessage/SubscribeMessageClient.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/UserSubscribeMessage.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/RouteAndFareVo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/pushMessage/SendSubscribeMessageVo.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpTaskController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpCruiseCheckInRuleServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/controller/SubscribeMessageController.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/Category.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/KeywordEnum.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/MessageTemplate.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/PubTemplateKeywords.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/PubTemplatetitles.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/utils/SubscribeMessageUtil.java 301 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/UserSubscribeMessageController.java
New file
@@ -0,0 +1,63 @@
package com.xiaopeng.account.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.account.service.IUserSubscribeMessageService;
import com.xiaopeng.account.vo.UserSubscribeMessageVo;
import com.xiaopeng.api.feignClient.pushMessage.SubscribeMessageClient;
import com.xiaopeng.api.model.account.UserSubscribeMessage;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.unifiedverification.interceptor.XpClientCheck;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@RequestMapping("")
public class UserSubscribeMessageController {
    @Resource
    private IUserSubscribeMessageService userSubscribeMessageService;
    @Resource
    private SubscribeMessageClient subscribeMessageClient;
    @PostMapping("/api/v1/mini-program/subscribeMessage/saveUserSubscribeMessage")
    @ApiOperation(value = "授权消息模板", tags = {"小程序-优惠券"})
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<?> saveUserSubscribeMessage(@RequestBody UserSubscribeMessageVo vo, HttpServletRequest request){
        String uid = request.getHeader("XP-Uid");
        String openid = subscribeMessageClient.getOpenId(vo.getJscode()).getData();
        if(StringUtils.isEmpty(openid)){
            return R.fail("获取openid失败");
        }
        List<String> templateIds = vo.getTemplateIds();
        userSubscribeMessageService.remove(new LambdaQueryWrapper<UserSubscribeMessage>()
                .eq(UserSubscribeMessage::getUserId, uid).in(UserSubscribeMessage::getTemplateId, templateIds));
        for (String templateId : templateIds) {
            UserSubscribeMessage userSubscribeMessage = new UserSubscribeMessage();
            userSubscribeMessage.setUserId(Long.valueOf(uid));
            userSubscribeMessage.setTemplateId(templateId);
            userSubscribeMessage.setStatus(1);
            userSubscribeMessage.setOpenId(openid);
            userSubscribeMessage.setDeleted(false);
            userSubscribeMessageService.save(userSubscribeMessage);
        }
        return R.ok();
    }
    @GetMapping("/logan/inner/v1/subscribeMessage/getUserOpenId/{v}")
    public R<String> getUserOpenId(@PathVariable("uid") Integer uid){
        UserSubscribeMessage one = userSubscribeMessageService.getOne(new LambdaQueryWrapper<UserSubscribeMessage>()
                .eq(UserSubscribeMessage::getUserId, uid).last(" limit 1"));
        return R.ok(null != one ? one.getOpenId() : "");
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/UserSubscribeMessageMapper.java
New file
@@ -0,0 +1,7 @@
package com.xiaopeng.account.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.account.UserSubscribeMessage;
public interface UserSubscribeMessageMapper extends BaseMapper<UserSubscribeMessage> {
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IUserSubscribeMessageService.java
New file
@@ -0,0 +1,7 @@
package com.xiaopeng.account.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.account.UserSubscribeMessage;
public interface IUserSubscribeMessageService extends IService<UserSubscribeMessage> {
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/UserSubscribeMessageServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.xiaopeng.account.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.account.mapper.UserSubscribeMessageMapper;
import com.xiaopeng.account.service.IUserSubscribeMessageService;
import com.xiaopeng.api.model.account.UserSubscribeMessage;
import org.springframework.stereotype.Service;
@Service
public class UserSubscribeMessageServiceImpl extends ServiceImpl<UserSubscribeMessageMapper, UserSubscribeMessage> implements IUserSubscribeMessageService {
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/vo/UserSubscribeMessageVo.java
New file
@@ -0,0 +1,19 @@
package com.xiaopeng.account.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel
public class UserSubscribeMessageVo {
    @ApiModelProperty("授权消息模板ID")
    private List<String> templateIds;
    @ApiModelProperty("微信jscode")
    private String jscode;
}
xp-robotaxi-account-boot/src/main/resources/mapper/account/UserSubscribeMessageMapper.xml
New file
@@ -0,0 +1,7 @@
<?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.xiaopeng.account.mapper.UserSubscribeMessageMapper">
</mapper>
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/account/UserSubscribeMessageClientFallbackFactory.java
New file
@@ -0,0 +1,25 @@
package com.xiaopeng.api.factory.account;
import com.xiaopeng.api.feignClient.account.UserRoutePlanRuleClient;
import com.xiaopeng.api.feignClient.account.UserSubscribeMessageClient;
import com.xiaopeng.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class UserSubscribeMessageClientFallbackFactory implements FallbackFactory<UserSubscribeMessageClient> {
    @Override
    public UserSubscribeMessageClient create(Throwable cause) {
        return new UserSubscribeMessageClient() {
            @Override
            public R<String> getUserOpenId(Integer uid) {
                log.error("获取用户openid失败:" + cause);
                return R.fail("获取用户openid失败");
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/pushMessage/SubscribeMessageClientFallbackFactory.java
New file
@@ -0,0 +1,24 @@
package com.xiaopeng.api.factory.pushMessage;
import com.xiaopeng.api.feignClient.pushMessage.SubscribeMessageClient;
import com.xiaopeng.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class SubscribeMessageClientFallbackFactory implements FallbackFactory<SubscribeMessageClient> {
    @Override
    public SubscribeMessageClient create(Throwable cause) {
        return new SubscribeMessageClient(){
            @Override
            public R<String> getOpenId(String code) {
                log.error("获取openid失败: {}", cause.getMessage());
                return R.fail("获取openid失败");
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/account/UserSubscribeMessageClient.java
New file
@@ -0,0 +1,25 @@
package com.xiaopeng.api.feignClient.account;
import com.xiaopeng.api.factory.account.UserRoutePlanRuleClientFallbackFactory;
import com.xiaopeng.api.factory.account.UserSubscribeMessageClientFallbackFactory;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(contextId = "UserSubscribeMessageClient",
        value = ServiceNameConstantsEnum.XP_ACCOUNT_SERVICE,
        fallbackFactory = UserSubscribeMessageClientFallbackFactory.class)
public interface UserSubscribeMessageClient {
    /**
     * 根据用户id获取openid
     * @param uid
     * @return
     */
    @GetMapping("/logan/inner/v1/subscribeMessage/getUserOpenId/{v}")
    R<String> getUserOpenId(@PathVariable("uid") Integer uid);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/pushMessage/SubscribeMessageClient.java
New file
@@ -0,0 +1,24 @@
package com.xiaopeng.api.feignClient.pushMessage;
import com.xiaopeng.api.factory.pushMessage.SubscribeMessageClientFallbackFactory;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(contextId = "SubscribeMessageClient",
        value = ServiceNameConstantsEnum.XP_PUSH_MESSAGE_SERVICE,
        fallbackFactory = SubscribeMessageClientFallbackFactory.class)
public interface SubscribeMessageClient {
    /**
     * 根据微信jscode获取openid
     * @param code
     * @return
     */
    @GetMapping("/logan/inner/v1/subscribeMessage/getOpenId/{code}")
    R<String> getOpenId(@PathVariable("code") String code);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/UserSubscribeMessage.java
New file
@@ -0,0 +1,42 @@
package com.xiaopeng.api.model.account;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xiaopeng.common.core.web.domain.BaseModel;
import lombok.Data;
/**
 * 用户订阅消息
 */
@Data
@TableName("xp_user_subscribe_message")
public class UserSubscribeMessage extends BaseModel {
    //生成实体类字段
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 微信openid
     */
    private String openId;
    /**
     * 消息模板id
     */
    private String templateId;
    /**
     * 授权状态(0=否,1=是)
     */
    private Integer status;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/RouteAndFareVo.java
@@ -30,6 +30,9 @@
    @ApiModelProperty(value = "是否开启试运营(0=否,1=是)")
    private Integer operateFree;
    @ApiModelProperty(value = "策略id")
    private Integer amapStrategy;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/pushMessage/SendSubscribeMessageVo.java
New file
@@ -0,0 +1,26 @@
package com.xiaopeng.api.vo.pushMessage;
import lombok.Data;
@Data
public class SendSubscribeMessageVo {
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 消息模板
     */
    private String templateId;
    /**
     * 消息内容
     */
    private String json;
    /**
     * 跳转页面
     */
    private String page;
}
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -53,4 +53,6 @@
com.xiaopeng.api.factory.map.AdcFencePushClientFallbackFactory
com.xiaopeng.api.factory.account.UserRoutePlanRuleClientFallbackFactory
com.xiaopeng.api.factory.order.XpOrderReassignClientFallbackFactory
com.xiaopeng.api.factory.map.XpStationClientFallbackFactory
com.xiaopeng.api.factory.map.XpStationClientFallbackFactory
com.xiaopeng.api.factory.pushMessage.SubscribeMessageClientFallbackFactory
com.xiaopeng.api.factory.account.UserSubscribeMessageClientFallbackFactory
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -433,7 +433,7 @@
                }
            }
            routeAndFareVo.setRoutePlanName(routePlan.getPlanName());
            routeAndFareVo.setAmapStrategy(routePlan.getRoutePlanRule());
            routeAndFareVos.add(routeAndFareVo);
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpTaskController.java
@@ -293,5 +293,4 @@
        return R.ok();
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpCruiseCheckInRuleServiceImpl.java
@@ -50,7 +50,7 @@
    @Override
    public AppXpCruiseCheckInRuleVo getMyXpCruiseCheckInRule(Long uid) {
        List<XpCruiseCheckInRule> list = this.list(new LambdaQueryWrapper<XpCruiseCheckInRule>().eq(XpCruiseCheckInRule::getDeleted, 0)
                .last(" and (now() BETWEEN start_time and end_time or a.cyclic_mode = 1)"));
                .last(" and (now() BETWEEN start_time and end_time or cyclic_mode = 1)"));
        if(list.isEmpty()){
            return null;
        }
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/controller/SubscribeMessageController.java
New file
@@ -0,0 +1,51 @@
package com.xiaopeng.pushMessage.controller;
import com.aliyun.core.annotation.Path;
import com.xiaopeng.api.feignClient.account.UserSubscribeMessageClient;
import com.xiaopeng.api.vo.pushMessage.SendSubscribeMessageVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.pushMessage.utils.SubscribeMessageUtil;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
@RestController
@RequestMapping("")
public class SubscribeMessageController {
    @Resource
    private SubscribeMessageUtil subscribeMessageUtil;
    @Resource
    private UserSubscribeMessageClient userSubscribeMessageClient;
    /**
     * 根据微信jscode获取openid
     * @param code
     * @return
     */
    @GetMapping("/logan/inner/v1/subscribeMessage/getOpenId/{code}")
    public R<String> getOpenId(@PathVariable("code") String code){
        Map<String, Object> map = subscribeMessageUtil.code2Session(code);
        if(null != map){
            return R.ok(map.get("openid").toString());
        }
        return R.fail("获取openid失败");
    }
    /**
     * 发送订阅消息
     * @param vo
     * @return
     */
    @PostMapping("/logan/inner/v1/subscribeMessage/sendSubscribeMessage")
    public R<?> sendSubscribeMessage(@RequestBody SendSubscribeMessageVo vo){
        String openid = userSubscribeMessageClient.getUserOpenId(vo.getUserId().intValue()).getData();
        return subscribeMessageUtil.send(vo.getTemplateId(), vo.getPage(), openid, vo.getJson(), "developer", "zh_CN");
    }
}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/Category.java
New file
@@ -0,0 +1,18 @@
package com.xiaopeng.pushMessage.model;
import lombok.Data;
/**
 * 订阅消息类目
 */
@Data
public class Category {
    /**
     * 类目id
     */
    private String id;
    /**
     * 类目名称
     */
    private String name;
}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/KeywordEnum.java
New file
@@ -0,0 +1,17 @@
package com.xiaopeng.pushMessage.model;
import lombok.Data;
import java.util.List;
@Data
public class KeywordEnum {
    /**
     * 枚举参数的 key
     */
    private String keywordCode;
    /**
     * 枚举参数值范围列表
     */
    private List<String> enumValueList;
}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/MessageTemplate.java
New file
@@ -0,0 +1,36 @@
package com.xiaopeng.pushMessage.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;
}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/PubTemplateKeywords.java
New file
@@ -0,0 +1,26 @@
package com.xiaopeng.pushMessage.model;
import lombok.Data;
/**
 * 公共消息模板关键字
 */
@Data
public class PubTemplateKeywords {
    /**
     * 关键词 id,选用模板时需要
     */
    private Integer kid;
    /**
     * 关键词内容
     */
    private String name;
    /**
     * 关键词内容对应的示例
     */
    private String example;
    /**
     * 参数类型
     */
    private String rule;
}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/model/PubTemplatetitles.java
New file
@@ -0,0 +1,26 @@
package com.xiaopeng.pushMessage.model;
import lombok.Data;
/**
 * 功能模板
 */
@Data
public class PubTemplatetitles {
    /**
     * 模版标题 id
     */
    private Integer tid;
    /**
     * 模版标题
     */
    private String title;
    /**
     * 模版类型,2 为一次性订阅,3 为长期订阅
     */
    private Integer type;
    /**
     * 模版所属类目 id
     */
    private Integer categoryId;
}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/utils/SubscribeMessageUtil.java
New file
@@ -0,0 +1,301 @@
package com.xiaopeng.pushMessage.utils;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.pushMessage.model.Category;
import com.xiaopeng.pushMessage.model.MessageTemplate;
import com.xiaopeng.pushMessage.model.PubTemplateKeywords;
import com.xiaopeng.pushMessage.model.PubTemplatetitles;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * 订阅消息
 */
@Slf4j
@Component
public class SubscribeMessageUtil {
    @Value("${wx.appletsAppid}")
    private String wxAppletsAppid;
    @Value("${wx.appletsAppSecret}")
    private String wxAppletsAppSecret;
    @Autowired
    private RedisService redisService;
    /**
     * 获取微信小程序token
     * @return
     */
    public String getWxAppletsAccessToken() {
        String accessToken = redisService.getCacheObject("wxAppletsAccessToken");
        if(StringUtils.isNotEmpty(accessToken)){
            return accessToken;
        }
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + wxAppletsAppid + "&secret=" + wxAppletsAppSecret;
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        if(execute.getStatus() != 200){
            log.info("获取微信小程序access_token失败:{}", execute.body());
            throw new RuntimeException("获取微信小程序access_token失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        redisService.setCacheObject("wxAppletsAccessToken", jsonObject.getString("access_token"), 7000L, TimeUnit.SECONDS);
        return jsonObject.getString("access_token");
    }
    /**
     * 小程序使用jscode获取openid
     * @param jscode
     * @return
     */
    public Map<String, Object> code2Session(String jscode) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxAppletsAppid + "&secret=" + wxAppletsAppSecret
                + "&js_code=" + jscode + "&grant_type=authorization_code";
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        if(execute.getStatus() != 200){
            log.info("小程序使用jscode获取openid失败:{}", execute.body());
            throw new RuntimeException("小程序使用jscode获取openid失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        int errcode = jsonObject.getIntValue("errcode");
        Map<String, Object> map = new HashMap<>();
        if(errcode == 0){//成功
            map.put("openid", jsonObject.getString("openid"));
            map.put("sessionKey", jsonObject.getString("session_key"));
            map.put("unionid", jsonObject.getString("unionid"));
            return map;
        }
        throw new RuntimeException(jsonObject.getString("errmsg"));
    }
    /**
     * 获取消息类目
     * @return
     */
    public List<Category> getCategory(){
        String url = "https://api.weixin.qq.com/wxaapi/newtmpl/getcategory?access_token=" + getWxAppletsAccessToken();
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        if(execute.getStatus() != 200){
            log.info("获取消息类目失败:{}", execute.body());
            throw new RuntimeException("获取消息类目失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer errcode = jsonObject.getInteger("errcode");
        if(0 != errcode){
            log.info("获取消息类目失败:{}", jsonObject.getString("errmsg"));
            throw new RuntimeException(jsonObject.getString("errmsg"));
        }
        JSONArray data = jsonObject.getJSONArray("data");
        List<Category> categories = data.toJavaList(Category.class);
        return categories;
    }
    /**
     * 获取所属类目下的公共模板
     * @param ids
     * @return
     */
    public List<PubTemplatetitles> getPubTemplateTitles(String ids){
        List<PubTemplatetitles> pubTemplatetitles = new ArrayList<>();
        Integer start = 0;
        while (true){
            String url = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles?access_token=" + getWxAppletsAccessToken();
            Map<String, Object> params = new HashMap<>();
            params.put("ids", ids);
            params.put("start", start + "");
            params.put("limit", 30);
            HttpRequest get = HttpUtil.createGet(url);
            get.form(params);
            HttpResponse execute = get.execute();
            if(execute.getStatus() != 200){
                log.info("获取公共模板失败:{}", execute.body());
                throw new RuntimeException("获取公共模板失败");
            }
            JSONObject jsonObject = JSON.parseObject(execute.body());
            Integer errcode = jsonObject.getInteger("errcode");
            if(0 != errcode){
                log.info("获取公共模板失败:{}", jsonObject.getString("errmsg"));
                throw new RuntimeException(jsonObject.getString("errmsg"));
            }
            JSONArray data = jsonObject.getJSONArray("data");
            List<PubTemplatetitles> pubTemplatetitles1 = data.toJavaList(PubTemplatetitles.class);
            if(pubTemplatetitles1.size() == 0){
                break;
            }
            pubTemplatetitles.addAll(pubTemplatetitles1);
            start += 30;
        }
        return pubTemplatetitles;
    }
    /**
     * 获取关键词列表
     * @param tid
     * @return
     */
    public List<PubTemplateKeywords> getPubTemplateKeywords(String tid){
        String url = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords?access_token=" + getWxAppletsAccessToken();
        Map<String, Object> params = new HashMap<>();
        params.put("tid", tid);
        HttpRequest get = HttpUtil.createGet(url);
        get.form(params);
        HttpResponse execute = get.execute();
        if(execute.getStatus() != 200){
            log.info("获取关键词列表失败:{}", execute.body());
            throw new RuntimeException("获取关键词列表失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer errcode = jsonObject.getInteger("errcode");
        if(0 != errcode){
            log.info("获取关键词列表失败:{}", jsonObject.getString("errmsg"));
            throw new RuntimeException(jsonObject.getString("errmsg"));
        }
        JSONArray data = jsonObject.getJSONArray("data");
        List<PubTemplateKeywords> pubTemplateKeywords = data.toJavaList(PubTemplateKeywords.class);
        return pubTemplateKeywords;
    }
    /**
     * 获取个人模板列表
     * @return
     */
    public List<MessageTemplate> getMessageTemplateList(){
        String url = "https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token=" + getWxAppletsAccessToken();
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        if(execute.getStatus() != 200){
            log.info("获取个人模板列表失败:{}", execute.body());
            throw new RuntimeException("获取个人模板列表失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer errcode = jsonObject.getInteger("errcode");
        if(0 != errcode){
            log.info("获取个人模板列表失败:{}", jsonObject.getString("errmsg"));
            throw new RuntimeException(jsonObject.getString("errmsg"));
        }
        JSONArray data = jsonObject.getJSONArray("data");
        List<MessageTemplate> messageTemplates = data.toJavaList(MessageTemplate.class);
        return messageTemplates;
    }
    /**
     * 添加消息模板
     * @param tid           模板标题 id
     * @param kidList       开发者自行组合好的模板关键词列表,关键词顺序可以自由搭配(例如 [3,5,4] 或 [4,5,3]),最多支持5个,最少2个关键词组合
     * @param sceneDesc     服务场景描述,15个字以内
     * @return
     */
    public String addTemplate(String tid, String[] kidList, String sceneDesc){
        String url = "https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token=" + getWxAppletsAccessToken();
        Map<String, Object> params = new HashMap<>();
        params.put("tid", tid);
        params.put("kidList", kidList);
        params.put("sceneDesc", sceneDesc);
        HttpRequest post = HttpUtil.createPost(url);
        post.body(JSON.toJSONString(params));
        HttpResponse execute = post.execute();
        if(execute.getStatus() != 200){
            log.info("添加消息模板失败:{}", execute.body());
            throw new RuntimeException("添加消息模板失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer errcode = jsonObject.getInteger("errcode");
        if(0 != errcode){
            log.info("添加消息模板失败:{}", jsonObject.getString("errmsg"));
            throw new RuntimeException(jsonObject.getString("errmsg"));
        }
        String priTmplId = jsonObject.getString("priTmplId");
        return priTmplId;
    }
    /**
     * 删除模板
     * @param priTmplId     模板id
     * @return
     */
    public R delTemplate(String priTmplId){
        String url = "https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate?access_token=" + getWxAppletsAccessToken();
        Map<String, Object> params = new HashMap<>();
        params.put("priTmplId", priTmplId);
        HttpRequest post = HttpUtil.createPost(url);
        post.body(JSON.toJSONString(params));
        HttpResponse execute = post.execute();
        if (execute.getStatus() != 200){
            log.info("删除模板失败:{}", execute.body());
            throw new RuntimeException("删除模板失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer errcode = jsonObject.getInteger("errcode");
        if(0 != errcode){
            log.info("删除模板失败:{}", jsonObject.getString("errmsg"));
            throw new RuntimeException(jsonObject.getString("errmsg"));
        }
        return R.ok();
    }
    /**
     * 发送消息
     * @param template_id           所需下发的订阅模板id
     * @param page                  点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
     * @param touser                接收者(用户)的 openid
     * @param data                  模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }的object
     * @param miniprogram_state     跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
     * @param lang                  进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
     * @return
     */
    public R send(String template_id, String page, String touser, String data, String miniprogram_state, String lang){
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + getWxAppletsAccessToken();
        Map<String, Object> params = new HashMap<>();
        params.put("template_id", template_id);
        params.put("page", page);
        params.put("touser", touser);
        params.put("data", JSON.parseObject(data));
        params.put("miniprogram_state", miniprogram_state);
        params.put("lang", lang);
        HttpRequest post = HttpUtil.createPost(url);
        post.body(JSON.toJSONString(params));
        HttpResponse execute = post.execute();
        if(execute.getStatus() != 200){
            log.info("发送消息失败:{}", execute.body());
            throw new RuntimeException("发送消息失败");
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer errcode = jsonObject.getInteger("errcode");
        if(0 != errcode){
            log.info("发送消息失败:{}", jsonObject.getString("errmsg"));
            throw new RuntimeException(jsonObject.getString("errmsg"));
        }
        return R.ok();
    }
}