| | |
| | | import com.sinata.appointment.config.WechatMiniAppProperties; |
| | | import com.sinata.appointment.constants.BizErrorCode; |
| | | import com.sinata.appointment.exception.BizException; |
| | | import java.util.Map; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | |
| | | "https://api.weixin.qq.com/cgi-bin/token"; |
| | | private static final String GET_USER_PHONE = |
| | | "https://api.weixin.qq.com/wxa/business/getuserphonenumber"; |
| | | private static final String SEND_SUBSCRIBE_MESSAGE = |
| | | "https://api.weixin.qq.com/cgi-bin/message/subscribe/send"; |
| | | |
| | | private final WechatMiniAppProperties props; |
| | | private final RestTemplate restTemplate; |
| | |
| | | } |
| | | } |
| | | |
| | | public void sendSubscribeMessage( |
| | | String openId, |
| | | String templateId, |
| | | String page, |
| | | Map<String, String> templateData) { |
| | | if (openId == null || openId.isBlank()) { |
| | | throw new BizException(BizErrorCode.MINI_WX_API_ERROR, "openId 不能为空"); |
| | | } |
| | | if (templateId == null || templateId.isBlank()) { |
| | | throw new BizException(BizErrorCode.MINI_WX_API_ERROR, "templateId 不能为空"); |
| | | } |
| | | if (templateData == null || templateData.isEmpty()) { |
| | | throw new BizException(BizErrorCode.MINI_WX_API_ERROR, "订阅消息参数不能为空"); |
| | | } |
| | | if (props.useStub()) { |
| | | log.info( |
| | | "Wechat mini stub: subscribe message openId={} templateId={} page={} data={}", |
| | | openId, |
| | | templateId, |
| | | page, |
| | | templateData); |
| | | return; |
| | | } |
| | | String token = getAccessToken(); |
| | | String url = |
| | | UriComponentsBuilder.fromHttpUrl(SEND_SUBSCRIBE_MESSAGE) |
| | | .queryParam("access_token", token) |
| | | .build() |
| | | .toUriString(); |
| | | try { |
| | | var root = objectMapper.createObjectNode(); |
| | | root.put("touser", openId); |
| | | root.put("template_id", templateId); |
| | | if (page != null && !page.isBlank()) { |
| | | root.put("page", page); |
| | | } |
| | | var dataNode = root.putObject("data"); |
| | | templateData.forEach( |
| | | (key, value) -> dataNode.putObject(key).put("value", value == null ? "" : value)); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.setContentType(MediaType.APPLICATION_JSON); |
| | | String body = |
| | | restTemplate.postForObject( |
| | | url, new HttpEntity<>(root.toString(), headers), String.class); |
| | | JsonNode response = objectMapper.readTree(body); |
| | | int err = response.path("errcode").asInt(-1); |
| | | if (err != 0) { |
| | | String msg = response.path("errmsg").asText("wx error"); |
| | | log.warn("sendSubscribeMessage errcode={} msg={}", err, msg); |
| | | throw new BizException(BizErrorCode.MINI_WX_API_ERROR, "发送订阅消息失败: " + msg); |
| | | } |
| | | } catch (BizException e) { |
| | | throw e; |
| | | } catch (Exception e) { |
| | | log.error("sendSubscribeMessage http error", e); |
| | | throw new BizException(BizErrorCode.MINI_WX_API_ERROR, "微信订阅消息接口异常"); |
| | | } |
| | | } |
| | | |
| | | private String getAccessToken() { |
| | | tokenLock.lock(); |
| | | try { |