news 2025/12/30 22:39:14

Java微信分享-签名算法实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java微信分享-签名算法实现

文章目录

  • 前言

前言

  1. 工具类 - WxJsapiSignature.java
importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;importjava.util.UUID;publicclassWxJsapiSignature{/** * 生成微信 JS-SDK 签名 * @param jsapiTicket 微信 jsapi_ticket * @param url 当前页面 URL(不包含 # 后面的部分) * @return 签名信息对象 */publicstaticSignatureResultgenerateSignature(StringjsapiTicket,Stringurl){// 生成随机字符串StringnonceStr=createNonceStr();// 生成时间戳(秒)longtimestamp=System.currentTimeMillis()/1000;// 按字典序拼接字符串Stringstring1="jsapi_ticket="+jsapiTicket+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url="+url;// SHA1 加密Stringsignature=sha1(string1);// 返回结果SignatureResultresult=newSignatureResult();result.setNonceStr(nonceStr);result.setTimestamp(timestamp);result.setSignature(signature);returnresult;}/** * SHA1 加密 */privatestaticStringsha1(Stringstr){try{MessageDigestdigest=MessageDigest.getInstance("SHA-1");digest.update(str.getBytes());byte[]messageDigest=digest.digest();// 转换为十六进制字符串StringBuilderhexString=newStringBuilder();for(byteb:messageDigest){Stringhex=Integer.toHexString(0xFF&b);if(hex.length()==1){hexString.append('0');}hexString.append(hex);}returnhexString.toString();}catch(NoSuchAlgorithmExceptione){thrownewRuntimeException("SHA1 加密失败",e);}}/** * 生成随机字符串 */privatestaticStringcreateNonceStr(){returnUUID.randomUUID().toString().replace("-","").substring(0,16);}}
  1. 签名结果类 - SignatureResult.java
publicclassSignatureResult{privateStringnonceStr;privateLongtimestamp;privateStringsignature;// Getters and SetterspublicStringgetNonceStr(){returnnonceStr;}publicvoidsetNonceStr(StringnonceStr){this.nonceStr=nonceStr;}publicLonggetTimestamp(){returntimestamp;}publicvoidsetTimestamp(Longtimestamp){this.timestamp=timestamp;}publicStringgetSignature(){returnsignature;}publicvoidsetSignature(Stringsignature){this.signature=signature;}}
  1. Controller 示例
importorg.springframework.web.bind.annotation.*;@RestController@RequestMapping("/wechat")publicclassWechatController{@AutowiredprivateWechatServicewechatService;/** * 获取微信 JS-SDK 签名 */@PostMapping("/jsapi-signature")publicResultgetJsapiSignature(@RequestBodySignatureRequestrequest){try{Stringurl=request.getUrl();// 1. 获取 access_token(需要缓存,有效期 7200 秒)StringaccessToken=wechatService.getAccessToken();// 2. 获取 jsapi_ticket(需要缓存,有效期 7200 秒)StringjsapiTicket=wechatService.getJsapiTicket(accessToken);// 3. 生成签名SignatureResultsignature=WxJsapiSignature.generateSignature(jsapiTicket,url);// 4. 返回结果Map<String,Object>data=newHashMap<>();data.put("appId",wechatService.getAppId());data.put("timestamp",signature.getTimestamp());data.put("nonceStr",signature.getNonceStr());data.put("signature",signature.getSignature());returnResult.success(data);}catch(Exceptione){returnResult.error("获取签名失败: "+e.getMessage());}}}
  1. Service 示例(获取 access_token 和 jsapi_ticket)
importorg.springframework.stereotype.Service;importorg.springframework.web.client.RestTemplate;importcom.alibaba.fastjson.JSONObject;@ServicepublicclassWechatService{@Value("${wechat.appId}")privateStringappId;@Value("${wechat.appSecret}")privateStringappSecret;@AutowiredprivateRestTemplaterestTemplate;// 缓存 access_token(实际项目中应该用 Redis 缓存)privateStringcachedAccessToken;privatelongaccessTokenExpireTime;// 缓存 jsapi_ticketprivateStringcachedJsapiTicket;privatelongjsapiTicketExpireTime;/** * 获取 access_token */publicStringgetAccessToken(){// 检查缓存if(cachedAccessToken!=null&&System.currentTimeMillis()<accessTokenExpireTime){returncachedAccessToken;}// 请求微信接口Stringurl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;Stringresponse=restTemplate.getForObject(url,String.class);JSONObjectjson=JSONObject.parseObject(response);if(json.containsKey("access_token")){cachedAccessToken=json.getString("access_token");// 提前 5 分钟过期accessTokenExpireTime=System.currentTimeMillis()+(json.getInteger("expires_in")-300)*1000;returncachedAccessToken;}else{thrownewRuntimeException("获取 access_token 失败: "+response);}}/** * 获取 jsapi_ticket */publicStringgetJsapiTicket(StringaccessToken){// 检查缓存if(cachedJsapiTicket!=null&&System.currentTimeMillis()<jsapiTicketExpireTime){returncachedJsapiTicket;}// 请求微信接口Stringurl="https://api.weixin.qq.com/cgi-bin/ticket/getjsapi_ticket?access_token="+accessToken;Stringresponse=restTemplate.getForObject(url,String.class);JSONObjectjson=JSONObject.parseObject(response);if(json.getInteger("errcode")==0){cachedJsapiTicket=json.getString("ticket");// 提前 5 分钟过期jsapiTicketExpireTime=System.currentTimeMillis()+(json.getInteger("expires_in")-300)*1000;returncachedJsapiTicket;}else{thrownewRuntimeException("获取 jsapi_ticket 失败: "+response);}}publicStringgetAppId(){returnappId;}}
  1. 请求对象
publicclassSignatureRequest{privateStringurl;publicStringgetUrl(){returnurl;}publicvoidsetUrl(Stringurl){this.url=url;}}
  1. application.yml 配置
wechat: appId: wxf123456789 appSecret: your_app_secret_here

关键点:
SHA1 加密必须转换为小写十六进制字符串
参数拼接顺序必须是字典序:jsapi_ticket、noncestr、timestamp、url
URL 不能 encode,保持原样
access_token 和 jsapi_ticket 必须缓存,避免频繁请求导致限流
时间戳单位是秒,不是毫秒

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/29 23:27:38

性能测试入门:使用 Playwright 测量关键 Web 性能指标

如果你正在寻找一种现代、可靠的方式来测量网站性能&#xff0c;Playwright 可能正是你需要的工具。虽然它主要以自动化测试闻名&#xff0c;但其强大的性能监控能力却常常被忽视。在这篇文章中&#xff0c;我将分享如何利用 Playwright 来测量那些影响用户体验的关键性能指标。…

作者头像 李华
网站建设 2025/12/27 0:02:37

从入门到精通:R语言极值分布拟合在气象数据中的4个关键步骤

第一章&#xff1a;R语言极值分布拟合在气象数据中的基本概念极值分析是研究罕见但具有重大影响事件的重要统计方法&#xff0c;广泛应用于气象、水文和金融等领域。在气象学中&#xff0c;极端气温、强降雨或飓风等事件虽发生频率低&#xff0c;但其潜在破坏力巨大。R语言提供…

作者头像 李华
网站建设 2025/12/25 21:09:37

仅1%人掌握的建模技术:R语言金融相关性矩阵稀疏化处理实战

第一章&#xff1a;金融风险的 R 语言相关性矩阵在金融风险管理中&#xff0c;资产收益率之间的相关性是评估投资组合波动性和分散化效果的核心指标。R 语言提供了强大的统计计算与可视化能力&#xff0c;能够高效构建和分析相关性矩阵。通过计算不同金融资产收益率之间的皮尔逊…

作者头像 李华
网站建设 2025/12/27 4:11:06

超越传统PLM理念,定义行业新标准:全星研发项目管理APQP软件系统

超越传统PLM&#xff0c;定义行业新标准&#xff1a;全星研发项目管理APQP软件系统 在汽车部件与芯片半导体行业&#xff0c;研发管理正面临前所未有的挑战&#xff1a;日益复杂的供应链协同、严苛的质量标准体系、不断压缩的产品上市周期&#xff0c;以及跨地域多团队的协作需…

作者头像 李华
网站建设 2025/12/26 2:14:40

【安全专家亲授】私有化Dify的SSL配置秘诀:保障数据传输不被窃取

第一章&#xff1a;私有化 Dify 的 SSL 配置在私有化部署 Dify 时&#xff0c;启用 HTTPS 是保障通信安全的关键步骤。通过配置 SSL 证书&#xff0c;可以确保前端与后端之间的数据传输加密&#xff0c;防止中间人攻击和敏感信息泄露。通常使用 Nginx 作为反向代理服务器来实现…

作者头像 李华
网站建设 2025/12/26 8:08:00

Vue3+JS 高级前端面试题

题目 1&#xff1a;Vue3 响应式边界问题与复杂状态管理&#xff08;电商购物车场景&#xff09;问题在 Vue3 电商项目的购物车模块中&#xff0c;存在以下场景&#xff1a;购物车数据为深层嵌套对象&#xff08;{ list: [{ goods: { sku: [], price: 0 }, count: 1 }], selecte…

作者头像 李华