GetOpenIdByCodeCmd.java
6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package com.java110.user.cmd.wechat;
import com.alibaba.fastjson.JSONObject;
import com.java110.core.annotation.Java110Cmd;
import com.java110.core.context.ICmdDataFlowContext;
import com.java110.core.event.cmd.Cmd;
import com.java110.core.event.cmd.CmdEvent;
import com.java110.core.factory.GenerateCodeFactory;
import com.java110.core.log.LoggerFactory;
import com.java110.dto.user.UserAttrDto;
import com.java110.dto.wechat.SmallWeChatDto;
import com.java110.intf.store.ISmallWechatV1InnerServiceSMO;
import com.java110.intf.user.IUserAttrV1InnerServiceSMO;
import com.java110.po.user.UserAttrPo;
import com.java110.utils.cache.MappingCache;
import com.java110.utils.constant.MappingConstant;
import com.java110.utils.exception.CmdException;
import com.java110.utils.util.Assert;
import com.java110.utils.util.StringUtil;
import com.java110.vo.ResultVo;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.text.ParseException;
import java.util.List;
/**
* 根据小程序授权码获取微信用户OpenID的命令类
* 主要功能:通过微信小程序的code获取用户的openid,并根据用户登录状态决定是否将openid保存到用户属性中
* 注意:此接口专为商城场景设计,支持已登录和未登录用户的openid获取
*
* @author Java110
* @version 1.0
* @serviceCode wechat.getOpenIdByCode
*/
@Java110Cmd(serviceCode = "wechat.getOpenIdByCode")
public class GetOpenIdByCodeCmd extends Cmd {
/** 日志记录器 */
private final static Logger logger = LoggerFactory.getLogger(GetOpenIdByCodeCmd.class);
/** 用于发送HTTP请求的RestTemplate */
@Autowired
private RestTemplate outRestTemplate;
/** 小程序信息服务接口 */
@Autowired
private ISmallWechatV1InnerServiceSMO smallWechatV1InnerServiceSMOImpl;
/** 用户属性服务接口 */
@Autowired
private IUserAttrV1InnerServiceSMO userAttrV1InnerServiceSMOImpl;
/**
* 参数验证方法
* 验证请求参数中是否包含必要的code和appId参数
*
* @param event 命令事件对象
* @param context 命令数据流上下文
* @param reqJson 请求参数JSON对象
* @throws CmdException 命令异常
* @throws ParseException 解析异常
*/
@Override
public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
// 验证请求参数中必须包含code参数
Assert.hasKeyAndValue(reqJson, "code", "未包含code");
// 验证请求参数中必须包含appId参数
Assert.hasKeyAndValue(reqJson, "appId", "未包含小程序ID");
}
/**
* 命令执行方法
* 根据小程序code获取微信openid,并根据用户登录状态决定是否保存到用户属性中
*
* @param event 命令事件对象
* @param context 命令数据流上下文
* @param reqJson 请求参数JSON对象
* @throws CmdException 命令异常
* @throws ParseException 解析异常
*/
@Override
public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) throws CmdException, ParseException {
// 从请求头中获取用户ID
String userId = context.getReqHeaders().get("user-id");
String appId = "";
String appSecret = "";
// 根据appId类型获取对应的微信配置信息
if ("MALL".equals(reqJson.getString("appId"))) {
// 如果是商城小程序,从缓存中获取配置信息
appId = MappingCache.getValue(MappingConstant.MALL_WECHAT_DOMAIN, "wechatAppId");
appSecret = MappingCache.getValue(MappingConstant.MALL_WECHAT_DOMAIN, "wechatAppSecret");
} else {
// 如果是其他小程序,从数据库中查询配置信息
SmallWeChatDto smallWeChatDto = new SmallWeChatDto();
smallWeChatDto.setAppId(reqJson.getString("appId"));
List<SmallWeChatDto> smallWeChatDtos = smallWechatV1InnerServiceSMOImpl.querySmallWechats(smallWeChatDto);
// 验证是否配置了小程序信息
if (smallWeChatDtos == null || smallWeChatDtos.size() < 1) {
throw new IllegalArgumentException("未配置小程序信息");
}
appId = smallWeChatDtos.get(0).getAppId();
appSecret = smallWeChatDtos.get(0).getAppSecret();
}
// 调用微信接口获取openid
String code = reqJson.getString("code");
String urlString = "https://api.weixin.qq.com/sns/jscode2session?appid={appId}&secret={secret}&js_code={code}&grant_type={grantType}";
String response = outRestTemplate.getForObject(
urlString, String.class,
appId,
appSecret,
code,
"authorization_code");
logger.debug("微信返回报文:" + response);
// 解析微信接口返回的JSON数据
JSONObject responseObj = JSONObject.parseObject(response);
// 检查微信接口返回是否包含错误码
if (responseObj.containsKey("errcode") && !"0".equals(responseObj.getString("errcode"))) {
throw new IllegalArgumentException("微信验证失败,可能是code失效" + responseObj);
}
// 从响应中提取openid
String openId = responseObj.getString("openid");
// 如果用户未登录或用户ID异常,直接返回openid
if (StringUtil.isEmpty(userId) || userId.startsWith("-")) {
context.setResponseEntity(ResultVo.createResponseEntity(openId));
return;
}
// 查询用户是否已存在商城openid属性
UserAttrDto userAttrDto = new UserAttrDto();
userAttrDto.setUserId(userId);
userAttrDto.setSpecCd(UserAttrDto.SPEC_MALL_OPEN_ID);
List<UserAttrDto> userAttrDtos = userAttrV1InnerServiceSMOImpl.queryUserAttrs(userAttrDto);
if (userAttrDtos == null || userAttrDtos.size() < 1) {
// 如果不存在,创建新的用户属性记录
UserAttrPo userAttrPo = new UserAttrPo();
userAttrPo.setAttrId(GenerateCodeFactory.getAttrId());
userAttrPo.setUserId(userId);
userAttrPo.setSpecCd(UserAttrDto.SPEC_MALL_OPEN_ID);
userAttrPo.setValue(openId);
userAttrV1InnerServiceSMOImpl.saveUserAttr(userAttrPo);
} else {
// 如果已存在,更新现有的用户属性记录
UserAttrPo userAttrPo = new UserAttrPo();
userAttrPo.setAttrId(userAttrDtos.get(0).getAttrId());
userAttrPo.setValue(openId);
userAttrV1InnerServiceSMOImpl.updateUserAttr(userAttrPo);
}
// 返回openid给前端
context.setResponseEntity(ResultVo.createResponseEntity(openId));
}
}