Browse Source

微信公众号相关接口开发

dev
wangfukang 1 year ago
parent
commit
1131c713bd
  1. 48
      hiver-admin/src/main/resources/application.yml
  2. 16
      hiver-admin/test-output/test-report.html
  3. 6
      hiver-core/pom.xml
  4. 15
      hiver-core/src/main/java/cc/hiver/core/dao/UserDao.java
  5. 14
      hiver-core/src/main/java/cc/hiver/core/entity/User.java
  6. 35
      hiver-core/src/main/java/cc/hiver/core/service/UserService.java
  7. 197
      hiver-core/src/main/java/cc/hiver/core/serviceimpl/UserServiceImpl.java
  8. 12
      hiver-core/src/main/java/cc/hiver/core/shopprint/controller/ShopPrintController.java
  9. 2
      hiver-core/src/main/java/cc/hiver/core/shopprint/service/ShopPrintService.java
  10. 96
      hiver-core/src/main/java/cc/hiver/core/shopprint/service/impl/ShopPrintServiceImpl.java
  11. 28
      hiver-core/src/main/java/cc/hiver/core/vo/WechatVo.java
  12. 12
      hiver-modules/hiver-base/pom.xml
  13. 229
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java
  14. 40
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/utils/WeChatUtil.java
  15. 43
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/CustomerController.java
  16. 36
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/SaleController.java
  17. 16
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/CustomerMapper.java
  18. 16
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Customer.java
  19. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/SaleQueryDTO.java
  20. 1
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchasereturn/service/impl/PurchaseReturnServiceImpl.java
  21. 28
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/CustomerService.java
  22. 12
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesAndDetailsServiceImpl.java
  23. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesCalculateServiceImpl.java
  24. 40
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/CustomerServiceImpl.java
  25. 55
      hiver-modules/hiver-mall/src/main/resources/mapper/CustomerMapper.xml
  26. 14
      hiver-modules/hiver-social/pom.xml
  27. 36
      hiver-modules/hiver-social/src/main/java/cc/hiver/social/config/MessageRouterConfig.java
  28. 44
      hiver-modules/hiver-social/src/main/java/cc/hiver/social/config/WxMpConfiguration.java
  29. 31
      hiver-modules/hiver-social/src/main/java/cc/hiver/social/config/WxMpProperties.java
  30. 168
      hiver-modules/hiver-social/src/main/java/cc/hiver/social/controller/WechatController.java
  31. 67
      hiver-modules/hiver-social/src/main/java/cc/hiver/social/handler/WxServerMsgHandler.java
  32. 29
      hiver-modules/hiver-social/src/main/java/cc/hiver/social/interceptor/WxServerMsgInterceptor.java
  33. 47
      hiver-modules/hiver-social/src/main/java/cc/hiver/social/vo/WeChatServerMsgVo.java

48
hiver-admin/src/main/resources/application.yml

@ -65,7 +65,7 @@ spring:
# 自动生成表结构 关闭设为none
hibernate:
ddl-auto: update
# Redis 若设有密码自行添加配置password
# Redis 若设有密码自行添加配置password
redis:
host: 154.8.162.157
# host: 8.140.198.243
@ -221,9 +221,9 @@ hiver:
callbackUrl: http://127.0.0.1:8888/hiver/social/weibo/callback
# wechat
wechat:
appId: 你的appId
appSecret: 你的appSecret
callbackUrl: http://127.0.0.1:8888/hiver/social/wechat/callback
appId: wx6d7d4fb58d1502db
appSecret: 3a2c8cd00926764bbd12fd7361e01f1d
callbackUrl: https://storage.xenjoyou.com/hiver/social/wechat/callback
# 钉钉
dingding:
# 扫码登录应用
@ -241,8 +241,38 @@ app:
social:
# 微信小程序
wxMini:
appId: 你的appId
appSecret: 你的appSecret
appId: wx6d7d4fb58d1502db
appSecret: 3a2c8cd00926764bbd12fd7361e01f1d
auth:
token: kuaiyidian
appId: wx6d7d4fb58d1502db
appSecret: 3a2c8cd00926764bbd12fd7361e01f1d
wx:
# 消息模板ID
templateId: o9YG7vWS8It-mddU2Wnknf1jgzTqZtLeBQRLhF54SXQ
mp:
# 微信公众号的appid
appId: wx415a86fa6c2eff11
# 信公众号的app secret
secret: b4bf01832f7a640353367d8979409900
# 微信公众号的toke
token: kuaiyidian
# 微信公众号的EncodingAESKey
aesKey: D6VSlBgYeKRRweR2rNuNQpcrBKdVDzRMnAvMflIJ931
config-storage:
# 配置类型: Memory(默认), Jedis, Redisson, RedisTemplate
type: RedisTemplate
# redis前缀配置: wx(默认)
key-prefix: wx
redis:
host: 154.8.162.157
# host: 8.140.198.243
password: reddoor168
# 数据库索引 默认0
database: 1
port: 6379
# 超时时间 Duration类型 3秒
timeout: 3S
# 需要验证码校验的接口路径 支持通配符 自动过滤拦截校验 无需开发人员再次校验
captcha:
# 图片验证码验证
@ -348,6 +378,10 @@ ignored:
- /hiver/app/customer/getCustomerData
- /hiver/app/supplier/getSupplierData
- /hiver/app/urlMapping/redirect
# 关注微信公众号回调
- /hiver/user/officialAccount
- /hiver/social/wechat/echo
# 临时增加
- /hiver/app/logisticsOrder/addLogisticsOrder
@ -355,6 +389,8 @@ ignored:
- /hiver/app/logisticsEntruckingLog/batchAddLogisticsEntruckingLog
- /hiver/purchaseOcrPicture/getLogisticsOrderOfAi
- /hiver/app/product/**
- /hiver/user/login
- /hiver/app/shopprint/printImg
# 限流及黑名单不拦截的路径
limitUrls:
- /**/*.js

16
hiver-admin/test-output/test-report.html

@ -35,7 +35,7 @@
<a href="#"><span class="badge badge-primary">Hiver</span></a>
</li>
<li class="m-r-10">
<a href="#"><span class="badge badge-primary">十一月 27, 2024 22:06:17</span></a>
<a href="#"><span class="badge badge-primary">一月 07, 2025 16:21:35</span></a>
</li>
</ul>
</div>
@ -84,7 +84,7 @@
<div class="test-detail">
<span class="meta text-white badge badge-sm"></span>
<p class="name">passTest</p>
<p class="text-sm"><span>22:06:18 下午</span> / <span>0.023 secs</span></p>
<p class="text-sm"><span>16:21:35 下午</span> / <span>0.016 secs</span></p>
</div>
<div class="test-contents d-none">
<div class="detail-head">
@ -92,9 +92,9 @@
<div class="info">
<div class='float-right'><span class='badge badge-default'>#test-id=1</span></div>
<h5 class="test-status text-pass">passTest</h5>
<span class='badge badge-success'>11.27.2024 22:06:18</span>
<span class='badge badge-danger'>11.27.2024 22:06:18</span>
<span class='badge badge-default'>0.023 secs</span>
<span class='badge badge-success'>01.07.2025 16:21:35</span>
<span class='badge badge-danger'>01.07.2025 16:21:35</span>
<span class='badge badge-default'>0.016 secs</span>
</div>
<div class="m-t-10 m-l-5"></div>
</div>
@ -104,7 +104,7 @@
<tbody>
<tr class="event-row">
<td><span class="badge log pass-bg">Pass</span></td>
<td>22:06:18</td>
<td>16:21:35</td>
<td>
Test passed
</td>
@ -128,13 +128,13 @@
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Started</p>
<h3>十一月 27, 2024 22:06:17</h3>
<h3>一月 07, 2025 16:21:35</h3>
</div></div>
</div>
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Ended</p>
<h3>十一月 27, 2024 22:06:18</h3>
<h3>一月 07, 2025 16:21:35</h3>
</div></div>
</div>
<div class="col-md-3">

6
hiver-core/pom.xml

@ -170,5 +170,11 @@
<artifactId>pinyin4j</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.6.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

15
hiver-core/src/main/java/cc/hiver/core/dao/UserDao.java

@ -85,7 +85,20 @@ public interface UserDao extends HiverBaseDao<User, String> {
@Query("select u from User u where u.email = ?1 and u.type like %?2% ")
User findByEmailAndType(String email,String type);
@Query(value = "select s.type,t.id,t.create_by,t.create_time,t.del_flag,t.update_by,t.update_time,t.address,t.avatar,t.description,t.email,t.mobile,t.nickname,t.password,t.sex,t.status,t.username,t.department_id,t.street,t.pass_strength,t.department_title,t.birth,t.invite_code,t.client_id from t_shop_user s left join t_user t on s.user_id = t.id where s.shop_id = ?",nativeQuery = true)
@Query(value = "select s.type,t.id,t.create_by,t.create_time,t.del_flag,t.update_by,t.update_time,t.address,t.avatar,t.description,t.email,t.mobile,t.nickname,t.password,t.sex,t.status,t.username,t.department_id,t.street,t.pass_strength,t.department_title,t.birth,t.invite_code,t.client_id,t.mini_program_openid,t.unionid,t.official_account_openid,t.wechat_name from t_shop_user s left join t_user t on s.user_id = t.id where s.shop_id = ?",nativeQuery = true)
List<User> findByShopId( String shopId);
@Query("select u from User u where u.unionid = ?1 ")
User findByUnionid(String unionid);
@Query("select u from User u where u.miniProgramOpenid = ?1 ")
User findByMiniProgramOpenid(String miniProgramOpenid);
@Modifying
@Query("update User u set u.mobile='' where u.mobile=?1")
void setUserPhoneToNull(String userPhone);
@Modifying
@Query("update User u set u.mobile=?1 where u.id=?2")
void updateUserPhoneById(String userPhone, String userId);
}

14
hiver-core/src/main/java/cc/hiver/core/entity/User.java

@ -20,7 +20,6 @@ import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.Date;
@ -122,4 +121,17 @@ public class User extends HiverBaseEntity {
@Transient
@ApiModelProperty(value = "是否有维护成本权限 1:是;0否")
private Integer shopAdminCost;
@ApiModelProperty(value = "小程序id")
private String miniProgramOpenid;
@ApiModelProperty(value = "微信平台统一id")
private String unionid;
@ApiModelProperty(value = "公众号id")
private String officialAccountOpenid;
@ApiModelProperty(value = "微信昵称")
private String wechatName;
}

35
hiver-core/src/main/java/cc/hiver/core/service/UserService.java

@ -3,11 +3,11 @@ package cc.hiver.core.service;
import cc.hiver.core.base.HiverBaseService;
import cc.hiver.core.common.vo.SearchVo;
import cc.hiver.core.entity.User;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
@ -43,6 +43,15 @@ public interface UserService extends HiverBaseService<User, String> {
*/
User findByEmail(String email);
/**
* 获取用户角色权限
* @author 王富康
* @date 2024/12/3
* @param user
* @return User
*/
User userToDTO(User user);
/**
* 多条件分页获取用户
*
@ -107,4 +116,26 @@ public interface UserService extends HiverBaseService<User, String> {
User findByUserNameAndType(String userName,String type);
User findByMobileAndType(String mobile,String type);
List<User> findByShopId(String shopId);
/**
* 公众号关注
* @author 王富康
* @date 2024/12/29
*/
void subscribeWxServer(WxMpUser user);
/**
* 取消公众号关注
* @author 王富康
* @date 2024/12/29
*/
void unSubscribeWxServer(WxMpXmlMessage wxMessage);
User findByUnionid(String unionid);
User findByMiniProgramOpenid(String miniProgramOpenid);
void setUserPhoneToNull(String userPhone);
void updateUserPhoneById(String userPhone, String userId);
}

197
hiver-core/src/main/java/cc/hiver/core/serviceimpl/UserServiceImpl.java

@ -1,7 +1,10 @@
package cc.hiver.core.serviceimpl;
import cc.hiver.core.common.constant.CommonConstant;
import cc.hiver.core.common.constant.UserConstant;
import cc.hiver.core.common.utils.PageUtil;
import cc.hiver.core.common.utils.SecurityUtil;
import cc.hiver.core.common.vo.PageVo;
import cc.hiver.core.common.vo.SearchVo;
import cc.hiver.core.dao.UserDao;
import cc.hiver.core.dao.mapper.PermissionMapper;
@ -9,12 +12,17 @@ import cc.hiver.core.dao.mapper.UserRoleMapper;
import cc.hiver.core.entity.Permission;
import cc.hiver.core.entity.Role;
import cc.hiver.core.entity.User;
import cc.hiver.core.entity.UserRole;
import cc.hiver.core.service.RoleService;
import cc.hiver.core.service.UserRoleService;
import cc.hiver.core.service.UserService;
import cc.hiver.core.vo.PermissionDTO;
import cc.hiver.core.vo.RoleDTO;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.text.CharSequenceUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@ -24,9 +32,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -50,6 +56,12 @@ public class UserServiceImpl implements UserService {
@Autowired
private SecurityUtil securityUtil;
@Autowired
private UserRoleService userRoleService;
@Autowired
private RoleService roleService;
@Override
public UserDao getRepository() {
return userDao;
@ -57,35 +69,36 @@ public class UserServiceImpl implements UserService {
@Override
public User findByUsername(String username) {
User user = userDao.findByUsername(username);
final User user = userDao.findByUsername(username);
return userToDTO(user);
}
@Override
public User findByMobile(String mobile) {
User user = userDao.findByMobile(mobile);
final User user = userDao.findByMobile(mobile);
return userToDTO(user);
}
@Override
public User findByEmail(String email) {
User user = userDao.findByEmail(email);
final User user = userDao.findByEmail(email);
return userToDTO(user);
}
@Override
public User userToDTO(User user) {
if (user == null) {
return null;
}
// 关联角色
List<Role> roleList = userRoleMapper.findByUserId(user.getId());
List<RoleDTO> roleDTOList = roleList.stream().map(e -> {
final List<Role> roleList = userRoleMapper.findByUserId(user.getId());
final List<RoleDTO> roleDTOList = roleList.stream().map(e -> {
return new RoleDTO().setId(e.getId()).setName(e.getName());
}).collect(Collectors.toList());
user.setRoles(roleDTOList);
// 关联权限菜单
List<Permission> permissionList = permissionMapper.findByUserId(user.getId());
List<PermissionDTO> permissionDTOList = permissionList.stream()
final List<Permission> permissionList = permissionMapper.findByUserId(user.getId());
final List<PermissionDTO> permissionDTOList = permissionList.stream()
.filter(e -> CommonConstant.PERMISSION_OPERATION.equals(e.getType()))
.map(e -> {
return new PermissionDTO().setTitle(e.getTitle()).setPath(e.getPath());
@ -100,43 +113,43 @@ public class UserServiceImpl implements UserService {
@Nullable
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Path<String> idField = root.get("id");
Path<String> usernameField = root.get("username");
Path<String> nicknameField = root.get("nickname");
Path<String> mobileField = root.get("mobile");
Path<String> emailField = root.get("email");
Path<String> departmentIdField = root.get("departmentId");
Path<String> sexField = root.get("sex");
Path<Integer> statusField = root.get("status");
Path<Date> createTimeField = root.get("createTime");
List<Predicate> list = new ArrayList<>();
if (StrUtil.isNotBlank(user.getId())) {
final Path<String> idField = root.get("id");
final Path<String> usernameField = root.get("username");
final Path<String> nicknameField = root.get("nickname");
final Path<String> mobileField = root.get("mobile");
final Path<String> emailField = root.get("email");
final Path<String> departmentIdField = root.get("departmentId");
final Path<String> sexField = root.get("sex");
final Path<Integer> statusField = root.get("status");
final Path<Date> createTimeField = root.get("createTime");
final List<Predicate> list = new ArrayList<>();
if (CharSequenceUtil.isNotBlank(user.getId())) {
list.add(cb.equal(idField, user.getId()));
}
// 模糊搜素
if (StrUtil.isNotBlank(user.getUsername())) {
if (CharSequenceUtil.isNotBlank(user.getUsername())) {
list.add(cb.like(usernameField, '%' + user.getUsername() + '%'));
}
if (StrUtil.isNotBlank(user.getNickname())) {
if (CharSequenceUtil.isNotBlank(user.getNickname())) {
list.add(cb.like(nicknameField, '%' + user.getNickname() + '%'));
}
if (StrUtil.isNotBlank(user.getMobile())) {
if (CharSequenceUtil.isNotBlank(user.getMobile())) {
list.add(cb.like(mobileField, '%' + user.getMobile() + '%'));
}
if (StrUtil.isNotBlank(user.getEmail())) {
if (CharSequenceUtil.isNotBlank(user.getEmail())) {
list.add(cb.like(emailField, '%' + user.getEmail() + '%'));
}
// 部门
if (StrUtil.isNotBlank(user.getDepartmentId())) {
if (CharSequenceUtil.isNotBlank(user.getDepartmentId())) {
list.add(cb.equal(departmentIdField, user.getDepartmentId()));
}
// 性别
if (StrUtil.isNotBlank(user.getSex())) {
if (CharSequenceUtil.isNotBlank(user.getSex())) {
list.add(cb.equal(sexField, user.getSex()));
}
// 状态
@ -144,19 +157,19 @@ public class UserServiceImpl implements UserService {
list.add(cb.equal(statusField, user.getStatus()));
}
// 创建时间
if (StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) {
Date start = DateUtil.parse(searchVo.getStartDate());
Date end = DateUtil.parse(searchVo.getEndDate());
if (CharSequenceUtil.isNotBlank(searchVo.getStartDate()) && CharSequenceUtil.isNotBlank(searchVo.getEndDate())) {
final Date start = DateUtil.parse(searchVo.getStartDate());
final Date end = DateUtil.parse(searchVo.getEndDate());
list.add(cb.between(createTimeField, start, DateUtil.endOfDay(end)));
}
// 数据权限
List<String> depIds = securityUtil.getDeparmentIds();
final List<String> depIds = securityUtil.getDeparmentIds();
if (depIds != null && depIds.size() > 0) {
list.add(departmentIdField.in(depIds));
}
Predicate[] arr = new Predicate[list.size()];
final Predicate[] arr = new Predicate[list.size()];
cq.where(list.toArray(arr));
return null;
}
@ -169,33 +182,33 @@ public class UserServiceImpl implements UserService {
@Nullable
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Path<String> usernameField = root.get("username");
Path<String> nicknameField = root.get("nickname");
Path<String> mobileField = root.get("mobile");
Path<String> sexField = root.get("sex");
Path<Integer> statusField = root.get("status");
Path<Date> createTimeField = root.get("createTime");
Path<String> inviteCodeField = root.get("inviteCode");
final Path<String> usernameField = root.get("username");
final Path<String> nicknameField = root.get("nickname");
final Path<String> mobileField = root.get("mobile");
final Path<String> sexField = root.get("sex");
final Path<Integer> statusField = root.get("status");
final Path<Date> createTimeField = root.get("createTime");
final Path<String> inviteCodeField = root.get("inviteCode");
List<Predicate> list = new ArrayList<>();
final List<Predicate> list = new ArrayList<>();
// 模糊搜素
if (StrUtil.isNotBlank(user.getUsername())) {
if (CharSequenceUtil.isNotBlank(user.getUsername())) {
list.add(cb.like(usernameField, '%' + user.getUsername() + '%'));
}
if (StrUtil.isNotBlank(user.getNickname())) {
if (CharSequenceUtil.isNotBlank(user.getNickname())) {
list.add(cb.like(nicknameField, '%' + user.getNickname() + '%'));
}
if (StrUtil.isNotBlank(user.getMobile())) {
if (CharSequenceUtil.isNotBlank(user.getMobile())) {
list.add(cb.like(mobileField, '%' + user.getMobile() + '%'));
}
// 性别
if (StrUtil.isNotBlank(user.getSex())) {
if (CharSequenceUtil.isNotBlank(user.getSex())) {
list.add(cb.equal(sexField, user.getSex()));
}
// 邀请人
if (StrUtil.isNotBlank(user.getInviteCode())) {
if (CharSequenceUtil.isNotBlank(user.getInviteCode())) {
list.add(cb.equal(inviteCodeField, user.getInviteCode()));
}
// 状态
@ -203,13 +216,13 @@ public class UserServiceImpl implements UserService {
list.add(cb.equal(statusField, user.getStatus()));
}
// 创建时间
if (StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) {
Date start = DateUtil.parse(searchVo.getStartDate());
Date end = DateUtil.parse(searchVo.getEndDate());
if (CharSequenceUtil.isNotBlank(searchVo.getStartDate()) && CharSequenceUtil.isNotBlank(searchVo.getEndDate())) {
final Date start = DateUtil.parse(searchVo.getStartDate());
final Date end = DateUtil.parse(searchVo.getEndDate());
list.add(cb.between(createTimeField, start, DateUtil.endOfDay(end)));
}
Predicate[] arr = new Predicate[list.size()];
final Predicate[] arr = new Predicate[list.size()];
cq.where(list.toArray(arr));
return null;
}
@ -241,16 +254,86 @@ public class UserServiceImpl implements UserService {
return userDao.findByRoleName(roleName);
}
public User findByUserNameAndType(String userName,String type){
User user = userDao.findByUserNameAndType(userName,type);
@Override
public User findByUserNameAndType(String userName, String type) {
final User user = userDao.findByUserNameAndType(userName, type);
return userToDTO(user);
}
public User findByMobileAndType(String mobile,String type){
User user = userDao.findByMobileAndType(mobile,type);
@Override
public User findByMobileAndType(String mobile, String type) {
final User user = userDao.findByMobileAndType(mobile, type);
return userToDTO(user);
}
public List<User> findByShopId(String shopId){
@Override
public List<User> findByShopId(String shopId) {
return userDao.findByShopId(shopId);
}
@Override
public void subscribeWxServer(WxMpUser user) {
// 判断是否绑定用户
final String unionid = user.getUnionId();
final String openid = user.getOpenId();
User wechatUser = findByUnionid(unionid);
final Map<String, Object> resultMap = new HashMap<>();
if (wechatUser != null) {
wechatUser.setOfficialAccountOpenid(openid);
} else {
try {
// 新增用户信息
wechatUser = new User();
wechatUser.setUnionid(unionid);
wechatUser.setOfficialAccountOpenid(openid);
wechatUser.setStatus(UserConstant.USER_STATUS_NORMAL);
wechatUser = save(wechatUser);
// 设置用户角色
final UserRole userRole = new UserRole();
final PageVo pageVo = new PageVo();
pageVo.setPageNumber(1);
pageVo.setPageSize(1);
final Page<Role> roleCustomer = roleService.findByCondition("ROLE_CUSTOMER", PageUtil.initPage(pageVo));
final Role role = roleCustomer.getContent().get(0);
//客户角色
userRole.setRoleId(role.getId());
userRole.setRoleName("客户");
userRole.setUserId(wechatUser.getId());
userRoleService.save(userRole);
// 更新客户信息,绑定登录用户
// customerService.updateUserId(wechatVo.getCustomId(),wechatUser.getId());
// 返回当前登录人的信息
resultMap.put("msg", "新增用户信息,并绑定成功!");
// resultMap.put("customId", wechatVo.getCustomId());
} catch (Exception e) {
log.error("公众号关注出现错误,请查看!" + e.getMessage(), e);
}
}
save(wechatUser);
}
@Override
public void unSubscribeWxServer(WxMpXmlMessage wxMessage) {
}
@Override
public User findByUnionid(String unionid) {
return userDao.findByUnionid(unionid);
}
@Override
public User findByMiniProgramOpenid(String miniProgramOpenid) {
return userDao.findByMiniProgramOpenid(miniProgramOpenid);
}
@Override
public void setUserPhoneToNull(String userPhone) {
userDao.setUserPhoneToNull(userPhone);
}
@Override
public void updateUserPhoneById(String userPhone, String userId) {
userDao.updateUserPhoneById(userPhone, userId);
}
}

12
hiver-core/src/main/java/cc/hiver/core/shopprint/controller/ShopPrintController.java

@ -2,13 +2,9 @@ package cc.hiver.core.shopprint.controller;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.core.logisticsroute.entity.LogisticsRoute;
import cc.hiver.core.logisticsroute.service.LogisticsRouteService;
import cc.hiver.core.logisticsroute.vo.LogisticsRouteQueryVo;
import cc.hiver.core.shopprint.entity.ShopPrint;
import cc.hiver.core.shopprint.service.ShopPrintService;
import cc.hiver.core.shopprint.vo.ShopPrintQueryVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@ -88,4 +84,12 @@ public class ShopPrintController {
final List<ShopPrint> result = shopPrintService.getShopPrintList(shopPrintQueryVo);
return new ResultUtil<List<ShopPrint>>().setData(result);
}
// 打印图片
@RequestMapping(value = "/printImg", method = RequestMethod.POST)
@ApiOperation(value = "打印图片")
public Result<String> printImg(String imgPath) {
final String result = shopPrintService.printImg(imgPath);
return new ResultUtil<String>().setData(result);
}
}

2
hiver-core/src/main/java/cc/hiver/core/shopprint/service/ShopPrintService.java

@ -10,4 +10,6 @@ public interface ShopPrintService extends IService<ShopPrint> {
List<ShopPrint> getShopPrintList(ShopPrintQueryVo shopPrintQueryVo);
String printImg(String imgPath);
}

96
hiver-core/src/main/java/cc/hiver/core/shopprint/service/impl/ShopPrintServiceImpl.java

@ -1,19 +1,17 @@
package cc.hiver.core.shopprint.service.impl;
import cc.hiver.core.logisticsroute.mapper.LogisticsRouteMapper;
import cc.hiver.core.logisticsroute.service.LogisticsRouteService;
import cc.hiver.core.logisticsuser.entity.LogisticsUser;
import cc.hiver.core.logisticsuser.mapper.LogisticsUserMapper;
import cc.hiver.core.logisticsuser.service.LogisticsUserService;
import cc.hiver.core.shopprint.entity.ShopPrint;
import cc.hiver.core.shopprint.mapper.ShopPrintMapper;
import cc.hiver.core.shopprint.service.ShopPrintService;
import cc.hiver.core.shopprint.vo.ShopPrintQueryVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.List;
/**
@ -22,6 +20,7 @@ import java.util.List;
* @Date: 2024/10/22 22:01
* @Description:
*/
@Slf4j
@Service
public class ShopPrintServiceImpl extends ServiceImpl<ShopPrintMapper, ShopPrint> implements ShopPrintService {
@ -29,8 +28,91 @@ public class ShopPrintServiceImpl extends ServiceImpl<ShopPrintMapper, ShopPrint
private ShopPrintMapper shopPrintMapper;
@Override
public List<ShopPrint> getShopPrintList(ShopPrintQueryVo shopPrintQueryVo){
public List<ShopPrint> getShopPrintList(ShopPrintQueryVo shopPrintQueryVo) {
return shopPrintMapper.getShopPrintList(shopPrintQueryVo);
}
@Override
public String printImg(String imgPath) {
final URL url;
BufferedImage image = null;
try {
url = new URL(imgPath);
image = ImageIO.read(url);
} catch (Exception e) {
log.error("读取文件错误: " + e.getMessage());
}
if (image != null) {
return drawGraphic(0,0, image);
}
return "未读取到图片信息!";
}
public static String drawGraphic(int start_x, int start_y, BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int col = (width - 1) / 8 + 1;
String str = "";
byte[] arrayOfByte = new byte[width * height];
int h = 0;
//int b1 = 0;
int arrindex = 0;
//int m = 0;
while (h < height) {
for (int w = 0; w < width; w++) {
arrindex = h * col + w / 8;
System.out.println("w:" + w + ", h:" + h);
if ((image.getRGB(w, h) & 0xFFFFFF) < 3092271) {
int n = arrindex;
byte[] arrayOfByte1 = arrayOfByte;
arrayOfByte1[n] = (byte) (arrayOfByte1[n] | 128 >> w % 8);
} else {
int n = arrindex;
byte[] arrayOfByte1 = arrayOfByte;
arrayOfByte1[n] = (byte) (arrayOfByte1[n] & (128 >> w % 8 ^ 0xFFFFFFFF));
}
}
++h;
//if ((++h - b1) * col >= 1024 || h == height) {
// str = bbbb(aaaaaa(arrayOfByte, m, arrindex - m + 1));
// m = arrindex + 1;
// String str1 = "EG " + col + " " + (h - b1) + " " + start_x + " " + (start_y + b1) + " " + str + "\r\n";
//
// System.out.println(str1);
// //b(str1);
// b1 = h;
// k++;
//}
}
str = toHexString(copy(arrayOfByte, 0, arrindex + 1));
System.out.println(str);
return str;
}
static String toHexString(byte[] paramArrayOfbyte) {
String str = "";
for (int i = 0; i < paramArrayOfbyte.length; i++) {
String hex = Integer.toHexString(paramArrayOfbyte[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
str = str + hex;
}
return str;
}
private static byte[] copy(byte[] paramArrayOfbyte, int start, int length) {
byte[] arrayOfByte = new byte[length];
for (int i = 0; i < length; i++) {
arrayOfByte[i] = paramArrayOfbyte[start + i];
}
return arrayOfByte;
}
}

28
hiver-core/src/main/java/cc/hiver/core/vo/WechatVo.java

@ -0,0 +1,28 @@
package cc.hiver.core.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class WechatVo {
@ApiModelProperty(value = "jsCode")
private String jsCode;
@ApiModelProperty(value = "grantType")
private String grantType = "authorization_code";
@ApiModelProperty(value = "customId")
private String customId;
@ApiModelProperty(value = "wechatName")
private String wechatName;
@ApiModelProperty(value = "userType")
private String userType;
@ApiModelProperty(value = "userId")
private String userId;
}

12
hiver-modules/hiver-base/pom.xml

@ -16,6 +16,18 @@
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.6.0</version>
</dependency>
</dependencies>
<artifactId>hiver-base</artifactId>

229
hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java

@ -1,9 +1,12 @@
package cc.hiver.base.controller.manage;
import cc.hiver.base.async.AddMessage;
import cc.hiver.core.common.annotation.SystemLog;
import cc.hiver.core.common.constant.CommonConstant;
import cc.hiver.core.common.constant.MemberConstant;
import cc.hiver.core.common.constant.SecurityConstant;
import cc.hiver.core.common.constant.UserConstant;
import cc.hiver.core.common.enums.LogType;
import cc.hiver.core.common.redis.RedisTemplateHelper;
import cc.hiver.core.common.utils.*;
import cc.hiver.core.common.vo.PageVo;
@ -17,13 +20,22 @@ import cc.hiver.core.entity.UserRole;
import cc.hiver.core.service.*;
import cc.hiver.core.service.mybatis.IUserRoleService;
import cc.hiver.core.vo.RoleDTO;
import cc.hiver.core.vo.WechatVo;
import cc.hiver.mall.entity.Shop;
import cc.hiver.mall.entity.ShopUser;
import cc.hiver.mall.service.ShopService;
import cc.hiver.mall.service.ShopUserService;
import cc.hiver.mall.service.mybatis.CustomerService;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.http.HttpUtil;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
@ -36,9 +48,7 @@ import javax.persistence.PersistenceContext;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -91,6 +101,30 @@ public class UserController {
@Autowired
private CustomerService customerService;
@Value("${app.social.wxMini.appId}")
private String appId;
@Value("${app.social.wxMini.appSecret}")
private String appSecret;
private static final Integer TYPE = MemberConstant.MEMBER_PLATFORM_WECHAT;
@Autowired
private ShopUserService shopUserService;
@Autowired
private ShopService shopService;
@Autowired
private MemberSocialService memberSocialService;
/**
* 微信小程序登录凭证校验
*/
private static final String JSCODETOSESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
@RequestMapping(value = "/info", method = RequestMethod.GET)
@ApiOperation("获取当前登录用户接口")
public Result<User> getUserInfo() {
@ -141,7 +175,7 @@ public class UserController {
@ApiParam("手机号") @RequestParam String mobile,
@ApiParam("旧密码") @RequestParam String password,
@ApiParam("新密码") @RequestParam String newPass) {
if(StringUtils.isEmpty(mobile) && StringUtils.isEmpty(newPass)){
if (StringUtils.isEmpty(mobile) && StringUtils.isEmpty(newPass)) {
return ResultUtil.error("未修改任何信息!");
}
final User user = userService.findById(userId);
@ -511,4 +545,191 @@ public class UserController {
}
return ResultUtil.success(message);
}
/**
* 根据userId更新user表mini_program_openid和unionid
*
* @param user
* @return Result
* @author 王富康
* @date 2024/11/30
*/
@RequestMapping(value = "/updateMiniProgramAndUnionid", method = RequestMethod.POST)
@ApiOperation("根据userId更新user表mini_program_openid和unionid")
public Result updateMiniProgramAndUnionid(@RequestBody User user) {
final User oldUser = userService.findById(user.getId());
oldUser.setMiniProgramOpenid(user.getMiniProgramOpenid());
oldUser.setUnionid(user.getUnionid());
userService.update(oldUser);
return ResultUtil.success("更新成功");
}
/**
* 获取微信小程序认证链接
*
* @param wechatVo
* @return Result
* @author 王富康
* @date 2024/12/3
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ApiOperation("获取微信小程序认证链接")
@ResponseBody
@SystemLog(description = "微信小程序登录", type = LogType.MEMBER_LOGIN)
public Result login(@RequestBody WechatVo wechatVo) {
if (StringUtils.isEmpty(wechatVo.getJsCode())) {
return ResultUtil.error("您未同意授权");
}
final String jscode2sessionUrl = JSCODETOSESSION_URL + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + wechatVo.getJsCode() +
"&grant_type=" + wechatVo.getGrantType();
// 申请openid
final String result = HttpUtil.get(jscode2sessionUrl);
if (!result.contains("session_key")) {
return ResultUtil.error("获取session_key失败");
}
final JsonObject jsonObject = JsonParser.parseString(result).getAsJsonObject();
final String sessionKey = jsonObject.get("session_key").getAsString();
final String openId = jsonObject.get("openid").getAsString();
final String unionid = jsonObject.get("unionid").getAsString();
// 判断是否绑定用户
User wechatUser = null;
final Map<String, Object> resultMap = new HashMap<>();
if(StringUtils.isEmpty(wechatVo.getUserId())){
wechatUser = userService.findByUnionid(unionid);
}else{
wechatUser = userService.findById(wechatVo.getUserId());
}
if (wechatUser == null) {
try {
// 新增用户信息
wechatUser = new User();
wechatUser.setStatus(UserConstant.USER_STATUS_NORMAL);
wechatUser = userService.save(wechatUser);
// 设置用户角色
final UserRole userRole = new UserRole();
final PageVo pageVo = new PageVo();
pageVo.setPageNumber(1);
pageVo.setPageSize(1);
final Page<Role> roleCustomer = roleService.findByCondition("ROLE_CUSTOMER", PageUtil.initPage(pageVo));
final Role role = roleCustomer.getContent().get(0);
//客户角色
userRole.setRoleId(role.getId());
userRole.setRoleName("客户");
userRole.setUserId(wechatUser.getId());
userRoleService.save(userRole);
// 更新客户信息,绑定登录用户
customerService.updateUserId(wechatVo.getCustomId(), wechatUser.getId());
// 返回当前登录人的信息
resultMap.put("msg", "新增用户信息,并绑定成功!");
resultMap.put("customId", wechatVo.getCustomId());
} catch (Exception e) {
return ResultUtil.error(e.getMessage());
}
} else {
// 更新客户信息,绑定登录用户
customerService.updateUserId(wechatVo.getCustomId(), wechatUser.getId());
}
wechatUser.setUnionid(unionid);
wechatUser.setWechatName(wechatVo.getWechatName());
wechatUser.setMiniProgramOpenid(openId);
// 统一更新小程序的一些信息
userService.save(wechatUser);
// 锁定当前登录用户的类型
wechatUser.setType(wechatVo.getUserType());
final String accessToken = securityUtil.getToken(userService.userToDTO(wechatUser), true);
resultMap.put("accessToken", accessToken);
// 返回当前登录人的信息
resultMap.put("user", wechatUser);
// 店铺登录的话,根据登录人查询所有关联的店铺(店铺启用,并且在有效期内)
if (UserConstant.USER_TYPE_NORMAL.equals(wechatUser.getType())) {
// 获取
final List<ShopUser> shopUsers = shopUserService.selectByUserId(wechatUser.getId());
if (shopUsers != null && !shopUsers.isEmpty()) {
// 获取店主手机号
for (ShopUser shopUser : shopUsers) {
final Shop shop = shopService.findById(shopUser.getShopId());
if (shop != null && shop.getShopOwnerId() != null && StringUtils.isNotEmpty(shop.getShopOwnerId())) {
final User shopOwner = userService.findById(shop.getShopOwnerId());
if (shopOwner != null) {
shopUser.setShopOwnerName(shopOwner.getNickname());
shopUser.setShopOwnerPhone(shopOwner.getMobile());
}
}
}
resultMap.put("shopList", shopUsers);
} else {
return ResultUtil.error("店铺未开通!");
}
}
return ResultUtil.data(resultMap);
}
// 关注公众号-回调
// 根据unionid查user表有没有数据,没有就新增一条user数据,同时绑定official_account_openid(公众号id)、unionid,有就更新一下official_account_openid
@RequestMapping(value = "/officialAccount", method = RequestMethod.GET)
@ApiOperation("关注公众号-回调")
public Result officialAccount(String openid, String unionid) {
if (StringUtils.isEmpty(unionid)) {
return ResultUtil.error("unionid不能为空!");
}
// 判断是否绑定用户
User wechatUser = userService.findByUnionid(unionid);
final Map<String, Object> resultMap = new HashMap<>();
if (wechatUser != null) {
wechatUser.setOfficialAccountOpenid(openid);
} else {
try {
// 新增用户信息
wechatUser = new User();
wechatUser.setUnionid(unionid);
wechatUser.setOfficialAccountOpenid(openid);
wechatUser.setStatus(UserConstant.USER_STATUS_NORMAL);
wechatUser = userService.save(wechatUser);
// 设置用户角色
final UserRole userRole = new UserRole();
final PageVo pageVo = new PageVo();
pageVo.setPageNumber(1);
pageVo.setPageSize(1);
final Page<Role> roleCustomer = roleService.findByCondition("ROLE_CUSTOMER", PageUtil.initPage(pageVo));
final Role role = roleCustomer.getContent().get(0);
//客户角色
userRole.setRoleId(role.getId());
userRole.setRoleName("客户");
userRole.setUserId(wechatUser.getId());
userRoleService.save(userRole);
// 更新客户信息,绑定登录用户
// customerService.updateUserId(wechatVo.getCustomId(),wechatUser.getId());
// 返回当前登录人的信息
resultMap.put("msg", "新增用户信息,并绑定成功!");
// resultMap.put("customId", wechatVo.getCustomId());
} catch (Exception e) {
return ResultUtil.error(e.getMessage());
}
}
userService.save(wechatUser);
return ResultUtil.data(resultMap);
}
/**
* mini_program_openid查询user表的所有信息
*
* @param miniProgramOpenid
* @return Result
* @author 王富康
* @date 2024/12/18
*/
@RequestMapping(value = "/getUserInfo", method = RequestMethod.POST)
@ApiOperation("mini_program_openid查询user表的所有信息")
public Result getUserInfo(String miniProgramOpenid) {
if (StringUtils.isEmpty(miniProgramOpenid)) {
return ResultUtil.error("miniProgramOpenid!");
}
return ResultUtil.data(userService.findByMiniProgramOpenid(miniProgramOpenid));
}
}

40
hiver-modules/hiver-base/src/main/java/cc/hiver/base/utils/WeChatUtil.java

@ -0,0 +1,40 @@
package cc.hiver.base.utils;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jetbrains.annotations.Nullable;
public class WeChatUtil {
private static final String APP_ID = "wx6d7d4fb58d1502db";
private static final String APP_SECRET = "3a2c8cd00926764bbd12fd7361e01f1d";
private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}";
/**
* 获取Access Token
* @author 王富康
* @date 2024/12/19
* @return String
*/
@Nullable
public static String getAccessToken() throws Exception {
final String url = TOKEN_URL.replace("{}", APP_ID).replace("{}", APP_SECRET);
final HttpGet request = new HttpGet(url);
final CloseableHttpClient httpClient = HttpClients.createDefault();
final String result = httpClient.execute(request, httpResponse ->
EntityUtils.toString(httpResponse.getEntity()));
// 解析JSON获取access_token,这里假设已经通过某种方式(如Jackson, Gson)解析
// 这里简单用String.split()模拟解析
final String[] parts = result.split(",");
for (String part : parts) {
if (part.contains("access_token")) {
final String[] tokenParts = part.split(":");
return tokenParts[1].trim().replace("\"", "");
}
}
return null;
}
}

43
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/CustomerController.java

@ -226,8 +226,8 @@ public class CustomerController {
@ApiOperation("根据用户id查询客户列表")
public Result findByUserId(String userId,String shopId) {
// shopId从缓存中设置
final List<String> list = customerService.findByUserId(userId,shopId);
return new ResultUtil<List<String>>().setData(list);
final List<Customer> list = customerService.findByUserId(userId,shopId);
return new ResultUtil<List<Customer>>().setData(list);
}
@RequestMapping(value = "/findByUserName", method = RequestMethod.POST)
@ -252,11 +252,8 @@ public class CustomerController {
@RequestMapping(value = "/findByUserPhoneAndShopId", method = RequestMethod.POST)
@ApiOperation("根据客户手机号及店铺id精准查询查询客户列表")
public Result findByUserPhoneAndShopId(String userPhone, String shopId) {
if(StringUtils.isEmpty(userPhone)){
return ResultUtil.error("用户手机号不能为空");
}
if(StringUtils.isEmpty(userPhone)){
return ResultUtil.error("店铺id不能为空");
if(StringUtils.isEmpty(userPhone) && StringUtils.isEmpty(userPhone)){
return ResultUtil.error("用户手机号和店铺id不能都为空!");
}
// shopId从缓存中设置
final List<Customer> list = customerService.findByUserPhoneAndShopId(userPhone, shopId);
@ -307,4 +304,36 @@ public class CustomerController {
final CustomerDataVo customerData = customerService.getCustomerData(customerPageQuery);
return new ResultUtil<CustomerDataVo>().setData(customerData);
}
/**
* 根据customer表id更新userId字段
* @author 王富康
* @date 2024/11/30
* @param customerId
* @param userId
* @return Result
*/
@RequestMapping(value = "/updateUserId", method = RequestMethod.POST)
@ApiOperation("根据customer表id更新userId字段")
public Result updateUserId(String customerId, String userId) {
if(StringUtils.isEmpty(customerId)){
return ResultUtil.error("客户id不能为空");
}
customerService.updateUserId(customerId, userId);
return ResultUtil.success("更新成功!");
}
// 根据userPhone更新userid
@RequestMapping(value = "/updateUserIdByUserPhone", method = RequestMethod.POST)
@ApiOperation("根据userPhone更新userid")
public Result updateUserIdByUserPhone(String userPhone, String userId) {
if(StringUtils.isEmpty(userPhone)){
return ResultUtil.error("手机号不能为空");
}
if(StringUtils.isEmpty(userId)){
return ResultUtil.error("用户id不能为空");
}
customerService.updateUserIdByUserPhone(userPhone, userId);
return ResultUtil.success("更新成功!");
}
}

36
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/SaleController.java

@ -14,6 +14,7 @@ import cc.hiver.core.entity.LogiticsCompany;
import cc.hiver.core.entity.User;
import cc.hiver.core.entity.Worker;
import cc.hiver.core.service.LogiticsCompanyService;
import cc.hiver.core.service.UserService;
import cc.hiver.core.service.WorkerService;
import cc.hiver.core.vo.WorkerQueryVO;
import cc.hiver.mall.common.constant.OrderConstant;
@ -107,6 +108,9 @@ public class SaleController {
@Autowired
private DebtService debtService;
@Autowired
private UserService userService;
@RequestMapping(value = "/buy", method = RequestMethod.POST)
@ApiOperation("下单操作")
@ -238,7 +242,7 @@ public class SaleController {
sale.setCreateBy(currUser.getId());
sale.setCreateByName(currUser.getNickname());
sale.setCreateByPhone(currUser.getMobile());
if(sale.getCreateTime() == null) {
if (sale.getCreateTime() == null) {
sale.setCreateTime(new Date());
}
sale.setDelFlag(CommonConstant.DEL_FLAG_FALSE);
@ -255,9 +259,9 @@ public class SaleController {
// 回填销售单id
saleReturnDTO.getReturnSale().setSaleId(sale.getId());
// 时间
if(sale.getCreateTime() == null) {
if (sale.getCreateTime() == null) {
saleReturnDTO.getReturnSale().setCreateTime(new Date());
}else{
} else {
saleReturnDTO.getReturnSale().setCreateTime(sale.getCreateTime());
}
// 申请退货
@ -397,8 +401,12 @@ public class SaleController {
final QueryWrapper<Sale> queryWrapper = new QueryWrapper<>();
final User user = securityUtil.getCurrUser();
// 查询下游客户的id
final List<String> customerIdList = customerService.findByUserId(user.getId(),"");
queryWrapper.in("user_id", customerIdList);
final List<Customer> customerIdList = customerService.findByUserId(user.getId(), "");
List<String> customerId = new ArrayList<>();
for (Customer customer : customerIdList) {
customerId.add(customer.getId());
}
queryWrapper.in("user_id", customerId);
if (!ObjectUtils.isEmpty(saleVO)) {
if (!StringUtils.isEmpty(saleVO.getPayStatus())) {
queryWrapper.eq("pay_status", saleVO.getPayStatus());
@ -586,6 +594,16 @@ public class SaleController {
//增加客户信息明细
final String addCustomerId = sale.getUserId();
final Customer customer = customerService.getById(addCustomerId);
if (customer != null && StringUtils.isNotEmpty(customer.getUserId())) {
final User user = userService.get(customer.getUserId());
if (user != null) {
customer.setMiniProgramOpenid(user.getMiniProgramOpenid());
customer.setUnionid(user.getUnionid());
customer.setOfficialAccountOpenid(user.getOfficialAccountOpenid());
customer.setWechatName(user.getWechatName());
}
}
saleNewVO.setCustomer(customer);
// 增加物流公司信息
final String transCompanyId = sale.getTransCompany();
@ -688,10 +706,10 @@ public class SaleController {
startTime = saleVO.getStartTime() == null ? dateText : saleVO.getStartTime();
if (StringUtils.isEmpty(saleVO.getEndTime())) {
// 为空,使用当前日期+1
endTime = DateUtil.getAfterDayTime(dateText, 1);
endTime = DateUtil.addDay(dateText,1);
} else {
// 不为空,使用传参日期+1
endTime = DateUtil.getAfterDayTime(saleVO.getEndTime(), 1);
endTime = DateUtil.addDay(saleVO.getEndTime(), 1);
}
saleAllVO = salesCalculateService.calculateService(startTime, endTime);
// 获取本周营收统计
@ -1179,11 +1197,11 @@ public class SaleController {
@RequestMapping(value = "/buyAi", method = RequestMethod.POST)
@ApiOperation("同步步Ai开单")
public Result buyAi(String aiMsg, String customerId,String productId) {
public Result buyAi(String aiMsg, String customerId, String productId) {
if (StringUtils.isEmpty(aiMsg)) {
ResultUtil.error("指令不能为空!");
}
JSONObject jsonObject = saleService.buyAi(aiMsg, customerId, productId);
final JSONObject jsonObject = saleService.buyAi(aiMsg, customerId, productId);
return new ResultUtil<JSONObject>().setData(jsonObject);
}

16
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/CustomerMapper.java

@ -39,15 +39,21 @@ public interface CustomerMapper extends BaseMapper<Customer> {
void delById(String id);
List<String> findByUserId(@Param("userId") String userId,@Param("shopId") String shopId);
List<Customer> findByUserId(@Param("userId") String userId, @Param("shopId") String shopId);
Page<Customer> getCustomerList(Page<Customer> page,@Param("queryParams") CustomerPageQuery customerPageQuery);
Page<Customer> getCustomerList(Page<Customer> page, @Param("queryParams") CustomerPageQuery customerPageQuery);
void updatePhone(@Param("newMobile")String newMobile,@Param("userId") String userId);
void updatePhone(@Param("newMobile") String newMobile, @Param("userId") String userId);
boolean batchDeleteCustomer(@Param("idList") List<String> idList);
List<Customer> findByUserName(@Param("userName") String userName,@Param("shopId") String shopId);
List<Customer> findByUserName(@Param("userName") String userName, @Param("shopId") String shopId);
List<Customer> findByUserPhoneAndShopId(@Param("userPhone") String userPhone,@Param("shopId") String shopId);
List<Customer> findByUserPhoneAndShopId(@Param("userPhone") String userPhone, @Param("shopId") String shopId);
void updateUserId(@Param("customerId") String customerId, @Param("userId") String userId);
List<String> getOfficialAccountOpenids(@Param("shopId") String shopId, @Param("userId") String userId, @Param("categoryId") String categoryId, @Param("isAll") String isAll);
void updateUserIdByUserPhone(@Param("userPhone")String userPhone,@Param("userId") String userId);
}

16
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/Customer.java

@ -88,4 +88,20 @@ public class Customer implements Serializable {
@ApiModelProperty(value = "排序字段")
private String orderByField;
@TableField(exist = false)
@ApiModelProperty(value = "小程序id")
private String miniProgramOpenid;
@TableField(exist = false)
@ApiModelProperty(value = "")
private String unionid;
@TableField(exist = false)
@ApiModelProperty(value = "公众号id")
private String officialAccountOpenid;
@TableField(exist = false)
@ApiModelProperty(value = "微信昵称")
private String wechatName;
}

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/SaleQueryDTO.java

@ -33,6 +33,9 @@ public class SaleQueryDTO implements Serializable {
@ApiModelProperty(value = "客户id")
private String userId;
@ApiModelProperty(value = "客户电话")
private String userPhone;
@ApiModelProperty(value = "客户名称")
private String username;

1
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchasereturn/service/impl/PurchaseReturnServiceImpl.java

@ -149,6 +149,7 @@ public class PurchaseReturnServiceImpl extends ServiceImpl<PurchaseReturnMapper,
purchaseReturnDetail.setPrice(product.getPrice());
purchaseReturnDetail.setWholesalePrice(product.getWholesalePrice());
purchaseReturnDetail.setPurchasePrice(product.getPurchasePrice());
purchaseReturnDetail.setAttrId(product.getAttrId());
}
}
purchaseReturnDataVo.setPurchaseReturnDetails(purchaseReturnDetails);

28
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/CustomerService.java

@ -15,7 +15,7 @@ public interface CustomerService extends IService<Customer> {
boolean deleteById(String id);
List<String> findByUserId(String userId,String shopId);
List<Customer> findByUserId(String userId, String shopId);
Customer addCustomer(Customer customer);
@ -29,11 +29,12 @@ public interface CustomerService extends IService<Customer> {
/**
* 根据客户手机号及店铺id精准查询查询客户列表
* @author 王富康
* @date 2024/9/6
*
* @param userPhone
* @param shopId
* @return List<Customer>
* @author 王富康
* @date 2024/9/6
*/
List<Customer> findByUserPhoneAndShopId(String userPhone, String shopId);
@ -41,10 +42,27 @@ public interface CustomerService extends IService<Customer> {
/**
* 查询客户 拿货总金额商品总款数总件数退货总金额商品总款数总件数
* @author 王富康
* @date 2024/10/24
*
* @param customerPageQuery
* @return SupplierDataVo
* @author 王富康
* @date 2024/10/24
*/
CustomerDataVo getCustomerData(CustomerPageQuery customerPageQuery);
/**
* 跟新客户登录用户id
*
* @param customerId
* @param userId
* @return Customer
* @author 王富康
* @date 2024/11/30
*/
void updateUserId(String customerId, String userId);
// 获取符合条件的客户公众号id
List<String> getOfficialAccountOpenids(String userId, String categoryId, String isAll);
void updateUserIdByUserPhone(String userPhone, String userId);
}

12
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesAndDetailsServiceImpl.java

@ -455,8 +455,9 @@ public class SalesAndDetailsServiceImpl implements SalesAndDetailsService {
String customerId = "";
if (StringUtils.isNotEmpty(saleQueryDTO.getMobile())) {
// 20240906如果前台传了客户id了,不要新增客户了就
byMobile = userService.findByMobile(saleQueryDTO.getMobile());
if(StringUtils.isEmpty(saleQueryDTO.getUserId())){
byMobile = userService.findByMobile(saleQueryDTO.getMobile());
// byMobile = userService.findByMobile(saleQueryDTO.getMobile());
if (byMobile == null) {
//默认密码
final String encryptPass = new BCryptPasswordEncoder().encode("123456");
@ -543,7 +544,14 @@ public class SalesAndDetailsServiceImpl implements SalesAndDetailsService {
dealingsRecordService.save(dealingsRecord);
}else{
// 客户id拿前台传的
customerId = saleQueryDTO.getUserId();
String byMobileMobile = byMobile.getMobile();
if(byMobileMobile.equals(saleQueryDTO.getUserId())){
customerId = saleQueryDTO.getUserId();
}else{
// 根据手机号查询的用户id和前台传的不一样,则根据 userPhone 查customer表(所有数据)更新 userid 为传过来的这个
customerService.updateUserIdByUserPhone(saleQueryDTO.getMobile(),saleQueryDTO.getUserId());
}
}
} else {
log.error("下游客户未填写手机号!");

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/SalesCalculateServiceImpl.java

@ -207,7 +207,7 @@ public class SalesCalculateServiceImpl implements SalesCalculateService {
String searchDate;
for (int i = -6; i < 1; i++) {
// 查询的日期加一天
searchDate = DateUtil.getAfterDayTime(todayDateStr, i);
searchDate = DateUtil.addDay(todayDateStr, i);
// 店铺id从缓存中获取,并放到数据中去
final String shopId = securityUtil.getShopId();
// 查询日期范围内数据

40
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/CustomerServiceImpl.java

@ -84,7 +84,7 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
}
@Override
public List<String> findByUserId(String userId,String shopId) {
public List<Customer> findByUserId(String userId, String shopId) {
return customerMapper.findByUserId(userId, shopId);
}
@ -138,12 +138,12 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
final String createBy;
final String createByName;
// shopId从缓存中设置
if(StringUtils.isEmpty(customer.getShopId())){
if (StringUtils.isEmpty(customer.getShopId())) {
shopId = securityUtil.getShopId();
final User user = securityUtil.getCurrUser();
createBy = user.getId();
createByName = user.getNickname();
}else{
} else {
shopId = customer.getShopId();
createBy = customer.getCreateBy();
createByName = customer.getCreateByName();
@ -219,12 +219,12 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
@Override
public List<Customer> findByUserName(String userName) {
String shopId = securityUtil.getShopId();
return customerMapper.findByUserName(userName,shopId);
return customerMapper.findByUserName(userName, shopId);
}
@Override
public List<Customer> findByUserPhoneAndShopId(String userPhone, String shopId) {
return customerMapper.findByUserPhoneAndShopId(userPhone,shopId);
return customerMapper.findByUserPhoneAndShopId(userPhone, shopId);
}
@Override
@ -232,19 +232,20 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
Map<String, Object> result = new HashMap<>();
// 获取客户购买该商品规格的总件数
Integer buyCount = saleDetailService.getCustomerBuyHistory(productId, attributeList, customerId);
result.put("buyCount",buyCount);
result.put("buyCount", buyCount);
// 获取客户购买该商品退货总件数
Integer returnCount = returnSaleService.getCustomerReturnHistory(productId, attributeList, customerId);
result.put("returnCount",returnCount);
result.put("returnCount", returnCount);
return result;
}
/**
* 查询客户 拿货总金额商品总款数总件数退货总金额商品总款数总件数
* @author 王富康
* @date 2024/10/24
*
* @param customerPageQuery
* @return SupplierDataVo
* @author 王富康
* @date 2024/10/24
*/
@Override
public CustomerDataVo getCustomerData(CustomerPageQuery customerPageQuery) {
@ -261,4 +262,25 @@ public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> i
customerDataVo.setReturnProductDataVos(returnSaleInfo.getReturnProductDataVos());
return customerDataVo;
}
@Override
public void updateUserId(String customerId, String userId) {
customerMapper.updateUserId(customerId, userId);
}
@Override
public List<String> getOfficialAccountOpenids(String userId, String categoryId, String isAll) {
// shopId从缓存中设置
final String shopId = securityUtil.getShopId();
return customerMapper.getOfficialAccountOpenids(shopId, userId, categoryId, isAll);
}
@Override
public void updateUserIdByUserPhone(String userPhone, String userId) {
customerMapper.updateUserIdByUserPhone(userPhone, userId);
// 根据userPhone获取用户信息
userService.setUserPhoneToNull(userPhone);
userService.updateUserPhoneById(userPhone, userId);
}
}

55
hiver-modules/hiver-mall/src/main/resources/mapper/CustomerMapper.xml

@ -430,10 +430,11 @@
order by no_earn desc
</select>
<select id="getCustomerList" resultMap="BaseResultMap">
<select id="getCustomerList" resultType="cc.hiver.mall.entity.Customer">
select
a.id, a.name, a.sex, a.phone, a.address,
a.province, a.city, a.area, a.shop_id, a.user_id, a.category_id, a.category_name,a.order_by_field,s.amount_owed as no_earn,t.not_buy_days
a.province, a.city, a.area, a.shop_id, a.user_id, a.category_id, a.category_name,a.order_by_field,s.amount_owed as no_earn,t.not_buy_days,
tu.mini_program_openid,tu.unionid,tu.official_account_openid,tu.wechat_name
from t_customer a
left join t_debt s
on a.id = s.user_id
@ -442,6 +443,8 @@
where ts.shop_id = #{queryParams.shopId}
group by ts.user_id) t
on a.id = t.user_id
left join t_user tu
on a.user_id = tu.id
where a.shop_id = #{queryParams.shopId}
and a.del_flag = #{queryParams.delFlag}
<if test=" queryParams.searchStr != null and queryParams.searchStr != ''">
@ -480,8 +483,9 @@
where id = #{id,jdbcType=VARCHAR}
</update>
<select id="findByUserId" resultType="java.lang.String">
select id
<select id="findByUserId" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_customer a
where a.user_id = #{userId,jdbcType=VARCHAR}
<if test=" shopId != null and shopId != ''">
@ -518,7 +522,48 @@
<include refid="Base_Column_List" />
from t_customer a
where del_flag = '0'
<if test=" shopId != null and shopId != ''">
and a.shop_id = #{shopId,jdbcType=VARCHAR}
and a.phone = #{userPhone,jdbcType=VARCHAR}
</if>
<if test=" userPhone != null and userPhone != ''">
and a.user_id = #{userPhone,jdbcType=VARCHAR}
</if>
</select>
<update id="updateUserId">
update t_customer
set user_id = #{userId,jdbcType=VARCHAR}
where id = #{customerId,jdbcType=VARCHAR}
</update>
<select id="getOfficialAccountOpenids" resultType="java.lang.String">
SELECT
official_account_openid
FROM
t_user
WHERE
id IN (
SELECT
user_id
FROM
t_customer
WHERE
shop_id = #{shopId}
<if test=" categoryId != null and categoryId != ''">
and category_id = #{categoryId}
</if>
<if test=" userId != null and userId != ''">
and user_id = #{userId}
</if>
<if test=" isAll != null and isAll != ''">
and category_id is null
</if>
)
</select>
<update id="updateUserIdByUserPhone" parameterType="java.lang.String">
update t_customer
set user_id = #{userId,jdbcType=VARCHAR}
where phone = #{userPhone,jdbcType=VARCHAR}
</update>
</mapper>

14
hiver-modules/hiver-social/pom.xml

@ -7,6 +7,20 @@
<groupId>cc.hiver</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.6.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.hiver</groupId>
<artifactId>hiver-mall</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<modelVersion>4.0.0</modelVersion>
<name>Hiver社交模块</name>
<artifactId>hiver-social</artifactId>

36
hiver-modules/hiver-social/src/main/java/cc/hiver/social/config/MessageRouterConfig.java

@ -0,0 +1,36 @@
package cc.hiver.social.config;
import cc.hiver.social.handler.WxServerMsgHandler;
import cc.hiver.social.interceptor.WxServerMsgInterceptor;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MessageRouterConfig {
@Autowired
private WxMpService wxMpService;
@Autowired
private WxServerMsgHandler wxServerMsgHandler;
@Autowired
private WxServerMsgInterceptor wxServerMsgInterceptor;
@Bean
public WxMpMessageRouter messageRouter() {
// 创建消息路由
final WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
// 添加一个同步处理文本消息的路由规则 同时添加interceptor、handler
router.rule()
.async(false)
.interceptor(wxServerMsgInterceptor)
.handler(wxServerMsgHandler)
.end();
return router;
}
}

44
hiver-modules/hiver-social/src/main/java/cc/hiver/social/config/WxMpConfiguration.java

@ -0,0 +1,44 @@
package cc.hiver.social.config;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WxMpConfiguration {
@Autowired
private WxMpProperties wxMpProperties;
/**
* 微信客户端配置存储
*/
@Bean
public WxMpConfigStorage wxMpConfigStorage() {
final WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
// 设置微信公众号appId
configStorage.setAppId(wxMpProperties.getAppId());
// 设置微信公众号appSecret
configStorage.setSecret(wxMpProperties.getSecret());
// 设置微信公众号的token
configStorage.setToken(wxMpProperties.getToken());
// 设置微信公众号的EncodingAESKey
configStorage.setAesKey(wxMpProperties.getAesKey());
return configStorage;
}
/**
* WxMpService多个实现类 声明一个实例
*/
@Bean
public WxMpService wxMpService() {
final WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
return wxMpService;
}
}

31
hiver-modules/hiver-social/src/main/java/cc/hiver/social/config/WxMpProperties.java

@ -0,0 +1,31 @@
package cc.hiver.social.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "wx.mp")
public class WxMpProperties {
/**
* 设置微信公众号的appid
*/
private String appId;
/**
* 设置微信公众号的app secret
*/
private String secret;
/**
* 设置微信公众号的token
*/
private String token;
/**
* 设置微信公众号的EncodingAESKey
*/
private String aesKey;
}

168
hiver-modules/hiver-social/src/main/java/cc/hiver/social/controller/WechatController.java

@ -8,11 +8,13 @@ import cc.hiver.core.common.redis.RedisTemplateHelper;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.utils.SecurityUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.mall.service.mybatis.CustomerService;
import cc.hiver.social.entity.Social;
import cc.hiver.social.service.SocialService;
import cc.hiver.social.vo.WeChatServerMsgVo;
import cc.hiver.social.vo.WechatUserInfo;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
@ -20,16 +22,23 @@ import com.google.gson.JsonParser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@ -70,6 +79,15 @@ public class WechatController {
@Autowired
private RedisTemplateHelper redisTemplate;
@Autowired
private WxMpService wxMpService;
@Autowired
private WxMpMessageRouter wxMpMessageRouter;
@Autowired
private CustomerService customerService;
/**
* 微信认证服务器地址
*/
@ -86,73 +104,175 @@ public class WechatController {
private static final String GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";
@RequestMapping(value = "/login", method = RequestMethod.GET)
@ApiOperation(value = "获取wechat认证链接")
@ApiOperation("获取wechat认证链接")
@ResponseBody
public Result login() throws UnsupportedEncodingException {
// 生成并保存state 忽略该参数有可能导致CSRF攻击
String state = String.valueOf(System.currentTimeMillis());
final String state = String.valueOf(System.currentTimeMillis());
redisTemplate.set(STATE + state, "VALID", 3L, TimeUnit.MINUTES);
// 传递参数response_type、client_id、state、redirect_uri
String url = AUTHORIZE_URL + "?appid=" + appId + "&redirect_uri=" + URLEncoder.encode(callbackUrl, "utf-8") + "&response_type=code" +
final String url = AUTHORIZE_URL + "?appid=" + appId + "&redirect_uri=" + URLEncoder.encode(callbackUrl, "utf-8") + "&response_type=code" +
"&scope=snsapi_login&state=" + state;
return ResultUtil.data(url);
}
@RequestMapping(value = "/callback", method = RequestMethod.GET)
@ApiOperation(value = "获取accessToken")
@ApiOperation("获取accessToken")
@SystemLog(description = "微信关联登录", type = LogType.LOGIN)
public String callback(@RequestParam(required = false) String code,
@RequestParam(required = false) String state) throws UnsupportedEncodingException {
if (StrUtil.isBlank(code)) {
if (CharSequenceUtil.isBlank(code)) {
return "redirect:" + callbackFeUrl + "?error=" + URLEncoder.encode("您未同意授权", "utf-8");
}
// 验证state
String v = redisTemplate.get(STATE + state);
final String v = redisTemplate.get(STATE + state);
redisTemplate.delete(STATE + state);
if (StrUtil.isBlank(v)) {
if (CharSequenceUtil.isBlank(v)) {
return "redirect:" + callbackFeUrl + "?error=" + URLEncoder.encode("授权超时或state不正确", "utf-8");
}
// 传递参数grant_type、code、redirect_uri、appid、appsecret
String accessTokenUrl = ACCESS_TOKEN_URL + "?appid=" + appId + "&secret=" + appSecret + "&code=" + code +
final String accessTokenUrl = ACCESS_TOKEN_URL + "?appid=" + appId + "&secret=" + appSecret + "&code=" + code +
"&grant_type=authorization_code";
// 申请令牌
String result = HttpUtil.get(accessTokenUrl);
final String result = HttpUtil.get(accessTokenUrl);
if (!result.contains("access_token")) {
return "redirect:" + callbackFeUrl + "?error=" + URLEncoder.encode("获取access_token失败", "utf-8");
}
JsonObject jsonObject = JsonParser.parseString(result).getAsJsonObject();
String accessToken = jsonObject.get("access_token").getAsString();
String openId = jsonObject.get("openid").getAsString();
final JsonObject jsonObject = JsonParser.parseString(result).getAsJsonObject();
final String accessToken = jsonObject.get("access_token").getAsString();
final String openId = jsonObject.get("openid").getAsString();
// 获取用户信息
String userInfo = HttpUtil.get(GET_USERINFO_URL + "?access_token=" + accessToken + "&openid=" + openId);
WechatUserInfo wu = new Gson().fromJson(userInfo, WechatUserInfo.class);
final String userInfo = HttpUtil.get(GET_USERINFO_URL + "?access_token=" + accessToken + "&openid=" + openId);
final WechatUserInfo wu = new Gson().fromJson(userInfo, WechatUserInfo.class);
// 存入数据库
Social wechat = socialService.findByOpenIdAndPlatform(wu.getOpenid(), TYPE);
if (wechat == null) {
Social w = new Social().setOpenId(wu.getOpenid()).setUsername(wu.getNickname()).setAvatar(wu.getHeadimgurl()).setPlatform(TYPE);
final Social w = new Social().setOpenId(wu.getOpenid()).setUsername(wu.getNickname()).setAvatar(wu.getHeadimgurl()).setPlatform(TYPE);
wechat = socialService.save(w);
}
String url = "";
// 判断是否绑定账号
if (StrUtil.isNotBlank(wechat.getRelateUsername())) {
if (CharSequenceUtil.isNotBlank(wechat.getRelateUsername())) {
// 已绑定 直接登录
String JWT = securityUtil.getToken(wechat.getRelateUsername(), true);
final String JWT = securityUtil.getToken(wechat.getRelateUsername(), true);
// 存入redis
String JWTKey = IdUtil.simpleUUID();
final String JWTKey = IdUtil.simpleUUID();
redisTemplate.set(JWTKey, JWT, 2L, TimeUnit.MINUTES);
url = callbackFeUrl + "?related=1&JWTKey=" + JWTKey;
} else {
// 未绑定 Redis存入id
String idToken = IdUtil.simpleUUID();
final String idToken = IdUtil.simpleUUID();
redisTemplate.set(idToken, wechat.getId(), 5L, TimeUnit.MINUTES);
url = callbackFeRelateUrl + "?socialType=" + TYPE + "&id=" + idToken;
}
return "redirect:" + url;
}
@RequestMapping("echo")
@ResponseBody
public String configAccess(@RequestBody String requestBody, @RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) {
// 校验签名
if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
log.error("签名校验 ===》 非法请求");
// 消息签名不正确,说明不是公众平台发过来的消息
return null;
}
log.error("签名校验 ===》 验证成功");
// 解析消息体,封装为对象
final WxMpXmlMessage xmlMessage = WxMpXmlMessage.fromXml(requestBody);
WxMpXmlOutMessage outMessage = null;
try {
// 将消息路由给对应的处理器,获取响应
outMessage = wxMpMessageRouter.route(xmlMessage);
} catch (Exception e) {
log.error("消息路由异常", e);
}
if (outMessage != null) {
log.info("到了返回了========" + outMessage.toXml());
} else {
log.info("到了返回了========outMessage为空!");
}
// 将响应消息转换为xml格式返回
return outMessage == null ? null : outMessage.toXml();
}
/**
* 发送模版消息
*
* @param weChatServerMsgVo 消息Vo
* @throws Exception
*/
@ResponseBody
@RequestMapping("sendWechatTempMessage")
public Result sendWechatTempMessage(@RequestBody WeChatServerMsgVo weChatServerMsgVo) throws Exception {
// 查询相关人员信息
// 情况说明:1、upNewType,0零售价,1批发价,userId和categoryId为空,则按照零售价或者批发价推送给所有客户
//1、如果传了userId,则只给这一个用户推送,这个客户有客户分类就是用客户分类价格,没有分类则使用批发价
//2、如果传了categoryId,则只给该分类的客户推送
//3、如果这三个参数都为空,则给全部客户推送,有客户分类按客户分类,没有按批发价推送
// 获取店铺客户openId集合
final List<String> officialAccountOpenids = customerService.getOfficialAccountOpenids(weChatServerMsgVo.getUserId(), weChatServerMsgVo.getCategoryId(),weChatServerMsgVo.getIsAll());
for (String openId : officialAccountOpenids) {
final WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
// 要推送的用户openid
.toUser(openId)
// 消息详情跳转地址:https://blog.csdn.net/qq_34272760/article/details/120152903
// 若需要跳转小程序,url则设置为:http://mp.weixin.qq.com,然后设置相关的MiniProgram参数【跳转的小程序必须是公众号关联的小程序!!!】
.url("http://mp.weixin.qq.com")
// 微信模板ID
.templateId(weChatServerMsgVo.getTempId())
.build();
// data的字段及内容是自定义的,不必按我这儿的来,具体怎么和已有的系统消息结合,实现key和color可配置化需自行考虑
final JsonObject jsonObject = JsonParser.parseString(weChatServerMsgVo.getContent()).getAsJsonObject();
final List<WxMpTemplateData> data = new ArrayList<>();
for (String key : jsonObject.keySet()) {
final Object value = jsonObject.get(key);
String afterValue = String.valueOf(value).replace("\"", "");
log.info("Key: " + key + ", Value: " + afterValue);
data.add(new WxMpTemplateData(key, afterValue));
}
templateMessage.setData(data);
// 跳转小程序相关配置【跳转的小程序必须是公众号关联的小程序!!!】
final WxMpTemplateMessage.MiniProgram miniProgram = new WxMpTemplateMessage.MiniProgram();
log.info("appId============" + appId);
// 小程序的appId
miniProgram.setAppid(appId);
// 小程序的pagePath 注意,这里是支持传参的!!!
miniProgram.setPagePath(weChatServerMsgVo.getPagePath());
// 需要跳转首页时,需要设置 usePath = true (默认是 false,只跳转非首页)
miniProgram.setUsePath(false);
templateMessage.setMiniProgram(miniProgram);
try {
// 发送模板消息
wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
} catch (Exception e) {
log.error("微信公众号模板消息推送失败,接收userId: " + openId, e);
return ResultUtil.error("发送失败" + e.getMessage());
}
}
return ResultUtil.success("发送成功!");
}
// 根据openid获取用户信息
@ResponseBody
@RequestMapping("getUserInfo")
public Result getUserInfo(String openid) throws WxErrorException {
// 拼接请求地址
String lang = "zh_CN"; //语言
WxMpUser user = wxMpService.getUserService().userInfo(openid,lang);
return ResultUtil.data(user);
}
}

67
hiver-modules/hiver-social/src/main/java/cc/hiver/social/handler/WxServerMsgHandler.java

@ -0,0 +1,67 @@
package cc.hiver.social.handler;
import cc.hiver.core.service.UserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
@Slf4j
public class WxServerMsgHandler implements WxMpMessageHandler {
@Autowired
private UserService userService;
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
log.info("接收到的消息MsgType:{};Event:{};OpenId:{};FromUser:{};",wxMessage.getMsgType(),wxMessage.getEvent(),wxMessage.getOpenId(),wxMessage.getFromUser());
// 响应的消息内容
String outContent = "";
//判断是否是事件类型
if(wxMessage.getMsgType().equals(WxConsts.XmlMsgType.EVENT)){
//订阅
if(wxMessage.getEvent().equals(WxConsts.EventType.SUBSCRIBE)){
outContent = "【快衣店信息推送】欢迎您!致力于帮助服装店主们更好地进行商品管理和营销推广,我们会持续发布实用技巧、成功案例分析等内容。期待与您共同成长,共创辉煌业绩!";
final String lang = "zh_CN"; //语言
final WxMpUser user = wxMpService.getUserService().userInfo(wxMessage.getFromUser(),lang);
log.info("关注公众号的用户信息:user====:{}",user);
userService.subscribeWxServer(user);
}
//取消订阅
if(wxMessage.getEvent().equals(WxConsts.EventType.UNSUBSCRIBE)){
}
} else if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.TEXT)){
//判断为文本消息
// 接收消息内容
final String inContent = wxMessage.getContent();
// 根据不同的关键字回复消息
if (inContent.contains("hello")) {
outContent = "hello world";
} else if (inContent.contains("java")) {
outContent = "hello java";
} else if (inContent.contains("***")) {
outContent = "请文明用语";
} else {
outContent = "服务繁忙,暂时不能回复";
}
}else{
outContent = "服务繁忙,暂时不能回复";
}
log.info("outContent========"+outContent);
// 构造响应消息对象
return WxMpXmlOutMessage.TEXT().content(outContent).fromUser(wxMessage.getToUser())
.toUser(wxMessage.getFromUser()).build();
}
}

29
hiver-modules/hiver-social/src/main/java/cc/hiver/social/interceptor/WxServerMsgInterceptor.java

@ -0,0 +1,29 @@
package cc.hiver.social.interceptor;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageInterceptor;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 对微信公众号消息进行预处理过滤等操作根据具体业务需求决定是否允许继续执行后面的路由处理方法
* <p>
* 如果要中止消息的继续处理即表示拦截了这个消息需要返回 false否则在执行完当前拦截器操作后允许消息的继续处理返回 true
*/
@Component
public class WxServerMsgInterceptor implements WxMpMessageInterceptor {
@Override
public boolean intercept(WxMpXmlMessage wxMpXmlMessage, Map<String, Object> map, WxMpService wxMpService, WxSessionManager wxSessionManager) {
final String msg = wxMpXmlMessage.getContent();
final String msgType = wxMpXmlMessage.getMsgType();
if ("text".equals(msgType) && msg.contains("混蛋")) {
wxMpXmlMessage.setContent("***");
return true;
}
return true;
}
}

47
hiver-modules/hiver-social/src/main/java/cc/hiver/social/vo/WeChatServerMsgVo.java

@ -0,0 +1,47 @@
package cc.hiver.social.vo;
import lombok.Data;
@Data
public class WeChatServerMsgVo {
/**
* 模版id
*/
private String tempId;
/**
* 模版标头
*/
private String title;
/**
* 模版内容
*/
private String content;
/**
* 跳转小程序的页面
*/
private String pagePath;
/**
* 非必传 0零售价 1批发价
*/
private String upNewType;
/*
* 客户id
*/
private String userId;
/**
* 客户分类id
*/
private String categoryId;
/**
* isAIl=1的时候,则需要给该店铺所有没有绑定客户分类的客户推送消息
*/
private String isAll;
}
Loading…
Cancel
Save