Просмотр исходного кода

生成微信小程序码接口

ximinghao 3 месяцев назад
Родитель
Сommit
1dfa005972

+ 34 - 0
src/main/java/com/skyversation/xjcy/controller/OtherController.java

@@ -0,0 +1,34 @@
+package com.skyversation.xjcy.controller;
+
+import com.skyversation.xjcy.service.SerialNumberGenerator;
+import com.skyversation.xjcy.service.WeChatService;
+import com.skyversation.xjcy.util.MessageManage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+
+@Slf4j
+@Validated
+@RestController
+@RequestMapping()
+public class OtherController {
+
+    private final WeChatService weChatService;
+
+    public OtherController(WeChatService weChatService) {
+        this.weChatService = weChatService;
+    }
+
+    @RequestMapping(value = "/wxacode", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public ResponseEntity<byte[]> serialNumber(@RequestParam(required = false)String path,
+                                       @RequestParam(required = false)String scene) {
+        return weChatService.createWxacode(path, scene);
+    }
+}

+ 3 - 2
src/main/java/com/skyversation/xjcy/oauth/WxAuthServiceMock.java → src/main/java/com/skyversation/xjcy/mock/WxAuthServiceMock.java

@@ -1,9 +1,10 @@
-package com.skyversation.xjcy.oauth;
+package com.skyversation.xjcy.mock;
 
+import com.skyversation.xjcy.service.WeChatService;
 import org.springframework.stereotype.Service;
 
 @Service
-public class WxAuthServiceMock extends WxAuthService {
+public class WxAuthServiceMock extends WeChatService {
     @Override
     public Result wxLogin(String code) {
         return new Result(true,null,"abc1234567890defabc1234567890def","");

+ 5 - 4
src/main/java/com/skyversation/xjcy/oauth/AuthService.java

@@ -2,6 +2,7 @@ package com.skyversation.xjcy.oauth;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.skyversation.xjcy.service.WeChatService;
 import com.skyversation.xjcy.util.HttpUtil;
 import com.skyversation.xjcy.util.MessageManage;
 import lombok.Getter;
@@ -87,7 +88,7 @@ public class AuthService {
     // ============================ 实例变量 ============================
 
     /** 微信认证服务 */
-    private final WxAuthService wxAuthService;
+    private final WeChatService weChatService;
 
     private final PhoneService phoneService;
     /** 服务账户用户名 */
@@ -110,8 +111,8 @@ public class AuthService {
 
     // ============================ 构造方法 ============================
 
-    public AuthService(WxAuthService wxAuthService, PhoneService phoneService) {
-        this.wxAuthService = wxAuthService;
+    public AuthService(WeChatService weChatService, PhoneService phoneService) {
+        this.weChatService = weChatService;
         this.phoneService = phoneService;
     }
 
@@ -184,7 +185,7 @@ public class AuthService {
      * @return 完整的response.body
      */
     public String logOrRegWxAccount(String wxCode) {
-        WxAuthService.Result wxResult = wxAuthService.wxLogin(wxCode);
+        WeChatService.Result wxResult = weChatService.wxLogin(wxCode);
         if (wxResult.isSuccess()) {
             return logOrReg(generateAccount(wxResult.getWxOpenId(), WX_NAME_PREFIX, WX_PASSWORD_PREFIX, WX_SALT));
         } else {

+ 0 - 51
src/main/java/com/skyversation/xjcy/oauth/WxAuthService.java

@@ -1,51 +0,0 @@
-package com.skyversation.xjcy.oauth;
-
-import com.alibaba.fastjson.JSONObject;
-import com.skyversation.xjcy.util.HttpUtil;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-
-@SuppressWarnings("SpellCheckingInspection")
-@Service
-public class WxAuthService {
-    @Getter
-    @AllArgsConstructor
-    public static class Result {
-        private final boolean success;
-        private final String error;
-        private final String wxOpenId;
-        private final String wxSessionKey;
-    }
-    @Value("${app.wechat.secret-key}")
-    private String secretKey;
-    @Value("${app.wechat.appid}")
-    private String appid;
-    private static final String WX_AUTH_PATH = "https://api.weixin.qq.com/sns/jscode2session";
-
-    public Result wxLogin(String code) {
-        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
-        params.add("appid", appid);
-        params.add("secret", secretKey);
-        params.add("js_code", code);
-        params.add("grant_type", "authorization_code");
-        String body = HttpUtil.requestGet(WX_AUTH_PATH, params, null);
-        try {
-            JSONObject jsonObject = JSONObject.parseObject(body);
-            String openId = jsonObject.getString("openid");
-            String sessionKey = jsonObject.getString("session_key");
-            Integer errcode = jsonObject.getInteger("errcode");
-            if (errcode==null) {
-                return new Result(true,null,openId,sessionKey);
-            }else {
-                return new Result(false,errcode ==40029?"提供的code无效":"微信鉴权异常"+errcode,null,null);
-            }
-        } catch (NullPointerException e) {
-            return new Result(false,"无法访问wx鉴权接口",null,null);
-        }
-    }
-
-}

+ 124 - 0
src/main/java/com/skyversation/xjcy/service/WeChatService.java

@@ -0,0 +1,124 @@
+package com.skyversation.xjcy.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.skyversation.xjcy.util.HttpUtil;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.apache.http.Header;
+import org.htmlparser.http.HttpHeader;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+@SuppressWarnings("SpellCheckingInspection")
+@Service
+public class WeChatService {
+    @Getter
+    @AllArgsConstructor
+    public static class Result {
+        private final boolean success;
+        private final String error;
+        private final String wxOpenId;
+        private final String wxSessionKey;
+    }
+
+    @Value("${app.wechat.secret-key}")
+    private String secretKey;
+    @Value("${app.wechat.appid}")
+    private String appid;
+
+    private String accessToken;
+    private LocalDateTime accessTokenExpireTime;
+
+    private static final String WX_AUTH_PATH = "https://api.weixin.qq.com/sns/jscode2session";
+    private static final String WX_ACCESS_KEY_PATH = "https://api.weixin.qq.com/cgi-bin/token";
+    private static final String WX_ACODE_PATH = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
+
+    public Result wxLogin(String code) {
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
+        params.add("appid", appid);
+        params.add("secret", secretKey);
+        params.add("js_code", code);
+        params.add("grant_type", "authorization_code");
+        String body = HttpUtil.requestGet(WX_AUTH_PATH, params, null);
+        try {
+            JSONObject jsonObject = JSONObject.parseObject(body);
+            String openId = jsonObject.getString("openid");
+            String sessionKey = jsonObject.getString("session_key");
+            Integer errcode = jsonObject.getInteger("errcode");
+            if (errcode == null) {
+                return new Result(true, null, openId, sessionKey);
+            } else {
+                return new Result(false, errcode == 40029 ? "提供的code无效" : "微信鉴权异常" + errcode, null, null);
+            }
+        } catch (NullPointerException e) {
+            return new Result(false, "无法访问wx鉴权接口", null, null);
+        }
+    }
+
+    public ResponseEntity<byte[]> createWxacode(String path, String scene) {
+        Map<String, String> body = new HashMap<>();
+        body.put("page", path);
+        body.put("scene", scene);
+        ResponseEntity<byte[]> res = HttpUtil.requestPostWithJson(
+                WX_ACODE_PATH + getAccessToken(),
+                body,
+                null
+        );
+        HttpHeaders headers = new HttpHeaders();
+        copyHeader(headers, res.getHeaders(), HttpHeaders.CONTENT_TYPE);
+        copyHeader(headers, res.getHeaders(), HttpHeaders.CONTENT_LENGTH);
+
+        headers.add(HttpHeaders.CACHE_CONTROL,"public, max-age=3600");
+        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,"*");
+        return new ResponseEntity<>(res.getBody(), headers, res.getStatusCode());
+    }
+
+    private static void copyHeader(HttpHeaders copyTo, HttpHeaders orange, String header) {
+        List<String> list = orange.get(header);
+        if (list != null) {
+            for (String str : list) {
+                copyTo.add(header, str);
+            }
+        }
+
+    }
+
+    private String getAccessToken() {
+        if (accessTokenExpireTime == null || accessTokenExpireTime.isBefore(LocalDateTime.now())) {
+            refreshAccessToken();
+        }
+        if (accessToken == null || accessToken.isEmpty()) {
+            refreshAccessToken();
+        }
+        return accessToken;
+    }
+
+    private void refreshAccessToken() {
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
+        params.add("appid", appid);
+        params.add("secret", secretKey);
+        params.add("grant_type", "client_credential");
+        String body = HttpUtil.requestGet(WX_ACCESS_KEY_PATH, params, null);
+        try {
+            JSONObject jsonObject = JSONObject.parseObject(body);
+            String accessToken = jsonObject.getString("access_token");
+            int sessionKey = jsonObject.getInteger("expires_in");
+            this.accessToken = accessToken;
+            this.accessTokenExpireTime = LocalDateTime.now().plusSeconds(sessionKey);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

+ 54 - 18
src/main/java/com/skyversation/xjcy/util/HttpUtil.java

@@ -1,7 +1,6 @@
 package com.skyversation.xjcy.util;
 
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpGet;
@@ -16,7 +15,6 @@ import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 import org.springframework.http.client.SimpleClientHttpRequestFactory;
 import org.springframework.http.converter.StringHttpMessageConverter;
 import org.springframework.stereotype.Service;
-import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.util.UriComponentsBuilder;
@@ -38,11 +36,7 @@ public class HttpUtil {
 
 
     public static String requestPost(String url, MultiValueMap<String, Object> params, Map<String, String> headerMap) {
-        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
-        requestFactory.setConnectTimeout(10 * 1000);
-        requestFactory.setReadTimeout(10 * 1000);
-        RestTemplate client = new RestTemplate(requestFactory);
-        client.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+        RestTemplate client = getRestTemplate();
 
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.MULTIPART_FORM_DATA);
@@ -60,32 +54,76 @@ public class HttpUtil {
     }
 
     public static String requestGet(String url,
-                                                    MultiValueMap<String, String> params,
-                                                    Map<String, String> headerMap) {
+                                    MultiValueMap<String, String> params,
+                                    Map<String, String> headerMap) {
+
+        ResponseEntity<String> res = requestWithRes(url, params,null, headerMap, String.class, HttpMethod.GET);
+        return res.getBody();
+    }
+
+    public static <T> ResponseEntity<T> requestWithRes(String url,
+                                                       MultiValueMap<String, String> params,
+                                                       MultiValueMap<String, String> body,
+                                                       Map<String, String> headerMap,
+                                                       Class<T> clazz,
+                                                       HttpMethod method) {
+        RestTemplate client = getRestTemplate();
+
+        // 构建带参数的完整 URL
+        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
+        if (params != null) {
+            builder.queryParams(params);
+        }
+
+        // 构建 headers
+        HttpHeaders headers = new HttpHeaders();
+        if (headerMap != null) {
+            headerMap.forEach(headers::add);
+        }
+        HttpEntity<?> entity;
+        if (body != null) {
+            entity = new HttpEntity<>(body, headers);
+        }else {
+            entity = new HttpEntity<>(headers);
+        }
+        URI uri = URI.create(builder.toUriString());
+        return client.exchange(uri, method, entity, clazz);
+    }
+
+    private static RestTemplate getRestTemplate() {
         SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
         requestFactory.setConnectTimeout(10 * 1000);
         requestFactory.setReadTimeout(10 * 1000);
         RestTemplate client = new RestTemplate(requestFactory);
         client.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+        return client;
+    }
+
+    public static ResponseEntity<byte[]> requestPostWithJson(String url,
+                                                             Map<String, String> body,
+                                                             Map<String, String> headerMap){
+        RestTemplate client = getRestTemplate();
 
         // 构建带参数的完整 URL
         UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
-        if (params != null) {
-            builder.queryParams(params);
-        }
 
         // 构建 headers
         HttpHeaders headers = new HttpHeaders();
         if (headerMap != null) {
             headerMap.forEach(headers::add);
         }
-
-        HttpEntity<?> entity = new HttpEntity<>(headers);
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        HttpEntity<?> entity;
+        if (body != null) {
+            String json = JSON.toJSONString(body);
+             entity = new HttpEntity<>(json, headers);
+        }else {
+            entity = new HttpEntity<>(headers);
+        }
         URI uri = URI.create(builder.toUriString());
-        return client.exchange(uri, HttpMethod.GET, entity, String.class).getBody();
+        return client.exchange(uri, HttpMethod.POST, entity, byte[].class);
     }
 
-
     public static ResponseEntity<String> requestGetHttps(String url, MultiValueMap<String, String> params, Map<String, String> headerMap) {
         try {
             // 创建忽略 SSL 验证的 HttpClient
@@ -127,8 +165,6 @@ public class HttpUtil {
     }
 
 
-
-
     public static String sendGetRequest(String urlString) throws Exception {
         HttpClient httpClient = HttpClients.createDefault();
         HttpGet httpGet = new HttpGet(urlString);