oying-common/src/main/java/com/oying/utils/HttpRequest.java | ●●●●● patch | view | raw | blame | history | |
oying-common/src/main/java/com/oying/utils/RedisUtils.java | ●●●●● patch | view | raw | blame | history | |
oying-system/src/main/java/com/oying/modules/security/config/WeiXinProperties.java | ●●●●● patch | view | raw | blame | history | |
oying-system/src/main/java/com/oying/modules/security/service/WeiXinService.java | ●●●●● patch | view | raw | blame | history | |
oying-system/src/main/resources/config/application-dev.yml | ●●●●● patch | view | raw | blame | history | |
oying-system/src/main/resources/config/application-prod.yml | ●●●●● patch | view | raw | blame | history | |
pom.xml | ●●●●● patch | view | raw | blame | history |
oying-common/src/main/java/com/oying/utils/HttpRequest.java
New file @@ -0,0 +1,101 @@ package com.oying.utils; import com.alibaba.fastjson2.JSONObject; import com.oying.exception.BadRequestException; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import javax.net.ssl.SSLContext; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Map; /** * 功能描述: * * @author LIX * @date 创建时间 :2022/6/15 下午4:19 */ public class HttpRequest { /** * 读取请求数据流 * * @param request 请求数据 * @return String */ public static String getRequestBody(HttpServletRequest request) { StringBuilder sb = new StringBuilder(); try (ServletInputStream inputStream = request.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { throw new BadRequestException("读取数据流异常"); } return sb.toString(); } /** * 忽略ssl证书验证 * * @return HttpComponentsClientHttpRequestFactory */ public static HttpComponentsClientHttpRequestFactory getFactory() { HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); try { TrustStrategy acceptingTrustStrategy = (chain, authType) -> true; SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); HttpClientBuilder clientBuilder = HttpClients.custom(); CloseableHttpClient httpClient = clientBuilder.setSSLSocketFactory(socketFactory).build(); requestFactory.setHttpClient(httpClient); } catch (Exception e) { throw new BadRequestException("忽略ssl证书验证失败!!!"); } return requestFactory; } private static HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } /** * http返回String */ public static String exchangeString(HttpMethod httpMethod, String url, Map<String, Object> map) { HttpHeaders headers = getHeaders(); HttpEntity<Object> httpEntity = new HttpEntity<>(map, headers); RestTemplate restTemplate = new RestTemplate(); return restTemplate.exchange(url, httpMethod, httpEntity, String.class).getBody(); } /** * http返回JSONObject */ public static JSONObject exchangeJsonObject(HttpMethod httpMethod, String url, Map<String, Object> map) { HttpHeaders headers = getHeaders(); HttpEntity<Object> httpEntity = new HttpEntity<>(map, headers); RestTemplate restTemplate = new RestTemplate(); return restTemplate.exchange(url, httpMethod, httpEntity, JSONObject.class).getBody(); } } oying-common/src/main/java/com/oying/utils/RedisUtils.java
@@ -31,6 +31,16 @@ } /** * 判断key是否过期 * * @param key * @return */ public boolean isExpire(Object key) { return getExpire(key) > 1 ? false : true; } /** * 指定缓存失效时间 * * @param key 键 oying-system/src/main/java/com/oying/modules/security/config/WeiXinProperties.java
New file @@ -0,0 +1,31 @@ package com.oying.modules.security.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "wx") public class WeiXinProperties { // APPID private String appId; // APP密钥 private String appSecret; // 跳转小程序类型 private String miniProgramState; /*access_token的KEY*/ private String tokenKey; /*access_token的失效时间间隔,微信是2小时,此处隔7200秒就重新获取*/ private Long tokenTime; /*POST 获取稳定版接口调用凭据 获取小程序全局唯一后台接口调用凭据,token有效期为7200s,开发者需要进行妥善保存。*/ private String getStableAccessToken; /*GET 小程序登录 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程*/ private String code2Session; /*POST 获取手机号 该接口用于将code换取用户手机号。 说明,每个code只能使用一次,code的有效期为5min。*/ private String getPhoneNumber; /*POST 该接口用于发送订阅消息。*/ private String sendMessage; /* 是否生成环境*/ private boolean enabled; } oying-system/src/main/java/com/oying/modules/security/service/WeiXinService.java
New file @@ -0,0 +1,109 @@ package com.oying.modules.security.service; import com.alibaba.fastjson2.JSONObject; import com.oying.modules.security.config.WeiXinProperties; import com.oying.utils.HttpRequest; import com.oying.utils.RedisUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @Service @Slf4j public class WeiXinService { @Resource private WeiXinProperties weiXinProperties; @Resource private RedisUtils redisUtils; @Value("${wx.enabled}") private Boolean wxEnabled; /** * POST 获取稳定版接口调用凭据 获取小程序全局唯一后台接口调用凭据,token有效期为7200s,开发者需要进行妥善保存。 * * @return accessToken */ public String getStableAccessToken() { String accessToken; if (redisUtils.isExpire(weiXinProperties.getTokenKey())) { // 获取接口调用凭据 String url = weiXinProperties.getGetStableAccessToken(); Map<String, Object> map = new LinkedHashMap<>(); map.put("grant_type", "client_credential"); map.put("appid", weiXinProperties.getAppId()); map.put("secret", weiXinProperties.getAppSecret()); map.put("force_refresh", false); JSONObject jsonObject = HttpRequest.exchangeJsonObject(HttpMethod.POST, url, map); accessToken = jsonObject.getString("access_token"); redisUtils.set(weiXinProperties.getTokenKey(), accessToken, weiXinProperties.getTokenTime()); } else { // 查询接口调用凭据 accessToken = (String) redisUtils.get(weiXinProperties.getTokenKey()); } return accessToken; } /** * GET 小程序登录 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程 * * @param js_code 登录时获取的 code,可通过wx.login获取 * @return JSONObject */ public JSONObject code2Session(String js_code) { String url = weiXinProperties.getCode2Session(); url = url.replace("{appid}", weiXinProperties.getAppId()) .replace("{secret}", weiXinProperties.getAppSecret()) .replace("{js_code}", js_code); return HttpRequest.exchangeJsonObject(HttpMethod.GET, url, null); } /** * POST 获取手机号 该接口用于将code换取用户手机号。 说明,每个code只能使用一次,code的有效期为5min。 * * @param code 手机号获取凭证 * @return JSONObject */ public JSONObject getPhoneNumber(String code) { String url = weiXinProperties.getGetPhoneNumber(); url = url.replace("{accessToken}", getStableAccessToken()); Map<String, Object> map = new LinkedHashMap<>(); map.put("code", code); return HttpRequest.exchangeJsonObject(HttpMethod.POST, url, map); } /** * POST 该接口用于发送订阅消息。 * * @param data 请求参数 * @return JSONObject */ public JSONObject sendMessage(Map<String, Object> data, String openId, String templateId, String page) { if (wxEnabled) { String url = weiXinProperties.getSendMessage(); url = url.replace("{accessToken}", getStableAccessToken()); Map<String, Object> map = getSendMessageDto(data, openId, templateId, page); return HttpRequest.exchangeJsonObject(HttpMethod.POST, url, map); } JSONObject jsonObject = new JSONObject(); jsonObject.put("message", "测试环境"); return jsonObject; } private Map<String, Object> getSendMessageDto(Map<String, Object> data, String openId, String templateId, String page) { Map<String, Object> map = new HashMap<>(); map.put("touser", openId); map.put("template_id", templateId); map.put("page", page); map.put("miniprogram_state", weiXinProperties.getMiniProgramState()); map.put("lang", "zh_CN"); map.put("data", data); return map; } } oying-system/src/main/resources/config/application-dev.yml
@@ -116,3 +116,57 @@ # 文件大小 /M maxSize: 100 avatarMaxSize: 5 # 短信验证码key 时间 sms: key: lyhd-sms-key- time: 300 #微信配置 wx: # 测试环境 enabled: false # AppID app-id: wx2273296a5569cbad # AppSecret app-secret: 4526d72d885be322b17d0694cd6d03f1 # 跳转小程序类型 developer为开发版;trial为体验版;formal为正式版;默认为正式版 mini-program-state: trial # access_token的KEY token-key: wx_access_token # access_token的失效时间间隔,微信是2小时,此处隔7200秒就重新获取 token-time: 7200 # 微信URL调用 # POST 获取稳定版接口调用凭据 获取小程序全局唯一后台接口调用凭据,token有效期为7200s,开发者需要进行妥善保存。 get-stable-access-token: https://api.weixin.qq.com/cgi-bin/stable_token # GET 小程序登录 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程 code2-session: https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={js_code}&grant_type=authorization_code # POST 获取手机号 该接口用于将code换取用户手机号。 说明,每个code只能使用一次,code的有效期为5min。 get-phone-number: https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={accessToken} # POST 该接口用于发送订阅消息。 send-message: https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={accessToken} # 汇旺财 swift-pass: # 密钥1 key-1: qqqqqqqqqqqqqqqqqqqq # 私钥 mch-private-key: qqqqqqqqqqqq # 公钥 plat-public-key: qqqqq # 门店编号1 mch-id-1: 1111 # 签名方式 sign-type: MD5 # 原生JS is-raw: 1 # 是否小程序支付 is-minipg: 1 # AppID app-id: wx2273296a5569cbad # 请求url req-url: https://pay.hstypay.com/v2/pay/gateway # 支付通知地址 notify-url: https://localhost/lyhd/api/swiftPass/alipayCallback # 退款通知地址 refund-url: https://localhost/lyhd/api/swiftPass/returnNotify oying-system/src/main/resources/config/application-prod.yml
@@ -127,3 +127,56 @@ # 文件大小 /M maxSize: 100 avatarMaxSize: 5 # 短信验证码key 时间 sms: key: lyhd-sms-key- time: 300 #微信配置 wx: # 测试环境 enabled: false # AppID app-id: wx2273296a5569cbad # AppSecret app-secret: 4526d72d885be322b17d0694cd6d03f1 # 跳转小程序类型 developer为开发版;trial为体验版;formal为正式版;默认为正式版 mini-program-state: trial # access_token的KEY token-key: wx_access_token # access_token的失效时间间隔,微信是2小时,此处隔7200秒就重新获取 token-time: 7200 # 微信URL调用 # POST 获取稳定版接口调用凭据 获取小程序全局唯一后台接口调用凭据,token有效期为7200s,开发者需要进行妥善保存。 get-stable-access-token: https://api.weixin.qq.com/cgi-bin/stable_token # GET 小程序登录 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程 code2-session: https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={js_code}&grant_type=authorization_code # POST 获取手机号 该接口用于将code换取用户手机号。 说明,每个code只能使用一次,code的有效期为5min。 get-phone-number: https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={accessToken} # POST 该接口用于发送订阅消息。 send-message: https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={accessToken} # 汇旺财 swift-pass: # 密钥1 key-1: qqqqqqqqqqqqqqqqqqqq # 私钥 mch-private-key: qqqqqqqqqqqq # 公钥 plat-public-key: qqqqq # 门店编号1 mch-id-1: 1111 # 签名方式 sign-type: MD5 # 原生JS is-raw: 1 # 是否小程序支付 is-minipg: 1 # AppID app-id: wx2273296a5569cbad # 请求url req-url: https://pay.hstypay.com/v2/pay/gateway # 支付通知地址 notify-url: https://localhost/lyhd/api/swiftPass/alipayCallback # 退款通知地址 refund-url: https://localhost/lyhd/api/swiftPass/returnNotify pom.xml
@@ -210,6 +210,20 @@ <version>${fastjson2.version}</version> </dependency> <!-- 请求跳过ssl证书验证 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> </dependency> <!-- Java图形验证码 --> <dependency> <groupId>com.github.whvcse</groupId>