Java中的微信支付: 微信API-V3签名生成工具类
生活随笔
收集整理的這篇文章主要介紹了
Java中的微信支付: 微信API-V3签名生成工具类
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
微信支付API v3簡介
微信官方文檔地址
為了在 保證支付 安全的前提下,帶給商戶 簡單、一致且易用的開發體驗,我們推出了全新的微信支付API v3。
相較于之前的微信支付API,主要區別是:
- 遵循統一的REST ful的設計風格
- 使用JSON作為數據交互的格式,不再使用XML
- 使用基于非對稱密鑰的SHA256-RSA的數字簽名算法,不再使用MD5或HMAC-SHA256
- 不再要求HTTPS客戶端證書
- 使用AES-256-GCM,對回調中的關鍵信息進行加密保護
在接口規則中,你將了解到微信支付API v3的基礎約定,如數據格式,參數兼容性,錯誤處理等。隨后我們重點介紹了微信支付API v3新的認證機制。你可以跟隨著簽名指南,使用命令行或者你熟悉的編程語言,一步一步實踐如何簽名和驗簽。
在進行v3簽名開發之前,可以先了解一下微信v3簽名基本規則
所需要獲取的各種證書需要提前準備,簽名需要用到商戶號,微信支付平臺序列號,商戶API的私鑰, 這里不講解怎么獲取, 網上一大堆,進入此微信官方鏈接了解證書
開始開發,可參考微信簽名生成文檔
注:代碼框架使用springboot
<!-- 引入jar包><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>3.5.0</version></dependency>SignV3Utils
import okhttp3.HttpUrl; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import java.io.UnsupportedEncodingException; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.Random;@Component public class SignV3Utils {//V3主商戶IDprivate static String merchantId;//微信商戶平臺APIv3證書序列號private static String certificateSerialNo;//私鑰(不要把私鑰文件暴露在公共場合,如上傳到Github,寫在客戶端代碼等。)private static String privateKey;//配置文件配置好主商戶號@Value("${wechat.v3.merchantId}")public void setMerchantId(String merchantId) {SignV3Utiles.merchantId = merchantId;}//配置文件配置好序列號@Value("${wechat.v3.certificateSerialNo}")public void setCertificateSerialNo(String certificateSerialNo) {SignV3Utiles.certificateSerialNo = certificateSerialNo;}//配置文件配置好私鑰@Value("${wechat.v3.privateKey}")public void setPrivateKey(String privateKey) {SignV3Utiles.privateKey = privateKey;}/*** 使用方法* @param method 請求方法* @param url 請求url* @param body 請求內容* @return*/public static HashMap<String, String> getSignMap(String method, String url, String body) throws InvalidKeySpecException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException, SignatureException {String authorization = getSign(method, url, body);HashMap<String, String> headsMap = new HashMap<>();headsMap.put("Authorization", authorization);headsMap.put("Content-Type", "application/json");headsMap.put("Accept", "application/json");return headsMap;}public static String getSign(String method, String url, String body) throws NoSuchAlgorithmException, SignatureException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException {return "WECHATPAY2-SHA256-RSA2048 " + getToken(method, HttpUrl.parse(url), body);}public static String getToken(String method, HttpUrl url, String body) throws UnsupportedEncodingException, SignatureException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {String nonceStr = nonceString();long timestamp = System.currentTimeMillis() / 1000;String message = buildMessage(method, url, timestamp, nonceStr, body);String signature = sign(message.getBytes("utf-8"));return "mchid=\"" + merchantId + "\","+ "nonce_str=\"" + nonceStr + "\","+ "timestamp=\"" + timestamp + "\","+ "serial_no=\"" + certificateSerialNo + "\","+ "signature=\"" + signature + "\"";}public static String sign(byte[] message) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {Signature sign = Signature.getInstance("SHA256withRSA");sign.initSign(getPKCS8PrivateKey(privateKey));sign.update(message);return Base64.getEncoder().encodeToString(sign.sign());}public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {String canonicalUrl = url.encodedPath();if (url.encodedQuery() != null) {canonicalUrl += "?" + url.encodedQuery();}return method + "\n"+ canonicalUrl + "\n"+ timestamp + "\n"+ nonceStr + "\n"+ body + "\n";}private static PrivateKey getPKCS8PrivateKey(String strPk) throws NoSuchAlgorithmException, InvalidKeySpecException {String realPK = strPk.replaceAll("-----END PRIVATE KEY-----", "").replaceAll("-----BEGIN PRIVATE KEY-----", "").replaceAll("\n", "");byte[] b1 = Base64.getDecoder().decode(realPK);PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1);KeyFactory kf = KeyFactory.getInstance("RSA");return kf.generatePrivate(spec);}public static String nonceString() {String currTime = String.format("%d", (long) System.currentTimeMillis() / 1000);String strTime = currTime.substring(8, currTime.length());Random random = new Random();int num = (int) (random.nextDouble() * (1000000 - 100000) + 100000);String code = String.format("%06d", num);String nonce_str = currTime.substring(2) + code;return nonce_str;} }簡單調用實例demo
@RequestMapping(value = "/test", method = RequestMethod.POST, produces = "application/json; charset=utf-8") @ApiOperation("測試") public void test() throws Exception{//處理請求參數String param = JSON.toJSONString("請求參數");//獲取簽名請求頭HashMap<String, String> heads = SignV3Utils.getSignMap("POST", "微信接口url", param);//請求微信接口HttpUtils.requestPostBody("微信接口url", param, heads);}具體每個接口使用文檔,請參考微信API文檔
請求方式,請求參數不用寫法都不同,這里就不一一列舉,有興趣的兄弟可以溝通交流下。
有幫助的人可以幫忙點下收藏和點贊喔!
總結
以上是生活随笔為你收集整理的Java中的微信支付: 微信API-V3签名生成工具类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第九节 信度、效度分析
- 下一篇: 原创:《倚天》:后期的俞莲舟有多强?江湖