xin
2025-05-30 347909bae241fff128b628ea6d12992d7e5b4b10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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 请求参数
     * @param openId 用户openId
     * @param templateId 订阅模板id
     * @param page 小程序跳转链接
     * @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;
    }
}