收藏
回答

native回调验签失败

按照文档指引,一步步执行验签仍然失败。

  1. 已检测过获取的平台证书序列号和微信支付后台和回调数据头部wechatpay-serial一致。
  2. 已根据平台证书生成的对应公钥
  3. signature.txt是根据返回数据的头部wechatpay-signature进行base64解码
回答关注问题邀请回答
收藏

3 个回答

  • Memory (私信不回复)
    Memory (私信不回复)
    02-18

    随手搓了一个html版本的验证代码拿去验证吧

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>WeChat Pay Signature Verification</title>
    </head>
    <body>
        <h1>WeChat Pay Signature Verification</h1>
        <label for="timestamp">Wechatpay-Timestamp:</label>
        <input type="text" id="timestamp"><br><br>
        
        <label for="nonce">Wechatpay-Nonce:</label>
        <input type="text" id="nonce"><br><br>
        
        <label for="responseBody">Response Body:</label><br>
        <textarea id="responseBody" rows="10" cols="30"></textarea><br><br>
        
        <label for="signature">Wechatpay-Signature (Base64 Encoded):</label>
        <input type="text" id="signature"><br><br>
        
        <label for="publicKeyFile">Upload Platform Public Key Certificate:</label>
        <input type="file" id="publicKeyFile" accept=".pem"><br><br>
        
        <button onclick="verifySignature()">Verify Signature</button>
        
        <p id="result"></p>
        
        <script>
            function verifySignature() {
                const timestamp = document.getElementById('timestamp').value;
                const nonce = document.getElementById('nonce').value;
                const responseBody = document.getElementById('responseBody').value;
                const signatureBase64 = document.getElementById('signature').value;
                const publicKeyFile = document.getElementById('publicKeyFile').files[0];
                
                const signatureString = `${timestamp}\n${nonce}\n${responseBody}\n`;
                const decodedSignature = base64ToArrayBuffer(signatureBase64);
    
    
                const reader = new FileReader();
                reader.onload = function(event) {
                    const publicKeyPem = event.target.result;
                    const publicKeyBuffer = pemToArrayBuffer(publicKeyPem);
                    
                    verify(publicKeyBuffer, decodedSignature, signatureString).then(isValid => {
                        document.getElementById('result').textContent = `Signature is valid: ${isValid}`;
                    }).catch(err => {
                        document.getElementById('result').textContent = `Error: ${err.message}`;
                    });
                };
                reader.readAsText(publicKeyFile);
            }
            
            const base64ToArrayBuffer = (base64) => {
                const binaryString = window.atob(base64);
                const len = binaryString.length;
                const bytes = new Uint8Array(len);
                for (let i = 0; i < len; i++) {
                    bytes[i] = binaryString.charCodeAt(i);
                }
                return bytes.buffer;
            };
            
            const pemToArrayBuffer = (pem) => {
                const b64Lines = pem.replace(/-----(BEGIN|END) PUBLIC KEY-----/g, "").trim();
                const b64 = b64Lines.replace(/\n/g, "");
                return base64ToArrayBuffer(b64);
            };
            
            const verify = async (publicKey, signature, data) => {
                const key = await crypto.subtle.importKey(
                    'spki',
                    publicKey,
                    {
                        name: 'RSASSA-PKCS1-v1_5',
                        hash: 'SHA-256'
                    },
                    false,
                    ['verify']
                );
                return crypto.subtle.verify(
                    'RSASSA-PKCS1-v1_5',
                    key,
                    signature,
                    new TextEncoder().encode(data)
                );
            };
        </script>
    </body>
    </html>
    
    
    
    02-18
    有用 1
    回复
  • RealSys
    RealSys
    02-18

    验签还是失败的

    我的平台证书是这样获取的

    java -jar CertificateDownloader.jar -k 3fd35d3b*************3ed -m 1648189956 -f /Users/sky/Desktop/1648189956_20250211_cert/apiclient_key.pem -s 4A64C6204EADAB***********D749E88 -o ./


    公钥使用了如下生成方式

    openssl pkcs7 -print_certs -in CertTrustChain.p7b -inform der -out CertTrustChain.pem


    02-18
    有用
    回复 2
    • Memory (私信不回复)
      Memory (私信不回复)
      02-18
      openssl x509 -in 1900009191_wxp_cert.pem -pubkey -noout > 1900009191_wxp_pub.pem 这样去导出
      02-18
      1
      回复
    • RealSys
      RealSys
      02-18回复Memory (私信不回复)
      可以了 谢谢大佬 确实是生成公钥这步有问题
      02-18
      回复
登录 后发表内容