WxMiniProgramHttpClient.java 4.42 KB
package com.infoloop.tianting.service.client;

import com.infoloop.tianting.model.dto.WxUserDto.WxUserOpenIdDto;
import com.infoloop.tianting.model.dto.WxUserDto.WxUserPhoneResponseDto;
import com.infoloop.tianting.model.dto.WxUserDto.WxUserTokenDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static com.infoloop.tianting.constant.ConfigConstants.MINI_PROGRAM_APP_ID;
import static com.infoloop.tianting.constant.ConfigConstants.MINI_PROGRAM_APP_SECRET;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WxMiniProgramHttpClient {

    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={appSecret}";
    private static final String PHONE_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={accessToken}";

    private final RestTemplate restTemplate;

    @Value(MINI_PROGRAM_APP_ID)
    private String appId;

    @Value(MINI_PROGRAM_APP_SECRET)
    private String appSecret;

    public WxUserPhoneResponseDto getUserPhoneInfoByCode(String code) {
        try {
            String accessToken = fetchAccessToken();
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            Map<String, Object> jsonDataMap = new HashMap<>();
            jsonDataMap.put("code", code);
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(jsonDataMap, headers);
            return fetchPhoneNumber(accessToken, requestEntity);
        } catch (Exception e) {
            log.error("Error fetching user phone info", e);
            throw new IllegalArgumentException("获取用户手机号失败");
        }
    }

    private String fetchAccessToken() {
        log.info("Fetching WeChat access token...");
        ResponseEntity<WxUserTokenDto> tokenResponse = restTemplate.getForEntity(TOKEN_URL, WxUserTokenDto.class, appId, appSecret);
        if (!tokenResponse.getStatusCode().is2xxSuccessful() || tokenResponse.getBody() == null) {
            log.error("Failed to fetch access token: {}", tokenResponse);
            throw new IllegalArgumentException("获取 access_token 失败");
        }
        String accessToken = tokenResponse.getBody().getAccess_token();
        log.info("WeChat access token received: {}", accessToken);
        return accessToken;
    }

    private WxUserPhoneResponseDto fetchPhoneNumber(String accessToken, HttpEntity<Map<String, Object>> requestEntity) {
        log.info("Fetching phone number...");
        ResponseEntity<WxUserPhoneResponseDto> phoneResponse = restTemplate.exchange(PHONE_URL, HttpMethod.POST, requestEntity, WxUserPhoneResponseDto.class, accessToken);
        if (!phoneResponse.getStatusCode().is2xxSuccessful() || phoneResponse.getBody() == null) {
            log.error("Failed to fetch phone number: {}", phoneResponse);
            throw new IllegalArgumentException("获取手机号失败");
        }
        log.info("WeChat phone number response: {}", phoneResponse.getBody());
        return phoneResponse.getBody();
    }

    public WxUserOpenIdDto getUserOpenIdByCode(String code) {
        try {
            final var url = "https://api.weixin.qq.com/sns/jscode2session" +
                    "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
            HttpEntity<Void> requestEntity = new HttpEntity<>(headers);
            ResponseEntity<WxUserOpenIdDto> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, WxUserOpenIdDto.class);
            return response.getBody();
        } catch (Exception e) {
            log.error("Error fetching user openid", e);
            throw new IllegalArgumentException("获取用户openid失败");
        }
    }

}