WeChat Pay V3: Parse API Certificates & Generate Secure Signatures in Java

This guide walks you through the essential steps for handling WeChat Pay V3 integration, including obtaining and parsing the API certificate with Java's KeyStore, extracting the key pair, constructing the required signature string, performing SHA256withRSA signing, and assembling the Authorization token for secure payment requests.

Programmer DD
Programmer DD
Programmer DD
WeChat Pay V3: Parse API Certificates & Generate Secure Signatures in Java

1. Introduction

Recently I have been working on WeChat Pay integration, and the certificates can be quite troublesome, so it is necessary to share some experience to reduce the pitfalls when developing WeChat Pay. The current WeChat Pay API has evolved to the V3 version and adopts a popular Restful style.

Today I share the hardest part of WeChat Pay – the signature . Although many useful SDKs exist, understanding the signature deeply is still helpful.

2. API Certificate

To ensure the security of sensitive financial data and guarantee that transactions are flawless, the authoritative CA certificate (API certificate) issued by WeChat Pay provides a private key for signing. You can set and obtain the API certificate through the merchant platform.

Note that the first time you set it up you will be prompted to download; later downloads are no longer provided. See the documentation for details.

After setting, find the zip package, unzip it, and for Java development you only need to focus on the apiclient_cert.p12 file, which contains the public and private keys. Place it on the server and use Java to parse the .p12 file to obtain the key pair.

Be sure to keep the certificate secure on the server; it involves fund security.

Parsing API Certificate

The next step is parsing the certificate. Many methods exist online; here we use a more "formal" approach with JDK's security package java.security.KeyStore.

WeChat Pay API certificates use the PKCS12 algorithm. By using KeyStore we obtain a KeyPair and the certificate serial number serialNumber. I have encapsulated a utility class (you handle the serial number yourself):

import org.springframework.core.io.ClassPathResource;

import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;

/**
 * KeyPairFactory
 *
 * @author dax
 * @since 13:41
 */
public class KeyPairFactory {

    private KeyStore store;

    private final Object lock = new Object();

    /**
     * Get public and private key.
     *
     * @param keyPath  the key path
     * @param keyAlias the key alias
     * @param keyPass  password
     * @return the key pair
     */
    public KeyPair createPKCS12(String keyPath, String keyAlias, String keyPass) {
        ClassPathResource resource = new ClassPathResource(keyPath);
        char[] pem = keyPass.toCharArray();
        try {
            synchronized (lock) {
                if (store == null) {
                    synchronized (lock) {
                        store = KeyStore.getInstance("PKCS12");
                        store.load(resource.getInputStream(), pem);
                    }
                }
            }
            X509Certificate certificate = (X509Certificate) store.getCertificate(keyAlias);
            certificate.checkValidity();
            // certificate serial number is also useful
            String serialNumber = certificate.getSerialNumber().toString(16).toUpperCase();
            // public key
            PublicKey publicKey = certificate.getPublicKey();
            // private key
            PrivateKey storeKey = (PrivateKey) store.getKey(keyAlias, pem);

            return new KeyPair(publicKey, storeKey);

        } catch (Exception e) {
            throw new IllegalStateException("Cannot load keys from store: " + resource, e);
        }
    }
}
It resembles the public‑private key extraction method used in Spring Security JWT tutorials.

This method has three parameters, which need explanation: keyPath – the classpath location of apiclient_cert.p12, usually placed under resources. keyAlias – the certificate alias; WeChat documentation does not provide it, but debugging shows it is fixed as Tenpay Certificate. keyPass – the certificate password, which defaults to the merchant ID ( mchid), the numeric string you see when logging into the merchant platform as a super administrator.

3. V3 Signature

The WeChat Pay V3 signature is carried in the HTTP request header as a specially encoded string for the WeChat Pay server to verify the request source, ensuring the request is authentic.

Signature Format

The signature string consists of five lines, each terminated by a newline character \n:

HTTP request method
URL
timestamp
nonce string
request body

HTTP request method – e.g., POST.

URL – the path part of the API endpoint, e.g., /v3/pay/transactions/app. If there are query parameters, append ‘?’ and the query string.

Timestamp – server system timestamp, obtained via System.currentTimeMillis() / 1000.

Nonce string – a random string such as 593BEC0C930BF1AFEB40B4A08C8FB242.

Request body – empty string "" for GET; for POST or PUT use the actual JSON payload; for image upload APIs use the meta JSON.

Generating the Signature

We sign the assembled string with the merchant private key using SHA256withRSA, then Base64‑encode the result. Core Java code:

/**
 * V3 SHA256withRSA signature.
 *
 * @param method        request method (GET, POST, PUT, DELETE, etc.)
 * @param canonicalUrl  e.g. https://api.mch.weixin.qq.com/v3/pay/transactions/app?version=1 → /v3/pay/transactions/app?version=1
 * @param timestamp     current timestamp (must match the token timestamp)
 * @param nonceStr      random string (must match the token nonce)
 * @param body          request body ("" for GET, JSON for POST)
 * @param keyPair       merchant API certificate key pair (private key)
 * @return the signature string
 */
@SneakyThrows
String sign(String method, String canonicalUrl, long timestamp, String nonceStr, String body, KeyPair keyPair) {
    String signatureStr = Stream.of(method, canonicalUrl, String.valueOf(timestamp), nonceStr, body)
            .collect(Collectors.joining("
", "", "
"));
    Signature sign = Signature.getInstance("SHA256withRSA");
    sign.initSign(keyPair.getPrivate());
    sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
    return Base64Utils.encodeToString(sign.sign());
}

4. Using the Signature

After generating the signature, combine it with other parameters to form a Token placed in the Authorization header:

Authorization: WECHATPAY2-SHA256-RSA2048 {Token}

The token consists of five parts:

Merchant ID ( mchid)

Certificate serial number ( serial_no)

Nonce string ( nonce_str)

Timestamp ( timestamp)

Signature ( signature)

Code to build the token:

/**
 * Generate Token.
 *
 * @param mchId    merchant ID
 * @param nonceStr random string
 * @param timestamp timestamp
 * @param serialNo certificate serial number
 * @param signature signature
 * @return the token string
 */
String token(String mchId, String nonceStr, long timestamp, String serialNo, String signature) {
    final String TOKEN_PATTERN = "mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",serial_no=\"%s\",signature=\"%s\"";
    return String.format(TOKEN_PATTERN, wechatPayProperties.getMchId(), nonceStr, timestamp, serialNo, signature);
}

5. Summary

This article provided a complete analysis of the challenging signature aspect of WeChat Pay V3, explained how to parse the API certificate in Java, generate the required signature string, and assemble the Authorization token, helping developers solve concrete problems in payment development.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSecuritysignatureWeChat PayPayment IntegrationAPI Certificate
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.