微信分享

xiaoxiao2021-02-28  17

1、首先需要去微信申请账号2、微信会分配appid和secret3、由于微信的接口需要获取token才行4、获取token的URL:get方式请求(https请求)https://api.weixin.qq.com/cgi-bin/token5、获取ticket的URL:get方式请求(https请求)

https://api.weixin.qq.com/cgi-bin/ticket/getticket

6、注意:要是本地测试的话把自己的IP配置到微信的公众平台的白名单里,否则取不到token

Controller层

import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.Map; @Slf4j @RestController @RequestMapping("wechat") @Api(tags = "微信分享") public class WeChatShareController { @Autowired private IWeChatShareService weChatShareService; @PostMapping("/share") @ApiOperation(value = "微信分享") public ControllerResponse share(HttpServletRequest request) { ControllerResponse controllerResponse = new ControllerResponse(); log.info("微信分享请求参数为:" + request.getParameter("url")); if (StringUtils.isBlank(request.getParameter("url"))) { controllerResponse.setStatus_code(Resp.FAIL.getCode()); controllerResponse.setMessage("请求参数为空"); return controllerResponse; } Map<String, String> map = weChatShareService.getSign(request.getParameter("url")); if (null == map) { controllerResponse.setStatus_code(Resp.FAIL.getCode()); controllerResponse.setMessage("获取token失败"); } else { controllerResponse.setBody(map); controllerResponse.setStatus_code(Resp.SUCCESS.getCode()); controllerResponse.setMessage(Resp.SUCCESS.getDesc()); } return controllerResponse; } }

Service层

import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @Service @Slf4j public class WeChatShareServiceImpl implements IWeChatShareService {     @Value("${wechat.appid}")     private String appid;     @Value("${wechat.secret}")     private String secret;     @Value("${wechat.token.url}")     private String tokenUrl;     @Value("${wechat.ticket.url}")     private String ticketUrl;     @Value("${wechat.grantType}")     private String grantType;     @Value("${wechat.type}")     private String type;     @Value("${wechat.time}")     private int time;     //创建一个读写锁     private static ReadWriteLock lock = new ReentrantReadWriteLock();     @Autowired     private RedisClient redisClient;     @Override     public TokenJson getAccessToken() {         String url = tokenUrl + "?grant_type=" + grantType + "&appid=" + appid + "&secret=" + secret;         log.info("微信服务器获取token请求报文为:" + url);         try {             String result = HttpRequesUtil.sendHttpRequest(true, url,null,"GET");             log.info("微信服务器获取token返回报文为:" + result);             Gson gson = new Gson();             TokenJson TokenJson = gson.fromJson(result, TokenJson.class);             return TokenJson;         } catch (Exception e) {             log.info("微信服务器获取token异常:" + e.getMessage());             return null;         }     }     @Override     public TicketJson getTicket(String token) {         String url = ticketUrl + "?access_token=" + token + "&type=" + type;         log.info("微信服务器获取Ticket请求报文为:" + url);         try {             String result = HttpRequesUtil.sendHttpRequest(true, url,null,"GET");             log.info("微信服务器获取Ticket返回报文:" + result);             Gson gson = new Gson();             TicketJson ticketJson = gson.fromJson(result, TicketJson.class);             return ticketJson;         } catch (Exception e) {             log.info("微信服务器获取Ticket异常:" + e.getMessage());             return null;         }     }     @Override     public Map<String, String> getSign(String url) {         Map<String, String> ret = null;         String token = getRedisToken();         if(StringUtils.isNotBlank(token)){             String ticket = getRedisTicket(token);             ret = SignUtil.sign(ticket, url);             log.info("微信分享计算出的签名为:" + ret.toString());             ret.put("appid",appid);         }         return ret;     }   //由于微信每天调用token的上限为2000次,所以采用放置缓存中   //这里用锁的原因是并发:若一个A请求获取token,此时token已失效,需重新获取,这时候token还未放置缓存中,同时B请求过来,发现//token也是失效的,也会重新获取,这时要是B获取的token放置缓存中覆盖A已获取到的token,A获取到的token会失效,导致A请求无法获取到有效的token     @Override     public String getRedisToken() {         String token = "";         try {             lock.readLock().lock();             log.info("----------Token获取读锁---------");             String key = ConstantKey.WECHAT_PREIX+ConstantKey.WECHAT_TOKEN;             token = redisClient.getStringValue(key);             if (StringUtils.isBlank(token)) {                 lock.readLock().unlock();//释放读锁,获取写锁                 log.info("----------Token释放读锁---------");                 try {                     lock.writeLock().lock();                     log.info("----------Token获取写锁---------");                     //获取写锁后再次判断对象是否为null,方式下一个等待的写线程进入后直接获取数据去                     if (StringUtils.isBlank(token)) {                         TokenJson tokenJson = getAccessToken();                         if (null != tokenJson && StringUtils.isNotBlank(tokenJson.getAccess_token())) {                             redisClient.putStringValue(key, tokenJson.getAccess_token(), tokenJson.getExpires_in()-time);                             token = tokenJson.getAccess_token();                         }                     }                     //自身锁降级为读锁                     lock.readLock().lock();                     log.info("----------Token自身锁降级为读锁---------");                 } catch (Exception e) {                     log.info("获取微信Token异常:" + e.getMessage());                 } finally {                     lock.writeLock().unlock();//释放写锁                     log.info("----finally------Token释放写锁---------");                 }             }         } catch (Exception e) {             log.info("获取微信Token异常:" + e.getMessage());         } finally {             lock.readLock().unlock();             log.info("----finally------Token释放读锁---------");         }         return token;     }     @Override     public String getRedisTicket(String token) {         String ticket = "";         try {             lock.readLock().lock();             log.info("----------Ticket获取读锁---------");             String key = ConstantKey.WECHAT_PREIX+ConstantKey.WECHAT_TICKET+token;             ticket = redisClient.getStringValue(key);             if (StringUtils.isBlank(ticket)) {                 lock.readLock().unlock();//释放读锁,获取写锁                 log.info("----------Ticket释放读锁---------");                 try {                     lock.writeLock().lock();                     log.info("----------Ticket获取写锁---------");                     //获取写锁后再次判断对象是否为空,方式下一个等待的写线程进入后直接获取数据去                     if (StringUtils.isBlank(ticket)) {                         TicketJson ticketJson = getTicket(token);                         if (null != ticketJson  && StringUtils.isNotBlank(ticketJson.getTicket())) {                             redisClient.putStringValue(key, ticketJson.getTicket(), Integer.valueOf(ticketJson.getExpires_in())-time);                             ticket = ticketJson.getTicket();                         }                     }                     //自身锁降级为读锁                     lock.readLock().lock();                     log.info("----------Ticket自身锁降级为读锁---------");                 } catch (Exception e) {                     log.info("获取微信ticket异常:" + e.getMessage());                 } finally {                     lock.writeLock().unlock();//释放写锁                     log.info("---finally-------Ticket释放写锁---------");                 }             }         } catch (Exception e) {             log.info("获取微信ticket异常:" + e.getMessage());         } finally {             lock.readLock().unlock();             log.info("---finally-------Ticket释放读锁---------");         }         return ticket;     } } 微信分享签名工具类 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.UUID; import java.util.Map; import java.util.HashMap; import java.util.Formatter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.io.UnsupportedEncodingException; /** * 微信分享签名工具类 */ public class SignUtil { private static Logger logger = LoggerFactory.getLogger(SignUtil.class); /** * 生成签名方法 * @param jsapi_ticket * @param url 分享的url * @return map */ public static Map<String, String> sign(String jsapi_ticket, String url) { Map<String, String> ret = new HashMap<String, String>(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String string1; String signature = ""; //注意这里参数名必须全部小写,且必须有序 string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; logger.info("签名参数:" + string1); try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(string1.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret.put("url", url); ret.put("jsapi_ticket", jsapi_ticket); ret.put("nonceStr", nonce_str); ret.put("timestamp", timestamp); ret.put("signature", signature); return ret; } private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("x", b); } String result = formatter.toString(); formatter.close(); return result; } private static String create_nonce_str() { return UUID.randomUUID().toString(); } private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); } }

http请求或https请求工具类 import org.apache.commons.lang3.StringUtils; import javax.net.ssl.*; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; public class HttpRequesUtil { /** * http请求或https请求 * * @param isSsl * @param url 请求地址 必传 * @param param 请求参数 可以为空 * @param requestMethod 请求方式:GET or POST 必传 * @return 返回请求报文 * @throws Exception */ public static String sendHttpRequest(boolean isSsl, String url, String param, String requestMethod) throws Exception { int timeOut = 60000; PrintWriter out = null; BufferedReader in = null; URL targetUrl = null; StringBuffer result = new StringBuffer(); try { if (isSsl) { // 信任所有证书 targetUrl = new URL(url); ignoreSsl(); } else { targetUrl = new URL(url); } // 打开和URL之间的连接 HttpURLConnection httpConnection = (HttpURLConnection) targetUrl.openConnection(); // 设置超时 httpConnection.setConnectTimeout(timeOut); httpConnection.setReadTimeout(timeOut); // 设置通用的请求属性 httpConnection.setRequestProperty("connection", "Keep-Alive"); httpConnection.setRequestProperty("Charset", "UTF-8"); httpConnection.setRequestProperty("Content-Type", "application/json"); // 发送POST请求 httpConnection.setRequestMethod(requestMethod); httpConnection.setDoOutput(true); httpConnection.setDoInput(true); out = new PrintWriter(httpConnection.getOutputStream()); if (StringUtils.isNotBlank(param)) { out.print(param); } out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(httpConnection.getInputStream(), "UTF-8")); String line; while ((line = in.readLine()) != null) { result.append(line); } } //使用finally块来关闭输出流、输入流 finally { if (out != null) { try { out.close(); } catch (Exception e) { } } if (in != null) { try { in.close(); } catch (Exception e) { } } } return result.toString(); } private static void trustAllHttpsCertificates() throws Exception { TrustManager[] trustAllCerts = new TrustManager[1]; TrustManager tm = new GetOriginalData.miTM(); trustAllCerts[0] = tm; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } /** * 忽略HTTPS请求的SSL证书,必须在openConnection之前调用 * * @throws Exception */ public static void ignoreSsl() throws Exception { HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { return true; } }; trustAllHttpsCertificates(); HttpsURLConnection.setDefaultHostnameVerifier(hv); } static class miTM implements TrustManager, X509TrustManager { public X509Certificate[] getAcceptedIssuers() { return null; } public boolean isServerTrusted(X509Certificate[] certs) { return true; } public boolean isClientTrusted(X509Certificate[] certs) { return true; } public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } } } TokenJson实体类 public class TokenJson { private String access_token; private int expires_in; private String errcode; private String errmsg; public String getErrcode() { return errcode; } public void setErrcode(String errcode) { this.errcode = errcode; } public String getErrmsg() { return errmsg; } public void setErrmsg(String errmsg) { this.errmsg = errmsg; } public String getAccess_token() { return access_token; } public void setAccess_token(String access_token) { this.access_token = access_token; } public int getExpires_in() { return expires_in; } public void setExpires_in(int expires_in) { this.expires_in = expires_in; } } TicketJson实体类 public class TicketJson { private int errcode; private String errmsg; private String ticket; private String expires_in; public int getErrcode() { return errcode; } public void setErrcode(int errcode) { this.errcode = errcode; } public String getErrmsg() { return errmsg; } public void setErrmsg(String errmsg) { this.errmsg = errmsg; } public String getTicket() { return ticket; } public void setTicket(String ticket) { this.ticket = ticket; } public String getExpires_in() { return expires_in; } public void setExpires_in(String expires_in) { this.expires_in = expires_in; } }

转载请注明原文地址: https://www.6miu.com/read-2649991.html

最新回复(0)