流程:
- 前端请求后台接口,传入url
- 后端接收请求,处理业务逻辑,返回签名等参数
1.获取token
2.拿token获取ticket
3.获取随机字符串(用自带的UUID就行)
4.获取当前时间戳,记得除以1000(10位数) 例如:1626139722
5.拼接参数(url是前端传过来的)
1
| String context = "jsapi_ticket=xxxx&noncestr=xxxx×tamp=xxxx&url=xxxx"
|
6.参数SHA1加密
7.封装,返回前端
分步骤解析:
如果不想了解,直接去最下面Cope完整代码
获取token
appid、secret、grant_type这三个值都是固定值
前两个值是微信公众号开发者平台上的凭据,AppId 和 AppSecret
微信公众平台凭据调试工具:微信公众平台接口调试工具
appid:公众号的id
secret:公众号的秘钥
grant_type:授权码发放类型(固定值:client_credential
) grant_type=client_credential
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import com.google.gson.JsonObject; import com.google.gson.JsonParser;
private static JsonParser parse = new JsonParser();
public static String getToken() { String url = ACCESS_TOKEN_URL + "?grant_type=" + GRANT_TYPE + "&appid=" + APPID + "&secret=" + SECRET; String response = httpGetForJson(url); return ((JsonObject) parse.parse(response)).get(ACCESS_TOKEN_KEY).getAsString(); }
|
拿token获取ticket
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import com.google.gson.JsonObject; import com.google.gson.JsonParser; private static JsonParser parse = new JsonParser();
public static String getTicket(String token) { String url = TICKET_URL + "?access_token=" + token + "&type=" + TYPE; String response = httpGetForJson(url); return ((JsonObject) parse.parse(response)).get(TICKET_KEY).getAsString(); }
|
获取随机字符串
1 2
| import java.util.UUID; String nonceStr = UUID.randomUUID().toString();
|
获取当前时间戳
记得除以1000(10位数) 例如:1626139722
1
| String timestamp = Long.toString(System.currentTimeMillis() / 1000);
|
拼接参数,并加密
微信 JS 接口签名校验工具:【微信 JS 接口签名校验工具】
1 2 3 4
| String context = "jsapi_ticket=xxxx&noncestr=xxxx×tamp=xxxx&url=xxxx";
String signature = SHA1(context);
|
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
| import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;
public static String SHA1(final String value) { MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-1"); digest.update(value.getBytes()); byte messageDigest[] = digest.digest(); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; }
|
完整代码:
直接拿来用,前端传入url直接请求
返回类型自己封装个就行,不一定直接返回Map<String, String>
WxSignatureUtil
是自己封装的微信生成签名工具类
微信 JS 接口签名校验工具:【微信 JS 接口签名校验工具】
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
| import com.smart.wechat.config.WxSignatureUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @RestController @RequestMapping("/wx/config") public class WxConfigController { private final Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping("/gerWxConfig") public Map<String, String> gerWxConfig(@RequestBody Map<String,Object> params) { try { String url = String.valueOf(params.get("url")); Map<String, String> returnMap = WxSignatureUtil.getWechatSignature(url); return returnMap; } catch (Exception e) { return null; } } }
|
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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
| import com.google.gson.JsonObject; import com.google.gson.JsonParser; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; import java.util.UUID; @Component public class WxSignatureUtil {
private static fianl String APPID = "xxxxxxxx";
private static fianl String SECRET = "xxxxxxxx";
private static final String GRANT_TYPE = "client_credential";
private static final String TYPE = "jsapi";
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
private static final String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
private static final String ACCESS_TOKEN_KEY = "access_token";
private static final String TICKET_KEY = "ticket";
private static JsonParser parse = new JsonParser();
public static Map<String, String> getWechatSignature(String url) { String token = getToken(); String ticket = getTicket(token); String nonceStr = UUID.randomUUID().toString(); String timestamp = Long.toString(System.currentTimeMillis() / 1000); String context = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url; String signature = SHA1(context); Map<String, String> result = new HashMap<String, String>(); result.put("url", url); result.put("jsapi_ticket", ticket); result.put("nonceStr", nonceStr); result.put("timestamp", timestamp); result.put("signature", signature); result.put("appId", APPID); return result; }
public static String getToken() { String url = ACCESS_TOKEN_URL + "?grant_type=" + GRANT_TYPE + "&appid=" + APPID + "&secret=" + SECRET; String response = httpGetForJson(url); return ((JsonObject) parse.parse(response)).get(ACCESS_TOKEN_KEY).getAsString(); }
public static String getTicket(String token) { String url = TICKET_URL + "?access_token=" + token + "&type=" + TYPE; String response = httpGetForJson(url); return ((JsonObject) parse.parse(response)).get(TICKET_KEY).getAsString(); }
public static String SHA1(final String value) { MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-1"); digest.update(value.getBytes()); byte messageDigest[] = digest.digest(); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; }
public static String httpGetForJson(String url) { CloseableHttpClient httpclient = HttpClients.createDefault(); try { HttpGet httpget = new HttpGet(url); CloseableHttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); return entity == null ? "" : EntityUtils.toString(entity); } catch (Exception e) { e.printStackTrace(); } finally { try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return ""; } }
|
总结
需要前端多配合,校验工具不一定准确,仅供参考,避坑!!!
注意:还有一个前端的坑:微信公众平台
得先添加配置(JS接口安全域名
),微信扫一扫才能拉起来