微信上传图片时签名及请求格式问题,python伪代码
发布于 3 年前 作者 longgang 3377 次浏览 来自 分享
import json
import random
import string
import time
from base64 import encodebytes

import requests
from Cryptodome.PublicKey import RSA
from Crypto.Hash import SHA256
from Crypto.Signature import PKCS1_v1_5

KEY_PATH = "证书路径"
mch_id = "商户号"
serial_No = "商户序列号"

def nonce_str(length=30):
    char = string.ascii_letters + string.digits
    return "".join(random.choice(char) for _ in range(length))

def sign_v3(method, url, timestamp, nonce_str, body):
    sign_list = [
        method,
        url,
        timestamp,
        nonce_str,
        body
    ]
    # 每个字符都需要"\n"拼接
    message = '\n'.join(sign_list) + '\n'
    with open(KEY_PATH, mode='r') as f:
        signer = PKCS1_v1_5.new(RSA.importKey(f.read()))
    signature = signer.sign(SHA256.new(message.encode("utf-8")))
    sign = encodebytes(signature).decode("utf8").replace("\n", "")
    return sign

def authorization(sign, nonce_str, timestamp):
    """
     拼接api版本中请求头的authorization的值
    """
    return 'WECHATPAY2-SHA256-RSA2048 mchid="{michid}",' \
           'nonce_str="{nonce_str}",timestamp="{timestamp}",' \
           'serial_no="{serial_no}",signature="{signature}"'.format(
        michid=mch_id, nonce_str=nonce_str, timestamp=timestamp,
        serial_no=serial_No, signature=sign)

def get_authorization(method: str, url: str, body: str = ""):
    timestamp = str(int(time.time()))
    nonce_tr = nonce_str()
    # 拼接签名时的url需要从/v3开始,["", "/v3..."]
    sign_url = url.split("https://api.mch.weixin.qq.com",
                         maxsplit=1)[1]
    sign = sign_v3(method, sign_url, timestamp, nonce_tr, body)
    # headers里'Authorization'请求字段
    aut = authorization(sign, nonce_tr, timestamp)
    
    return aut

file_path = "图片路径"
file_name = "图片名字"
url = "https://api.mch.weixin.qq.com/v3/merchant-service/" \
                  "images/upload"
with open(file_paths, "rb") as f:
    data_sha256 = SHA256.new(f.read()).hexdigest()

meta = {"filename": file_name, "sha256": data_sha256}
aut = get_authorization("POST", url, json.dumps(meta))
# 请求头构建
headers = {
    "Content-Type": "multipart/form-data",
    "Authorization": aut
}

# 数据请求体
body = {
    "meta": json.dumps(meta)
}
# 传文件时格式
files = [("file", ("file_name", open(file_path, "rb"), "image/png"))]

response = requests.post(url, data=body, files=files, headers=headers)

回到顶部