or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analytics.mdcloud-development.mdconfiguration.mdcore-services.mddevelopment-tools.mdecommerce.mdindex.mdlive-streaming.mdlogistics.mdmedia-content.mdmessaging.mdqr-codes.mduser-management.md

user-management.mddocs/

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.