|
|
@@ -0,0 +1,128 @@
|
|
|
+package com.zhongshu.card.server.core.service.wxQRCode;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.github.microservice.core.util.net.HttpClient;
|
|
|
+import com.github.microservice.core.util.net.apache.HttpClientUtil;
|
|
|
+import com.github.microservice.core.util.net.apache.HttpModel;
|
|
|
+import com.github.microservice.core.util.net.apache.MethodType;
|
|
|
+import com.github.microservice.core.util.net.apache.ResponseModel;
|
|
|
+import com.github.microservice.net.ResultContent;
|
|
|
+import com.github.microservice.net.ResultState;
|
|
|
+import com.zhongshu.card.client.model.pay.UnionApplySignParam;
|
|
|
+import com.zhongshu.card.client.model.projectAbout.ProjectWeChatInfoModel;
|
|
|
+import com.zhongshu.card.client.model.wechat.AccessTokenVo;
|
|
|
+import com.zhongshu.card.client.model.wechat.UnlimitedQRCodeParam;
|
|
|
+import com.zhongshu.card.server.core.controller.projectAbout.ProjectWeChatInfoController;
|
|
|
+import com.zhongshu.card.server.core.service.base.RedisService;
|
|
|
+import com.zhongshu.card.server.core.service.projectAbout.ProjectWeChatInfoService;
|
|
|
+import com.zhongshu.card.server.core.util.wx.WechatCUtil;
|
|
|
+import jakarta.servlet.http.HttpServletResponse;
|
|
|
+import lombok.Cleanup;
|
|
|
+import lombok.SneakyThrows;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class WeChatService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ WechatCUtil wechatCUtil;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ RedisService redisService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ ProjectWeChatInfoService projectWeChatInfoService;
|
|
|
+
|
|
|
+ private final static String ACCESS_TOKEN_KEY = "com:zswl:card:wechat:accessToken:";
|
|
|
+
|
|
|
+ private final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token?grant_type=client_credential&appid=%s&secret=%s";
|
|
|
+
|
|
|
+ private final static String UNLIMITED_QRCODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
|
|
|
+
|
|
|
+
|
|
|
+ @SneakyThrows
|
|
|
+ public void UnlimitedQRCode(UnlimitedQRCodeParam param, HttpServletResponse response) {
|
|
|
+
|
|
|
+ ResultContent<ProjectWeChatInfoModel> weChatInfoRet = projectWeChatInfoService.getProjectWeChatInfo(param.getProjectId());
|
|
|
+ if (!weChatInfoRet.getState().equals(ResultState.Success)){
|
|
|
+ throw new RuntimeException("项目未配置微信小程序");
|
|
|
+ }
|
|
|
+
|
|
|
+ ProjectWeChatInfoModel weChatInfoModel = weChatInfoRet.getContent();
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(weChatInfoModel.getAppId()) || StringUtils.isBlank(weChatInfoModel.getAppSecret())){
|
|
|
+ throw new RuntimeException("appId或者secret为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String accessToken = getAccessToken(weChatInfoModel.getAppId(), weChatInfoModel.getAppSecret());
|
|
|
+
|
|
|
+ byte[] unlimitedQRCodeToByte = getUnlimitedQRCodeToByte(param.getScene(), param.getPage(), accessToken);
|
|
|
+ response.addHeader("Content-Type","image/jpeg");
|
|
|
+ @Cleanup OutputStream outputStream = response.getOutputStream();
|
|
|
+ outputStream.write(unlimitedQRCodeToByte);
|
|
|
+ outputStream.flush();
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getAccessToken(String appId, String secret) throws Exception {
|
|
|
+ String value = redisService.getValue(ACCESS_TOKEN_KEY + appId + ":");
|
|
|
+ if (Objects.isNull(value)) {
|
|
|
+ AccessTokenVo accessTokenVo = getAccess_token(appId, secret);
|
|
|
+
|
|
|
+ value = accessTokenVo.getAccessToken();
|
|
|
+ Integer expiresIn = accessTokenVo.getExpiresIn();
|
|
|
+
|
|
|
+ redisService.setValueSecond(ACCESS_TOKEN_KEY, value, expiresIn);
|
|
|
+ }
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ private synchronized AccessTokenVo getAccess_token(String appId, String secret) throws IOException {
|
|
|
+ String url = String.format(ACCESS_TOKEN_URL, appId, secret);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("grant_type", "client_credential");
|
|
|
+ map.put("appid", appId.trim());
|
|
|
+ map.put("secret", secret.trim());
|
|
|
+ String json = JSONUtil.toJsonStr(map);
|
|
|
+ ResponseModel request = HttpClientUtil.request(HttpModel.builder()
|
|
|
+ .url(url).method(MethodType.Post).body(json).build());
|
|
|
+ if (200 == request.getCode()) {
|
|
|
+ return BeanUtil.copyProperties(request.getBody(), AccessTokenVo.class);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成微信小程序 页面二维码
|
|
|
+ *
|
|
|
+ * @param scene
|
|
|
+ * @param page
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public byte[] getUnlimitedQRCodeToByte(String scene, String page, String accessToken) throws Exception {
|
|
|
+ String url = String.format(UNLIMITED_QRCODE_URL, accessToken);
|
|
|
+ Map<String, String> header = new HashMap<>();
|
|
|
+ header.put("Content-Type", "image/jpeg");
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("scene", scene);
|
|
|
+ if (StringUtils.isNotEmpty(page)) {
|
|
|
+ map.put("page", page);
|
|
|
+ }
|
|
|
+ map.put("env_version", "trial");
|
|
|
+ HttpClient.ResultBean resultBean = new HttpClient().ReadDocuments(url, true,
|
|
|
+ JSONUtil.toJsonStr(map).getBytes(), header);
|
|
|
+ if (200 == resultBean.getStat()) {
|
|
|
+ return resultBean.getData();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+}
|