收藏
回答

python 调用JSAPI下单接口时 提示签名错误,请检查后再试?

import json
import base64, time, os, struct, secrets, hashlib
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from Conf.golob import mchid, serial_no, appId


def generate_signature(payload):
    # 请求参数
    url_path = "/v3/pay/transactions/jsapi"
    timestamp = f"{int(time.time())}"
    nonce_str = secrets.token_hex(16).upper()
    # 转换 payload 为 JSON 字符串,保持中文字符
    json_payload = json.dumps(payload, ensure_ascii=False, indent=2)
    # 将每一行的末尾添加 \n
    # formatted_payload = '\n'.join(line + '\\n' for line in json_payload.splitlines())
    # 构造待签名字符串
    sign_string = r'POST\n{}\n{}\n{}\n{}\n'.format(url_path, timestamp, nonce_str, json_payload)
    print(sign_string)
    # 读取私钥
    with open("apiclient_key.pem", "rb") as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )

    # Create a SHA-256 hash of the data
    digest = hashlib.sha256(sign_string.encode()).digest()

    # Sign the hash with the private key
    signature = private_key.sign(
        digest,
        padding.PKCS1v15(),
        hashes.SHA256()
    )

    # Encode the signature in base64
    base64_signature = base64.b64encode(signature).decode('utf-8')

    rep_header = {
        "Authorization": f'WECHATPAY2-SHA256-RSA2048 mchid="{mchid}",nonce_str="{nonce_str}",signature="{base64_signature}",timestamp="{timestamp}",serial_no="{serial_no}"',
        'Accept': "application/json",
        "Content-Type": "application/json"
    }
    return rep_header


if __name__ == '__main__':
    generate_signature()
  这块签名有问题吗
最后一次编辑于  11-05
回答关注问题邀请回答
收藏

1 个回答

  • Memory
    Memory
    11-05

    你需要直接对签名字符串进行签名,而不是对哈希值进行签名

    11-05
    有用
    回复 4
    • L🦀 🦀
      L🦀 🦀
      11-05
      # 读取私钥
          with open("apiclient_key.pem", "rb") as key_file:
              private_key = serialization.load_pem_private_key(
                  key_file.read(),
                  password=None,
                  backend=default_backend()
              )


          # # Create a SHA-256 hash of the data
          # digest = hashlib.sha256(sign_string.encode()).digest()


          # 直接对签名字符串进行签名
          signature = private_key.sign(
              sign_string.encode(),
              padding.PKCS1v15(),
              hashes.SHA256()
          )


          # 对签名结果进行 base64 编码
          base64_signature = base64.b64encode(signature).decode('utf-8')

      是这样嘛
      11-05
      回复
    • Memory
      Memory
      11-05回复L🦀 🦀
      对,不要对哈希值进行签名
      11-05
      回复
    • L🦀 🦀
      L🦀 🦀
      11-05
      import json
      import base64, time, os, struct, secrets, hashlib
      from cryptography.hazmat.primitives import hashes
      from cryptography.hazmat.primitives.asymmetric import padding
      from cryptography.hazmat.backends import default_backend
      from cryptography.hazmat.primitives import serialization
      from Conf.golob import mchid, serial_no, appId




      def generate_signature(payload):
          # 请求参数
          url_path = "/v3/pay/transactions/jsapi"
          timestamp = f"{int(time.time())}"
          nonce_str = secrets.token_hex(16).upper()
          # 转换 payload 为 JSON 字符串,保持中文字符
          json_payload = json.dumps(payload, ensure_ascii=False)
          # 构造待签名字符串
          sign_string = 'POST\n{}\n{}\n{}\n{}\n'.format(url_path, timestamp, nonce_str, json_payload)
          print(sign_string)
          # 读取私钥
          with open("apiclient_key.pem", "rb") as key_file:
              private_key = serialization.load_pem_private_key(
                  key_file.read(),
                  password=None,
                  backend=default_backend()
              )


          # 使用 SHA256 with RSA 对签名字符串进行签名
          signature = private_key.sign(
              sign_string.encode(), # 待签名字符串转为字节格式
              padding.PKCS1v15(),
              hashes.SHA256() # 指定 SHA256 哈希算法
          )


          # 对签名结果进行 base64 编码
          base64_signature = base64.b64encode(signature).decode('UTF-8')
          rep_header = {
              "Authorization": f'WECHATPAY2-SHA256-RSA2048 mchid="{mchid}",nonce_str="{nonce_str}",signature="{base64_signature}",timestamp="{timestamp}",serial_no="{serial_no}"',
              'Accept': "application/json",
              "Content-Type": "application/json"
          }
          print(rep_header)
          return rep_header


      改成这样后 还是报签名错误,请检查后再试
      11-05
      回复
    • Memory
      Memory
      11-05回复L🦀 🦀
      你还是直接去用sdk吧https://github.com/minibear2021/wechatpayv3
      11-05
      回复
登录 后发表内容