wujiefeng пре 9 месеци
родитељ
комит
45b7db706d
16 измењених фајлова са 716 додато и 57 уклоњено
  1. 19 0
      RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/AccessTokenVo.java
  2. 25 0
      RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/GenerateSchemeVo.java
  3. 25 0
      RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/MiniAppUserInfoVo.java
  4. 19 0
      RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/PhoneLoginParam.java
  5. 18 0
      RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/PhoneModel.java
  6. 43 0
      RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/WechatPhoneNumber.java
  7. 12 0
      RewardClient/src/main/java/com/zhongshu/reward/client/type/PlatformType.java
  8. 0 37
      RewardServer/src/main/java/com/zhongshu/reward/server/core/config/PaymentConfig.java
  9. 29 2
      RewardServer/src/main/java/com/zhongshu/reward/server/core/controller/wallet/WalletController.java
  10. 90 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/service/RedisService.java
  11. 18 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatCAuthConfig.java
  12. 194 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatCUtil.java
  13. 18 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatSAuthConfig.java
  14. 194 0
      RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatSUtil.java
  15. 3 17
      RewardServer/src/main/resources/application-dev.yml
  16. 9 1
      RewardServer/src/main/resources/application.yml

+ 19 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/AccessTokenVo.java

@@ -0,0 +1,19 @@
+package com.zhongshu.reward.client.model.wechat;
+
+import lombok.Data;
+
+/**
+ */
+@Data
+public class AccessTokenVo {
+
+    /**
+     * token
+     */
+    private String accessToken;
+
+    /**
+     * 有效时间,默认2小时
+     */
+    private Integer expiresIn;
+}

+ 25 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/GenerateSchemeVo.java

@@ -0,0 +1,25 @@
+package com.zhongshu.reward.client.model.wechat;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @Author: wy
+ * @Date: 2023/7/14 10:00
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class GenerateSchemeVo {
+
+    @Schema(description = "错误码")
+    private Integer errCode;
+
+    @Schema(description = "错误信息")
+    private String errMsg;
+
+    @Schema(description = "生成的小程序 scheme 码")
+    private String openLink;
+}

+ 25 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/MiniAppUserInfoVo.java

@@ -0,0 +1,25 @@
+package com.zhongshu.reward.client.model.wechat;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @Author: wy
+ * @Date: 2023/6/25 17:02
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class MiniAppUserInfoVo {
+
+    private String openid;
+
+    @JsonProperty("session_key")
+    private String sessionKey;
+
+    private String unionid;
+
+    private String msg;
+}

+ 19 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/PhoneLoginParam.java

@@ -0,0 +1,19 @@
+package com.zhongshu.reward.client.model.wechat;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2024/4/17
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PhoneLoginParam {
+    private String phoneNumber;
+    private String deviceType;
+    private String loginType;
+    String iv;
+}

+ 18 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/PhoneModel.java

@@ -0,0 +1,18 @@
+package com.zhongshu.reward.client.model.wechat;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2024/4/17
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class PhoneModel {
+    private String phone;
+}

+ 43 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/model/wechat/WechatPhoneNumber.java

@@ -0,0 +1,43 @@
+package com.zhongshu.reward.client.model.wechat;
+
+import lombok.Data;
+
+/**
+ *
+ */
+@Data
+public class WechatPhoneNumber {
+
+    /**
+     * 用户绑定的手机号(国外手机号会有区号)
+     */
+    private String phoneNumber;
+
+    /**
+     * 没有区号的手机号
+     */
+    private String purePhoneNumber;
+
+    /**
+     * 区号
+     */
+    private String countryCode;
+
+    /**
+     * 数据水印
+     */
+    private Watermark watermark;
+
+    @Data
+    static class Watermark {
+        /**
+         * 用户获取手机号操作的时间戳
+         */
+        private Integer timestamp;
+
+        /**
+         * 小程序appid
+         */
+        private String appid;
+    }
+}

+ 12 - 0
RewardClient/src/main/java/com/zhongshu/reward/client/type/PlatformType.java

@@ -0,0 +1,12 @@
+package com.zhongshu.reward.client.type;
+
+/**
+ * @author wjf
+ * @date 2024/8/13
+ */
+public enum PlatformType {
+
+    CLIENT,
+
+    SHOP
+}

+ 0 - 37
RewardServer/src/main/java/com/zhongshu/reward/server/core/config/PaymentConfig.java

@@ -1,37 +0,0 @@
-package com.zhongshu.reward.server.core.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-@Data
-@Component
-@ConfigurationProperties(prefix = "payment")
-public class PaymentConfig {
-
-    private String mer_no;
-
-    private String tid;
-
-    private String accesser_id;
-
-    private String key;
-
-    private String h5_page_url;
-
-    private String pc_page_url;
-
-    private String interface_url;
-
-    private String pay_key;
-
-    private String pay_url;
-
-    private String withdrawals_url;
-
-    private String withdrawals_key;
-
-    private String notifyUrl;
-
-
-}

+ 29 - 2
RewardServer/src/main/java/com/zhongshu/reward/server/core/controller/wallet/WalletController.java

@@ -4,13 +4,18 @@ import com.github.microservice.auth.security.annotations.ResourceAuth;
 import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.auth.security.type.AuthType;
 import com.zhongshu.reward.client.model.param.QueryTransferParam;
 import com.zhongshu.reward.client.model.param.QueryTransferParam;
 import com.zhongshu.reward.client.model.param.WalletTransferParam;
 import com.zhongshu.reward.client.model.param.WalletTransferParam;
-import com.zhongshu.reward.server.core.domain.WalletReceipts;
+import com.zhongshu.reward.client.model.wechat.MiniAppUserInfoVo;
+import com.zhongshu.reward.client.ret.ResultContent;
+import com.zhongshu.reward.client.type.PlatformType;
 import com.zhongshu.reward.server.core.service.WalletReceiptsService;
 import com.zhongshu.reward.server.core.service.WalletReceiptsService;
 import com.zhongshu.reward.server.core.service.WalletService;
 import com.zhongshu.reward.server.core.service.WalletService;
 import com.zhongshu.reward.server.core.service.WxTransferService;
 import com.zhongshu.reward.server.core.service.WxTransferService;
+import com.zhongshu.reward.server.core.util.wx.WechatCUtil;
+import com.zhongshu.reward.server.core.util.wx.WechatSUtil;
+import groovyjarjarpicocli.CommandLine;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
 import org.springframework.http.MediaType;
@@ -35,6 +40,12 @@ public class WalletController {
     @Autowired
     @Autowired
     WalletReceiptsService walletReceiptsService;
     WalletReceiptsService walletReceiptsService;
 
 
+    @Autowired
+    WechatCUtil wechatCUtil;
+
+    @Autowired
+    WechatSUtil wechatSUtil;
+
     @Operation(summary = "获取(开通)当前用户钱包信息", description = "获取(开通)当前用户钱包信息")
     @Operation(summary = "获取(开通)当前用户钱包信息", description = "获取(开通)当前用户钱包信息")
     @ResourceAuth(value = "user", type = AuthType.User)
     @ResourceAuth(value = "user", type = AuthType.User)
     @GetMapping ("getWallet")
     @GetMapping ("getWallet")
@@ -42,6 +53,22 @@ public class WalletController {
         return walletService.getWallet();
         return walletService.getWallet();
     }
     }
 
 
+    @SneakyThrows
+    @Operation(summary = "获取openid", description = "获取openid")
+//    @ResourceAuth(value = "user", type = AuthType.User)
+    @GetMapping ("getOpenId")
+    public Object getOpenId(@RequestParam("platformType") PlatformType platformType, @RequestParam("jscode") String jscode){
+
+        if (platformType.equals(PlatformType.CLIENT)){
+            MiniAppUserInfoVo miniAppUserInfo = wechatCUtil.getMiniAppUserInfo(jscode);
+            return ResultContent.buildContent(miniAppUserInfo.getOpenid());
+        }else if (platformType.equals(PlatformType.SHOP)){
+            MiniAppUserInfoVo miniAppUserInfo = wechatSUtil.getMiniAppUserInfo(jscode);
+            return ResultContent.buildContent(miniAppUserInfo.getOpenid());
+        }
+        return ResultContent.buildFail("没有此平台");
+    }
+
     @Operation(summary = "发起提现", description = "发起提现")
     @Operation(summary = "发起提现", description = "发起提现")
     @ResourceAuth(value = "user", type = AuthType.User)
     @ResourceAuth(value = "user", type = AuthType.User)
     @PostMapping (value = "transfer", consumes = MediaType.APPLICATION_JSON_VALUE)
     @PostMapping (value = "transfer", consumes = MediaType.APPLICATION_JSON_VALUE)

+ 90 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/service/RedisService.java

@@ -0,0 +1,90 @@
+package com.zhongshu.reward.server.core.service;
+
+import com.zhongshu.reward.client.ret.CommentException;
+import org.checkerframework.checker.units.qual.C;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.TimeUnit;
+
+
+@Service
+public class RedisService {
+
+    @Autowired
+    private StringRedisTemplate template;
+
+    public void addExpireToken(String loginName, String token, long tokenExpirePeriod) {
+        try {
+            String[] tokens = token.split("\\.");
+            //template.boundValueOps(tokenKey).set(loginName, 10000, TimeUnit.MILLISECONDS);
+            template.opsForValue().set(tokens[1], loginName, tokenExpirePeriod, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+    public void removeExpireToken(String loginName, String token) {
+        try {
+            String[] tokens = token.split("\\.");
+            //template.boundValueOps(tokenKey).set(loginName, 10000, TimeUnit.MILLISECONDS);
+            template.delete(tokens[1]);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+    public boolean verifyExpireJwtToken(String loginName, String jwtToken) {
+        try {
+            String[] tokens = jwtToken.split("\\.");
+            //template.boundValueOps(tokenKey).set(loginName, 10000, TimeUnit.MILLISECONDS);
+            return template.hasKey(tokens[1]);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+    public boolean verifyExpireCode(String code) {
+        try {
+            //template.boundValueOps(tokenKey).set(loginName, 10000, TimeUnit.MILLISECONDS);
+            return template.hasKey(code);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+
+    public void setValue(String key, String value, long expirePeriod) {
+        try {
+            template.opsForValue().set(key, value, expirePeriod, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+    public void setValueSecond(String key, String value, long expirePeriod) {
+        try {
+            template.opsForValue().set(key, value, expirePeriod, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+    public String getValue(String key) {
+        try {
+            return template.opsForValue().get(key);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+    public void removeValue(String key) {
+        try {
+            template.delete(key);
+        } catch (Exception e) {
+            throw new CommentException("系统故障,请联系服务商");
+        }
+    }
+
+}

+ 18 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatCAuthConfig.java

@@ -0,0 +1,18 @@
+package com.zhongshu.reward.server.core.util.wx;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * c端小程序的配置
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "cwechat")
+public class WechatCAuthConfig {
+
+    private String appid;
+
+    private String secret;
+}

+ 194 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatCUtil.java

@@ -0,0 +1,194 @@
+package com.zhongshu.reward.server.core.util.wx;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONUtil;
+import com.github.microservice.core.util.net.HttpClient;
+import com.github.microservice.core.util.net.apache.HttpClientUtil;
+import com.github.microservice.core.util.net.apache.HttpModel;
+import com.github.microservice.core.util.net.apache.MethodType;
+import com.github.microservice.core.util.net.apache.ResponseModel;
+import com.zhongshu.reward.client.model.wechat.AccessTokenVo;
+import com.zhongshu.reward.client.model.wechat.GenerateSchemeVo;
+import com.zhongshu.reward.client.model.wechat.MiniAppUserInfoVo;
+import com.zhongshu.reward.client.model.wechat.WechatPhoneNumber;
+import com.zhongshu.reward.client.ret.ResultContent;
+import com.zhongshu.reward.client.ret.ResultState;
+import com.zhongshu.reward.server.core.service.RedisService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ *
+ */
+@Component
+@Slf4j
+public class WechatCUtil {
+
+    private final static String ACCESS_TOKEN_KEY = "com:zswl:cloud:bdb:wechat:accessToken:";
+
+    private final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token?grant_type=client_credential&appid=%s&secret=%s";
+
+    private final static String WECHAT_MINI_APP_AUTH_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=%s";
+
+    private final static String PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";
+
+    private final static String GENERATE_SCHEME = "https://api.weixin.qq.com/wxa/generatescheme?access_token=%s";
+
+    private final static String UNLIMITED_QRCODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
+
+    @Resource
+    private WechatCAuthConfig wechatAuthConfig;
+
+    @Autowired
+    private RedisService redisService;
+
+    //    @PostConstruct
+    public void init() throws Exception {
+        log.info("init微信Token... ");
+        AccessTokenVo accessTokenVo = getAccess_token();
+        if (Objects.nonNull(accessTokenVo) && StringUtils.isNotEmpty(accessTokenVo.getAccessToken())) {
+            log.info("accessTokenVo: {}", accessTokenVo);
+            redisService.setValueSecond(ACCESS_TOKEN_KEY, accessTokenVo.getAccessToken(), 300);
+            log.info("微信登录初始化成功");
+        } else {
+            log.error("*******fail *********");
+            log.error("WechatUtil init fail");
+            log.error("*******fail *********");
+        }
+    }
+
+    public AccessTokenVo genAccessToken() throws Exception {
+        String url = String.format(ACCESS_TOKEN_URL, wechatAuthConfig.getAppid().trim(), wechatAuthConfig.getSecret().trim());
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().method(MethodType.Get).url(url).build());
+        if (200 == request.getCode()) {
+            return BeanUtil.copyProperties(request.getBody(), AccessTokenVo.class);
+        }
+        return null;
+    }
+
+    public synchronized AccessTokenVo getAccess_token() throws IOException {
+        String url = String.format(ACCESS_TOKEN_URL, wechatAuthConfig.getAppid(), wechatAuthConfig.getSecret());
+        Map<String, Object> map = new HashMap<>();
+        map.put("grant_type", "client_credential");
+        map.put("appid", wechatAuthConfig.getAppid().trim());
+        map.put("secret", wechatAuthConfig.getSecret().trim());
+        String json = JSONUtil.toJsonStr(map);
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder()
+                .url(url).method(MethodType.Post).body(json).build());
+        if (200 == request.getCode()) {
+            return BeanUtil.copyProperties(request.getBody(), AccessTokenVo.class);
+        }
+        return null;
+    }
+
+    public String getAccessToken() throws Exception {
+        String value = redisService.getValue(ACCESS_TOKEN_KEY);
+        if (Objects.isNull(value)) {
+            init();
+            value = redisService.getValue(ACCESS_TOKEN_KEY);
+        }
+        return value;
+    }
+
+    public WechatPhoneNumber getPhoneNumber(String code) throws Exception {
+        String url = String.format(PHONE_NUMBER_URL, getAccessToken());
+        Map<String, Object> map = new HashMap<>();
+        map.put("code", code);
+        String json = JSONUtil.toJsonStr(map);
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().method(MethodType.Post)
+                .url(url).body(json).build());
+        if (200 == request.getCode()) {
+            try {
+                LinkedHashMap map1 = (LinkedHashMap) request.getBody();
+                if (map1.containsKey("errcode")) {
+                    log.error("getPhoneNumber error: {} {} {}", map1.get("errcode"), map1.get("errmsg"), code);
+                    String errcode = map1.get("errcode").toString();
+                    if (errcode.equals("40001")) {
+                        clear();
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            WechatPhoneNumber wechatPhoneNumber = BeanUtil.copyProperties(((LinkedHashMap) request.getBody()).get("phone_info"), WechatPhoneNumber.class);
+            log.info("wechatPhoneNumber: {}", wechatPhoneNumber);
+            return wechatPhoneNumber;
+        }
+        return null;
+    }
+
+    public MiniAppUserInfoVo getMiniAppUserInfo(String jsCode) throws Exception {
+        String url = String.format(WECHAT_MINI_APP_AUTH_URL, "wx92ae04fb0f325887", "09c789bfa6d6b66362c0794468a4470a", jsCode, "authorization_code");
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().url(url).build());
+        if (200 == request.getCode()) {
+            MiniAppUserInfoVo miniAppUserInfoVo = BeanUtil.copyProperties(
+                    JSONUtil.parseObj(request.getBody().toString()),
+                    MiniAppUserInfoVo.class);
+            if (Objects.nonNull(miniAppUserInfoVo.getOpenid())) {
+                return miniAppUserInfoVo;
+            }
+        } else {
+            MiniAppUserInfoVo vo = new MiniAppUserInfoVo();
+            vo.setMsg(request.toString());
+            return vo;
+        }
+        return null;
+    }
+
+    public ResultContent generateScheme() throws Exception {
+        String accessToken = getAccessToken();
+        String url = String.format(GENERATE_SCHEME, accessToken);
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().method(MethodType.Post).url(url).build());
+        String msg = "";
+        if (200 == request.getCode()) {
+            LinkedHashMap body = (LinkedHashMap) request.getBody();
+            Integer errcode = (Integer) body.get("errcode");
+            msg = body.get("errmsg").toString();
+            String openlink = (String) body.get("openlink");
+            GenerateSchemeVo vo = new GenerateSchemeVo(errcode, msg, openlink);
+            if (Objects.nonNull(vo.getOpenLink()))
+                return ResultContent.buildContent(vo.getOpenLink());
+            msg = vo.getErrMsg();
+        }
+        return ResultContent.build(ResultState.Exception, msg);
+    }
+
+    /**
+     * 生成微信小程序 页面二维码
+     *
+     * @param scene
+     * @param page
+     * @return
+     * @throws Exception
+     */
+    public byte[] getUnlimitedQRCodeToByte(String scene, String page) throws Exception {
+        String url = String.format(UNLIMITED_QRCODE_URL, getAccessToken());
+        Map<String, String> header = new HashMap<>();
+        header.put("Content-Type", "image/jpeg");
+        Map<String, Object> map = new HashMap<>();
+        map.put("scene", scene);
+        if (StringUtils.isNotEmpty(page)) {
+            map.put("page", page);
+        }
+        map.put("env_version", "trial");
+        HttpClient.ResultBean resultBean = new HttpClient().ReadDocuments(url, true,
+                JSONUtil.toJsonStr(map).getBytes(), header);
+        if (200 == resultBean.getStat()) {
+            return resultBean.getData();
+        }
+        return null;
+    }
+
+    public void clear() {
+        redisService.removeValue(ACCESS_TOKEN_KEY);
+    }
+}

+ 18 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatSAuthConfig.java

@@ -0,0 +1,18 @@
+package com.zhongshu.reward.server.core.util.wx;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 商户端小程序的配置
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "swechat")
+public class WechatSAuthConfig {
+
+    private String appid;
+
+    private String secret;
+}

+ 194 - 0
RewardServer/src/main/java/com/zhongshu/reward/server/core/util/wx/WechatSUtil.java

@@ -0,0 +1,194 @@
+package com.zhongshu.reward.server.core.util.wx;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONUtil;
+import com.github.microservice.core.util.net.HttpClient;
+import com.github.microservice.core.util.net.apache.HttpClientUtil;
+import com.github.microservice.core.util.net.apache.HttpModel;
+import com.github.microservice.core.util.net.apache.MethodType;
+import com.github.microservice.core.util.net.apache.ResponseModel;
+import com.zhongshu.reward.client.model.wechat.AccessTokenVo;
+import com.zhongshu.reward.client.model.wechat.GenerateSchemeVo;
+import com.zhongshu.reward.client.model.wechat.MiniAppUserInfoVo;
+import com.zhongshu.reward.client.model.wechat.WechatPhoneNumber;
+import com.zhongshu.reward.client.ret.ResultContent;
+import com.zhongshu.reward.client.ret.ResultState;
+import com.zhongshu.reward.server.core.service.RedisService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ *
+ */
+@Component
+@Slf4j
+public class WechatSUtil {
+
+    private final static String ACCESS_TOKEN_KEY = "com:zswl:cloud:bdb:wechat:accessToken:";
+
+    private final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token?grant_type=client_credential&appid=%s&secret=%s";
+
+    private final static String WECHAT_MINI_APP_AUTH_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=%s";
+
+    private final static String PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";
+
+    private final static String GENERATE_SCHEME = "https://api.weixin.qq.com/wxa/generatescheme?access_token=%s";
+
+    private final static String UNLIMITED_QRCODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
+
+    @Resource
+    private WechatSAuthConfig wechatAuthConfig;
+
+    @Autowired
+    private RedisService redisService;
+
+    //    @PostConstruct
+    public void init() throws Exception {
+        log.info("init微信Token... ");
+        AccessTokenVo accessTokenVo = getAccess_token();
+        if (Objects.nonNull(accessTokenVo) && StringUtils.isNotEmpty(accessTokenVo.getAccessToken())) {
+            log.info("accessTokenVo: {}", accessTokenVo);
+            redisService.setValueSecond(ACCESS_TOKEN_KEY, accessTokenVo.getAccessToken(), 300);
+            log.info("微信登录初始化成功");
+        } else {
+            log.error("*******fail *********");
+            log.error("WechatUtil init fail");
+            log.error("*******fail *********");
+        }
+    }
+
+    public AccessTokenVo genAccessToken() throws Exception {
+        String url = String.format(ACCESS_TOKEN_URL, wechatAuthConfig.getAppid().trim(), wechatAuthConfig.getSecret().trim());
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().method(MethodType.Get).url(url).build());
+        if (200 == request.getCode()) {
+            return BeanUtil.copyProperties(request.getBody(), AccessTokenVo.class);
+        }
+        return null;
+    }
+
+    public synchronized AccessTokenVo getAccess_token() throws IOException {
+        String url = String.format(ACCESS_TOKEN_URL, wechatAuthConfig.getAppid(), wechatAuthConfig.getSecret());
+        Map<String, Object> map = new HashMap<>();
+        map.put("grant_type", "client_credential");
+        map.put("appid", wechatAuthConfig.getAppid().trim());
+        map.put("secret", wechatAuthConfig.getSecret().trim());
+        String json = JSONUtil.toJsonStr(map);
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder()
+                .url(url).method(MethodType.Post).body(json).build());
+        if (200 == request.getCode()) {
+            return BeanUtil.copyProperties(request.getBody(), AccessTokenVo.class);
+        }
+        return null;
+    }
+
+    public String getAccessToken() throws Exception {
+        String value = redisService.getValue(ACCESS_TOKEN_KEY);
+        if (Objects.isNull(value)) {
+            init();
+            value = redisService.getValue(ACCESS_TOKEN_KEY);
+        }
+        return value;
+    }
+
+    public WechatPhoneNumber getPhoneNumber(String code) throws Exception {
+        String url = String.format(PHONE_NUMBER_URL, getAccessToken());
+        Map<String, Object> map = new HashMap<>();
+        map.put("code", code);
+        String json = JSONUtil.toJsonStr(map);
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().method(MethodType.Post)
+                .url(url).body(json).build());
+        if (200 == request.getCode()) {
+            try {
+                LinkedHashMap map1 = (LinkedHashMap) request.getBody();
+                if (map1.containsKey("errcode")) {
+                    log.error("getPhoneNumber error: {} {} {}", map1.get("errcode"), map1.get("errmsg"), code);
+                    String errcode = map1.get("errcode").toString();
+                    if (errcode.equals("40001")) {
+                        clear();
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            WechatPhoneNumber wechatPhoneNumber = BeanUtil.copyProperties(((LinkedHashMap) request.getBody()).get("phone_info"), WechatPhoneNumber.class);
+            log.info("wechatPhoneNumber: {}", wechatPhoneNumber);
+            return wechatPhoneNumber;
+        }
+        return null;
+    }
+
+    public MiniAppUserInfoVo getMiniAppUserInfo(String jsCode) throws Exception {
+        String url = String.format(WECHAT_MINI_APP_AUTH_URL, "wx92ae04fb0f325887", "09c789bfa6d6b66362c0794468a4470a", jsCode, "authorization_code");
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().url(url).build());
+        if (200 == request.getCode()) {
+            MiniAppUserInfoVo miniAppUserInfoVo = BeanUtil.copyProperties(
+                    JSONUtil.parseObj(request.getBody().toString()),
+                    MiniAppUserInfoVo.class);
+            if (Objects.nonNull(miniAppUserInfoVo.getOpenid())) {
+                return miniAppUserInfoVo;
+            }
+        } else {
+            MiniAppUserInfoVo vo = new MiniAppUserInfoVo();
+            vo.setMsg(request.toString());
+            return vo;
+        }
+        return null;
+    }
+
+    public ResultContent generateScheme() throws Exception {
+        String accessToken = getAccessToken();
+        String url = String.format(GENERATE_SCHEME, accessToken);
+        ResponseModel request = HttpClientUtil.request(HttpModel.builder().method(MethodType.Post).url(url).build());
+        String msg = "";
+        if (200 == request.getCode()) {
+            LinkedHashMap body = (LinkedHashMap) request.getBody();
+            Integer errcode = (Integer) body.get("errcode");
+            msg = body.get("errmsg").toString();
+            String openlink = (String) body.get("openlink");
+            GenerateSchemeVo vo = new GenerateSchemeVo(errcode, msg, openlink);
+            if (Objects.nonNull(vo.getOpenLink()))
+                return ResultContent.buildContent(vo.getOpenLink());
+            msg = vo.getErrMsg();
+        }
+        return ResultContent.build(ResultState.Exception, msg);
+    }
+
+    /**
+     * 生成微信小程序 页面二维码
+     *
+     * @param scene
+     * @param page
+     * @return
+     * @throws Exception
+     */
+    public byte[] getUnlimitedQRCodeToByte(String scene, String page) throws Exception {
+        String url = String.format(UNLIMITED_QRCODE_URL, getAccessToken());
+        Map<String, String> header = new HashMap<>();
+        header.put("Content-Type", "image/jpeg");
+        Map<String, Object> map = new HashMap<>();
+        map.put("scene", scene);
+        if (StringUtils.isNotEmpty(page)) {
+            map.put("page", page);
+        }
+        map.put("env_version", "trial");
+        HttpClient.ResultBean resultBean = new HttpClient().ReadDocuments(url, true,
+                JSONUtil.toJsonStr(map).getBytes(), header);
+        if (200 == resultBean.getStat()) {
+            return resultBean.getData();
+        }
+        return null;
+    }
+
+    public void clear() {
+        redisService.removeValue(ACCESS_TOKEN_KEY);
+    }
+}

+ 3 - 17
RewardServer/src/main/resources/application-dev.yml

@@ -20,23 +20,9 @@ swagger:
       description: "用户访问令牌"
       description: "用户访问令牌"
       parameterType: "HEADER"
       parameterType: "HEADER"
 
 
-payment:
-  mer_no: 89852017372911Y
-  tid: PEYAH8X1
-  accesser_id: GZHYXHSH52011
-  key: udik876ehjde32dU61edsxsf
-  h5_page_url: https://selfapply-test.chinaums.com/self-sign-mobile/#/chooseRole
-  pc_page_url: https://selfapply-test.chinaums.com/self-sign-web/#/verify
-  interface_url: https://selfapply-test.chinaums.com/self-contract-nmrs/interface/autoReg
-#  interface_url: http://192.168.110.241:7300/mock/654babd538574f002773e5f8/dev/autoReg
-#  interface_url: https://yinshangpai.chinaums.com/self-contract-nmrs/interface/autoReg
-  pay_url: https://dhjt-uat.chinaums.com/queryService/UmsWebPayPlugins
-  pay_key: 11111111111111111111111111111111
-  withdrawals_url: https://dhjt.chinaums.com/entryService/unified-withdrawals-api
-  # 提现秘钥
-  withdrawals_key: 11111111111111111111111111111111
-  notifyUrl: https://api.dev.zonelife.cn/springbatchservice/pay/sync
-#  pay_url: https://dhjt-api.chinaums.com/queryService/UmsWebPayPlugins
+cwechat:
+  appid: wx3be1d6d84d46cdf7
+  secret: 4401df45d409cbf28560e87c4c21b4bf
 
 
 
 
 
 

+ 9 - 1
RewardServer/src/main/resources/application.yml

@@ -52,9 +52,17 @@ wechat:
   privateKey: apiclientkey/apiclient_key.pem
   privateKey: apiclientkey/apiclient_key.pem
   merchantSerialNumber: 4A635020A23CDE38953A74CEC5DE903596165236
   merchantSerialNumber: 4A635020A23CDE38953A74CEC5DE903596165236
   apiV3Key: ExrdXlCSbr9R61pU2iacmz0T5JxuLHhL
   apiV3Key: ExrdXlCSbr9R61pU2iacmz0T5JxuLHhL
-  appid: 1111
+#  appid: 1111
   transferSceneId: 1000
   transferSceneId: 1000
 
 
+cwechat:
+  appid: wx3be1d6d84d46cdf7
+  secret: 4401df45d409cbf28560e87c4c21b4bf
+
+swechat:
+  appid: wx023ad5ebbcbf0353
+  secret: 0d587023ea18ee00eff505f27a2aec22
+
 
 
 
 
 #????????
 #????????