瀏覽代碼

获取用户OpenId

haogh 1 年之前
父節點
當前提交
b229b53c94

+ 19 - 0
src/main/java/com/qmth/exam/reserve/config/WxProperty.java

@@ -0,0 +1,19 @@
+package com.qmth.exam.reserve.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Component
+public class WxProperty {
+
+    @Value("${wx.app_id}")
+    private String appId;
+
+    @Value("${wx.app_secret}")
+    private String appSecret;
+}

+ 32 - 7
src/main/java/com/qmth/exam/reserve/controller/student/StudentLoginController.java

@@ -1,21 +1,30 @@
 package com.qmth.exam.reserve.controller.student;
 package com.qmth.exam.reserve.controller.student;
 
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
 import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.boot.api.constant.ApiConstant;
+import com.qmth.boot.core.exception.StatusException;
+import com.qmth.exam.reserve.bean.Constants;
 import com.qmth.exam.reserve.bean.login.LoginReq;
 import com.qmth.exam.reserve.bean.login.LoginReq;
 import com.qmth.exam.reserve.bean.login.LoginUser;
 import com.qmth.exam.reserve.bean.login.LoginUser;
 import com.qmth.exam.reserve.bean.login.WechatLoginReq;
 import com.qmth.exam.reserve.bean.login.WechatLoginReq;
+import com.qmth.exam.reserve.config.WxProperty;
 import com.qmth.exam.reserve.controller.BaseController;
 import com.qmth.exam.reserve.controller.BaseController;
 import com.qmth.exam.reserve.service.AuthService;
 import com.qmth.exam.reserve.service.AuthService;
+import com.qmth.exam.reserve.weixin.OauthAccessTokenRequest;
+import com.qmth.exam.reserve.weixin.response.OauthAccessTokenResponseJson;
+
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import io.swagger.annotations.ApiParam;
 
 
 @RestController
 @RestController
 @Api(tags = "【考生端】考生登录相关接口")
 @Api(tags = "【考生端】考生登录相关接口")
@@ -28,6 +37,9 @@ public class StudentLoginController extends BaseController {
     @Autowired
     @Autowired
     private AuthService authService;
     private AuthService authService;
 
 
+    @Autowired
+    private WxProperty wxProperty;
+
     @ApiOperation(value = "考生登录(账号)")
     @ApiOperation(value = "考生登录(账号)")
     @PostMapping(value = "/login")
     @PostMapping(value = "/login")
     public LoginUser login(@RequestBody LoginReq req) {
     public LoginUser login(@RequestBody LoginReq req) {
@@ -47,4 +59,17 @@ public class StudentLoginController extends BaseController {
         authService.logout(curLoginStudent());
         authService.logout(curLoginStudent());
     }
     }
 
 
+    @ApiOperation(value = "获取用户的openid")
+    @PostMapping(value = "/login/get/openid")
+    public String getOpenid(@ApiParam("微信平台返回的用户code") @RequestParam String code) {
+        OauthAccessTokenRequest tokenRequest = new OauthAccessTokenRequest(code, wxProperty.getAppId(),
+                wxProperty.getAppSecret());
+        OauthAccessTokenResponseJson responseJson = tokenRequest.request();
+        if (responseJson.getErrcode() != 0) {
+            log.warn("openId获取失败:用户code:" + code);
+            throw new StatusException(Constants.SYSTEM_BUSY);
+        }
+        return responseJson.getOpenid();
+    }
+
 }
 }

+ 158 - 0
src/main/java/com/qmth/exam/reserve/weixin/AbstractRequest.java

@@ -0,0 +1,158 @@
+package com.qmth.exam.reserve.weixin;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.ParameterizedType;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.qmth.boot.core.exception.StatusException;
+import com.qmth.exam.reserve.util.JsonHelper;
+import com.qmth.exam.reserve.weixin.response.WxResponseJson;
+
+public abstract class AbstractRequest<T extends WxResponseJson, K, V> {
+
+    private static final Logger log = LoggerFactory.getLogger(AbstractRequest.class);
+
+    /**********************
+     * 返回的结果转换成的json串
+     */
+    protected T jsonEntity;
+
+    /**********************
+     * 所有业务处理完成之后返回的实体类
+     */
+    protected K returnEntity;
+
+    /**********************
+     * 请求的实体类
+     */
+    protected V requestEntity;
+
+    protected String method = "get";
+
+    /*************
+     * 请求次数
+     */
+    protected int requestTotal = 1;
+
+    public static int HttpConnectTimeoutSeconds = 30;
+
+    protected HttpURLConnection http = null;
+
+    /***************************
+     * 请求的地址
+     */
+    protected abstract String makeUrl();
+
+    /********************
+     * 完成请求后逻辑处理
+     */
+    @SuppressWarnings("unchecked")
+    public void processBusiness() {
+        this.returnEntity = (K) this.jsonEntity;
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public K request() {
+        Class<?> clazz = getGenericsClass(this.getClass());
+        String ul = this.makeUrl();
+        try {
+            URL url = new URL(ul);
+            http = (HttpURLConnection) url.openConnection();
+            // get还是post方式
+            http.setRequestMethod(this.method.equalsIgnoreCase("post") ? "POST" : "GET");
+            // 连接超时时间
+            http.setConnectTimeout(HttpConnectTimeoutSeconds * 1000);
+            // 读取数据超时时间
+            http.setReadTimeout(HttpConnectTimeoutSeconds * 1000);
+            // 允许输出
+            http.setDoOutput(true);
+            // 允许传入
+            http.setDoInput(true);
+            http.setRequestProperty("Connection", "Keep-Alive");
+            http.setRequestProperty("Charset", "UTF-8");
+        } catch (Exception e) {
+            throw new StatusException("HTTP无法连接,请检查URL地址[" + ul + "]");
+        }
+        this.httpRequest();
+        String message = receiveMessage();
+        if (StringUtils.isNotEmpty(message)) {
+            jsonEntity = (T) JsonHelper.toObj(message, clazz);
+        }
+        if (jsonEntity != null) {
+            if (jsonEntity.getErrcode() == 40001 || jsonEntity.getErrcode() == 40014 || jsonEntity.getErrcode() == 40029
+                    || jsonEntity.getErrcode() == 42001) {
+                if (this.requestTotal < 5) {
+                    this.requestTotal++;
+                    this.request();
+                } else {
+                    log.info("error_code:" + jsonEntity.getErrcode() + ";err_message:" + jsonEntity.getErrmsg()
+                            + ";weixin_json:" + jsonEntity.getWeixin_json());
+                    throw new StatusException("无法获取openId");
+                }
+            }
+            this.processBusiness();
+        }
+        return returnEntity;
+    }
+
+    public static Class<?> getGenericsClass(Class<?> clazz) {
+        ParameterizedType superClass = (ParameterizedType) clazz.getGenericSuperclass();
+        Class<?> target = (Class<?>) superClass.getActualTypeArguments()[0];
+        return target;
+    }
+
+    /********************************
+     * http发出请求,发送json串
+     */
+    protected void httpRequest() {
+        try {
+            http.connect();
+            http.setConnectTimeout(15000);
+            http.setReadTimeout(15000);
+        } catch (Exception e) {
+        }
+        if (this.requestEntity != null) {
+            try {
+                OutputStream os = http.getOutputStream();
+                os.write(JsonHelper.toJson(this.requestEntity).getBytes("UTF-8"));
+                os.flush();
+                os.close();
+            } catch (Exception e) {
+            }
+        }
+    }
+
+    protected String receiveMessage() {
+        String message = null;
+        try {
+            InputStream is = http.getInputStream();
+            byte[] bcache = new byte[2048];
+            int readSize = 0;// 每次读取的字节长度
+            ByteArrayOutputStream infoStream = new ByteArrayOutputStream();
+            while ((readSize = is.read(bcache)) > 0) {
+                infoStream.write(bcache, 0, readSize);
+            }
+            message = infoStream.toString("UTF-8");
+            is.close();
+        } catch (Exception e) {
+
+        } finally {
+            try {
+                http.disconnect();
+                http = null;
+            } catch (Exception e) {
+
+            }
+        }
+        return message;
+    }
+
+}

+ 29 - 0
src/main/java/com/qmth/exam/reserve/weixin/OauthAccessTokenRequest.java

@@ -0,0 +1,29 @@
+package com.qmth.exam.reserve.weixin;
+
+import com.qmth.exam.reserve.weixin.response.OauthAccessTokenResponseJson;
+
+public class OauthAccessTokenRequest
+        extends AbstractRequest<OauthAccessTokenResponseJson, OauthAccessTokenResponseJson, String> {
+
+    private final static String URL = " https://api.weixin.qq.com/sns/oauth2/access_token?";
+
+    private String code;
+
+    private String appId;
+
+    private String appSecret;
+
+    public OauthAccessTokenRequest(String code, String appId, String appSecret) {
+        this.code = code;
+        this.appId = appId;
+        this.appSecret = appSecret;
+    }
+
+    @Override
+    protected String makeUrl() {
+        String accessTokenUrl = URL + "appid=" + this.appId + "&secret=" + this.appSecret + "&code=" + this.code
+                + "&grant_type=authorization_code";
+        return accessTokenUrl;
+    }
+
+}

+ 26 - 0
src/main/java/com/qmth/exam/reserve/weixin/response/OauthAccessTokenResponseJson.java

@@ -0,0 +1,26 @@
+package com.qmth.exam.reserve.weixin.response;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class OauthAccessTokenResponseJson extends WxResponseJson {
+
+    @ApiModelProperty("网页授权接口调用凭证")
+    private String access_token;
+
+    @ApiModelProperty("access_token接口调用凭证超时时间")
+    private int expires_in;
+
+    @ApiModelProperty("用户刷新access_token")
+    private String refresh_token;
+
+    @ApiModelProperty("用户唯一标识")
+    private String openid;
+
+    @ApiModelProperty("用户授权的作用域")
+    private String scope;
+
+}

+ 19 - 0
src/main/java/com/qmth/exam/reserve/weixin/response/WxResponseJson.java

@@ -0,0 +1,19 @@
+package com.qmth.exam.reserve.weixin.response;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class WxResponseJson {
+
+    @ApiModelProperty("返回的错误代码")
+    private int errcode = 0;
+
+    @ApiModelProperty("错误消息")
+    private String errmsg;
+
+    @ApiModelProperty("微信返回的json字符串")
+    private String weixin_json;
+}

+ 6 - 0
src/main/resources/application.properties

@@ -48,3 +48,9 @@ com.qmth.logging.file-path=logs/exam-reserve.log
 com.qmth.auth.time-max-delay=10m
 com.qmth.auth.time-max-delay=10m
 com.qmth.auth.time-max-ahead=10m
 com.qmth.auth.time-max-ahead=10m
 
 
+#
+# ********** wx config **********
+#
+wx.app_id=wxb501ca68bdeb52df
+wx.app_secret=aca244f836a76bdfa498a26be93e30a1
+