wechatpay-apache-httpclient icon indicating copy to clipboard operation
wechatpay-apache-httpclient copied to clipboard

支持微信支付公钥吗?

Open JackyChan opened this issue 1 year ago • 3 comments

现在微信支付新申请的账号,不再签发平台证书,而是提供微信支付公钥,请问现在支持吗?

JackyChan avatar Oct 28 '24 03:10 JackyChan

同问啊,现有系统用的这套api

Bloodythirsty avatar Nov 08 '24 11:11 Bloodythirsty

同问。现在新创建的商户都没有平台证书的入口了。

a414338069 avatar Nov 22 '24 05:11 a414338069

自己写了个,在setVerifier用这个就可以了

  /**
     * 获取微信证书
     *
     * @throws Exception
     */
    private void setVerifier() throws Exception {
        if (merchantPrivateKey == null) {
            setMerchantPrivateKey();
        }
        verifier = new PubKeyVerifier(wechatConfig.getPubKeyId());
    }

PubKeyVerifier:

package com.wechat.server.util.wechat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import org.springframework.core.io.ClassPathResource;

import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;

public class PubKeyVerifier implements Verifier {

    private PublicKey publicKey;

    private String publicKeyId;

    public PubKeyVerifier(String publicKeyId) {
        this.publicKeyId = publicKeyId;
        try {
            StringBuilder pemContent = new StringBuilder();
            ClassPathResource classPathResource = new ClassPathResource("pub_key.pem");
            InputStream inputStream = classPathResource.getInputStream();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
                String line;
                while ((line = br.readLine()) != null) {
                    if (line.contains("-----BEGIN PUBLIC KEY-----") || line.contains("-----END PUBLIC KEY-----")) {
                        continue;
                    }
                    pemContent.append(line.trim());
                }
            }
            byte[] keyBytes = Base64.getDecoder().decode(pemContent.toString());
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            this.publicKey = keyFactory.generatePublic(spec);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean verify(String serialNumber, byte[] message, String signature) {
        if (!serialNumber.isEmpty() && message.length != 0 && !signature.isEmpty()) {
            if (!this.publicKeyId.equals(serialNumber)) {
                throw new IllegalArgumentException("pub_key_id error");
            }
            try {
                Signature sign = Signature.getInstance("SHA256withRSA");
                sign.initVerify(this.publicKey);
                sign.update(message);
                return sign.verify(Base64.getDecoder().decode(signature));
            } catch (NoSuchAlgorithmException var8) {
                throw new RuntimeException("当前Java环境不支持SHA256withRSA", var8);
            } catch (SignatureException var9) {
                throw new RuntimeException("签名验证过程发生了错误", var9);
            } catch (InvalidKeyException var10) {
                throw new RuntimeException("无效的证书", var10);
            }
        } else {
            throw new IllegalArgumentException("serialNumber或message或signature为空");
        }
    }

    @Override
    public X509Certificate getValidCertificate() {
        return null;
    }
}

gudepeng avatar Dec 24 '24 07:12 gudepeng