he2802 4 سال پیش
والد
کامیت
deedfaccdd
17فایلهای تغییر یافته به همراه1440 افزوده شده و 8 حذف شده
  1. 79 0
      zhongzheng-api/src/main/java/com/zhongzheng/controller/user/UserSchoolInfoController.java
  2. 13 6
      zhongzheng-api/src/main/java/com/zhongzheng/controller/wx/WxPayController.java
  3. 265 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/utils/wxpay/WXPayReport.java
  4. 259 0
      zhongzheng-common/src/main/java/com/zhongzheng/common/utils/wxpay/WXPayRequest.java
  5. 12 2
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/WxLoginService.java
  6. 63 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/bo/UserSchoolInfoAddBo.java
  7. 80 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/bo/UserSchoolInfoEditBo.java
  8. 76 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/bo/UserSchoolInfoQueryBo.java
  9. 78 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/domain/UserSchoolInfo.java
  10. 15 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/mapper/UserSchoolInfoMapper.java
  11. 54 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/service/IUserSchoolInfoService.java
  12. 122 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/service/impl/UserSchoolInfoServiceImpl.java
  13. 76 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/user/vo/UserSchoolInfoVo.java
  14. 30 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/wx/service/IWxPayService.java
  15. 172 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/wx/service/impl/WxPayServiceImpl.java
  16. 19 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/wx/vo/WxPayVo.java
  17. 27 0
      zhongzheng-system/src/main/resources/mapper/modules/user/UserSchoolInfoMapper.xml

+ 79 - 0
zhongzheng-api/src/main/java/com/zhongzheng/controller/user/UserSchoolInfoController.java

@@ -0,0 +1,79 @@
+package com.zhongzheng.controller.user;
+
+import java.util.List;
+import java.util.Arrays;
+
+import com.zhongzheng.common.utils.ServletUtils;
+import com.zhongzheng.framework.web.service.WxTokenService;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoAddBo;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoEditBo;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoQueryBo;
+import com.zhongzheng.modules.user.entity.ClientLoginUser;
+import com.zhongzheng.modules.user.service.IUserBankRecordService;
+import com.zhongzheng.modules.user.service.IUserSchoolInfoService;
+import com.zhongzheng.modules.user.vo.UserSchoolInfoVo;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.zhongzheng.common.annotation.Log;
+import com.zhongzheng.common.core.controller.BaseController;
+import com.zhongzheng.common.core.domain.AjaxResult;
+import com.zhongzheng.common.enums.BusinessType;
+import com.zhongzheng.common.utils.poi.ExcelUtil;
+import com.zhongzheng.common.core.page.TableDataInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * 用户学校信息Controller
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+@Api(value = "用户学校信息控制器", tags = {"用户学校信息管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/school/info")
+public class UserSchoolInfoController extends BaseController {
+
+    private final IUserSchoolInfoService iUserSchoolInfoService;
+
+    private final WxTokenService wxTokenService;
+
+
+    /**
+     * 获取用户学校信息详细信息
+     */
+    @ApiOperation("获取用户学校信息详细信息")
+    @GetMapping("/getInfo")
+    public AjaxResult getInfo() {
+        ClientLoginUser loginUser = wxTokenService.getLoginUser(ServletUtils.getRequest());
+        return AjaxResult.success(iUserSchoolInfoService.queryByUserId(loginUser.getUser().getUserId()));
+    }
+
+
+
+    /**
+     * 修改用户学校信息
+     */
+    @ApiOperation("修改用户学校信息")
+    @Log(title = "用户学校信息", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    public AjaxResult<Void> edit(@RequestBody UserSchoolInfoEditBo bo) {
+        ClientLoginUser loginUser = wxTokenService.getLoginUser(ServletUtils.getRequest());
+        if(loginUser.getUser().getUserId()!=bo.getUserId()){
+            return AjaxResult.error("无权限修改");
+        }
+        return toAjax(iUserSchoolInfoService.updateByEditBo(bo) ? 1 : 0);
+    }
+
+
+}

+ 13 - 6
zhongzheng-api/src/main/java/com/zhongzheng/controller/wx/WxPayController.java

@@ -10,6 +10,7 @@ import com.zhongzheng.modules.user.entity.ClientLoginUser;
 import com.zhongzheng.modules.user.service.IUserService;
 import com.zhongzheng.modules.user.vo.UserVo;
 import com.zhongzheng.modules.wx.bo.WxLoginBody;
+import com.zhongzheng.modules.wx.service.IWxPayService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -33,6 +34,9 @@ public class WxPayController
     @Autowired
     private  IUserService iUserService;
 
+    @Autowired
+    private IWxPayService iWxPayService;
+
     /**
      * 支付方法
      *
@@ -41,13 +45,16 @@ public class WxPayController
      */
     @ApiOperation("获取支付凭证")
     @PostMapping("/payment")
-    public AjaxResult payment(@RequestBody WxLoginBody loginBody)
-    {
-        ClientLoginUser loginUser = wxTokenService.getLoginUser(ServletUtils.getRequest());
-        Map<String,String> map = wxLoginService.test_login();
-        return AjaxResult.success(map);
+    public AjaxResult payment(@RequestBody WxLoginBody loginBody) throws Exception {
+        iWxPayService.payment("34");
+        return AjaxResult.success();
     }
 
-
+    @ApiOperation("获取支付回调凭证")
+    @PostMapping("/callback")
+    public AjaxResult callback(@RequestBody WxLoginBody loginBody)
+    {
+        return AjaxResult.success();
+    }
 
 }

+ 265 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/wxpay/WXPayReport.java

@@ -0,0 +1,265 @@
+package com.zhongzheng.common.utils.wxpay;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.apache.http.util.EntityUtils;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * 交易保障
+ */
+public class WXPayReport {
+
+    public static class ReportInfo {
+
+        /**
+         * 布尔变量使用int。0为false, 1为true。
+         */
+
+        // 基本信息
+        private String version = "v1";
+        private String sdk = WXPayConstants.WXPAYSDK_VERSION;
+        private String uuid;  // 交易的标识
+        private long timestamp;   // 上报时的时间戳,单位秒
+        private long elapsedTimeMillis; // 耗时,单位 毫秒
+
+        // 针对主域名
+        private String firstDomain;  // 第1次请求的域名
+        private boolean primaryDomain; //是否主域名
+        private int firstConnectTimeoutMillis;  // 第1次请求设置的连接超时时间,单位 毫秒
+        private int firstReadTimeoutMillis;  // 第1次请求设置的读写超时时间,单位 毫秒
+        private int firstHasDnsError;  // 第1次请求是否出现dns问题
+        private int firstHasConnectTimeout; // 第1次请求是否出现连接超时
+        private int firstHasReadTimeout; // 第1次请求是否出现连接超时
+
+        public ReportInfo(String uuid, long timestamp, long elapsedTimeMillis, String firstDomain, boolean primaryDomain, int firstConnectTimeoutMillis, int firstReadTimeoutMillis, boolean firstHasDnsError, boolean firstHasConnectTimeout, boolean firstHasReadTimeout) {
+            this.uuid = uuid;
+            this.timestamp = timestamp;
+            this.elapsedTimeMillis = elapsedTimeMillis;
+            this.firstDomain = firstDomain;
+            this.primaryDomain = primaryDomain;
+            this.firstConnectTimeoutMillis = firstConnectTimeoutMillis;
+            this.firstReadTimeoutMillis = firstReadTimeoutMillis;
+            this.firstHasDnsError = firstHasDnsError?1:0;
+            this.firstHasConnectTimeout = firstHasConnectTimeout?1:0;
+            this.firstHasReadTimeout = firstHasReadTimeout?1:0;
+         }
+
+        @Override
+        public String toString() {
+            return "ReportInfo{" +
+                    "version='" + version + '\'' +
+                    ", sdk='" + sdk + '\'' +
+                    ", uuid='" + uuid + '\'' +
+                    ", timestamp=" + timestamp +
+                    ", elapsedTimeMillis=" + elapsedTimeMillis +
+                    ", firstDomain='" + firstDomain + '\'' +
+                    ", primaryDomain=" + primaryDomain +
+                    ", firstConnectTimeoutMillis=" + firstConnectTimeoutMillis +
+                    ", firstReadTimeoutMillis=" + firstReadTimeoutMillis +
+                    ", firstHasDnsError=" + firstHasDnsError +
+                    ", firstHasConnectTimeout=" + firstHasConnectTimeout +
+                    ", firstHasReadTimeout=" + firstHasReadTimeout +
+                    '}';
+        }
+
+        /**
+         * 转换成 csv 格式
+         *
+         * @return
+         */
+        public String toLineString(String key) {
+            String separator = ",";
+            Object[] objects = new Object[] {
+                version, sdk, uuid, timestamp, elapsedTimeMillis,
+                    firstDomain, primaryDomain, firstConnectTimeoutMillis, firstReadTimeoutMillis,
+                    firstHasDnsError, firstHasConnectTimeout, firstHasReadTimeout
+            };
+            StringBuffer sb = new StringBuffer();
+            for(Object obj: objects) {
+                sb.append(obj).append(separator);
+            }
+            try {
+                String sign = WXPayUtil.HMACSHA256(sb.toString(), key);
+                sb.append(sign);
+                return sb.toString();
+            }
+            catch (Exception ex) {
+                return null;
+            }
+
+        }
+
+    }
+
+    private static final String REPORT_URL = "http://report.mch.weixin.qq.com/wxpay/report/default";
+    // private static final String REPORT_URL = "http://127.0.0.1:5000/test";
+
+
+    private static final int DEFAULT_CONNECT_TIMEOUT_MS = 6*1000;
+    private static final int DEFAULT_READ_TIMEOUT_MS = 8*1000;
+
+    private LinkedBlockingQueue<String> reportMsgQueue = null;
+    private WXPayConfig config;
+    private ExecutorService executorService;
+
+    private volatile static WXPayReport INSTANCE;
+
+    private WXPayReport(final WXPayConfig config) {
+        this.config = config;
+        reportMsgQueue = new LinkedBlockingQueue<String>(config.getReportQueueMaxSize());
+
+        // 添加处理线程
+        executorService = Executors.newFixedThreadPool(config.getReportWorkerNum(), new ThreadFactory() {
+            public Thread newThread(Runnable r) {
+                Thread t = Executors.defaultThreadFactory().newThread(r);
+                t.setDaemon(true);
+                return t;
+            }
+        });
+
+        if (config.shouldAutoReport()) {
+            WXPayUtil.getLogger().info("report worker num: {}", config.getReportWorkerNum());
+            for (int i = 0; i < config.getReportWorkerNum(); ++i) {
+                executorService.execute(new Runnable() {
+                    public void run() {
+                        while (true) {
+                            // 先用 take 获取数据
+                            try {
+                                StringBuffer sb = new StringBuffer();
+                                String firstMsg = reportMsgQueue.take();
+                                WXPayUtil.getLogger().info("get first report msg: {}", firstMsg);
+                                String msg = null;
+                                sb.append(firstMsg); //会阻塞至有消息
+                                int remainNum = config.getReportBatchSize() - 1;
+                                for (int j=0; j<remainNum; ++j) {
+                                    WXPayUtil.getLogger().info("try get remain report msg");
+                                    // msg = reportMsgQueue.poll();  // 不阻塞了
+                                    msg = reportMsgQueue.take();
+                                    WXPayUtil.getLogger().info("get remain report msg: {}", msg);
+                                    if (msg == null) {
+                                        break;
+                                    }
+                                    else {
+                                        sb.append("\n");
+                                        sb.append(msg);
+                                    }
+                                }
+                                // 上报
+                                WXPayReport.httpRequest(sb.toString(), DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_READ_TIMEOUT_MS);
+                            }
+                            catch (Exception ex) {
+                                WXPayUtil.getLogger().warn("report fail. reason: {}", ex.getMessage());
+                            }
+                        }
+                    }
+                });
+            }
+        }
+
+    }
+
+    /**
+     * 单例,双重校验,请在 JDK 1.5及更高版本中使用
+     *
+     * @param config
+     * @return
+     */
+    public static WXPayReport getInstance(WXPayConfig config) {
+        if (INSTANCE == null) {
+            synchronized (WXPayReport.class) {
+                if (INSTANCE == null) {
+                    INSTANCE = new WXPayReport(config);
+                }
+            }
+        }
+        return INSTANCE;
+    }
+
+    public void report(String uuid, long elapsedTimeMillis,
+                       String firstDomain, boolean primaryDomain, int firstConnectTimeoutMillis, int firstReadTimeoutMillis,
+                       boolean firstHasDnsError, boolean firstHasConnectTimeout, boolean firstHasReadTimeout) {
+        long currentTimestamp = WXPayUtil.getCurrentTimestamp();
+        ReportInfo reportInfo = new ReportInfo(uuid, currentTimestamp, elapsedTimeMillis,
+                firstDomain, primaryDomain, firstConnectTimeoutMillis, firstReadTimeoutMillis,
+                firstHasDnsError, firstHasConnectTimeout, firstHasReadTimeout);
+        String data = reportInfo.toLineString(config.getKey());
+        WXPayUtil.getLogger().info("report {}", data);
+        if (data != null) {
+            reportMsgQueue.offer(data);
+        }
+    }
+
+
+    @Deprecated
+    private void reportSync(final String data) throws Exception {
+        httpRequest(data, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_READ_TIMEOUT_MS);
+    }
+
+    @Deprecated
+    private void reportAsync(final String data) throws Exception {
+        new Thread(new Runnable() {
+            public void run() {
+                try {
+                    httpRequest(data, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_READ_TIMEOUT_MS);
+                }
+                catch (Exception ex) {
+                    WXPayUtil.getLogger().warn("report fail. reason: {}", ex.getMessage());
+                }
+            }
+        }).start();
+    }
+
+    /**
+     * http 请求
+     * @param data
+     * @param connectTimeoutMs
+     * @param readTimeoutMs
+     * @return
+     * @throws Exception
+     */
+    private static String httpRequest(String data, int connectTimeoutMs, int readTimeoutMs) throws Exception{
+        BasicHttpClientConnectionManager connManager;
+        connManager = new BasicHttpClientConnectionManager(
+                RegistryBuilder.<ConnectionSocketFactory>create()
+                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
+                        .register("https", SSLConnectionSocketFactory.getSocketFactory())
+                        .build(),
+                null,
+                null,
+                null
+        );
+        HttpClient httpClient = HttpClientBuilder.create()
+                .setConnectionManager(connManager)
+                .build();
+
+        HttpPost httpPost = new HttpPost(REPORT_URL);
+
+        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
+        httpPost.setConfig(requestConfig);
+
+        StringEntity postEntity = new StringEntity(data, "UTF-8");
+        httpPost.addHeader("Content-Type", "text/xml");
+        httpPost.addHeader("User-Agent", WXPayConstants.USER_AGENT);
+        httpPost.setEntity(postEntity);
+
+        HttpResponse httpResponse = httpClient.execute(httpPost);
+        HttpEntity httpEntity = httpResponse.getEntity();
+        return EntityUtils.toString(httpEntity, "UTF-8");
+    }
+
+}

+ 259 - 0
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/wxpay/WXPayRequest.java

@@ -0,0 +1,259 @@
+package com.zhongzheng.common.utils.wxpay;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.DefaultHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.apache.http.util.EntityUtils;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import java.io.InputStream;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+
+import static com.zhongzheng.common.utils.wxpay.WXPayConstants.USER_AGENT;
+
+
+public class WXPayRequest {
+    private WXPayConfig config;
+    public WXPayRequest(WXPayConfig config) throws Exception{
+
+        this.config = config;
+    }
+
+    /**
+     * 请求,只请求一次,不做重试
+     * @param domain
+     * @param urlSuffix
+     * @param uuid
+     * @param data
+     * @param connectTimeoutMs
+     * @param readTimeoutMs
+     * @param useCert 是否使用证书,针对退款、撤销等操作
+     * @return
+     * @throws Exception
+     */
+    private String requestOnce(final String domain, String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws Exception {
+        BasicHttpClientConnectionManager connManager;
+        if (useCert) {
+            // 证书
+            char[] password = config.getMchID().toCharArray();
+            InputStream certStream = config.getCertStream();
+            KeyStore ks = KeyStore.getInstance("PKCS12");
+            ks.load(certStream, password);
+
+            // 实例化密钥库 & 初始化密钥工厂
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+            kmf.init(ks, password);
+
+            // 创建 SSLContext
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
+
+            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
+                    sslContext,
+                    new String[]{"TLSv1"},
+                    null,
+                    new DefaultHostnameVerifier());
+
+            connManager = new BasicHttpClientConnectionManager(
+                    RegistryBuilder.<ConnectionSocketFactory>create()
+                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
+                            .register("https", sslConnectionSocketFactory)
+                            .build(),
+                    null,
+                    null,
+                    null
+            );
+        }
+        else {
+            connManager = new BasicHttpClientConnectionManager(
+                    RegistryBuilder.<ConnectionSocketFactory>create()
+                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
+                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
+                            .build(),
+                    null,
+                    null,
+                    null
+            );
+        }
+
+        HttpClient httpClient = HttpClientBuilder.create()
+                .setConnectionManager(connManager)
+                .build();
+
+        String url = "https://" + domain + urlSuffix;
+        HttpPost httpPost = new HttpPost(url);
+
+        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
+        httpPost.setConfig(requestConfig);
+
+        StringEntity postEntity = new StringEntity(data, "UTF-8");
+        httpPost.addHeader("Content-Type", "text/xml");
+        httpPost.addHeader("User-Agent", USER_AGENT + " " + config.getMchID());
+        httpPost.setEntity(postEntity);
+
+        HttpResponse httpResponse = httpClient.execute(httpPost);
+        HttpEntity httpEntity = httpResponse.getEntity();
+        return EntityUtils.toString(httpEntity, "UTF-8");
+
+    }
+
+
+    private String request(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert, boolean autoReport) throws Exception {
+        Exception exception = null;
+        long elapsedTimeMillis = 0;
+        long startTimestampMs = WXPayUtil.getCurrentTimestampMs();
+        boolean firstHasDnsErr = false;
+        boolean firstHasConnectTimeout = false;
+        boolean firstHasReadTimeout = false;
+        IWXPayDomain.DomainInfo domainInfo = config.getWXPayDomain().getDomain(config);
+        if(domainInfo == null){
+            throw new Exception("WXPayConfig.getWXPayDomain().getDomain() is empty or null");
+        }
+        try {
+            String result = requestOnce(domainInfo.domain, urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, useCert);
+            elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs;
+            config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, null);
+            WXPayReport.getInstance(config).report(
+                    uuid,
+                    elapsedTimeMillis,
+                    domainInfo.domain,
+                    domainInfo.primaryDomain,
+                    connectTimeoutMs,
+                    readTimeoutMs,
+                    firstHasDnsErr,
+                    firstHasConnectTimeout,
+                    firstHasReadTimeout);
+            return result;
+        }
+        catch (UnknownHostException ex) {  // dns 解析错误,或域名不存在
+            exception = ex;
+            firstHasDnsErr = true;
+            elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs;
+            WXPayUtil.getLogger().warn("UnknownHostException for domainInfo {}", domainInfo);
+            WXPayReport.getInstance(config).report(
+                    uuid,
+                    elapsedTimeMillis,
+                    domainInfo.domain,
+                    domainInfo.primaryDomain,
+                    connectTimeoutMs,
+                    readTimeoutMs,
+                    firstHasDnsErr,
+                    firstHasConnectTimeout,
+                    firstHasReadTimeout
+            );
+        }
+        catch (ConnectTimeoutException ex) {
+            exception = ex;
+            firstHasConnectTimeout = true;
+            elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs;
+            WXPayUtil.getLogger().warn("connect timeout happened for domainInfo {}", domainInfo);
+            WXPayReport.getInstance(config).report(
+                    uuid,
+                    elapsedTimeMillis,
+                    domainInfo.domain,
+                    domainInfo.primaryDomain,
+                    connectTimeoutMs,
+                    readTimeoutMs,
+                    firstHasDnsErr,
+                    firstHasConnectTimeout,
+                    firstHasReadTimeout
+            );
+        }
+        catch (SocketTimeoutException ex) {
+            exception = ex;
+            firstHasReadTimeout = true;
+            elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs;
+            WXPayUtil.getLogger().warn("timeout happened for domainInfo {}", domainInfo);
+            WXPayReport.getInstance(config).report(
+                    uuid,
+                    elapsedTimeMillis,
+                    domainInfo.domain,
+                    domainInfo.primaryDomain,
+                    connectTimeoutMs,
+                    readTimeoutMs,
+                    firstHasDnsErr,
+                    firstHasConnectTimeout,
+                    firstHasReadTimeout);
+        }
+        catch (Exception ex) {
+            exception = ex;
+            elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs;
+            WXPayReport.getInstance(config).report(
+                    uuid,
+                    elapsedTimeMillis,
+                    domainInfo.domain,
+                    domainInfo.primaryDomain,
+                    connectTimeoutMs,
+                    readTimeoutMs,
+                    firstHasDnsErr,
+                    firstHasConnectTimeout,
+                    firstHasReadTimeout);
+        }
+        config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, exception);
+        throw exception;
+    }
+
+
+    /**
+     * 可重试的,非双向认证的请求
+     * @param urlSuffix
+     * @param uuid
+     * @param data
+     * @return
+     */
+    public String requestWithoutCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception {
+        return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), false, autoReport);
+    }
+
+    /**
+     * 可重试的,非双向认证的请求
+     * @param urlSuffix
+     * @param uuid
+     * @param data
+     * @param connectTimeoutMs
+     * @param readTimeoutMs
+     * @return
+     */
+    public String requestWithoutCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs,  boolean autoReport) throws Exception {
+        return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, false, autoReport);
+    }
+
+    /**
+     * 可重试的,双向认证的请求
+     * @param urlSuffix
+     * @param uuid
+     * @param data
+     * @return
+     */
+    public String requestWithCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception {
+        return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), true, autoReport);
+    }
+
+    /**
+     * 可重试的,双向认证的请求
+     * @param urlSuffix
+     * @param uuid
+     * @param data
+     * @param connectTimeoutMs
+     * @param readTimeoutMs
+     * @return
+     */
+    public String requestWithCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean autoReport) throws Exception {
+        return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, true, autoReport);
+    }
+}

+ 12 - 2
zhongzheng-framework/src/main/java/com/zhongzheng/framework/web/service/WxLoginService.java

@@ -12,8 +12,10 @@ import com.zhongzheng.common.utils.ip.IpUtils;
 import com.zhongzheng.modules.course.mapper.CourseSectionMapper;
 import com.zhongzheng.modules.user.bo.UserAddBo;
 import com.zhongzheng.modules.user.domain.User;
+import com.zhongzheng.modules.user.domain.UserSchoolInfo;
 import com.zhongzheng.modules.user.entity.ClientLoginUser;
 import com.zhongzheng.modules.user.mapper.UserMapper;
+import com.zhongzheng.modules.user.mapper.UserSchoolInfoMapper;
 import com.zhongzheng.modules.user.service.IUserService;
 import com.zhongzheng.modules.wx.bo.WxLoginBody;
 import org.apache.commons.codec.binary.Base64;
@@ -52,6 +54,9 @@ public class WxLoginService
     @Autowired
     private UserMapper userMapper;
 
+    @Autowired
+    private UserSchoolInfoMapper userSchoolInfoMapper;
+
     public Map<String,String> test_login() {
         String unionId = "oQ2yp56PgQ-PfwN4vxTZhR5eTpzk";
         User user = iUserService.queryByUnionId(unionId);
@@ -98,7 +103,7 @@ public class WxLoginService
      * @return
      */
     public Boolean register_small(String openId,String unionId,String tel) {
-        UserAddBo bo = new UserAddBo();
+        User bo = new User();
         bo.setOpenId(openId);
         bo.setUnionId(unionId);
         bo.setTelphone(tel);
@@ -113,7 +118,12 @@ public class WxLoginService
         bo.setAvatar("oss/images/avatar/20210623/1624414559368_44562477.png");
         bo.setLastLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
         bo.setLastLoginTime(DateUtils.getNowTime());
-        return iUserService.insertByAddBo(bo);
+        if(iUserService.save(bo)){
+            UserSchoolInfo schoolInfo = new UserSchoolInfo();
+            schoolInfo.setUserId(bo.getUserId());
+            userSchoolInfoMapper.insert(schoolInfo);
+        }
+        return true;
     }
 
     public User getWxUnionIdUser(WxLoginBody loginBody) {

+ 63 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/bo/UserSchoolInfoAddBo.java

@@ -0,0 +1,63 @@
+package com.zhongzheng.modules.user.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 用户学校信息添加对象 user_school_info
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+@Data
+@ApiModel("用户学校信息添加对象")
+public class UserSchoolInfoAddBo {
+    private Long userId;
+    /** 学校名 */
+    @ApiModelProperty("学校名")
+    private String schoolName;
+    /** 全日制 */
+    @ApiModelProperty("全日制")
+    private String fullTimeSchool;
+    /** 入学时间 */
+    @ApiModelProperty("入学时间")
+    private String admissionTime;
+    /** 毕业时间 */
+    @ApiModelProperty("毕业时间")
+    private String graduationTime;
+    /** 学历 */
+    @ApiModelProperty("学历")
+    private String education;
+    /** 学位 */
+    @ApiModelProperty("学位")
+    private String academicDegree;
+    /** 学制 */
+    @ApiModelProperty("学制")
+    private String educationalSystem;
+    /** 院系 */
+    @ApiModelProperty("院系")
+    private String department;
+    /** 专业 */
+    @ApiModelProperty("专业")
+    private String major;
+    /** 班级 */
+    @ApiModelProperty("班级")
+    private String grade;
+    /** 专业学信网学籍照片 */
+    @ApiModelProperty("专业学信网学籍照片")
+    private String studentStatusImg;
+    /** $column.columnComment */
+    @ApiModelProperty("$column.columnComment")
+    private Long createTime;
+    /** $column.columnComment */
+    @ApiModelProperty("$column.columnComment")
+    private Long updateTime;
+    /** 0 失效 1启用 */
+    @ApiModelProperty("0 失效 1启用")
+    private Integer status;
+}

+ 80 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/bo/UserSchoolInfoEditBo.java

@@ -0,0 +1,80 @@
+package com.zhongzheng.modules.user.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.util.Date;
+
+
+/**
+ * 用户学校信息编辑对象 user_school_info
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+@Data
+@ApiModel("用户学校信息编辑对象")
+public class UserSchoolInfoEditBo {
+
+
+    /** $column.columnComment */
+    @ApiModelProperty("$column.columnComment")
+    private Long userSchoolId;
+
+    /** 用户ID */
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    /** 学校名 */
+    @ApiModelProperty("学校名")
+    private String schoolName;
+
+    /** 全日制 */
+    @ApiModelProperty("全日制")
+    private String fullTimeSchool;
+
+    /** 入学时间 */
+    @ApiModelProperty("入学时间")
+    private String admissionTime;
+
+    /** 毕业时间 */
+    @ApiModelProperty("毕业时间")
+    private String graduationTime;
+
+    /** 学历 */
+    @ApiModelProperty("学历")
+    private String education;
+
+    /** 学位 */
+    @ApiModelProperty("学位")
+    private String academicDegree;
+
+    /** 学制 */
+    @ApiModelProperty("学制")
+    private String educationalSystem;
+
+    /** 院系 */
+    @ApiModelProperty("院系")
+    private String department;
+
+    /** 专业 */
+    @ApiModelProperty("专业")
+    private String major;
+
+    /** 班级 */
+    @ApiModelProperty("班级")
+    private String grade;
+
+    /** 专业学信网学籍照片 */
+    @ApiModelProperty("专业学信网学籍照片")
+    private String studentStatusImg;
+
+    /** $column.columnComment */
+    @ApiModelProperty("$column.columnComment")
+    private Long updateTime;
+
+    /** 0 失效 1启用 */
+    @ApiModelProperty("0 失效 1启用")
+    private Integer status;
+}

+ 76 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/bo/UserSchoolInfoQueryBo.java

@@ -0,0 +1,76 @@
+package com.zhongzheng.modules.user.bo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.zhongzheng.common.core.domain.BaseEntity;
+
+/**
+ * 用户学校信息分页查询对象 user_school_info
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("用户学校信息分页查询对象")
+public class UserSchoolInfoQueryBo extends BaseEntity {
+
+	/** 分页大小 */
+	@ApiModelProperty("分页大小")
+	private Integer pageSize;
+	/** 当前页数 */
+	@ApiModelProperty("当前页数")
+	private Integer pageNum;
+	/** 排序列 */
+	@ApiModelProperty("排序列")
+	private String orderByColumn;
+	/** 排序的方向desc或者asc */
+	@ApiModelProperty(value = "排序的方向", example = "asc,desc")
+	private String isAsc;
+
+
+	/** 学校名 */
+	@ApiModelProperty("学校名")
+	private String schoolName;
+	/** 全日制 */
+	@ApiModelProperty("全日制")
+	private String fullTimeSchool;
+	/** 入学时间 */
+	@ApiModelProperty("入学时间")
+	private String admissionTime;
+	/** 毕业时间 */
+	@ApiModelProperty("毕业时间")
+	private String graduationTime;
+	/** 学历 */
+	@ApiModelProperty("学历")
+	private String education;
+	/** 学位 */
+	@ApiModelProperty("学位")
+	private String academicDegree;
+	/** 学制 */
+	@ApiModelProperty("学制")
+	private String educationalSystem;
+	/** 院系 */
+	@ApiModelProperty("院系")
+	private String department;
+	/** 专业 */
+	@ApiModelProperty("专业")
+	private String major;
+	/** 班级 */
+	@ApiModelProperty("班级")
+	private String grade;
+	/** 专业学信网学籍照片 */
+	@ApiModelProperty("专业学信网学籍照片")
+	private String studentStatusImg;
+	/** 0 失效 1启用 */
+	@ApiModelProperty("0 失效 1启用")
+	private Integer status;
+
+}

+ 78 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/domain/UserSchoolInfo.java

@@ -0,0 +1,78 @@
+package com.zhongzheng.modules.user.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import java.io.Serializable;
+import java.util.Date;
+import java.math.BigDecimal;
+import com.zhongzheng.common.annotation.Excel;
+
+/**
+ * 用户学校信息对象 user_school_info
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("user_school_info")
+public class UserSchoolInfo implements Serializable {
+
+private static final long serialVersionUID=1L;
+
+
+    /** $column.columnComment */
+    @TableId(value = "user_school_id")
+    private Long userSchoolId;
+
+    /** 用户ID */
+    private Long userId;
+
+    /** 学校名 */
+    private String schoolName;
+
+    /** 全日制 */
+    private String fullTimeSchool;
+
+    /** 入学时间 */
+    private String admissionTime;
+
+    /** 毕业时间 */
+    private String graduationTime;
+
+    /** 学历 */
+    private String education;
+
+    /** 学位 */
+    private String academicDegree;
+
+    /** 学制 */
+    private String educationalSystem;
+
+    /** 院系 */
+    private String department;
+
+    /** 专业 */
+    private String major;
+
+    /** 班级 */
+    private String grade;
+
+    /** 专业学信网学籍照片 */
+    private String studentStatusImg;
+
+    /** $column.columnComment */
+    @TableField(fill = FieldFill.INSERT)
+    private Long createTime;
+
+    /** $column.columnComment */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateTime;
+
+    /** 0 失效 1启用 */
+    private Integer status;
+
+}

+ 15 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/mapper/UserSchoolInfoMapper.java

@@ -0,0 +1,15 @@
+package com.zhongzheng.modules.user.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.modules.user.domain.UserSchoolInfo;
+
+/**
+ * 用户学校信息Mapper接口
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+public interface UserSchoolInfoMapper extends BaseMapper<UserSchoolInfo> {
+
+}

+ 54 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/service/IUserSchoolInfoService.java

@@ -0,0 +1,54 @@
+package com.zhongzheng.modules.user.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoAddBo;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoEditBo;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoQueryBo;
+import com.zhongzheng.modules.user.domain.UserSchoolInfo;
+import com.zhongzheng.modules.user.vo.UserSchoolInfoVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 用户学校信息Service接口
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+public interface IUserSchoolInfoService extends IService<UserSchoolInfo> {
+	/**
+	 * 查询单个
+	 * @return
+	 */
+	UserSchoolInfoVo queryById(Long userSchoolId);
+
+	UserSchoolInfo queryByUserId(Long userId);
+
+	/**
+	 * 查询列表
+	 */
+	List<UserSchoolInfoVo> queryList(UserSchoolInfoQueryBo bo);
+
+	/**
+	 * 根据新增业务对象插入用户学校信息
+	 * @param bo 用户学校信息新增业务对象
+	 * @return
+	 */
+	Boolean insertByAddBo(UserSchoolInfoAddBo bo);
+
+	/**
+	 * 根据编辑业务对象修改用户学校信息
+	 * @param bo 用户学校信息编辑业务对象
+	 * @return
+	 */
+	Boolean updateByEditBo(UserSchoolInfoEditBo bo);
+
+	/**
+	 * 校验并删除数据
+	 * @param ids 主键集合
+	 * @param isValid 是否校验,true-删除前校验,false-不校验
+	 * @return
+	 */
+	Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 122 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/service/impl/UserSchoolInfoServiceImpl.java

@@ -0,0 +1,122 @@
+package com.zhongzheng.modules.user.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.StrUtil;
+import com.zhongzheng.common.exception.CustomException;
+import com.zhongzheng.common.utils.DateUtils;
+import com.zhongzheng.modules.course.domain.MajorCategory;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoAddBo;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoEditBo;
+import com.zhongzheng.modules.user.bo.UserSchoolInfoQueryBo;
+import com.zhongzheng.modules.user.domain.UserSchoolInfo;
+import com.zhongzheng.modules.user.mapper.UserSchoolInfoMapper;
+import com.zhongzheng.modules.user.service.IUserSchoolInfoService;
+import com.zhongzheng.modules.user.vo.UserSchoolInfoVo;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.pagehelper.Page;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 用户学校信息Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+@Service
+public class UserSchoolInfoServiceImpl extends ServiceImpl<UserSchoolInfoMapper, UserSchoolInfo> implements IUserSchoolInfoService {
+
+    @Override
+    public UserSchoolInfoVo queryById(Long userSchoolId){
+        UserSchoolInfo db = this.baseMapper.selectById(userSchoolId);
+        return BeanUtil.toBean(db, UserSchoolInfoVo.class);
+    }
+
+    @Override
+    public UserSchoolInfo queryByUserId(Long userId) {
+        UserSchoolInfo info = getOne(new LambdaQueryWrapper<UserSchoolInfo>()
+                .eq(UserSchoolInfo::getUserId,userId)
+                .last("limit 1"));
+        return info;
+    }
+
+    @Override
+    public List<UserSchoolInfoVo> queryList(UserSchoolInfoQueryBo bo) {
+        LambdaQueryWrapper<UserSchoolInfo> lqw = Wrappers.lambdaQuery();
+        lqw.like(StrUtil.isNotBlank(bo.getSchoolName()), UserSchoolInfo::getSchoolName, bo.getSchoolName());
+        lqw.eq(StrUtil.isNotBlank(bo.getFullTimeSchool()), UserSchoolInfo::getFullTimeSchool, bo.getFullTimeSchool());
+        lqw.eq(StrUtil.isNotBlank(bo.getAdmissionTime()), UserSchoolInfo::getAdmissionTime, bo.getAdmissionTime());
+        lqw.eq(StrUtil.isNotBlank(bo.getGraduationTime()), UserSchoolInfo::getGraduationTime, bo.getGraduationTime());
+        lqw.eq(StrUtil.isNotBlank(bo.getEducation()), UserSchoolInfo::getEducation, bo.getEducation());
+        lqw.eq(StrUtil.isNotBlank(bo.getAcademicDegree()), UserSchoolInfo::getAcademicDegree, bo.getAcademicDegree());
+        lqw.eq(StrUtil.isNotBlank(bo.getEducationalSystem()), UserSchoolInfo::getEducationalSystem, bo.getEducationalSystem());
+        lqw.eq(StrUtil.isNotBlank(bo.getDepartment()), UserSchoolInfo::getDepartment, bo.getDepartment());
+        lqw.eq(StrUtil.isNotBlank(bo.getMajor()), UserSchoolInfo::getMajor, bo.getMajor());
+        lqw.eq(StrUtil.isNotBlank(bo.getGrade()), UserSchoolInfo::getGrade, bo.getGrade());
+        lqw.eq(StrUtil.isNotBlank(bo.getStudentStatusImg()), UserSchoolInfo::getStudentStatusImg, bo.getStudentStatusImg());
+        lqw.eq(bo.getStatus() != null, UserSchoolInfo::getStatus, bo.getStatus());
+        return entity2Vo(this.list(lqw));
+    }
+
+    /**
+    * 实体类转化成视图对象
+    *
+    * @param collection 实体类集合
+    * @return
+    */
+    private List<UserSchoolInfoVo> entity2Vo(Collection<UserSchoolInfo> collection) {
+        List<UserSchoolInfoVo> voList = collection.stream()
+                .map(any -> BeanUtil.toBean(any, UserSchoolInfoVo.class))
+                .collect(Collectors.toList());
+        if (collection instanceof Page) {
+            Page<UserSchoolInfo> page = (Page<UserSchoolInfo>)collection;
+            Page<UserSchoolInfoVo> pageVo = new Page<>();
+            BeanUtil.copyProperties(page,pageVo);
+            pageVo.addAll(voList);
+            voList = pageVo;
+        }
+        return voList;
+    }
+
+    @Override
+    public Boolean insertByAddBo(UserSchoolInfoAddBo bo) {
+        UserSchoolInfo add = BeanUtil.toBean(bo, UserSchoolInfo.class);
+        validEntityBeforeSave(add);
+        add.setCreateTime(DateUtils.getNowTime());
+        add.setUpdateTime(DateUtils.getNowTime());
+        return this.save(add);
+    }
+
+    @Override
+    public Boolean updateByEditBo(UserSchoolInfoEditBo bo) {
+        UserSchoolInfo update = BeanUtil.toBean(bo, UserSchoolInfo.class);
+        validEntityBeforeSave(update);
+        update.setUpdateTime(DateUtils.getNowTime());
+        return this.updateById(update);
+    }
+
+    /**
+     * 保存前的数据校验
+     *
+     * @param entity 实体类数据
+     */
+    private void validEntityBeforeSave(UserSchoolInfo entity){
+        //TODO 做一些数据校验,如唯一约束
+
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return this.removeByIds(ids);
+    }
+}

+ 76 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/user/vo/UserSchoolInfoVo.java

@@ -0,0 +1,76 @@
+package com.zhongzheng.modules.user.vo;
+
+import com.zhongzheng.common.annotation.Excel;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+
+
+/**
+ * 用户学校信息视图对象 mall_package
+ *
+ * @author ruoyi
+ * @date 2021-06-24
+ */
+@Data
+@ApiModel("用户学校信息视图对象")
+public class UserSchoolInfoVo {
+	private static final long serialVersionUID = 1L;
+
+	/** $pkColumn.columnComment */
+	@ApiModelProperty("$pkColumn.columnComment")
+	private Long userSchoolId;
+
+	/** 学校名 */
+	@Excel(name = "学校名")
+	@ApiModelProperty("学校名")
+	private String schoolName;
+	/** 全日制 */
+	@Excel(name = "全日制")
+	@ApiModelProperty("全日制")
+	private String fullTimeSchool;
+	/** 入学时间 */
+	@Excel(name = "入学时间")
+	@ApiModelProperty("入学时间")
+	private String admissionTime;
+	/** 毕业时间 */
+	@Excel(name = "毕业时间")
+	@ApiModelProperty("毕业时间")
+	private String graduationTime;
+	/** 学历 */
+	@Excel(name = "学历")
+	@ApiModelProperty("学历")
+	private String education;
+	/** 学位 */
+	@Excel(name = "学位")
+	@ApiModelProperty("学位")
+	private String academicDegree;
+	/** 学制 */
+	@Excel(name = "学制")
+	@ApiModelProperty("学制")
+	private String educationalSystem;
+	/** 院系 */
+	@Excel(name = "院系")
+	@ApiModelProperty("院系")
+	private String department;
+	/** 专业 */
+	@Excel(name = "专业")
+	@ApiModelProperty("专业")
+	private String major;
+	/** 班级 */
+	@Excel(name = "班级")
+	@ApiModelProperty("班级")
+	private String grade;
+	/** 专业学信网学籍照片 */
+	@Excel(name = "专业学信网学籍照片")
+	@ApiModelProperty("专业学信网学籍照片")
+	private String studentStatusImg;
+	/** 0 失效 1启用 */
+	@Excel(name = "0 失效 1启用")
+	@ApiModelProperty("0 失效 1启用")
+	private Integer status;
+
+}

+ 30 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/wx/service/IWxPayService.java

@@ -0,0 +1,30 @@
+package com.zhongzheng.modules.wx.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.modules.polyv.bo.PolyvVideoAddBo;
+import com.zhongzheng.modules.polyv.bo.PolyvVideoEditBo;
+import com.zhongzheng.modules.polyv.bo.PolyvVideoQueryBo;
+import com.zhongzheng.modules.polyv.domain.PolyvVideo;
+import com.zhongzheng.modules.polyv.vo.PolyvVideoQuerVo;
+import com.zhongzheng.modules.polyv.vo.PolyvVideoVo;
+import com.zhongzheng.modules.wx.vo.WxPayVo;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 保利威视频信息Service接口
+ *
+ * @author ruoyi
+ * @date 2021-06-11
+ */
+public interface IWxPayService {
+	/**
+	 * 查询单个
+	 * @return
+	 */
+	WxPayVo payment(String polyvId) throws Exception;
+
+
+}

+ 172 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/wx/service/impl/WxPayServiceImpl.java

@@ -0,0 +1,172 @@
+package com.zhongzheng.modules.wx.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpStatus;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.pagehelper.Page;
+import com.zhongzheng.common.core.redis.RedisCache;
+import com.zhongzheng.common.utils.DateUtils;
+import com.zhongzheng.common.utils.SnowflakeIdUtils;
+import com.zhongzheng.common.utils.http.HttpUtils;
+import com.zhongzheng.common.utils.polyv.PolyvUtils;
+import com.zhongzheng.common.utils.wxpay.WXPayConfig;
+import com.zhongzheng.common.utils.wxpay.WXPayConstants;
+import com.zhongzheng.common.utils.wxpay.WXPayRequest;
+import com.zhongzheng.common.utils.wxpay.WXPayUtil;
+import com.zhongzheng.modules.polyv.bo.PolyvVideoAddBo;
+import com.zhongzheng.modules.polyv.bo.PolyvVideoEditBo;
+import com.zhongzheng.modules.polyv.bo.PolyvVideoQueryBo;
+import com.zhongzheng.modules.polyv.domain.PolyvVideDo;
+import com.zhongzheng.modules.polyv.domain.PolyvVideo;
+import com.zhongzheng.modules.polyv.domain.TokenResponse;
+import com.zhongzheng.modules.polyv.mapper.PolyvVideoMapper;
+import com.zhongzheng.modules.polyv.service.IPolyvVideoService;
+import com.zhongzheng.modules.polyv.vo.PolyvVideoQuerVo;
+import com.zhongzheng.modules.polyv.vo.PolyvVideoVo;
+import com.zhongzheng.modules.wx.service.IWxPayService;
+import com.zhongzheng.modules.wx.vo.WxPayVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import static com.squareup.okhttp.internal.Util.md5Hex;
+
+/**
+ * 保利威视频信息Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2021-06-11
+ */
+@Service
+public class WxPayServiceImpl  implements IWxPayService {
+
+    @Value("${wx.small.appid}")
+    private String appid;
+
+    @Value("${wx.wepay.mchid}")
+    private String mchid;
+
+    @Value("${wx.wepay.key}")
+    private String key;
+
+    @Value("${wx.wepay.appsecret}")
+    private String appsecret;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    private WXPayConstants.SignType signType;
+
+    private String notifyUrl = "https://api.xyyxt.net/wx/pay/callback";
+
+    private WXPayRequest wxPayRequest;
+
+    private boolean autoReport = false;
+
+
+    @Override
+    public WxPayVo payment(String polyvId) throws Exception {
+        Map<String, String> reqData = new HashMap<>();
+        this.signType = WXPayConstants.SignType.MD5;
+        reqData.put("attach", "pay");
+        reqData.put("body", "test goods");
+        reqData.put("notify_url", notifyUrl);
+        reqData.put("openid", "owcQx5LtC4XAvz8Q9AQHO1ttTDiA");
+        reqData.put("appid", appid);
+        reqData.put("mch_id", mchid);
+        reqData.put("nonce_str", WXPayUtil.generateNonceStr());
+        SnowflakeIdUtils idWorker = new SnowflakeIdUtils(3, 1);
+        String out_trade_no = String.valueOf(idWorker.nextId());
+        reqData.put("out_trade_no", out_trade_no);
+        reqData.put("total_fee", "1");
+        reqData.put("trade_type", "JSAPI");
+        if (WXPayConstants.SignType.MD5.equals(this.signType)) {
+            reqData.put("sign_type", WXPayConstants.MD5);
+        }
+        else if (WXPayConstants.SignType.HMACSHA256.equals(this.signType)) {
+            reqData.put("sign_type", WXPayConstants.HMACSHA256);
+        }
+        reqData.put("sign", WXPayUtil.generateSignature(reqData, key, this.signType));
+        String url = WXPayConstants.MICROPAY_URL_SUFFIX;
+        String respXml = this.requestWithoutCert(url, reqData, 6*1000, 8*1000);
+        this.processResponseXml(respXml);
+        return null;
+    }
+
+    /**
+     * 不需要证书的请求
+     * @param urlSuffix String
+     * @param reqData 向wxpay post的请求数据
+     * @param connectTimeoutMs 超时时间,单位是毫秒
+     * @param readTimeoutMs 超时时间,单位是毫秒
+     * @return API返回数据
+     * @throws Exception
+     */
+    public String requestWithoutCert(String urlSuffix, Map<String, String> reqData,
+                                     int connectTimeoutMs, int readTimeoutMs) throws Exception {
+        String msgUUID = reqData.get("nonce_str");
+        String reqBody = WXPayUtil.mapToXml(reqData);
+        String resp = this.wxPayRequest.requestWithoutCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, autoReport);
+        return resp;
+    }
+    /**
+     * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。
+     * @param xmlStr API返回的XML格式数据
+     * @return Map类型数据
+     * @throws Exception
+     */
+    public Map<String, String> processResponseXml(String xmlStr) throws Exception {
+        String RETURN_CODE = "return_code";
+        String return_code;
+        Map<String, String> respData = WXPayUtil.xmlToMap(xmlStr);
+        if (respData.containsKey(RETURN_CODE)) {
+            return_code = respData.get(RETURN_CODE);
+        }
+        else {
+            throw new Exception(String.format("No `return_code` in XML: %s", xmlStr));
+        }
+
+        if (return_code.equals(WXPayConstants.FAIL)) {
+            return respData;
+        }
+        else if (return_code.equals(WXPayConstants.SUCCESS)) {
+            if (this.isResponseSignatureValid(respData)) {
+                return respData;
+            }
+            else {
+                throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr));
+            }
+        }
+        else {
+            throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr));
+        }
+    }
+
+    /**
+     * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。
+     *
+     * @param reqData 向wxpay post的请求数据
+     * @return 签名是否有效
+     * @throws Exception
+     */
+    public boolean isResponseSignatureValid(Map<String, String> reqData) throws Exception {
+        // 返回数据的签名方式和请求中给定的签名方式是一致的
+        return WXPayUtil.isSignatureValid(reqData, key, this.signType);
+    }
+}

+ 19 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/wx/vo/WxPayVo.java

@@ -0,0 +1,19 @@
+package com.zhongzheng.modules.wx.vo;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+@Data
+@ApiModel("wxPay")
+public class WxPayVo {
+
+    String nonceStr;
+
+    String wxPackage;
+
+    String signType;
+
+    String paySign;
+
+    String timeStamp;
+}

+ 27 - 0
zhongzheng-system/src/main/resources/mapper/modules/user/UserSchoolInfoMapper.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhongzheng.modules.user.mapper.UserSchoolInfoMapper">
+
+    <resultMap type="com.zhongzheng.modules.user.domain.UserSchoolInfo" id="UserSchoolInfoResult">
+        <result property="userSchoolId" column="user_school_id"/>
+        <result property="userId" column="user_id"/>
+        <result property="schoolName" column="school_name"/>
+        <result property="fullTimeSchool" column="full_time_school"/>
+        <result property="admissionTime" column="admission_time"/>
+        <result property="graduationTime" column="graduation_time"/>
+        <result property="education" column="education"/>
+        <result property="academicDegree" column="academic_degree"/>
+        <result property="educationalSystem" column="educational_system"/>
+        <result property="department" column="department"/>
+        <result property="major" column="major"/>
+        <result property="grade" column="grade"/>
+        <result property="studentStatusImg" column="student_status_img"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="status" column="status"/>
+    </resultMap>
+
+
+</mapper>