CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-github-binarywang--weixin-java-miniapp

Comprehensive Java SDK for WeChat MiniApp development with complete platform integration

Pending
Overview
Eval results
Files

user-management.mddocs/

User Management

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.

Capabilities

User Service Interface

Core user operations including session management, profile decryption, and user data storage.

public interface WxMaUserService {
    // Authentication
    WxMaJscode2SessionResult getSessionInfo(String jsCode) throws WxErrorException;
    
    // User Profile Data
    WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr) throws WxErrorException;
    boolean checkUserInfo(String sessionKey, String rawData, String signature) throws WxErrorException;
    
    // Phone Number Access (New Method - Base Library 2.21.2+)
    WxMaPhoneNumberInfo getPhoneNumber(String code) throws WxErrorException;
    
    // Phone Number Access (Legacy Method - Deprecated)
    @Deprecated
    WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr) throws WxErrorException;
    
    // User Storage (Mini Games)
    void setUserStorage(Map<String, String> kvMap, String sessionKey, String openid) throws WxErrorException;
}

User Information Models

Data models for user profile information and phone number data.

public class WxMaUserInfo implements Serializable {
    private String openId;          // User unique identifier
    private String nickName;        // User nickname  
    private String gender;          // Gender (0: unknown, 1: male, 2: female)
    private String city;            // City
    private String province;        // Province
    private String country;         // Country
    private String avatarUrl;       // Avatar URL
    private String unionId;         // Union ID (if available)
    private String language;        // User language (zh_CN, en_US, etc.)
    private WxMaUserInfo.Watermark watermark; // Watermark info
    
    // Getters and setters
    public String getOpenId();
    public void setOpenId(String openId);
    public String getNickName();
    public void setNickName(String nickName);
    public String getGender();
    public void setGender(String gender);
    public String getCity();
    public void setCity(String city);
    public String getProvince(); 
    public void setProvince(String province);
    public String getCountry();
    public void setCountry(String country);
    public String getAvatarUrl();
    public void setAvatarUrl(String avatarUrl);
    public String getUnionId();
    public void setUnionId(String unionId);
    public String getLanguage();
    public void setLanguage(String language);
    public Watermark getWatermark();
    public void setWatermark(Watermark watermark);
    
    // Nested watermark class
    public static class Watermark {
        private Long timestamp;     // Data timestamp
        private String appid;       // App ID
        
        public Long getTimestamp();
        public void setTimestamp(Long timestamp);
        public String getAppid();
        public void setAppid(String appid);
    }
    
    // Utility methods
    public static WxMaUserInfo fromJson(String json);
    public String toJson();
}
public class WxMaPhoneNumberInfo implements Serializable {
    private String phoneNumber;         // Phone number with country code
    private String purePhoneNumber;     // Pure phone number without country code
    private String countryCode;         // Country code
    private WxMaPhoneNumberInfo.Watermark watermark; // Watermark info
    
    // Getters and setters
    public String getPhoneNumber();
    public void setPhoneNumber(String phoneNumber);
    public String getPurePhoneNumber();
    public void setPurePhoneNumber(String purePhoneNumber);
    public String getCountryCode();
    public void setCountryCode(String countryCode);
    public Watermark getWatermark();
    public void setWatermark(Watermark watermark);
    
    // Nested watermark class  
    public static class Watermark {
        private Long timestamp;     // Data timestamp
        private String appid;       // App ID
        
        public Long getTimestamp();
        public void setTimestamp(Long timestamp);
        public String getAppid();
        public void setAppid(String appid);
    }
    
    // Utility methods
    public static WxMaPhoneNumberInfo fromJson(String json);
    public String toJson();
}

Session Management

Session data model for user login sessions.

public class WxMaJscode2SessionResult implements Serializable {
    private String sessionKey;      // Session key for encryption operations
    private String openid;          // User OpenID
    private String unionid;         // Union ID (cross-app identifier)
    
    // Factory method
    public static WxMaJscode2SessionResult fromJson(String json);
    
    // Getters and setters
    public String getSessionKey();
    public void setSessionKey(String sessionKey);
    public String getOpenid();
    public void setOpenid(String openid);
    public String getUnionid();
    public void setUnionid(String unionid);
    
    // Utility methods
    public String toJson();
    @Override
    public String toString();
}

Usage Examples

Complete User Login Flow

// 1. Exchange login code for session (from wx.login())
String jsCode = "061XaW100MIVdh1U8l000qdncT3XaW1g";

try {
    WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(jsCode);
    
    String openid = session.getOpenid();
    String sessionKey = session.getSessionKey();
    String unionid = session.getUnionid(); // May be null
    
    // Store session info securely (don't expose sessionKey to client)
    
} catch (WxErrorException e) {
    if (e.getError().getErrorCode() == 40029) {
        // Invalid js_code (expired, used, or invalid)
        return ResponseEntity.badRequest().body("Login code expired");
    }
    throw e;
}

Decrypt User Profile Information

// Client provides encrypted user data (from wx.getUserInfo() or getUserProfile())
String encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZM...";
String iv = "r7BXXKkLb8qrSNn05n0qiA==";

try {
    WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(
        sessionKey,     // From login session
        encryptedData,  // From client
        iv             // From client
    );
    
    // Access user profile data
    String nickname = userInfo.getNickName();
    String avatarUrl = userInfo.getAvatarUrl();
    String gender = userInfo.getGender();    // "0", "1", "2"
    String city = userInfo.getCity();
    String province = userInfo.getProvince();
    String country = userInfo.getCountry();
    String unionId = userInfo.getUnionId();  // Cross-app user ID
    
    // Check data freshness
    WxMaUserInfo.Watermark watermark = userInfo.getWatermark();
    if (watermark != null) {
        long timestamp = watermark.getTimestamp();
        String appid = watermark.getAppid();
        
        // Verify data is recent and from correct app
        long now = System.currentTimeMillis() / 1000;
        if (now - timestamp > 300) { // Data older than 5 minutes
            // Consider refreshing user data
        }
    }
    
} catch (WxErrorException e) {
    // Handle decryption errors
    logger.error("Failed to decrypt user info: {}", e.getMessage());
}

Verify User Data Integrity

// Verify user data hasn't been tampered with
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\"}";
String signature = "75e81ceda165f4ffa64f4068af58c64b8f54b88c";

try {
    boolean isValid = wxService.getUserService().checkUserInfo(sessionKey, rawData, signature);
    
    if (isValid) {
        // Data integrity verified - safe to use rawData
        ObjectMapper mapper = new ObjectMapper();
        JsonNode userJson = mapper.readTree(rawData);
        String nickname = userJson.get("nickName").asText();
    } else {
        // Data may have been tampered with
        logger.warn("User data signature verification failed");
    }
    
} catch (WxErrorException e) {
    logger.error("Error verifying user data: {}", e.getMessage());
}

Get Phone Number (New Method)

// New method for getting phone number (Base Library 2.21.2+)
// Client calls wx.getPhoneNumber() and provides code
String phoneCode = "e6fd60b3b24e4d24bb7c3b42e0b3b3b3";

try {
    WxMaPhoneNumberInfo phoneInfo = wxService.getUserService().getPhoneNumber(phoneCode);
    
    String fullPhoneNumber = phoneInfo.getPhoneNumber();     // +86138****1234
    String purePhoneNumber = phoneInfo.getPurePhoneNumber(); // 138****1234
    String countryCode = phoneInfo.getCountryCode();         // "86"
    
    // Verify data freshness
    WxMaPhoneNumberInfo.Watermark watermark = phoneInfo.getWatermark();
    if (watermark != null) {
        long timestamp = watermark.getTimestamp();
        String appid = watermark.getAppid();
    }
    
} catch (WxErrorException e) {
    int errorCode = e.getError().getErrorCode();
    if (errorCode == 40001) {
        // Invalid access token
    } else if (errorCode == 47001) {
        // Data decryption failed
    }
}

Get Phone Number (Legacy Method)

// Legacy method - decrypt phone number from encrypted data
String encryptedData = "Kf3TdPbzEmhWMuPKtlKxIWDkijhn...";
String iv = "r7BXXKkLb8qrSNn05n0qiA==";

try {
    @SuppressWarnings("deprecation")
    WxMaPhoneNumberInfo phoneInfo = wxService.getUserService().getPhoneNoInfo(
        sessionKey, encryptedData, iv
    );
    
    String phoneNumber = phoneInfo.getPhoneNumber();
    String purePhoneNumber = phoneInfo.getPurePhoneNumber();
    String countryCode = phoneInfo.getCountryCode();
    
} catch (WxErrorException e) {
    // Handle decryption errors
    logger.error("Phone number decryption failed: {}", e.getMessage());
}

Set User Storage (Mini Games)

// Store key-value data for user in mini games
Map<String, String> kvMap = new HashMap<>();
kvMap.put("level", "10");
kvMap.put("score", "95000");
kvMap.put("items", "sword,shield,potion");

try {
    wxService.getUserService().setUserStorage(kvMap, sessionKey, openid);
    
    // Data stored successfully
    // Can be retrieved by mini game client using wx.getStorageSync()
    
} catch (WxErrorException e) {
    // Handle storage errors
    int errorCode = e.getError().getErrorCode();
    if (errorCode == 47001) {
        // Invalid session key
    } else if (errorCode == 40003) {
        // Invalid openid
    }
}

Complete User Registration Example

@Service
public class UserService {
    
    @Autowired
    private WxMaService wxMaService;
    
    public UserRegistrationResult registerUser(String jsCode, String encryptedData, 
                                             String iv, String phoneCode) {
        try {
            // 1. Get session info
            WxMaJscode2SessionResult session = wxMaService.getUserService()
                .getSessionInfo(jsCode);
            
            String openid = session.getOpenid();
            String sessionKey = session.getSessionKey();
            String unionid = session.getUnionid();
            
            // 2. Decrypt user profile
            WxMaUserInfo userInfo = wxMaService.getUserService()
                .getUserInfo(sessionKey, encryptedData, iv);
            
            // 3. Get phone number 
            WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService()
                .getPhoneNumber(phoneCode);
            
            // 4. Create user record
            User user = new User();
            user.setOpenid(openid);
            user.setUnionid(unionid);
            user.setNickname(userInfo.getNickName());
            user.setAvatarUrl(userInfo.getAvatarUrl());
            user.setGender(userInfo.getGender());
            user.setCity(userInfo.getCity());
            user.setProvince(userInfo.getProvince());
            user.setCountry(userInfo.getCountry());
            user.setPhoneNumber(phoneInfo.getPurePhoneNumber());
            user.setCountryCode(phoneInfo.getCountryCode());
            user.setCreatedAt(new Date());
            
            // 5. Save to database
            userRepository.save(user);
            
            // 6. Generate JWT or session token
            String accessToken = jwtService.generateToken(user);
            
            return new UserRegistrationResult(user, accessToken);
            
        } catch (WxErrorException e) {
            throw new UserRegistrationException("Registration failed: " + e.getMessage(), e);
        }
    }
}

Error Handling Best Practices

public class WeChatUserException extends RuntimeException {
    private final int errorCode;
    
    public WeChatUserException(int errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }
    
    public int getErrorCode() { return errorCode; }
}

public WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String iv) {
    try {
        return wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
        
    } catch (WxErrorException e) {
        int code = e.getError().getErrorCode();
        String msg = e.getError().getErrorMsg();
        
        switch (code) {
            case 41003:
                throw new WeChatUserException(code, "Session key invalid or expired");
            case 47001: 
                throw new WeChatUserException(code, "Data decryption failed");
            case 40013:
                throw new WeChatUserException(code, "Invalid app ID");
            default:
                throw new WeChatUserException(code, "User info error: " + msg);
        }
    }
}

The user management service provides secure, comprehensive access to WeChat user data while handling encryption, verification, and data integrity automatically.

Install with Tessl CLI

npx tessl i tessl/maven-com-github-binarywang--weixin-java-miniapp

docs

analytics.md

cloud-development.md

configuration.md

core-services.md

development-tools.md

ecommerce.md

index.md

live-streaming.md

logistics.md

media-content.md

messaging.md

qr-codes.md

user-management.md

tile.json