微信小程序实现微信支付功能fastapi【前后端实现】

import datetime
import json
import os
import random
import string
import time
import OpenSSL
import base64
import requests
from urllib.parse import urlparse
from cryptography.hazmat.primitives.ciphers.aead import AESGCM


# V3版支付
class WxPayV3(object):
    basedir = os.path.abspath(os.path.dirname(__file__))  # 获取当前目录

    def __init__(self, ignore_resp_sign=False):
        """
        :param ignore_resp_sign: 是否忽略应答验签(用于第一次缓存证书)
        """
        self.app_id = 'wx14bcda174b'
        self.mch_id = '1626238'
        self.api_v3_key = 'Hyper_20220344566244_hyper'
        self.serial_no = '4F74DF09B282ED821206A'  # 证书序列号(微信支付商户平台获取)
        self.ignore_resp_sign = ignore_resp_sign
        self.certificates_path = self.basedir + '/certificates.json'
        self.get_certificates_from_wx()

        # 检查证书是否需要更新
        # if not os.path.exists(self.certificates_path):
        #       # 如果证书文件不存在,则获取证书
        #     print("证书文件不存在,则获取证书")
        # else:
        #     # 判断证书是否过期,如果过期则更新证书
        #     print("判断证书是否过期,如果过期则更新证书")
        #     with open(self.certificates_path, 'r') as f:
        #         content = f.read()
        #         print(content)
        #     certificates = json.loads(content)
        #     for certificate in certificates:
        #         expiry_time = certificate.get('expire_time')
        #         if expiry_time and datetime.datetime.now() > datetime.datetime.strptime(expiry_time,'%Y-%m-%dT%H:%M:%SZ'):
        #             print("证书过期,更新证书")
        #             self.get_certificates_from_wx()  # 证书过期,更新证书
        #             break
    # 支付签名
    @staticmethod
    def sign(s):
        # 这里的key为示例
        # api_client_key = ("-----BEGIN PRIVATE KEY-----\n"
        #                   "MIIEvQIBADANBgkqhkiG9w0BAQEFAAIBAQDAPM45XP7PC6qe\n"
        #                   "MIIEvQIBADANBgkqhkiG9w0BAgEAAoIBAQDAP7PC6qe\n"
        #                   "Kkh/7UGUD/hxkPwNB2PKAms=\n"
        #                   "-----END PRIVATE KEY-----")
        current_dir = os.path.dirname(os.path.abspath(__file__))

        # 构建 apiclient_key.pem 文件的完整路径
        pem_file_path = os.path.join(current_dir, 'apiclient_key.pem')

        # 打开文件
        with open(pem_file_path, 'r') as f:
            # 这里要注意的秘钥只能有三行
            # -----BEGIN PRIVATE KEY-----
            # ******************秘钥只能在一行,不能换行*****************
            # -----END PRIVATE KEY-----
            api_client_key = f.read()
        pkey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, api_client_key)
        signature = base64.b64encode(OpenSSL.crypto.sign(pkey=pkey, data=s.encode(), digest='SHA256'))
        return signature.decode()

    # 请求签名
    def _auth(self, req):
        data = req.method + '\n'
        parsed = urlparse(req.url)
        data += parsed.path
        if parsed.query:
            data += "?" + parsed.query
        data += '\n'
        timestamp = str(int(time.time()))
        data += timestamp + '\n'
        nonce_str = ''.join(random.sample(string.ascii_letters + string.digits, 32))
        data += nonce_str + '\n'
        if req.data:
            data += req.data
        data += '\n'
        signature = self.sign(data)
        authorization = ('WECHATPAY2-SHA256-RSA2048 '
                         'mchid="{0}",nonce_str="{1}",'
                         'signature="{2}",timestamp="{3}",'
                         'serial_no="{4}"').format(self.mch_id,
                                                   nonce_str,
                                                   signature,
                                                   timestamp,
                                                   self.serial_no)
        req.headers["Authorization"] = authorization
        req.headers['Content-Type'] = 'application/json'
        req.headers['Accept'] = 'application/json'
        req.headers['User-Agent'] = 'requests ' + requests.__version__
        r = req.prepare()
        s = requests.Session()
        resp = s.send(r, timeout=2)
        # 验签
        if not self.ignore_resp_sign:
            nonce = resp.headers
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值