微信API-V3签名计算方法Java版

微信API-V3签名计算方法Java版

public class WeixinSignUtils {
	static String schema="WECHATPAY2-SHA256-RSA2048";
	public static String getToken(String method, String url, String body,String merchantId,String serialNo,String filename) {
		 String nonceStr = getNonceStr();
		    long timestamp = System.currentTimeMillis() / 1000;
		    String message = buildMessage(method, url, timestamp, nonceStr, body);
		    String signature;
			try {
				signature = sign(message.getBytes("utf-8"),filename);
			} catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException
					| UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				signature=null;
			}	  
		    return " mchid=\"" + merchantId + "\","
		    + "nonce_str=\"" + nonceStr + "\","
		    + "timestamp=\"" + timestamp + "\","
		    + "serial_no=\"" + serialNo + "\","
		    +"signature=\"" + signature + "\"";
	}
	public static String sign(byte[] message,String filename) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
		Signature sign=Signature.getInstance("SHA256withRSA");
		sign.initSign(getPrivateKey(filename));
		sign.update(message);
		return Base64.getEncoder().encodeToString(sign.sign());
	}
	

	
	
	
	
	
	public static String buildMessage(String method,String url,long timestamp,String nonceStr,String body) {
//		String canonicalUrl=url.encodedPath();
//		if(url.encodedQuery()!=null) {
//			canonicalUrl+="?"+url.encodedQuery();
//		}
		String a=null;
		if(body==null) {
			a=method+"\n"
					+url+"\n"
					+timestamp+"\n"
					+nonceStr+"\n"
					+"\n";
		}else {
			a=method+"\n"
					+url+"\n"
					+timestamp+"\n"
					+nonceStr+"\n"
					+body+"\n";
		}
		System.out.println(a);
		return a;
	}
	//生成随机数 例如:12ced2db6f0193dda91ba86224ea1cd8
	public static String getNonceStr() {
		Random random = new Random();
		StringBuffer nonceStr=new StringBuffer();
		for ( int i = 0; i < 32; i++ )
		{
		String str = random.nextInt( 2 ) % 2 == 0 ? "num" : "char";
		if ( "char".equalsIgnoreCase( str ) )
		{ // 产生字母
			nonceStr.append((char)( 97 + random.nextInt( 26 )));
		}
		else if ( "num".equalsIgnoreCase( str ) )
		{ // 产生数字

			nonceStr.append(String.valueOf(random.nextInt( 10 )));
		}
		}
		return nonceStr.toString();
	}
	/**
	 * 获取私钥
	 * @param filename 私钥文件路径(required)
	 * @return 私钥对象
	 */
	 public static PrivateKey getPrivateKey(String filename) {
		 String content=null;
		try {
			content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			return null;
		}
		 try {
			 String privateKey=content.replace("-----BEGIN PRIVATE KEY-----", "")
					 .replace("-----END PRIVATE KEY-----", "")
					 .replace("\\s+", "");
			 KeyFactory kf=KeyFactory.getInstance("RSA");
			 return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(privateKey)));
		 }catch(NoSuchAlgorithmException e) {
			 throw new RuntimeException("当前java环境不支持RSA",e);
		 }catch(InvalidKeySpecException e) {
			 throw new RuntimeException("无效的密钥格式",e);
		 }
	 }
}

使用时,直接调用getToken(String method, String url, String body,String merchantId,String serialNo,String filename)方法,对应的传入参数为:
**method:**请求方法 大写的POST或GET
**url:**请求的绝对URL,并去除域名部分得到参与签名的URL。如果请求中有查询参数,URL末尾应附加有’?'和对应的查询字符串。例如:/v3/certificates
**body:**请求的报文主体,json格式,如果是GET请求,直接传入body=null即可
**merchantId:**发起请求的商户号
**serialNo:**商户API证书序列号
**filename:**计算私钥用的文件路径

你可能感兴趣的:(java)