本文是使用java语言调用微信提供的接口,获取签名的详细过程,大致步骤如下:
- 在官网生成appId 与 appSecret,然后通过appId 与 appSecret调用接口获取到Access token
- 通过Access token调用微信提供的接口获取到jsapi_ticket
- 最后使用jsapi_ticket、随机字符串、时间戳、url拼接字符串,在使用
sha1进行加密得到签名 - 将appid、时间戳、随机字符串、签名返回给前端
具体过程如下:
首先是请求参数:
package com.ncb.mbank.api.service.openact.dto.req;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @Description: 微信获取签名的请求参数
* @Author 胡尚
* @Date: 2022/1/4 11:40
* @Version 1.0
*/
@Data
public class GetWeChatSignatureReq implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "appid")
@NotBlank(message = "appid不能為空")
private String appId;
@ApiModelProperty(value = "appSecret")
@NotBlank(message = "appSecret不能為空")
private String appSecret;
@ApiModelProperty(value = "url",required = true)
@NotBlank(message = "url不能為空")
private String url;
}
接下来是业务层
package com.ncb.mbank.api.service.openact.bizsvc.impl;
import com.alibaba.fastjson.JSON;
import com.ncb.mbank.api.framework.core.constants.ErrorCodeConstants;
import com.ncb.mbank.api.framework.core.exception.ApplicationException;
import com.ncb.mbank.api.framework.web.constants.HsAccountConst;
import com.ncb.mbank.api.framework.web.utils.MbankHsUtils;
import com.ncb.mbank.api.framework.web.utils.RsaUtil;
import com.ncb.mbank.api.restclient.gateway.feignclient.WeChatFeignClient;
import com.ncb.mbank.api.service.openact.bizsvc.MWeChatTencentBizSvc;
import com.ncb.mbank.api.service.openact.dto.req.GetWeChatSignatureReq;
import com.ncb.mbank.api.service.openact.dto.resp.GetWeChatSignatureResp;
import com.ncb.mbank.api.service.openact.dto.resp.RsaEncryptResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @Description:
* @Author 胡尚
* @Date: 2022/1/4 11:54
* @Version 1.0
*/
@Service
@Slf4j
public class MWeChatTencentBizSvcImpl implements MWeChatTencentBizSvc {
/**
* 调用微信公众号的接口 获取Access token 必输的一个请求参数 该值是固定的
*/
private final static String GRANT_TYPE = "client_credential";
/**
* 调用微信公众号的接口 获取jsapi_ticket 必输的一个请求参数 该值是固定的
*/
private final static String GET_JSAPI_TICKET_TYPE = "jsapi";
@Autowired
private WeChatFeignClient weChatFeignClient;
@Override
public GetWeChatSignatureResp getWeChatSignature(GetWeChatSignatureReq req) throws ApplicationException {
// 调用微信公众号的接口 获取Access token
String accessToken = getAccessToken(req);
if (StringUtils.isEmpty(accessToken)) {
log.error("调用微信公众号的接口 未获取Access token ");
throw new ApplicationException(ErrorCodeConstants.CLI_GET_ACCESS_TOKEN_ERROR);
}
// 调用微信公众号的接口 获取jsapi_ticket
String jsapiTicket = getJsapiTicket(accessToken);
if (StringUtils.isEmpty(accessToken)) {
log.error("调用微信公众号的接口 未获取jsapi_ticket ");
throw new ApplicationException(ErrorCodeConstants.CLI_GET_JSAPI_TICKET_ERROR);
}
// 签名加密算法
GetWeChatSignatureResp resp = getSignature(jsapiTicket, req.getUrl());
resp.setAppId(req.getAppId());
return resp;
}
@Override
public String getAccessToken(GetWeChatSignatureReq req) throws ApplicationException {
Map<String, Object> reqMap = new HashMap<>();
reqMap.put("grant_type", GRANT_TYPE);
reqMap.put("appid", req.getAppId());
reqMap.put("secret", req.getAppSecret());
log.info("调用微信的接口 获取AccessToken,请求数据为:\n{}", JSON.toJSONString(reqMap));
String accessTokenResp = weChatFeignClient.getAccessToken(reqMap);
log.info("调用微信的接口 获取AccessToken,响应数据为:\n{}", accessTokenResp);
return JSON.parseObject(accessTokenResp).getString("access_token");
}
@Override
public String getJsapiTicket(String accessToken) throws ApplicationException {
Map<String, Object> reqMap = new HashMap<>();
reqMap.put("type", GET_JSAPI_TICKET_TYPE);
reqMap.put("access_token", accessToken);
log.info("调用微信的接口 获取jsapi_ticket,请求数据为:\n{}", JSON.toJSONString(reqMap));
String jsapiTicketResp = weChatFeignClient.getJsapiTicket(reqMap);
log.info("调用微信的接口 获取jsapi_ticket,响应数据为:\n{}", jsapiTicketResp);
return JSON.parseObject(jsapiTicketResp).getString("ticket");
}
@Override
public GetWeChatSignatureResp getSignature(String jsapiTicket, String url) throws ApplicationException {
GetWeChatSignatureResp resp = new GetWeChatSignatureResp();
// 生成随机字符串
String nonceStr = MbankHsUtils.createNonceStr();
// 时间戳
long timestamp = System.currentTimeMillis();
// 通过jsapi_ticket、随机字符串、时间戳
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("jsapi_ticket=").append(jsapiTicket).append("&")
.append("noncestr=").append(nonceStr).append("&")
.append("timestamp=").append(timestamp).append("&")
.append("url=").append(url.indexOf("#") >= 0 ? url.substring(0, url.indexOf("#")) : url);
String signatureStr = stringBuilder.toString();
log.info("微信签名 she1加密前的数据:{}", signatureStr);
String signature = DigestUtils.sha1Hex(signatureStr);
log.info("微信签名,she1加密后的数据:{}", signature);
// 返回数据
resp.setNonceStr(nonceStr);
resp.setTimestamp(String.valueOf(timestamp));
resp.setSignature(signature);
return resp;
}
}
这里使用FeignClient方式调用微信的接口
package com.ncb.mbank.api.restclient.gateway.feignclient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
/**
* @Description: 微信相关接口
* @Author 胡尚
* @Date: 2022/1/4 11:59
* @Version 1.0
*/
@FeignClient(name = "weChatFeignClient", url = "https://api.weixin.qq.com", path = "/cgi-bin")
public interface WeChatFeignClient {
@GetMapping("/token")
String getAccessToken(@RequestParam Map<String, Object> map);
@GetMapping("/ticket/getticket")
String getJsapiTicket(@RequestParam Map<String, Object> map);
}
需要注意的几点是,通过jsapi_ticket、随机字符串、时间戳、url拼接时,=左边需要使用小写,需要按照字典顺序升序摆放。
版权声明:本文为qq_44027353原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。