python --微信v3支付

关于py支付的资源

https://www.cnblogs.com/mxhmxh/p/10763313.html
https://blog.csdn.net/qq_37193537/article/details/89497071

https://github.com/minibear2021/wechatpayv3 【推荐】
https://gitee.com/minibear2021/wechatpayv3
https://blog.csdn.net/jstony/article/details/115699372

支付:

import json
from random import sample
from string import ascii_letters, digits
from wechatpayv3 import WeChatPayType, WeChatPay


class WxPay(object):


    def init(self):
        MCHID = '166499xx'  # 微信支付商户号,服务商模式下为服务商户号,即官方文档中的sp_mchid。
        PRIVATE_KEY = open(r'D:\yi\code\duty_free_shop\pay_cert\apiclient_key.pem').read()
        # 商户证书私钥,此文件不要放置在下面设置的CERT_DIR目录里。
        CERT_SERIAL_NO = '1C169704EDB71xx' # 商户证书序列号
        APIV3_KEY = 'sdfdsfgdfgdfh8j64gh6xxx' # API v3密钥, https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
        APPID = 'wx7b6b1fd4xxxx' # APPID,应用ID,服务商模式下为服务商应用ID,即官方文档中的sp_appid,也可以在调用接口的时候覆盖。
        NOTIFY_URL = 'https://www.xxxx.com/notify' # 回调地址,也可以在调用接口的时候覆盖。
        CERT_DIR = './cert'
        PARTNER_MODE = False  # 接入模式:False=直连商户模式,True=服务商模式。
        return WeChatPay(
                        wechatpay_type=WeChatPayType.NATIVE,
                        mchid=MCHID,
                        private_key=PRIVATE_KEY,
                        cert_serial_no=CERT_SERIAL_NO,
                        apiv3_key=APIV3_KEY,
                        appid=APPID,
                        notify_url=NOTIFY_URL,
                        cert_dir=CERT_DIR,
                        partner_mode=PARTNER_MODE)

    def pay(self):
        wxpay = self.init()
        _, prepay_id = wxpay.pay(
                description='商品',
                out_trade_no=''.join(sample(ascii_letters + digits, 8)),
                amount={'total': 1},
                pay_type=WeChatPayType.APP)
        return json.loads(prepay_id).get('prepay_id')

a = WxPay()
print(a.pay())

v3支付

# from Crypto.PublicKey import RSA
# import random
# from Crypto.Signature import PKCS1_v1_5
# from Crypto.Hash import SHA256
# import base64
# import time
import time
import random
from Cryptodome.PublicKey import RSA
from Cryptodome.Signature import pkcs1_15 as PKCS1_v1_5
from Cryptodome.Hash import SHA256
import base64

class Authorization(object):
    def __init__(self):
        self.mchid = '1431536202'
        self.serial_no = '证书序列号'

    # 生成欲签名字符串
    def sign_str(self, method, url_path, timestamp, nonce_str, request_body):
        if request_body:
            # POST
            sign_list = [
                method,
                url_path,
                timestamp,
                nonce_str,
                request_body
            ]
            return '\n'.join(sign_list) + '\n'
        else:
            # GET
            sign_list = [
                method,
                url_path,
                timestamp,
                nonce_str
            ]
            return '\n'.join(sign_list) + '\n\n'

    # 生成随机字符串
    def getNonceStr(self):
        data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP"
        nonce_str = ''.join(random.sample(data, 30))
        return nonce_str

    # 生成签名
    def sign(self, sign_str):
        with open(r'./rsa_private_key.pem', 'r')as f:
            # 这里要注意的秘钥只能有三行
            # -----BEGIN PRIVATE KEY-----
            # ******************秘钥只能在一行,不能换行*****************
            # -----END PRIVATE KEY-----
            private_key = f.read()
            f.close()
            pkey = RSA.importKey(private_key)
            h = SHA256.new(sign_str.encode('utf-8'))
            signature = PKCS1_v1_5.new(pkey).sign(h)
            sign = base64.b64encode(signature).decode()
            return sign

    # 生成 Authorization
    def authorization(self, method, url_path, nonce_str, timestamp, body=None):
        # 加密子串
        signstr = self.sign_str(method=method, url_path=url_path, timestamp=timestamp, nonce_str=nonce_str,
                                request_body=body)
        # print("加密原子串:" + signstr)
        # 加密后子串
        s = self.sign(signstr)
        # print("加密后子串:" + s)
        authorization = 'WECHATPAY2-SHA256-RSA2048 ' \
                        'mchid="{mchid}",' \
                        'nonce_str="{nonce_str}",' \
                        'signature="{sign}",' \
                        'timestamp="{timestamp}",' \
                        'serial_no="{serial_no}"'. \
            format(mchid=self.mchid,
                   nonce_str=nonce_str,
                   sign=s,
                   timestamp=timestamp,
                   serial_no=self.serial_no
                   )
        return authorization


if __name__ == '__main__':
    method = "POST"
    url_path = "/v3/pay/transactions/jsapi"
    timestamp = str(int(time.time()))
    nonce_str = Authorization().getNonceStr()
    body = "{'appid': '*********', 'mchid': '**********', 'description': '爱奇艺周卡', 'out_trade_no': 'LY1111111111', 'notify_url': '******', 'amount': {'total': 100, 'currency': 'CNY'}, 'payer': {'openid': '***************'}}"
    authorization = Authorization().authorization(method=method, url_path=url_path, nonce_str=nonce_str,
                                                  timestamp=timestamp)
    print(authorization)

    import requests
    def to_json(kwargs):
        import json
        return json.dumps(kwargs, separators=(',', ':'))

    def requests_wx3(data, authorization, key_path="", cert_path=""):
        """
          apiV3 版本的微信支付请求
        """
        headers = {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': authorization}
        response = requests.post(url, data=to_json(data), headers=headers, cert=(cert_path, key_path))

        print(response.text)

    print(requests_wx3(url='https://api.mch.weixin.qq.com/v3/pay/transactions/app', ))

安卓支付

import time
import random
from Cryptodome.PublicKey import RSA
from Cryptodome.Signature import pkcs1_15
from Cryptodome.Hash import SHA256
from base64 import b64encode

mchid = '1431536202'
serial_no = '001'
with open(r'./rsa_private_key.pem', 'r')as f:
    private_key = f.read()
# private_key = "-----BEGIN PRIVATE KEY-----\n" \
#               "NIIEvgIBADANBgkqhkiG9w0B3QEFAA5CBKgwggSkAgEAAoIBAQC2l/hfX5g6qjo7" \
#               "BcqTa+LldQpd7m4ZZEKT2BxUpYPNJ/YoZO1c3qB/+CfQQlKJYPseOsTnUeuAZ2AG" \
#               "z2LWuh/36gmiFX2Nw1pI0AkVwec8pB1+IqLGHzRsAaDJ++2J88TcWOuM5lOcBr6I" \
#               "VJOyl1ghYB4Dnuk2uid46rAZwWL3L2FZ+ktfdtePt4zOQrpILRuDNzR6TOcd1JER" \
#               "ylt8iDyoVTr69ALnQdhoNnofnrBK3R4sY5ON1BR01DpZM8yX8mmb6yOLjp1VoP+5" \
#               "n8pCPVAqZJEbwfDH90naeMZLYfoCvdaJhxHLblviZN7v4VW6Fx/W43O9sRTNPukU" \
#               "W5pLBP57AgMBAAECggEBAI9U6iZLzx62A7HTUPq6ZMkEQB2OEyUhe9W8fjjAGJ9R" \
#               "8DwzRdRx+gGaVf54IXwvwdAwB+MhfkE0ZL/Tyd2PC4s7j0ZJol5G7Ddd/tOye4cx" \
#               "uOkL3USyuB7UhFgpx4RT88OYlYbsQtOmw6gW5D376bWBUu46rw1Dwbp8V7JQCRTJ" \
#               "K+vbMj1ytgP10fg/hTQNe7RWmd+KC+OGZbBH6MxybLoR+BOwQQpwGEgoEoY9Rmlm" \
#               "E/8poPvdY/PLIaS2ca/rsgJ/ZhiSx6BL0DAqVkKtM9U9T0LRoZmJcCp6YgLKGA0X" \
#               "BrnbMXczFHFVfjmK1jw4UqWbPICsrbhF4dtIuSqZbDECgYEA4M8J4T/grNaNhQTc" \
#               "x6q/ylFZB3I8Qoih2YeLx7/JOBEL66jNJhHVrgyF8JChlL0J8RGMg8KdxzZ0OTEw" \
#               "Q5ZK4mo93cxwqFh87X4KUNaicNveCsxuEL80Bbhst7NmJKi5T2VQMR9kFd+eTwx8" \
#               "c5aOHX5W4RIogKyNHqvCdEqHohMCgYEAz+1/NfRtqI2F68olrtdlbReaHtlCZxRJ" \
#               "3XhaIT5OGjXE/0upRRx6EgDh4f+wvqpFdlutPHFTSz4H/5rBGyZ7NJ5D44WO3Z7K" \
#               "SdY3YJ+5J6Nu+2OX6FGZWmqyW9kgYRthzClqNduBWbgu0gRC8R8wLg1W7xe9HN5e" \
#               "bc0HnhnBfvkCgYBSNMNbH/2rlkVn1/BX/yNk+zxAEdDhT49HuV4u6/3Lx8gBI9fo" \
#               "zOrDW4b7AhhkCICDK7SjVd5WQ55ab5dDj8jQZK384Q5tMPZ17fodt27tMClQ75Js" \
#               "A08lrFvtDOg6DbK9ysF5RQ5XRU9hfqJfrjVHqbRhVz+CVhbAmXRhDAPvC5KBgQCX" \
#               "kXuCvCvXi1qNF+1CN3eS/3p0dFEITOzPSXUB+KX8SyfQJbo9S9XcG9KM6NNRGVPL" \
#               "RGbSwZVDKvOvqoKLpRB4ucmpJ+mNubuh+Uqi36ubrnIvRFkum5TbKR3dADivMMOo" \
#               "jKQEoH75BN70bvDRTbfUShsN8ZAA5EQXbDbaU9IOGQKBgEr+xQMksLCif8GrwlfJ" \
#               "Vrf3uyXTyY1QVRAGy9UIiM0RnsWDaGcRgNaz1K9YV3gqm7qHe2y8fzB0PLLw2TzY" \
#               "GUwxIttKpnEVlX1M59nmGFmQq08YNC+JRHZrvmmB0MyEBSA9lg0ugASdQQC5PGYa" \
#               "Rnn7p8VlUEauVmFpF6BTVZLQ\n" \
#               "-----END PRIVATE KEY-----"
timestamp = str(int(time.time()))
nonce_str = str(random.randint(100000, 10000000))

def sign_str(method, url_path, request_body):
  """
  生成欲签名字符串
  """
  sign_list = [
    method,
    url_path,
    timestamp,
    nonce_str,
    request_body
  ]
  return '\n'.join(sign_list) + '\n'


def sign(sign_str):
  """
  生成签名
  """
  rsa_key = RSA.importKey(private_key)
  signer = pkcs1_15.new(rsa_key)
  digest = SHA256.new(sign_str.encode('utf8'))
  sign = b64encode(signer.sign(digest)).decode('utf8')
  return sign


def authorization(method, url_path, request_body):
  """
  生成Authorization
  """
  signstr = sign_str(method, url_path, request_body)
  s = sign(signstr)
  authorization = 'WECHATPAY2-SHA256-RSA2048  ' \
            'mchid="{mchid}",' \
            'nonce_str="{nonce_str}",' \
            'signature="{sign}",' \
            'timestamp="{timestamp}",' \
            'serial_no="{serial_no}"'.\
            format(mchid=mchid,
                   nonce_str=nonce_str,
                   sign=s,
                   timestamp=timestamp,
                   serial_no=serial_no
                  )
  return authorization


if __name__ == '__main__':
  print(authorization('POST', '/v3/marketing/favor/users/openid/coupons', '{"stock_id":"123","stock_creator_mchid":"1302430101","out_request_no":"20190522_001","appid":"your appid"}'))
  # Authorization WECHATPAY2-SHA256-RSA2048 mchid="1312030806",nonce_str="f0wwnSIuQN8yDr0U4bYKNmUgALcMUCLM",sig
  # nature="dcFTPfaAewd+UXuXv+VA+KeGW1coUG68PtklWtsMiFGal5GxiljGUVGV60gBnIo2La1R3cxf7mOb62q7xoab9mP1SZ5dP8L+amQ
  # 9vyl+ZYTaJOg31vtkDwMU0ILNqy96SuKy+5/Q2NSCQU0fBLMWU11vbSoA2ycEsCjDEknc8Hiw+vyKkV6iGyUNBMizfwZhJWdRcWDWeyxAy
  # 0rsaZKVOpeEyJ2xPQnLX8uB+gqCIO5+vE8KYjseXPGun+Zr6i5gl7i0O/BdBfY4BDRAZsrF5v7LikptEbRwJ8+1IevIT5LaUc5J5BnGM00
  # 9BuzsZzK8cphhKvepVmA8Gy0gWvfDeA==",timestamp="1592375315",serial_no="14DFFAAAA79AF4BD56CC1O55E06246E95D3PAAS0"
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
微信支付v3 版本相比较 v2 版本有了很多变化和升级,包括接口地址、签名方式、请求参数等等。在 Python 中对接微信支付 v3 接口,需要使用到官方提供的 SDK 和第三方库。 下面是一个简单的对接微信支付 v3 的示例代码: 1. 安装依赖库:需要安装 `wechatpay` 和 `requests` 两个库,可以通过 pip 命令进行安装: ```python pip install wechatpay requests ``` 2. 导入 SDK 和库: ```python import wechatpay import wechatpay.utils as utils import requests ``` 3. 配置商户证书和密钥: ```python merchant_id = '商户号' api_key = 'API密钥' cert_file = 'apiclient_cert.pem' key_file = 'apiclient_key.pem' ``` 4. 使用 SDK 创建支付订单: ```python url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi' nonce_str = utils.generate_random_string(32) timestamp = utils.get_current_timestamp() body = { "mchid": merchant_id, "appid": "应用ID", "description": "商品描述", "out_trade_no": "商户订单号", "amount": { "total": 1, "currency": "CNY" }, "payer": { "openid": "用户openid" } } headers = { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': 'WECHATPAY2-SHA256-RSA2048 ' + wechatpay.get_authorization_header( method='POST', url=url, body=body, merchant_id=merchant_id, api_key=api_key, cert_file=cert_file, key_file=key_file, nonce_str=nonce_str, timestamp=timestamp ) } response = requests.post(url, headers=headers, json=body) ``` 5. 处理返回结果: ```python if response.status_code == 200: result = response.json() prepay_id = result.get('prepay_id') return_data = { 'appId': '应用ID', 'timeStamp': str(timestamp), 'nonceStr': nonce_str, 'package': 'prepay_id=' + prepay_id, 'signType': 'RSA', 'paySign': wechatpay.get_sha256withrsa_signature( timestamp + '\n' + nonce_str + '\n' + 'prepay_id=' + prepay_id + '\n', key_file=key_file ) } else: error_msg = response.json().get('message') return {'error': error_msg} ``` 以上是一个简单的微信支付 v3 对接示例,具体实现还需要根据自己的业务需求进行调整。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像风一样的男人@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值