0
# User Management
1
2
User authentication, profile information, phone number access, and user data management for WeChat MiniApp users. This service handles the complete user lifecycle from login to data access.
3
4
## Capabilities
5
6
### User Service Interface
7
8
Core user operations including session management, profile decryption, and user data storage.
9
10
```java { .api }
11
public interface WxMaUserService {
12
// Authentication
13
WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException;
14
15
// User Profile Data
16
WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr) throws WxErrorException;
17
boolean checkUserInfo(String sessionKey, String rawData, String signature) throws WxErrorException;
18
19
// Phone Number Access (New Method - Base Library 2.21.2+)
20
WxMaPhoneNumberInfo getPhoneNumber(String code) throws WxErrorException;
21
22
// Phone Number Access (Legacy Method - Deprecated)
23
@Deprecated
24
WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr) throws WxErrorException;
25
26
// User Storage (Mini Games)
27
void setUserStorage(Map<String, String> kvMap, String sessionKey, String openid) throws WxErrorException;
28
}
29
```
30
31
### User Information Models
32
33
Data models for user profile information and phone number data.
34
35
```java { .api }
36
public class WxMaUserInfo implements Serializable {
37
private String openId; // User unique identifier
38
private String nickName; // User nickname
39
private String gender; // Gender (0: unknown, 1: male, 2: female)
40
private String city; // City
41
private String province; // Province
42
private String country; // Country
43
private String avatarUrl; // Avatar URL
44
private String unionId; // Union ID (if available)
45
private String language; // User language (zh_CN, en_US, etc.)
46
private WxMaUserInfo.Watermark watermark; // Watermark info
47
48
// Getters and setters
49
public String getOpenId();
50
public void setOpenId(String openId);
51
public String getNickName();
52
public void setNickName(String nickName);
53
public String getGender();
54
public void setGender(String gender);
55
public String getCity();
56
public void setCity(String city);
57
public String getProvince();
58
public void setProvince(String province);
59
public String getCountry();
60
public void setCountry(String country);
61
public String getAvatarUrl();
62
public void setAvatarUrl(String avatarUrl);
63
public String getUnionId();
64
public void setUnionId(String unionId);
65
public String getLanguage();
66
public void setLanguage(String language);
67
public Watermark getWatermark();
68
public void setWatermark(Watermark watermark);
69
70
// Nested watermark class
71
public static class Watermark {
72
private Long timestamp; // Data timestamp
73
private String appid; // App ID
74
75
public Long getTimestamp();
76
public void setTimestamp(Long timestamp);
77
public String getAppid();
78
public void setAppid(String appid);
79
}
80
81
// Utility methods
82
public static WxMaUserInfo fromJson(String json);
83
public String toJson();
84
}
85
```
86
87
```java { .api }
88
public class WxMaPhoneNumberInfo implements Serializable {
89
private String phoneNumber; // Phone number with country code
90
private String purePhoneNumber; // Pure phone number without country code
91
private String countryCode; // Country code
92
private WxMaPhoneNumberInfo.Watermark watermark; // Watermark info
93
94
// Getters and setters
95
public String getPhoneNumber();
96
public void setPhoneNumber(String phoneNumber);
97
public String getPurePhoneNumber();
98
public void setPurePhoneNumber(String purePhoneNumber);
99
public String getCountryCode();
100
public void setCountryCode(String countryCode);
101
public Watermark getWatermark();
102
public void setWatermark(Watermark watermark);
103
104
// Nested watermark class
105
public static class Watermark {
106
private Long timestamp; // Data timestamp
107
private String appid; // App ID
108
109
public Long getTimestamp();
110
public void setTimestamp(Long timestamp);
111
public String getAppid();
112
public void setAppid(String appid);
113
}
114
115
// Utility methods
116
public static WxMaPhoneNumberInfo fromJson(String json);
117
public String toJson();
118
}
119
```
120
121
### Session Management
122
123
Session data model for user login sessions.
124
125
```java { .api }
126
public class WxMaJscode2SessionResult implements Serializable {
127
private String sessionKey; // Session key for encryption operations
128
private String openid; // User OpenID
129
private String unionid; // Union ID (cross-app identifier)
130
131
// Factory method
132
public static WxMaJscode2SessionResult fromJson(String json);
133
134
// Getters and setters
135
public String getSessionKey();
136
public void setSessionKey(String sessionKey);
137
public String getOpenid();
138
public void setOpenid(String openid);
139
public String getUnionid();
140
public void setUnionid(String unionid);
141
142
// Utility methods
143
public String toJson();
144
@Override
145
public String toString();
146
}
147
```
148
149
## Usage Examples
150
151
### Complete User Login Flow
152
153
```java
154
// 1. Exchange login code for session (from wx.login())
155
String jsCode = "061XaW100MIVdh1U8l000qdncT3XaW1g";
156
157
try {
158
WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(jsCode);
159
160
String openid = session.getOpenid();
161
String sessionKey = session.getSessionKey();
162
String unionid = session.getUnionid(); // May be null
163
164
// Store session info securely (don't expose sessionKey to client)
165
166
} catch (WxErrorException e) {
167
if (e.getError().getErrorCode() == 40029) {
168
// Invalid js_code (expired, used, or invalid)
169
return ResponseEntity.badRequest().body("Login code expired");
170
}
171
throw e;
172
}
173
```
174
175
### Decrypt User Profile Information
176
177
```java
178
// Client provides encrypted user data (from wx.getUserInfo() or getUserProfile())
179
String encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZM...";
180
String iv = "r7BXXKkLb8qrSNn05n0qiA==";
181
182
try {
183
WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(
184
sessionKey, // From login session
185
encryptedData, // From client
186
iv // From client
187
);
188
189
// Access user profile data
190
String nickname = userInfo.getNickName();
191
String avatarUrl = userInfo.getAvatarUrl();
192
String gender = userInfo.getGender(); // "0", "1", "2"
193
String city = userInfo.getCity();
194
String province = userInfo.getProvince();
195
String country = userInfo.getCountry();
196
String unionId = userInfo.getUnionId(); // Cross-app user ID
197
198
// Check data freshness
199
WxMaUserInfo.Watermark watermark = userInfo.getWatermark();
200
if (watermark != null) {
201
long timestamp = watermark.getTimestamp();
202
String appid = watermark.getAppid();
203
204
// Verify data is recent and from correct app
205
long now = System.currentTimeMillis() / 1000;
206
if (now - timestamp > 300) { // Data older than 5 minutes
207
// Consider refreshing user data
208
}
209
}
210
211
} catch (WxErrorException e) {
212
// Handle decryption errors
213
logger.error("Failed to decrypt user info: {}", e.getMessage());
214
}
215
```
216
217
### Verify User Data Integrity
218
219
```java
220
// Verify user data hasn't been tampered with
221
String rawData = "{\"nickName\":\"Band\",\"gender\":1,\"language\":\"zh_CN\",\"city\":\"Guangzhou\",\"province\":\"Guangdong\",\"country\":\"CN\",\"avatarUrl\":\"http://wx.qlogo.cn/mmopen/vi_32/1vS19XGlp/0\"}";
222
String signature = "75e81ceda165f4ffa64f4068af58c64b8f54b88c";
223
224
try {
225
boolean isValid = wxService.getUserService().checkUserInfo(sessionKey, rawData, signature);
226
227
if (isValid) {
228
// Data integrity verified - safe to use rawData
229
ObjectMapper mapper = new ObjectMapper();
230
JsonNode userJson = mapper.readTree(rawData);
231
String nickname = userJson.get("nickName").asText();
232
} else {
233
// Data may have been tampered with
234
logger.warn("User data signature verification failed");
235
}
236
237
} catch (WxErrorException e) {
238
logger.error("Error verifying user data: {}", e.getMessage());
239
}
240
```
241
242
### Get Phone Number (New Method)
243
244
```java
245
// New method for getting phone number (Base Library 2.21.2+)
246
// Client calls wx.getPhoneNumber() and provides code
247
String phoneCode = "e6fd60b3b24e4d24bb7c3b42e0b3b3b3";
248
249
try {
250
WxMaPhoneNumberInfo phoneInfo = wxService.getUserService().getPhoneNumber(phoneCode);
251
252
String fullPhoneNumber = phoneInfo.getPhoneNumber(); // +86138****1234
253
String purePhoneNumber = phoneInfo.getPurePhoneNumber(); // 138****1234
254
String countryCode = phoneInfo.getCountryCode(); // "86"
255
256
// Verify data freshness
257
WxMaPhoneNumberInfo.Watermark watermark = phoneInfo.getWatermark();
258
if (watermark != null) {
259
long timestamp = watermark.getTimestamp();
260
String appid = watermark.getAppid();
261
}
262
263
} catch (WxErrorException e) {
264
int errorCode = e.getError().getErrorCode();
265
if (errorCode == 40001) {
266
// Invalid access token
267
} else if (errorCode == 47001) {
268
// Data decryption failed
269
}
270
}
271
```
272
273
### Get Phone Number (Legacy Method)
274
275
```java
276
// Legacy method - decrypt phone number from encrypted data
277
String encryptedData = "Kf3TdPbzEmhWMuPKtlKxIWDkijhn...";
278
String iv = "r7BXXKkLb8qrSNn05n0qiA==";
279
280
try {
281
@SuppressWarnings("deprecation")
282
WxMaPhoneNumberInfo phoneInfo = wxService.getUserService().getPhoneNoInfo(
283
sessionKey, encryptedData, iv
284
);
285
286
String phoneNumber = phoneInfo.getPhoneNumber();
287
String purePhoneNumber = phoneInfo.getPurePhoneNumber();
288
String countryCode = phoneInfo.getCountryCode();
289
290
} catch (WxErrorException e) {
291
// Handle decryption errors
292
logger.error("Phone number decryption failed: {}", e.getMessage());
293
}
294
```
295
296
### Set User Storage (Mini Games)
297
298
```java
299
// Store key-value data for user in mini games
300
Map<String, String> kvMap = new HashMap<>();
301
kvMap.put("level", "10");
302
kvMap.put("score", "95000");
303
kvMap.put("items", "sword,shield,potion");
304
305
try {
306
wxService.getUserService().setUserStorage(kvMap, sessionKey, openid);
307
308
// Data stored successfully
309
// Can be retrieved by mini game client using wx.getStorageSync()
310
311
} catch (WxErrorException e) {
312
// Handle storage errors
313
int errorCode = e.getError().getErrorCode();
314
if (errorCode == 47001) {
315
// Invalid session key
316
} else if (errorCode == 40003) {
317
// Invalid openid
318
}
319
}
320
```
321
322
### Complete User Registration Example
323
324
```java
325
@Service
326
public class UserService {
327
328
@Autowired
329
private WxMaService wxMaService;
330
331
public UserRegistrationResult registerUser(String jsCode, String encryptedData,
332
String iv, String phoneCode) {
333
try {
334
// 1. Get session info
335
WxMaJscode2SessionResult session = wxMaService.getUserService()
336
.getSessionInfo(jsCode);
337
338
String openid = session.getOpenid();
339
String sessionKey = session.getSessionKey();
340
String unionid = session.getUnionid();
341
342
// 2. Decrypt user profile
343
WxMaUserInfo userInfo = wxMaService.getUserService()
344
.getUserInfo(sessionKey, encryptedData, iv);
345
346
// 3. Get phone number
347
WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService()
348
.getPhoneNumber(phoneCode);
349
350
// 4. Create user record
351
User user = new User();
352
user.setOpenid(openid);
353
user.setUnionid(unionid);
354
user.setNickname(userInfo.getNickName());
355
user.setAvatarUrl(userInfo.getAvatarUrl());
356
user.setGender(userInfo.getGender());
357
user.setCity(userInfo.getCity());
358
user.setProvince(userInfo.getProvince());
359
user.setCountry(userInfo.getCountry());
360
user.setPhoneNumber(phoneInfo.getPurePhoneNumber());
361
user.setCountryCode(phoneInfo.getCountryCode());
362
user.setCreatedAt(new Date());
363
364
// 5. Save to database
365
userRepository.save(user);
366
367
// 6. Generate JWT or session token
368
String accessToken = jwtService.generateToken(user);
369
370
return new UserRegistrationResult(user, accessToken);
371
372
} catch (WxErrorException e) {
373
throw new UserRegistrationException("Registration failed: " + e.getMessage(), e);
374
}
375
}
376
}
377
```
378
379
### Error Handling Best Practices
380
381
```java
382
public class WeChatUserException extends RuntimeException {
383
private final int errorCode;
384
385
public WeChatUserException(int errorCode, String message) {
386
super(message);
387
this.errorCode = errorCode;
388
}
389
390
public int getErrorCode() { return errorCode; }
391
}
392
393
public WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String iv) {
394
try {
395
return wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
396
397
} catch (WxErrorException e) {
398
int code = e.getError().getErrorCode();
399
String msg = e.getError().getErrorMsg();
400
401
switch (code) {
402
case 41003:
403
throw new WeChatUserException(code, "Session key invalid or expired");
404
case 47001:
405
throw new WeChatUserException(code, "Data decryption failed");
406
case 40013:
407
throw new WeChatUserException(code, "Invalid app ID");
408
default:
409
throw new WeChatUserException(code, "User info error: " + msg);
410
}
411
}
412
}
413
```
414
415
The user management service provides secure, comprehensive access to WeChat user data while handling encryption, verification, and data integrity automatically.