提交 473af6da 作者: 沈振路

关回接口(完成-未测试)

上级 8b1bd7ac
package com.yaoyaozw.customer.components;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.yaoyaozw.customer.common.R;
import com.yaoyaozw.customer.constants.ApiResultConstant;
import com.yaoyaozw.customer.constants.CustomerCommonConstant;
import com.yaoyaozw.customer.constants.FollowReplyCommonConstant;
import com.yaoyaozw.customer.entity.AuthorizerInfo;
import com.yaoyaozw.customer.entity.CommonReferralBody;
import com.yaoyaozw.customer.entity.CustomerFollowReply;
import com.yaoyaozw.customer.entity.ReferralEntity;
import com.yaoyaozw.customer.enums.CustomerStoreTemplateEnum;
import com.yaoyaozw.customer.feigns.ReferralFeignClient;
import com.yaoyaozw.customer.service.AuthorizerInfoService;
import com.yaoyaozw.customer.service.ReferralEntityService;
import com.yaoyaozw.customer.utils.TencentCustomerUtil;
import com.yaoyaozw.customer.vo.AuthInfoVO;
import com.yaoyaozw.customer.vo.TencentMediaResponseVO;
import com.yaoyaozw.customer.vo.follow.FollowReplyCopyResultVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author darker
* @date 2023/3/14 14:36
*/
@Component
public class FollowReplyComponent {
private final static Logger localLog = LoggerFactory.getLogger(FollowReplyComponent.class);
@Autowired
private ReferralEntityService referralEntityService;
@Autowired
private TencentCustomerUtil tencentCustomerUtil;
@Autowired
private ReferralFeignClient referralFeignClient;
@Autowired
private SnowflakeComponent snowflakeComponent;
@Autowired
private AuthorizerInfoService authorizerInfoService;
/**
* 获取链接实体
* @param referralBody 链接参数
* @return 转化之后的链接实体
*/
public ReferralEntity getCreateReferralEntity(CommonReferralBody referralBody) {
ReferralEntity referralEntity = new ReferralEntity();
// 赋值链接参数
BeanUtil.copyProperties(referralBody, referralEntity);
Integer newsType = referralEntity.getNewsType();
// 判断是否需要获取书城链接
if (CustomerCommonConstant.REMOTE_LINK_NEWS_TYPE_LIST.contains(referralBody.getNewsType())) {
// 处理链接名称
if (CustomerCommonConstant.BOOK_NEWS_TYPE.equals(newsType) || CustomerCommonConstant.ACTIVITY_NEWS_TYPE.equals(newsType)) {
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
String dateStr = format.format(new Date());
AuthorizerInfo authorizerInfo = authorizerInfoService.getById(referralBody.getInfoId());
handleReferralName(dateStr, authorizerInfo.getNickName(), referralEntity);
}
// 获取链接
doGetReferral(referralEntity);
}
return referralEntity;
}
/**
* 获取复用时的链接数据
*
* @param dateStr 日期
* @param authInfoVo 目标公众号
* @param sourceReferral 链接参数
* @return {@link ReferralEntity}
*/
public ReferralEntity getCopyReferralEntity(String dateStr, AuthInfoVO authInfoVo, ReferralEntity sourceReferral) {
ReferralEntity targetReferral = new ReferralEntity();
BeanUtil.copyProperties(sourceReferral, targetReferral,
"id", "accountId", "name", "referral", "materialGraphicsId", "infoId");
// 为参数设置公众号相关参数
targetReferral.setAccountId(authInfoVo.getAccountId());
targetReferral.setInfoId(authInfoVo.getId());
Integer newsType = targetReferral.getNewsType();
if (CustomerCommonConstant.REMOTE_LINK_NEWS_TYPE_LIST.contains(newsType)) {
// 需要获取第三方链接的类型
if (CustomerCommonConstant.USUAL_LINK_NEWS_TYPE.equals(newsType)) {
// 常用链接延用name
targetReferral.setName(sourceReferral.getName());
} else {
// 书籍、活动 类型, 重新构造name
handleReferralName(dateStr, authInfoVo.getAccountName(), targetReferral);
}
doGetReferral(targetReferral);
}
return targetReferral;
}
/**
* 素材复用到目标公众号
*
* @param targetAuth 目标公众号
* @param sourceMaterialList 源素材列表
* @return 执行结果
*/
public FollowReplyCopyResultVO copyMaterialToTarget(AuthInfoVO targetAuth, List<CustomerFollowReply> sourceMaterialList) {
FollowReplyCopyResultVO result = new FollowReplyCopyResultVO();
result.setHasError(false);
List<CustomerFollowReply> finalMaterialList = new ArrayList<>(sourceMaterialList.size());
List<ReferralEntity> finalReferralList = new ArrayList<>();
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
String dateStr = format.format(new Date());
for (CustomerFollowReply sourceMaterial : sourceMaterialList) {
CustomerFollowReply entity = new CustomerFollowReply();
int status = 1;
// 主体赋值
entity.setId(snowflakeComponent.snowflakeId());
entity.setAppid(targetAuth.getAppId());
entity.setName(sourceMaterial.getName());
entity.setType(sourceMaterial.getType());
entity.setOriginMediaUrl(sourceMaterial.getOriginMediaUrl());
entity.setExtendTitle(sourceMaterial.getExtendTitle());
entity.setExtendDesc(sourceMaterial.getExtendDesc());
entity.setSort(sourceMaterial.getSort());
if (FollowReplyCommonConstant.needUpload(entity.getType())) {
// 向腾讯后台上传素材文件
TencentMediaResponseVO uploadResult = tencentCustomerUtil.uploadTencentMedia(targetAuth.getAppId(), entity.getOriginMediaUrl(), entity.getType());
if (StringUtils.isNotEmpty(uploadResult.getErrmsg())) {
localLog.warn("公众号: {} 上传素材失败", targetAuth.getAccountName());
}
entity.setTxMediaUrl(uploadResult.getUrl());
entity.setTxMediaId(uploadResult.getMedia_id());
// 需要上传后台的类型不需要处理链接
continue;
}
// 处理 图文、文本 链接
List<ReferralEntity> referralEntityList = sourceMaterial.getReferralEntityList();
if (CollectionUtil.isNotEmpty(referralEntityList)) {
List<ReferralEntity> singleMaterialReferralList = new ArrayList<>(referralEntityList.size());
for (ReferralEntity sourceReferral : referralEntityList) {
try {
ReferralEntity finalReferral = getCopyReferralEntity(dateStr, targetAuth, sourceReferral);
finalReferral.setMaterialGraphicsId(entity.getId());
singleMaterialReferralList.add(finalReferral);
finalReferralList.add(finalReferral);
} catch (Exception e) {
// 获取链接出现异常, 修改状态, 修改标识
status = 0;
result.setHasError(true);
}
}
if (CollectionUtil.isNotEmpty(singleMaterialReferralList)) {
// 处理链接的后续操作
if (FollowReplyCommonConstant.TENCENT_MEDIA_TYPE_NEWS.equals(entity.getType())) {
// 图文, 将链接处理结果设置到主题表中
ReferralEntity referralEntity = singleMaterialReferralList.get(0);
entity.setSourceUrl(referralEntity.getReferral());
} else if (FollowReplyCommonConstant.TENCENT_MEDIA_TYPE_TEXT.equals(entity.getType())) {
// 文本, 构造H5
StringBuilder builder = new StringBuilder();
for (ReferralEntity referralEntity : singleMaterialReferralList) {
builder.append(structH5Line(referralEntity)).append("\n\n");
}
entity.setContent(builder.toString().trim());
}
}
}
entity.setStatus(status);
finalMaterialList.add(entity);
}
result.setMaterialList(finalMaterialList);
result.setReferralEntityList(finalReferralList);
return result;
}
/**
* 重新排序和保存文本子素材
*
* @param referralList 文本子素材列表
* @return {@link String}
*/
public String reSortAndSaveTextItem(List<ReferralEntity> referralList) {
// 遍历进行排序,并且构造H5
int idx = 1;
StringBuilder builder = new StringBuilder();
for (ReferralEntity referral : referralList) {
referral.setSort(idx);
builder.append(structH5Line(referral));
if (idx < referralList.size()) {
builder.append("\n\n");
idx++;
}
}
// 保存排序之后的referral列表
referralEntityService.updateBatchById(referralList);
return builder.toString();
}
/**
* 构造 h5
*
* @param referralEntity 链接实体
* @return {@link String}
*/
private String structH5Line(ReferralEntity referralEntity) {
Integer newsType = referralEntity.getNewsType();
// 文本类型替换h5链接
String context = null;
if (CustomerCommonConstant.REPLACE_LINK_NEWS_TYPE_LIST.contains(newsType)) {
context = CustomerCommonConstant.CUSTOMER_TEXT_LINK_TEMPLATE.replace(CustomerCommonConstant.CUSTOMER_TEXT_CONTENT_PLACEHOLDER, referralEntity.getTextContent());
} else if (CustomerCommonConstant.COMMON_NEWS_TYPE_LIST.contains(newsType)){
context = referralEntity.getTextContent();
}
if (ObjectUtil.isNotNull(context)) {
context = context.replace(CustomerCommonConstant.CUSTOMER_TEXT_URL_PLACEHOLDER, referralEntity.getReferral());
}
return context;
}
/**
* 处理链接名称
* @param dateStr 处理日期
* @param accountName 公众号名称
* @param referral 链接参数实体
*/
private void handleReferralName(String dateStr, String accountName, ReferralEntity referral) {
Integer newsType = referral.getNewsType();
// 书籍、活动 类型, 重新构造name
String name = CustomerCommonConstant.getLinkNameModel(newsType);
String newsTypeName = CustomerCommonConstant.getNewsTypeName(newsType);
name = name.replace("{newsType}", newsTypeName).replace("{accountNickName}", accountName)
.replace("{storeType}", referral.getStoreTypeName()).replace("{currentDate}", dateStr);
if (newsType.equals(CustomerCommonConstant.BOOK_NEWS_TYPE)) {
// 系统-客服-{newsType}-{accountNickName}-{storeType}-{currentDate}-{bookName}
name = name.replace("{bookName}", referral.getBookName());
} else if (newsType.equals(CustomerCommonConstant.ACTIVITY_NEWS_TYPE)) {
// 系统-客服-{newsType}-{accountNickName}-{storeType}-{currentDate}-充{recharge}送{gift}
name = name.replace("{recharge}", referral.getRechargeAmount().stripTrailingZeros().toPlainString()).replace("{gift}", referral.getGiftAmount().toString());
}
referral.setName(name + "-" +System.currentTimeMillis() % 100000);
}
/**
* 获取链接
*
* @param referralEntity 链接参数
*/
private void doGetReferral(ReferralEntity referralEntity) {
// 获取链接
R r = referralFeignClient.productReferral(referralEntity);
if (!r.getCode().equals(ApiResultConstant.SUCCESS_CODE)) {
localLog.warn("获取链接异常, 异常信息: {}, 参数: {}", r.getMessage(), referralEntity);
throw new RuntimeException(r.getMessage());
}
String res = r.getData("storeReferral", new TypeReference<String>() {});
JSONObject jsonObject1 = JSON.parseObject(res);
String referral = jsonObject1.getString("referral");
referralEntity.setPromoteId(jsonObject1.getString("promoteId"));
referralEntity.setReferral(referral);
}
}
...@@ -22,13 +22,13 @@ public class MyMetaObjectHandler implements MetaObjectHandler { ...@@ -22,13 +22,13 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
@Override @Override
public void insertFill(MetaObject metaObject) { public void insertFill(MetaObject metaObject) {
Long userId = tokenManager.getUserIdFromToken(); Long userId = tokenManager.getUserIdFromToken();
if (ObjectUtil.isNull(userId)){ if (ObjectUtil.isNotNull(userId)){
this.setFieldValByName("gmtModifiedUser", "0", metaObject);
this.setFieldValByName("gmtCreateUser", "0", metaObject);
}else {
String userIdStr = userId.toString(); String userIdStr = userId.toString();
this.setFieldValByName("gmtModifiedUser", userIdStr, metaObject); this.setFieldValByName("gmtModifiedUser", userIdStr, metaObject);
this.setFieldValByName("gmtCreateUser", userIdStr, metaObject); this.setFieldValByName("gmtCreateUser", userIdStr, metaObject);
this.setFieldValByName("modifiedUser", userId, metaObject);
this.setFieldValByName("createUser", userId, metaObject);
} }
this.setFieldValByName("gmtCreate", new Date(), metaObject); this.setFieldValByName("gmtCreate", new Date(), metaObject);
this.setFieldValByName("gmtModified", new Date(), metaObject); this.setFieldValByName("gmtModified", new Date(), metaObject);
...@@ -41,10 +41,9 @@ public class MyMetaObjectHandler implements MetaObjectHandler { ...@@ -41,10 +41,9 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
public void updateFill(MetaObject metaObject) { public void updateFill(MetaObject metaObject) {
this.setFieldValByName("gmtModified",new Date(),metaObject); this.setFieldValByName("gmtModified",new Date(),metaObject);
Long userId = tokenManager.getUserIdFromToken(); Long userId = tokenManager.getUserIdFromToken();
if (ObjectUtil.isNull(userId)){ if (ObjectUtil.isNotNull(userId)){
this.setFieldValByName("gmtModifiedUser", "0", metaObject);
}else {
this.setFieldValByName("gmtModifiedUser", userId.toString(), metaObject); this.setFieldValByName("gmtModifiedUser", userId.toString(), metaObject);
this.setFieldValByName("modifiedUser", userId, metaObject);
} }
} }
} }
...@@ -89,7 +89,7 @@ public class CustomerCommonConstant { ...@@ -89,7 +89,7 @@ public class CustomerCommonConstant {
public static String getNewsTypeName(Integer code) { public static String getNewsTypeName(Integer code) {
if (ObjectUtil.isNull(code)) { if (ObjectUtil.isNull(code)) {
return null; return "";
} }
if (code.equals(BOOK_NEWS_TYPE)) { if (code.equals(BOOK_NEWS_TYPE)) {
return BOOK_NEWS_TYPE_NAME; return BOOK_NEWS_TYPE_NAME;
...@@ -100,12 +100,12 @@ public class CustomerCommonConstant { ...@@ -100,12 +100,12 @@ public class CustomerCommonConstant {
if (code.equals(USUAL_LINK_NEWS_TYPE)) { if (code.equals(USUAL_LINK_NEWS_TYPE)) {
return USUAL_LINK_NEWS_TYPE_NAME; return USUAL_LINK_NEWS_TYPE_NAME;
} }
return null; return "";
} }
public static String getLinkNameModel(Integer code) { public static String getLinkNameModel(Integer code) {
if (ObjectUtil.isNull(code)) { if (ObjectUtil.isNull(code)) {
return null; return "";
} }
if (code.equals(BOOK_NEWS_TYPE)) { if (code.equals(BOOK_NEWS_TYPE)) {
return BOOK_NEWS_TYPE_NAME_MODEL; return BOOK_NEWS_TYPE_NAME_MODEL;
...@@ -114,7 +114,7 @@ public class CustomerCommonConstant { ...@@ -114,7 +114,7 @@ public class CustomerCommonConstant {
return ACTIVITY_NEWS_TYPE_NAME_MODEL; return ACTIVITY_NEWS_TYPE_NAME_MODEL;
} }
return null; return "";
} }
} }
package com.yaoyaozw.customer.constants;
import java.util.Arrays;
import java.util.List;
/**
* @author darker
* @date 2023/3/14 11:56
*/
public class FollowReplyCommonConstant {
public final static String TENCENT_MEDIA_TYPE_PIC = "image";
public final static String TENCENT_MEDIA_TYPE_VOICE = "voice";
public final static String TENCENT_MEDIA_TYPE_NEWS = "news";
public final static String TENCENT_MEDIA_TYPE_TEXT = "text";
public static Boolean needUpload(String type) {
return TENCENT_MEDIA_TYPE_PIC.equals(type) || TENCENT_MEDIA_TYPE_VOICE.equals(type);
}
public static Boolean needReferral(String type) {
return TENCENT_MEDIA_TYPE_NEWS.equals(type) || TENCENT_MEDIA_TYPE_TEXT.equals(type);
}
}
...@@ -2,12 +2,14 @@ package com.yaoyaozw.customer.controller; ...@@ -2,12 +2,14 @@ package com.yaoyaozw.customer.controller;
import com.yaoyaozw.customer.common.BaseResult; import com.yaoyaozw.customer.common.BaseResult;
import com.yaoyaozw.customer.common.GenericsResult; import com.yaoyaozw.customer.common.GenericsResult;
import com.yaoyaozw.customer.dto.follow.FollowReturnCopyDTO; import com.yaoyaozw.customer.dto.follow.FollowReplyCopyDTO;
import com.yaoyaozw.customer.entity.CommonReferralBody; import com.yaoyaozw.customer.entity.CommonReferralBody;
import com.yaoyaozw.customer.dto.follow.FollowReturnQueryDTO; import com.yaoyaozw.customer.dto.follow.FollowReplyQueryDTO;
import com.yaoyaozw.customer.dto.follow.FollowReturnSaveDTO; import com.yaoyaozw.customer.dto.follow.FollowReplySaveDTO;
import com.yaoyaozw.customer.vo.follow.FollowReturnListVO; import com.yaoyaozw.customer.service.CustomerFollowReplyService;
import com.yaoyaozw.customer.vo.follow.FollowReturnTextItemVO; import com.yaoyaozw.customer.vo.follow.FollowReplyInfoVO;
import com.yaoyaozw.customer.vo.follow.FollowReplyListVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
...@@ -17,38 +19,46 @@ import java.util.List; ...@@ -17,38 +19,46 @@ import java.util.List;
* @date 2023/3/13 19:47 * @date 2023/3/13 19:47
*/ */
@RestController @RestController
@RequestMapping("/follow-return") @RequestMapping("/follow-reply")
public class FollowReturnController { public class FollowReplyController {
@Autowired
private CustomerFollowReplyService followReplyService;
@PostMapping("/list") @PostMapping("/list")
public GenericsResult<List<FollowReturnListVO>> list(@RequestBody FollowReturnQueryDTO queryDto) { public GenericsResult<List<FollowReplyListVO>> list(@RequestBody FollowReplyQueryDTO queryDto) {
return null; return followReplyService.list(queryDto);
} }
@PostMapping("/create") @PostMapping("/create")
public GenericsResult<String> create(@RequestBody FollowReturnSaveDTO saveDto) { public GenericsResult<String> create(@RequestBody FollowReplySaveDTO saveDto) {
return null; return followReplyService.create(saveDto);
} }
@PostMapping("/createTextItem") @PostMapping("/createTextItem")
public GenericsResult<List<FollowReturnTextItemVO>> createTextItem(@RequestBody CommonReferralBody referralBody) { public GenericsResult<List<CommonReferralBody>> createTextItem(@RequestBody CommonReferralBody referralBody) {
return null; return followReplyService.createTextItem(referralBody);
}
@GetMapping("/info/{id}")
public GenericsResult<FollowReplyInfoVO> getInfo(@PathVariable("id") Long id) {
return followReplyService.getInfo(id);
} }
@GetMapping("/remove/{id}") @GetMapping("/remove/{id}")
public BaseResult remove(@PathVariable("id") Long id) { public BaseResult remove(@PathVariable("id") Long id) {
return null; return followReplyService.remove(id);
} }
@GetMapping("/removeTextItem/{id}") @GetMapping("/removeTextItem/{id}")
public GenericsResult<List<FollowReturnTextItemVO>> removeTextItem(@PathVariable("id") Long id) { public GenericsResult<List<CommonReferralBody>> removeTextItem(@PathVariable("id") Long id) {
return null; return followReplyService.removeTextItem(id);
} }
@PostMapping("/copy") @PostMapping("/copy")
public BaseResult copy(@RequestBody FollowReturnCopyDTO copyDto) { public BaseResult copy(@RequestBody FollowReplyCopyDTO copyDto) {
return null; return followReplyService.copy(copyDto);
} }
......
package com.yaoyaozw.customer.dto.follow; package com.yaoyaozw.customer.dto.follow;
import com.yaoyaozw.customer.vo.AuthInfoVO;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
* @author darker * @author darker
* @date 2023/3/13 19:59 * @date 2023/3/13 19:59
*/ */
@Data @Data
public class FollowReturnQueryDTO implements Serializable { public class FollowReplyCopyDTO implements Serializable {
private AuthInfoVO sourceAuth;
private List<AuthInfoVO> targetAuthList;
} }
...@@ -3,11 +3,15 @@ package com.yaoyaozw.customer.dto.follow; ...@@ -3,11 +3,15 @@ package com.yaoyaozw.customer.dto.follow;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
* @author darker * @author darker
* @date 2023/3/13 19:59 * @date 2023/3/13 19:59
*/ */
@Data @Data
public class FollowReturnCopyDTO implements Serializable { public class FollowReplyQueryDTO implements Serializable {
private String appId;
} }
package com.yaoyaozw.customer.dto.follow; package com.yaoyaozw.customer.dto.follow;
import cn.hutool.core.util.ObjectUtil;
import com.yaoyaozw.customer.entity.CommonReferralBody;
import com.yaoyaozw.customer.vo.AuthInfoVO;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
...@@ -9,5 +12,24 @@ import java.io.Serializable; ...@@ -9,5 +12,24 @@ import java.io.Serializable;
* @date 2023/3/13 19:59 * @date 2023/3/13 19:59
*/ */
@Data @Data
public class FollowReturnSaveDTO implements Serializable { public class FollowReplySaveDTO implements Serializable {
private Long id;
private String appid;
private String name;
private String type;
private String originMediaUrl;
private String extendTitle;
private String extendDesc;
private Integer sort;
private CommonReferralBody referralBody;
} }
...@@ -36,6 +36,8 @@ public class CommonReferralBody implements Serializable { ...@@ -36,6 +36,8 @@ public class CommonReferralBody implements Serializable {
@ApiModelProperty("appId") @ApiModelProperty("appId")
private String appId; private String appId;
private Long infoId;
@ApiModelProperty("链接类型") @ApiModelProperty("链接类型")
private Integer newsType; private Integer newsType;
......
package com.yaoyaozw.customer.entity;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import org.springframework.data.annotation.Id;
/**
* 客户跟进回复
*
* @author darker
* @date 2023/03/14
*/
@Data
@TableName("customer_follow_reply")
public class CustomerFollowReply implements Serializable {
/**
* 主键id
*/
@Id
@TableId(value = "id", type = IdType.ID_WORKER)
private Long id;
/**
* 公众号appid
*/
@TableField("appid")
private String appid;
/**
* 素材名称
*/
@TableField("name")
private String name;
/**
* 类型
*/
@TableField("type")
private String type;
/**
* 图片/音频 原文件地址
*/
@TableField("origin_media_url")
private String originMediaUrl;
/**
* 图片/音频 腾讯后台地址
*/
@TableField("tx_media_url")
private String txMediaUrl;
/**
* 图片/音频 腾讯后台标识
*/
@TableField("tx_media_id")
private String txMediaId;
/**
* 图文-推广标题
*/
@TableField("extend_title")
private String extendTitle;
/**
* 图文-推广描述
*/
@TableField("extend_desc")
private String extendDesc;
/**
* 图文链接地址
*/
@TableField("source_url")
private String sourceUrl;
/**
* 文本-H5
*/
@TableField("content")
private String content;
/**
* 发文排序
*/
@TableField("sort")
private Integer sort;
/**
* 状态
*/
@TableField("status")
private Integer status;
/**
* 逻辑删除
*/
@TableField(value = "is_deleted", fill = FieldFill.INSERT)
@TableLogic
private Integer isDeleted;
/**
* 创建人
*/
@TableField(value = "gmt_create", fill = FieldFill.INSERT)
private Long createUser;
/**
* 创建时间
*/
@TableField(value = "gmt_create", fill = FieldFill.INSERT)
private Date gmtCreate;
/**
* 更新人
*/
@TableField(value = "gmt_modified", fill = FieldFill.INSERT_UPDATE)
private Long modifiedUser;
/**
* 更新时间
*/
@TableField(value = "gmt_modified", fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
@TableField(exist = false)
private List<ReferralEntity> referralEntityList;
private static final long serialVersionUID = 1L;
}
package com.yaoyaozw.customer.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yaoyaozw.customer.entity.CustomerFollowReply;
import org.springframework.stereotype.Repository;
/**
* @author darker
* @date 2023/3/14 11:14
*/
@Repository
public interface CustomerFollowReplyMapper extends BaseMapper<CustomerFollowReply> {
}
package com.yaoyaozw.customer.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yaoyaozw.customer.common.BaseResult;
import com.yaoyaozw.customer.common.GenericsResult;
import com.yaoyaozw.customer.dto.follow.FollowReplyCopyDTO;
import com.yaoyaozw.customer.dto.follow.FollowReplyQueryDTO;
import com.yaoyaozw.customer.dto.follow.FollowReplySaveDTO;
import com.yaoyaozw.customer.entity.CommonReferralBody;
import com.yaoyaozw.customer.entity.CustomerFollowReply;
import com.yaoyaozw.customer.vo.follow.FollowReplyInfoVO;
import com.yaoyaozw.customer.vo.follow.FollowReplyListVO;
import java.util.List;
/**
* @author darker
* @date 2023/3/14 11:14
*/
public interface CustomerFollowReplyService extends IService<CustomerFollowReply> {
/**
* 列表
*
* @param queryDto 查询dto
* @return {@link GenericsResult}<{@link List}<{@link FollowReplyListVO}>>
*/
GenericsResult<List<FollowReplyListVO>> list(FollowReplyQueryDTO queryDto);
/**
* 创建
*
* @param saveDto 保存dto
* @return {@link GenericsResult}<{@link String}>
*/
GenericsResult<String> create(FollowReplySaveDTO saveDto);
/**
* 创建文本项
*
* @param referralBody 推荐身体
* @return {@link GenericsResult}<{@link List}<{@link CommonReferralBody}>>
*/
GenericsResult<List<CommonReferralBody>> createTextItem(CommonReferralBody referralBody);
/**
* 删除
*
* @param id id
* @return {@link BaseResult}
*/
BaseResult remove(Long id);
/**
* 删除文本项
*
* @param id id
* @return {@link GenericsResult}<{@link List}<{@link CommonReferralBody}>>
*/
GenericsResult<List<CommonReferralBody>> removeTextItem(Long id);
/**
* 复制
*
* @param copyDto 复制dto
* @return {@link BaseResult}
*/
BaseResult copy(FollowReplyCopyDTO copyDto);
/**
* 得到信息
*
* @param id id
* @return {@link GenericsResult}<{@link FollowReplyInfoVO}>
*/
GenericsResult<FollowReplyInfoVO> getInfo(Long id);
}
package com.yaoyaozw.customer.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yaoyaozw.customer.common.BaseResult;
import com.yaoyaozw.customer.common.GenericsResult;
import com.yaoyaozw.customer.components.FollowReplyComponent;
import com.yaoyaozw.customer.components.SnowflakeComponent;
import com.yaoyaozw.customer.constants.FollowReplyCommonConstant;
import com.yaoyaozw.customer.dto.follow.FollowReplyCopyDTO;
import com.yaoyaozw.customer.dto.follow.FollowReplyQueryDTO;
import com.yaoyaozw.customer.dto.follow.FollowReplySaveDTO;
import com.yaoyaozw.customer.entity.CommonReferralBody;
import com.yaoyaozw.customer.entity.CustomerFollowReply;
import com.yaoyaozw.customer.entity.ReferralEntity;
import com.yaoyaozw.customer.mapper.CustomerFollowReplyMapper;
import com.yaoyaozw.customer.service.CustomerFollowReplyService;
import com.yaoyaozw.customer.service.ReferralEntityService;
import com.yaoyaozw.customer.utils.TencentCustomerUtil;
import com.yaoyaozw.customer.vo.AuthInfoVO;
import com.yaoyaozw.customer.vo.TencentMediaResponseVO;
import com.yaoyaozw.customer.vo.follow.FollowReplyCopyResultVO;
import com.yaoyaozw.customer.vo.follow.FollowReplyInfoVO;
import com.yaoyaozw.customer.vo.follow.FollowReplyListVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author darker
* @date 2023/3/14 11:15
*/
@Service
public class CustomerFollowReplyServiceImpl extends ServiceImpl<CustomerFollowReplyMapper, CustomerFollowReply> implements CustomerFollowReplyService {
private final static Logger localLog = LoggerFactory.getLogger(CustomerFollowReplyServiceImpl.class);
@Autowired
private TencentCustomerUtil tencentCustomerUtil;
@Autowired
private SnowflakeComponent snowflakeComponent;
@Autowired
private FollowReplyComponent followReplyComponent;
@Autowired
private ReferralEntityService referralEntityService;
@Override
public GenericsResult<List<FollowReplyListVO>> list(FollowReplyQueryDTO queryDto) {
return null;
}
@Override
public GenericsResult<String> create(FollowReplySaveDTO saveDto) {
CustomerFollowReply entity = new CustomerFollowReply();
BeanUtil.copyProperties(saveDto, entity);
CustomerFollowReply sourceEntity = this.getById(entity.getId());
boolean isCreate = ObjectUtil.isNull(entity.getId());
if (isCreate) {
// 新增的id
entity.setId(snowflakeComponent.snowflakeId());
} else if (FollowReplyCommonConstant.needReferral(sourceEntity.getType())) {
// 如果编辑更换过类型,清除掉referral数据
referralEntityService.remove(new QueryWrapper<ReferralEntity>().eq(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, sourceEntity.getId()));
}
// 判断是否需要上传文件(图片、语音)
if (FollowReplyCommonConstant.needUpload(entity.getType())) {
// 编辑的时候,删除原来的media
if (!isCreate) {
if (StringUtils.isNotBlank(sourceEntity.getTxMediaId())) {
TencentMediaResponseVO removeResponse = tencentCustomerUtil.removePermanentMedia(sourceEntity.getAppid(), sourceEntity.getTxMediaId());
if (ObjectUtil.isNull(removeResponse.getErrcode()) || removeResponse.getErrcode() != 0) {
return new GenericsResult<>(false, "删除原本素材失败: " + removeResponse.getErrmsg());
}
}
}
// 上传文件
TencentMediaResponseVO uploadResponse = tencentCustomerUtil.uploadTencentMedia(entity.getAppid(), entity.getOriginMediaUrl(), entity.getType());
if (StringUtils.isNotBlank(uploadResponse.getErrmsg())) {
// 上传失败
return new GenericsResult<>(false, uploadResponse.getErrmsg());
}
entity.setTxMediaUrl(uploadResponse.getUrl());
entity.setTxMediaId(uploadResponse.getMedia_id());
} else {
// 获取书城公众号链接(图文)
ReferralEntity referralEntity;
try {
referralEntity = followReplyComponent.getCreateReferralEntity(saveDto.getReferralBody());
} catch (Exception e) {
throw new RuntimeException("获取链接异常: " + e.getMessage());
}
referralEntity.setMaterialGraphicsId(entity.getId());
// 保存链接数据
if (ObjectUtil.isNull(referralEntity.getId())) {
referralEntityService.save(referralEntity);
} else {
referralEntityService.updateById(referralEntity);
}
}
// 保存主体数据
if (isCreate) {
this.save(entity);
} else {
this.updateById(entity);
}
return new GenericsResult<>(String.valueOf(entity.getId()));
}
@Override
public GenericsResult<List<CommonReferralBody>> createTextItem(CommonReferralBody referralBody) {
CustomerFollowReply entity = this.getById(referralBody.getMaterialGraphicsId());
if (ObjectUtil.isNull(entity)) {
return new GenericsResult<>(false, "找不到主体数据");
}
ReferralEntity referralEntity;
try {
referralEntity = followReplyComponent.getCreateReferralEntity(referralBody);
} catch (Exception e) {
throw new RuntimeException("获取链接异常: " + e.getMessage());
}
// 保存链接数据
if (ObjectUtil.isNull(referralEntity.getId())) {
referralEntityService.save(referralEntity);
} else {
referralEntityService.updateById(referralEntity);
}
List<ReferralEntity> referralList = referralEntityService.list(new QueryWrapper<ReferralEntity>().eq(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, entity.getId()).orderByAsc(ReferralEntity.COL_GMT_CREATE));
String content = followReplyComponent.reSortAndSaveTextItem(referralList);
entity.setContent(content);
// 保存主体
this.updateById(entity);
JSONArray referralJsonArray = JSONUtil.parseArray(referralList);
List<CommonReferralBody> referralBodyList = JSONUtil.toList(referralJsonArray, CommonReferralBody.class);
return new GenericsResult<>(referralBodyList);
}
@Override
public BaseResult remove(Long id) {
// 从腾讯删除文件
CustomerFollowReply entity = this.getById(id);
if (ObjectUtil.isNull(entity)) {
return new BaseResult().error("找不到实体数据");
}
if (StringUtils.isNotEmpty(entity.getTxMediaId())) {
tencentCustomerUtil.removePermanentMedia(entity.getAppid(), entity.getTxMediaId());
}
// 删除本体
this.removeById(id);
// 删除相关链接
referralEntityService.remove(new QueryWrapper<ReferralEntity>().eq(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, id));
return new BaseResult().success("删除");
}
@Override
public GenericsResult<List<CommonReferralBody>> removeTextItem(Long id) {
ReferralEntity referralEntity = referralEntityService.getById(id);
if (ObjectUtil.isNull(referralEntity)) {
return new GenericsResult<>(false, "未找到该文本子素材");
}
// 查询子素材所属素材
CustomerFollowReply entity = this.getById(referralEntity.getMaterialGraphicsId());
if (ObjectUtil.isNull(entity)) {
return new GenericsResult<>(false, "未找到该文本所属素材");
}
// 删除子文本
referralEntityService.removeById(id);
// 重新排序构造
List<ReferralEntity> referralList = referralEntityService.list(new QueryWrapper<ReferralEntity>().eq(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, referralEntity.getMaterialGraphicsId()).orderByAsc(ReferralEntity.COL_GMT_CREATE));
String content = followReplyComponent.reSortAndSaveTextItem(referralList);
entity.setContent(content);
// 保存实体
this.updateById(entity);
JSONArray referralJsonArray = JSONUtil.parseArray(referralList);
List<CommonReferralBody> referralBodyList = JSONUtil.toList(referralJsonArray, CommonReferralBody.class);
return new GenericsResult<>(referralBodyList);
}
@Override
public BaseResult copy(FollowReplyCopyDTO copyDto) {
AuthInfoVO sourceAuth = copyDto.getSourceAuth();
List<AuthInfoVO> targetAuthList = copyDto.getTargetAuthList();
localLog.info("调用复用, 源公众号: {}, 目标公众号: {}条", sourceAuth.getAccountName(), targetAuthList.size());
List<CustomerFollowReply> sourceMaterialList = getSourceMaterialList(sourceAuth.getAppId());
if (CollectionUtil.isEmpty(sourceMaterialList)) {
return new BaseResult().error("源公众号找不到素材");
}
// 删除目标公众号现有的素材和链接
removeOriginMaterialList(targetAuthList);
List<String> errorAuthList = null;
for (AuthInfoVO targetAuth : targetAuthList) {
// 调用复用
FollowReplyCopyResultVO result = followReplyComponent.copyMaterialToTarget(targetAuth, sourceMaterialList);
if (result.getHasError()) {
if (errorAuthList == null) {
errorAuthList = new ArrayList<>();
}
errorAuthList.add(targetAuth.getAccountName());
}
}
if (CollectionUtil.isNotEmpty(errorAuthList)) {
return new BaseResult().error("部分成功; 复用异常公众号: " + errorAuthList);
}
return new BaseResult().success();
}
@Override
public GenericsResult<FollowReplyInfoVO> getInfo(Long id) {
CustomerFollowReply entity = this.getById(id);
FollowReplyInfoVO infoVo = new FollowReplyInfoVO();
BeanUtil.copyProperties(entity, infoVo);
// 获取素材的链接数据
if (FollowReplyCommonConstant.needReferral(entity.getType())) {
// 是需要设置referral的类型
if (FollowReplyCommonConstant.TENCENT_MEDIA_TYPE_TEXT.equals(entity.getType())) {
// 文本类型
List<ReferralEntity> referralList = referralEntityService.list(new QueryWrapper<ReferralEntity>().eq(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, id).orderByAsc("sort"));
JSONArray referralJsonArray = JSONUtil.parseArray(referralList);
List<CommonReferralBody> referralBodyList = JSONUtil.toList(referralJsonArray, CommonReferralBody.class);
infoVo.setTextBodyList(referralBodyList);
} else if (FollowReplyCommonConstant.TENCENT_MEDIA_TYPE_NEWS.equals(entity.getType())) {
try {
// 设置图文类型的链接数据
ReferralEntity referralEntity = referralEntityService.getOne(new QueryWrapper<ReferralEntity>().eq(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, id));
if (ObjectUtil.isNotNull(referralEntity)) {
CommonReferralBody referralBody = new CommonReferralBody();
BeanUtil.copyProperties(referralEntity, referralBody);
infoVo.setReferralBody(referralBody);
}
} catch (Exception e) {
return new GenericsResult<>(false, "获取图文链接实体异常");
}
}
}
return new GenericsResult<>(infoVo);
}
private List<CustomerFollowReply> getSourceMaterialList(String appid) {
List<CustomerFollowReply> sourceMaterialList = this.list(new QueryWrapper<CustomerFollowReply>().eq("appid", appid));
if (CollectionUtil.isEmpty(sourceMaterialList)) {
return null;
}
localLog.info("获取到源公众号素材: {}条", sourceMaterialList.size());
// 获取链接
List<Long> materialIdList = sourceMaterialList.stream().map(CustomerFollowReply::getId).collect(Collectors.toList());
List<ReferralEntity> referralEntityList = referralEntityService.list(new QueryWrapper<ReferralEntity>().eq(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, materialIdList));
localLog.info("获取到源公众号链接数据: {}条", referralEntityList.size());
Map<Long, List<ReferralEntity>> referralMap = referralEntityList.stream().collect(Collectors.groupingBy(ReferralEntity::getMaterialGraphicsId));
// 分配referral
for (CustomerFollowReply sourceEntity : sourceMaterialList) {
sourceEntity.setReferralEntityList(referralMap.get(sourceEntity.getId()));
}
return sourceMaterialList;
}
private void removeOriginMaterialList(List<AuthInfoVO> targetList) {
List<String> targetAppidList = targetList.stream().map(AuthInfoVO::getAppId).collect(Collectors.toList());
List<CustomerFollowReply> sourceMaterialList = this.list(new QueryWrapper<CustomerFollowReply>().in("appid", targetAppidList));
// 原来没有
if (CollectionUtil.isEmpty(sourceMaterialList)) {
return;
}
List<Long> sourceMaterialIdList = new ArrayList<>();
for (CustomerFollowReply sourceMaterial : sourceMaterialList) {
sourceMaterialIdList.add(sourceMaterial.getId());
if (StringUtils.isNotEmpty(sourceMaterial.getTxMediaId())) {
// 删除公众号后台的素材
tencentCustomerUtil.removePermanentMedia(sourceMaterial.getAppid(), sourceMaterial.getTxMediaId());
}
}
// 删除主体
this.removeByIds(sourceMaterialIdList);
// 删除链接
referralEntityService.remove(new QueryWrapper<ReferralEntity>().in(ReferralEntity.COL_MATERIAL_GRAPHICS_ID, sourceMaterialIdList));
}
}
package com.yaoyaozw.customer.utils;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class HttpClientUtil {
static PoolingHttpClientConnectionManager poolingClient = null;
/**
* 得到http客户端
*
* @param timeout 超时
* @return {@link CloseableHttpClient}
*/
public static CloseableHttpClient getHttpClient(int timeout) {
// 设置连接超时时间
int connectTimeout = 2 * 1000;
int socketTimeout = timeout * 1000;
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setSocketTimeout(socketTimeout).build();
//因为服务端断开连接,但并没有通知客户端,导致下次请求该服务时httpclient继续使用该连接导致报错。
ConnectionKeepAliveStrategy connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse httpResponse,
HttpContext httpContext) {
return 10000L;
}
};
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
httpClientBuilder.setConnectionManager(poolingClient);
httpClientBuilder.setDefaultRequestConfig(requestConfig);
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler());
httpClientBuilder.setKeepAliveStrategy(connectionKeepAliveStrategy);
return httpClientBuilder.build();
}
public static String doPostJson(String url, String json, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
//创建post方法连接实例,在post方法中传入待连接地址
HttpPost httpPost = new HttpPost(uri);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return resultString;
}
public static String uploadFile(String url, MultipartFile file, Map<String, String> param) {
String result = "";
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
//创建post方法连接实例,在post方法中传入待连接地址
HttpPost httpPost = new HttpPost(uri);
//HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
MultipartEntityBuilder entity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
// httpPost.addHeader("header1", "111");//头部放文件上传的head可自定义
entity.addBinaryBody("media", file.getBytes(), ContentType.MULTIPART_FORM_DATA, file.getOriginalFilename());
HttpEntity httpEntity = entity.build();
httpPost.setEntity(httpEntity);
// 执行提交
response = httpClient.execute(httpPost);
//接收调用外部接口返回的内容
HttpEntity responseEntity = response.getEntity();
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回的内容都在content中
InputStream content = responseEntity.getContent();
// 定义BufferedReader输入流来读取URL的响应
BufferedReader in = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
}
} catch (Exception e) {
log.error("上传文件失败:", e);
} finally {//处理结束后关闭httpclient的链接
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
public static String uploadFileByte(String url, byte[] data, Map<String, String> param, String fileSuffix) {
String result = "";
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
//创建post方法连接实例,在post方法中传入待连接地址
HttpPost httpPost = new HttpPost(uri);
//HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
MultipartEntityBuilder entity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
// httpPost.addHeader("header1", "111");//头部放文件上传的head可自定义
entity.addBinaryBody("media", data, ContentType.MULTIPART_FORM_DATA, UUID.randomUUID() + "." + fileSuffix);
HttpEntity httpEntity = entity.build();
httpPost.setEntity(httpEntity);
// 执行提交
response = httpClient.execute(httpPost);
//接收调用外部接口返回的内容
HttpEntity responseEntity = response.getEntity();
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回的内容都在content中
InputStream content = responseEntity.getContent();
// 定义BufferedReader输入流来读取URL的响应
BufferedReader in = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
}
} catch (Exception e) {
log.error("上传文件失败:", e);
} finally {//处理结束后关闭httpclient的链接
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
public static byte[] readInputStream(String sUrl) {
try {
URL url = new URL(sUrl);
URLConnection connection = url.openConnection();
InputStream inStream = connection.getInputStream();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[10240];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
} catch (Exception e) {
log.info("获取网络图片失败");
throw new RuntimeException(e.getMessage());
}
}
/**
* 根据地址获得数据的字节流
*
* @param strUrl 网络连接地址
* @return
*/
public static byte[] getImageFromNetByUrl(String strUrl) {
try {
URL url = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
InputStream inStream = conn.getInputStream();
byte[] btImg = readInputStream(inStream);
return btImg;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 从输入流中获取数据
*
* @param inStream 输入流
* @return
* @throws Exception
*/
public static byte[] readInputStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[10240];
int len;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
}
public static String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
log.info("请求uri:{}", uri.toString());
// 创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
// 创建Httpclient对象
CloseableHttpClient httpClient = getHttpClient(4);
String resultString = "";
CloseableHttpResponse response = null;
// 创建http GET请求
HttpGet httpGet = new HttpGet(url);
try {
// 执行请求
response = httpClient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (ConnectTimeoutException | SocketTimeoutException e) {
//再重试一遍
return doRepeat(httpGet);
} catch (Exception e) {
e.printStackTrace();
log.error("HttpClientUtil url: " + url + "+ error:{}", e);
} finally {
try {
if (response != null) {
response.close();
}
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
log.error("HttpClientUtil url: " + url + "+ error:{}", e);
}
}
return resultString;
}
public static String doPostToTpm(String url, Map<String, Object> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = getHttpClient(1000);
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
StringBuffer sb = new StringBuffer();
sb.append(url).append("?appKey=").append(param.get("appKey"))
.append("&messageType=").append(param.get("messageType"))
.append("&sign=").append(param.get("sign"))
.append("&timestamp=").append(param.get("timestamp"));
url = sb.toString();
HttpPost httpPost = new HttpPost(url);
log.info("url : " + url);
//添加body
ByteArrayEntity entity = null;
try {
entity = new ByteArrayEntity(JSON.toJSONString(JSON.toJSONString(param)).getBytes("UTF-8"));
entity.setContentType("application/json");
} catch (UnsupportedEncodingException e) {
log.error("向服务器承保接口发起http请求,封装请求body时出现异常", e);
throw new RuntimeException("向服务器承保接口发起http请求,封装请求body时出现异常", e);
}
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
log.error("doPostToTpm error: {} ", e.getMessage());
} finally {
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPost(String url) {
return doPost(url, null);
}
public static String doPost(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPostJson(String url, String json) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
/**
* 做重复
*
* @param request 请求
* @return {@link String}
*/
private static String doRepeat(HttpRequestBase request) {
CloseableHttpClient httpClient = getHttpClient(6);
HttpResponse response = null;
try {
response = httpClient.execute(request);
if (response.getStatusLine().getStatusCode() != 200) {
log.error("重发,接口请求失败,httpcode="
+ response.getStatusLine().getStatusCode() + "; url="
+ request.getURI());
return null;
}
return EntityUtils.toString(response.getEntity());
} catch (Exception e) {
log.error("重发,调用API错误, url:" + request.getURI(), e);
return null;
} finally {
close(response, httpClient);
}
}
private static void close(HttpResponse response, CloseableHttpClient httpClient) {
if (response != null) {
try {
EntityUtils.consume(response.getEntity());
} catch (IOException e) {
log.error("response close error: {}", e.getMessage());
}
}
}
public static String doPostToCustomerTpm(String url, Map<String, Object> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = getHttpClient(1000);
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
StringBuffer sb = new StringBuffer();
sb.append(url).append("?appKey=").append(param.get("appKey"))
.append("&messageType=").append(param.get("messageType"))
.append("&sign=").append(param.get("sign"))
.append("&timestamp=").append(param.get("timestamp"))
.append("&customerCode=").append(param.get("customerCode"));
url = sb.toString();
HttpPost httpPost = new HttpPost(url);
log.info("url : " + url);
//添加body
ByteArrayEntity entity = null;
try {
entity = new ByteArrayEntity(JSON.toJSONString(JSON.toJSONString(param)).getBytes("UTF-8"));
entity.setContentType("application/json");
} catch (UnsupportedEncodingException e) {
log.error("向服务器承保接口发起http请求,封装请求body时出现异常", e);
throw new RuntimeException("向服务器承保接口发起http请求,封装请求body时出现异常", e);
}
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
log.error("doPostToTpm error: {} ", e.getMessage());
} finally {
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPostFromDate(String url, Map<String, String> data, Map<String, String> param) {
StringBuilder result = new StringBuilder();
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
//创建post方法连接实例,在post方法中传入待连接地址
HttpPost httpPost = new HttpPost(uri);
//HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
MultipartEntityBuilder entity = MultipartEntityBuilder.create();
// httpPost.addHeader("header1", "111");//头部放文件上传的head可自定义
for (Map.Entry<String, String> stringStringEntry : data.entrySet()) {
entity.addTextBody(stringStringEntry.getKey(),stringStringEntry.getValue());
}
HttpEntity httpEntity = entity.build();
httpPost.setEntity(httpEntity);
// 执行提交
response = httpClient.execute(httpPost);
//接收调用外部接口返回的内容
HttpEntity responseEntity = response.getEntity();
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 返回的内容都在content中
InputStream content = responseEntity.getContent();
// 定义BufferedReader输入流来读取URL的响应
BufferedReader in = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
}
} catch (Exception e) {
log.error("上传文件失败:", e);
} finally {//处理结束后关闭httpclient的链接
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result.toString();
}
}
package com.yaoyaozw.customer.utils; package com.yaoyaozw.customer.utils;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yaoyaozw.customer.entity.AuthorizerToken;
import com.yaoyaozw.customer.entity.ReferralEntity;
import com.yaoyaozw.customer.service.AuthorizerTokenService;
import com.yaoyaozw.customer.service.ReferralEntityService;
import com.yaoyaozw.customer.vo.TencentMediaResponseVO; import com.yaoyaozw.customer.vo.TencentMediaResponseVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* @author darker * @author darker
* @date 2023/3/13 20:11 * @date 2023/3/13 20:11
*/ */
public class TencentCustomerUtil { @Component
public class TencentCustomerUtil{
private final static Logger localLog = LoggerFactory.getLogger(TencentCustomerUtil.class);
private final static String AUTH_ACCESS_TOKEN_REDIS_KEY = "AUTH_ACCESS_TOKEN";
private final static String MEDIA_ADD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material";
private final static String MEDIA_DEL_URL = "https://api.weixin.qq.com/cgi-bin/material/del_material";
@Autowired
private AuthorizerTokenService authorizerTokenService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/** /**
* 上传腾讯媒体 * 上传腾讯媒体
* *
* @param appid 公众号
* @param fileUrl 文件url * @param fileUrl 文件url
* @param accessToken 访问令牌
* @return {@link TencentMediaResponseVO} * @return {@link TencentMediaResponseVO}
*/ */
public static TencentMediaResponseVO uploadTencentMedia(String fileUrl, String accessToken) { public TencentMediaResponseVO uploadTencentMedia(String appid, String fileUrl, String mediaType) {
localLog.info("上传媒体文件, 原始文件地址: {}", fileUrl);
// 获取公众号token
String accessToken = getAccessTokenByAppid(appid);
if (StringUtils.isEmpty(accessToken)) {
localLog.warn("appid: {} 没找到accessToken", appid);
TencentMediaResponseVO response = new TencentMediaResponseVO();
response.setErrmsg("appid: " + appid + "没找到accessToken");
return response;
}
// 根据文件地址获取文件 // 根据文件地址获取文件
String suffix = fileUrl.substring(fileUrl.lastIndexOf("=") + 1);
byte[] fileByte = HttpClientUtil.readInputStream(fileUrl);
// 构造参数,上传到腾讯后台
Map<String, String> map = new HashMap<>(4);
map.put("access_token", accessToken);
map.put("type", mediaType);
String json = HttpClientUtil.uploadFileByte(MEDIA_ADD_URL, fileByte, map, suffix);
return JSONUtil.toBean(JSONUtil.parseObj(json), TencentMediaResponseVO.class);
}
/**
* 删除永久媒体
*
* @param appid appid
* @param mediaId 媒体id
* @return {@link TencentMediaResponseVO}
*/
public TencentMediaResponseVO removePermanentMedia(String appid, String mediaId) {
// 获取公众号token
String accessToken = getAccessTokenByAppid(appid);
// 构造参数,上传到腾讯后台
Map<String, String> map = new HashMap<>(4);
map.put("access_token", accessToken);
JSONObject json = new JSONObject();
json.put("media_id", mediaId);
String jsonStr = JSONUtil.toJsonStr(json);
String delResult = HttpClientUtil.doPostJson(MEDIA_DEL_URL, jsonStr, map);
localLog.info("删除素材结果: {}", delResult);
// 上传文件到腾讯后台 return JSONUtil.toBean(JSONUtil.parseObj(delResult), TencentMediaResponseVO.class);
}
/**
* 通过appid获取访问令牌
*
* @param appid appid
* @return {@link String}
*/
private String getAccessTokenByAppid(String appid) {
return null; Object token = redisTemplate.opsForHash().get(AUTH_ACCESS_TOKEN_REDIS_KEY, appid);
// 如果redis中没找到, 去数据库找
if (ObjectUtil.isNull(token)) {
AuthorizerToken authorizerToken = authorizerTokenService.findTokenByAppid(appid);
return ObjectUtil.isNull(authorizerToken) ? null : authorizerToken.getAuthorizerAccessToken();
}
return String.valueOf(token);
} }
} }
...@@ -15,4 +15,8 @@ public class TencentMediaResponseVO implements Serializable { ...@@ -15,4 +15,8 @@ public class TencentMediaResponseVO implements Serializable {
private String url; private String url;
private Integer errcode;
private String errmsg;
} }
package com.yaoyaozw.customer.vo.follow; package com.yaoyaozw.customer.vo.follow;
import com.yaoyaozw.customer.entity.CustomerFollowReply;
import com.yaoyaozw.customer.entity.ReferralEntity;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
* @author darker * @author darker
* @date 2023/3/13 20:07 * @date 2023/3/14 16:48
*/ */
@Data @Data
public class FollowReturnListVO implements Serializable { public class FollowReplyCopyResultVO implements Serializable {
private Boolean hasError;
private List<CustomerFollowReply> materialList;
private List<ReferralEntity> referralEntityList;
} }
package com.yaoyaozw.customer.vo.follow;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.yaoyaozw.customer.entity.CommonReferralBody;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author darker
* @date 2023/3/13 20:07
*/
@Data
public class FollowReplyInfoVO implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String appid;
private String name;
private Integer type;
private String originMediaUrl;
private String extendTitle;
private String extendDesc;
private Integer sort;
private CommonReferralBody referralBody;
private List<CommonReferralBody> textBodyList;
}
package com.yaoyaozw.customer.vo.follow; package com.yaoyaozw.customer.vo.follow;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data; import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
...@@ -9,5 +11,15 @@ import java.io.Serializable; ...@@ -9,5 +11,15 @@ import java.io.Serializable;
* @date 2023/3/13 20:07 * @date 2023/3/13 20:07
*/ */
@Data @Data
public class FollowReturnInfoVO implements Serializable { public class FollowReplyListVO implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private String authName;
private String typeDesc;
} }
package com.yaoyaozw.customer.vo.follow;
import lombok.Data;
import java.io.Serializable;
/**
* @author darker
* @date 2023/3/13 19:55
*/
@Data
public class FollowReturnTextItemVO implements Serializable {
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论