微信签名生成
1、微信签名生成
参照微信支付文档中心:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_0.shtml
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.HashMap; import java.util.Map; import java.util.UUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class WxSendConfig { private static final Logger logger = LoggerFactory.getLogger(WxSendConfig.class); private static final Map<String,Object> wechatV3ApiParam = new HashMap<String,Object>(); /** * 获取私钥。 * * @param filename 私钥文件路径 (required) * @return 私钥对象 */ public static PrivateKey getPrivateKey(String filename) throws IOException { String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8"); try { String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s+", ""); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate( new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持RSA", e); } catch (InvalidKeySpecException e) { throw new RuntimeException("无效的密钥格式"); } } /** * 获取证书。 * * @param fis 证书文件流 * @return X509证书 */ public static X509Certificate getCertificate(InputStream fis) throws IOException { BufferedInputStream bis = new BufferedInputStream(fis); try { CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(bis); cert.checkValidity(); return cert; } catch (CertificateExpiredException e) { throw new RuntimeException("证书已过期", e); } catch (CertificateNotYetValidException e) { throw new RuntimeException("证书尚未生效", e); } catch (CertificateException e) { throw new RuntimeException("无效的证书文件", e); } finally { bis.close(); } } /*组装签名串*/ public static String getToken(String method,String url,String body) throws Exception{ String noncestr = UUID.randomUUID().toString().replace("-",""); Long timestamp = System.currentTimeMillis()/1000;//精确到秒 String message = buildMessage(method,url,body,timestamp,noncestr); String signature = getSign(message); String auth = "WECHATPAY2-SHA256-RSA2048 mchid=\""+wechatV3ApiParam.get("wechatMchId")+"\",nonce_str=\""+noncestr+"\",timestamp=\""+timestamp+"\",serial_no=\""+wechatV3ApiParam.get("serialNo")+"\",signature=\""+signature+"\""; logger.info("获得的Authorization:"+auth); return auth; } /** * V3 SHA256withRSA http请求签名. * @param method 请求方法 GET POST PUT DELETE 等 * @param canonicalUrl 请求地址 * @param timestamp 当前时间戳 因为要配置到TOKEN 中所以 签名中的要跟TOKEN 保持一致 * @param nonceStr 随机字符串 要和TOKEN中的保持一致 * @param body 请求体 GET 为 "" POST 为JSON * @return the string * @throws Exception */ public static String buildMessage(String method, String canonicalUrl, String body, long timestamp, String nonceStr) throws Exception { URL url = new URL(canonicalUrl); String signUrl = ""; if ("GET".equals(method) && url.getQuery()!=null) { signUrl = url.getPath() + "?" + url.getQuery(); }else{ signUrl = url.getPath(); } String messageStr = method + "\n" + signUrl+ "\n" + timestamp + "\n" + nonceStr+ "\n" + body+ "\n"; logger.info("messageStr>>>\n"+messageStr); return messageStr; } /** * 获取签名 * @param signatureStr 签名字符串 * @return * @throws InvalidKeyException * @throws NoSuchAlgorithmException * @throws SignatureException */ public static String getSign(String message) throws Exception{ Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign((PrivateKey)wechatV3ApiParam.get("privateKey")); sign.update(message.getBytes("utf-8")); String signature = Base64.getEncoder().encodeToString(sign.sign()); return signature; } public static Map<String, Object> getWechatv3apiparam() { return wechatV3ApiParam; } public static void main(String[] args) throws Exception { PrivateKey privateKey = getPrivateKey("/cert/apiclient_key.pem"); System.out.println("key>>>"+privateKey); X509Certificate certificate = getCertificate(new FileInputStream("/cert/apiclient_cert.pem")); String serNo = certificate.getSerialNumber().toString(16); System.out.println("serNo>>>"+serNo); String noncestr = "c205f6726b1640a5a285cd999bceb5d4"; Long timestamp = System.currentTimeMillis()/1000;//精确到秒 String body = "{\"stock_id\":\"17822878\",\"out_request_no\":\"134348880120230804162600\",\"appid\":\"wx6d24a3a57853dde2\",\"stock_creator_mchid\":\"1343488801\"}"; String message = buildMessage("POST","https://api.mch.weixin.qq.com/v3/marketing/favor/users/2323dfsdf342342/coupons",body,timestamp,noncestr); System.out.println("message>>>\n"+message); Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(privateKey); sign.update(message.getBytes("utf-8")); String signature = Base64.getEncoder().encodeToString(sign.sign()); System.out.println("加密后得到signature>>>"+signature); } }
标签:调用,java,String,微信,cert,签名,new,import,security From: https://www.cnblogs.com/vincentYw/p/17612851.html