java版微信v3签名

java版微信v3签名

java版微信v3签名

第一次研究微信支付功能,采用了微信最新的v3支付版本,此文章编辑的是微信支付签名。
文章有借鉴FrankyTurbo
的文章,此文章仅作为demo
微信官方签名文档

核心代码

对应的替换appid,serial_no等,
证书都放在resources文件夹下


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

/**
 * @description:
 * @author: zl
 * @create: 2020-11-25 16:56
 **/
@Slf4j
public class WxPay2 {
    String schema = "WECHATPAY2-SHA256-RSA2048 ";
    String mchid = "xxxxxxx";
    long timestamp = DateUtil.currentSeconds();
    String nonceStr = RandomUtil.randomString(16);
    String serial_no = "xxxxxxx";

    /** 
    * 
    * @Description: 获取秘钥
    * @Author: zl 
    * @Date: 2020/11/25 0025 
    */ 
    public static PrivateKey getPrivateKey(String filename) throws IOException {
        InputStream inputStream = WxPay.class.getClassLoader().getResourceAsStream(filename);
        StringBuilder sb = new StringBuilder();
        String line;
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        String content = sb.toString();
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(org.apache.commons.codec.binary.Base64.decodeBase64(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            log.info("异常:" + e);
            throw new RuntimeException("无效的密钥格式");
        }
    }

    public String getToken(String method, HttpUrl url, String body) throws IOException {
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("utf-8"));

        return "mchid=\"" + mchid + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + serial_no + "\","
                + "signature=\"" + signature + "\"";
    }

    @SneakyThrows
    public String sign(byte[] message) {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(getPrivateKey("apiclient_key.pem"));
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    public 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";
    }


    public void transactions(){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appid","xxxxxxxx");
        jsonObject.put("mchid","1604272089");
        jsonObject.put("description","测试商品");
        jsonObject.put("out_trade_no","202011254529660000001");
        jsonObject.put("notify_url","http://127.0.0.1/api/wechatService/weixin/auth");

        JSONObject amountJson = new JSONObject();
        amountJson.put("total",100);
        amountJson.put("currency","CNY");
        jsonObject.put("amount",amountJson);

        JSONObject payer = new JSONObject();
        payer.put("openid","12dadawdlwadlwaojd");
        jsonObject.put("payer",payer);

        String method = "POST";
        HttpUrl httpUrl = HttpUrl.parse("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        try {
            HttpRequest request = HttpUtil.createPost(httpUrl.url().toString()).auth(schema + getToken(method,httpUrl,jsonObject.toString())).body(jsonObject.toString());
            HttpResponse response = request.execute();
            System.out.println(response.body());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws IOException {
        WxPay2 wxPay2 = new WxPay2();
        wxPay2.transactions();
    }
}

签名后,调用预支付接口结果:
在这里插入图片描述

  1. 文章仅供参考
  2. 文章若有不对之处,请提出,避免误导他人
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值