亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python實現支付寶二維碼支付(沙箱環境)

系統 1910 0

Python實現支付寶二維碼支付

一.沙箱環境配置

1.登陸螞蟻金融開放平臺:https://openhome.alipay.com

2.選擇進入我的開放平臺。尋找開發中心的研發服務。

Python實現支付寶二維碼支付(沙箱環境)_第1張圖片

3.點擊沙箱環境—沙箱應用

Python實現支付寶二維碼支付(沙箱環境)_第2張圖片

4.這里博主已經配置好密鑰了,所以在RSA2(SHA256)密鑰(推薦)這邊跟沒有注冊的不太一樣。

? ?如果沒有配置過密鑰請繼續向下看,密鑰配置完畢跳到代碼處

5.下載RSA密鑰生成工具:https://docs.open.alipay.com/291/105971

? ?根據網頁中的使用步驟配置即可

6.因為是沙箱測試,需要下載沙箱支付寶以便測試,但是沙箱支付寶僅支持安卓系統,需要一部安卓手機。

二.Python代碼編寫

1.首先準備需要的庫:

如果是使用pycharm,博主在自己的github上已經配好了所需要的庫,

可以直接訪問博主的github:https://github.com/PythonStriker/Alipay_for_QR_code

省下很多步驟如果不是使用paycharm,需要自己配置所需要的庫:

Python實現支付寶二維碼支付(沙箱環境)_第3張圖片

?2.代碼如下所示:

pay.py

            
              __author__ = 'PythonStriker'

from self_Alipay import *
import qrcode,time

APPID = 自己的appid號
private_key = '''-----BEGIN RSA PRIVATE KEY-----
自己的支付寶私鑰
-----END RSA PRIVATE KEY-----
'''
public_key = '''-----BEGIN PUBLIC KEY-----
自己的支付寶公鑰
-----END PUBLIC KEY-----
'''

class pay:
    def __init__(self,out_trade_no,total_amount,subject,timeout_express):
        self.out_trade_no = out_trade_no
        self.total_amount = total_amount
        self.subject = subject
        self.timeout_express = timeout_express

    def get_qr_code(self,code_url):
        '''
        生成二維碼
        :return None
        '''
        qr = qrcode.QRCode(
             version=1,
             error_correction=qrcode.constants.ERROR_CORRECT_H,
             box_size=10,
             border=1
        )
        qr.add_data(code_url)  # 二維碼所含信息
        img = qr.make_image()  # 生成二維碼圖片
        img.save(r'自己需要保存的路徑')
        print('二維碼保存成功!')

    def query_order(self,out_trade_no: int):
        '''
        :param out_trade_no: 商戶訂單號
        :return: Nonem
        '''
        _time = 0
        for i in range(600):
            time.sleep(1)
            result = alipay.init_alipay_cfg().api_alipay_trade_query(out_trade_no=out_trade_no)
            if result.get("trade_status", "") == "TRADE_SUCCESS":
                print('訂單已支付!')
                print('訂單查詢返回值:', result)
                return True
            _time += 2
        return False


if __name__ == '__main__':
    alipay = alipay(APPID, private_key, public_key)
    payer = pay(out_trade_no="訂單號",total_amount= 價格,subject = "商品名字",timeout_express='訂單超時取消時間 單位:s,m')
    dict = alipay.trade_pre_create(out_trade_no=payer.out_trade_no,total_amount=payer.total_amount,subject =payer.subject,timeout_express=payer.timeout_express )

    payer.get_qr_code(dict['qr_code'])
    payer.query_order(payer.out_trade_no)
            
          

代碼有幾處需要注意的地方: 公鑰私鑰,appid,二維碼圖片保存地址,主函數中payer實例化訂單號,價格,商品名字,超市取消時間都是需要自己填寫的!

在主函數中,調用的方法已經寫出來了,可以在別的模塊中用相同的調用方法,博主會在之后的文章中演示,如何在別的模塊中,完成調用,并驗證是否付款成功。

self_Alipay.py

            
              # -*- coding: UTF-8 -*-
import base64
import collections
import copy
import json
from datetime import datetime
from urllib import request, parse
import rsa
from alipay import AliPay
APP_ID = '需要填寫'
private_key = '''-----BEGIN RSA PRIVATE KEY-----
需要填寫
-----END RSA PRIVATE KEY-----
'''
public_key = '''-----BEGIN PUBLIC KEY-----
需要填寫
-----END PUBLIC KEY-----
'''

class alipay:
    def __init__(self, app_id, private_key, public_key, notify_url=None, charset='gbk', sign_type='RSA2',
                 version='1.0', DEBUG=True):#需要注意,自己編碼類型是否是RSA2
        self.requesturl = 'https://openapi.alipay.com/gateway.do' if DEBUG is False else "https://openapi.alipaydev.com/gateway.do"
        self.private_key = private_key
        self.public_key = public_key
        self.params = dict(app_id=app_id, charset=charset, sign_type=sign_type, version=version,
                           biz_content={}, timestamp='', notify_url=notify_url)

    def _sort(self, params):
        #print(collections.OrderedDict(sorted(dict(params).items(), key=lambda x: x[0])))
        return collections.OrderedDict(sorted(dict(params).items(), key=lambda x: x[0]))

    @staticmethod
    def make_goods_etail(goods_detail=None, alipay_goods_id=None, goods_name=None, quantity=None, price=None,
                         goods_category=None, body=None, show_url=None):
        params = dict(goods_detail=goods_detail, alipay_goods_id=alipay_goods_id, goods_name=goods_name,
                      quantity=quantity, price=price, goods_category=goods_category, body=body, show_url=show_url)
        return dict(filter(lambda x: x[1] is not None, params.items()))

    def _make_sign(self, params, **kwargs):
        private_key = rsa.PrivateKey.load_pkcs1(kwargs.get('private_key', None) or self.private_key)
        sign = base64.b64encode(rsa.sign(params.encode(), private_key, "SHA-256")).decode('gbk')
        return sign

    def _check_sign(self, message, sign, **kwargs):
        message = self._sort(message)
        data = '{'
        for key, value in message.items():
            data += '"{}":"{}",'.format(key, value)
        data = data[:-1] + '}'
        sign = base64.b64decode(sign)
        public_key = rsa.PublicKey.load_pkcs1_openssl_pem(kwargs.get('public_key', None) or self.public_key)
        try:
            rsa.verify(data.encode(), sign, public_key)
            return True
        except Exception:
            return False

    def _make_request(self, params, biz_content, **kwargs):
        buf = ''
        params['timestamp'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        params['biz_content'] = json.dumps(self._sort(biz_content))
        for key, value in kwargs.items():
            params[key] = value
        params = self._sort(params)
        for key in params:
            buf += '{}={}&'.format(key, params[key])
        params['sign'] = self._make_sign(buf[:-1], **kwargs)
        #print(params)
        # 發射http請求取回數據
        data = request.urlopen(self.requesturl, data=parse.urlencode(params).encode('gbk')).read().decode('gbk')
        #print(parse.urlencode(params).encode('gbk'))
        return data

    def parse_response(self, params, **kwargs):
        sign = params['sign']
        if self._check_sign(dict(filter(lambda x: 'sign' not in x[0], params.items())), sign, **kwargs):
            return True
        else:
            return False

    def trade_pre_create(self, out_trade_no, total_amount, subject, seller_id=None, discountable_amount=None,
                         undiscountable_amount=None, buyer_logon_id=None, body=None, goods_detail=None,
                         operator_id=None, store_id=None, terminal_id=None, timeout_express=None, alipay_store_id=None,
                         royalty_info=None, extend_params=None, **kwargs):
        """
        :param out_trade_no:    商戶訂單號,64個字符以內、只能包含字母、數字、下劃線;需保證在商戶端不重復.
        :param total_amount:    訂單總金額,單位為元,精確到小數點后兩位.
        :param subject:         訂單標題.
        :param seller_id:       賣家支付寶用戶ID。 如果該值為空,則默認為商戶簽約賬號對應的支付寶用戶ID.
        :param discountable_amount:可打折金額. 參與優惠計算的金額,單位為元,精確到小數點后兩位,取值范圍[0.01,100000000]
        :param undiscountable_amount:不可打折金額. 不參與優惠計算的金額,單位為元,精確到小數點后兩位,取值范圍[0.01,100000000]
        :param buyer_logon_id:      買家支付寶賬號
        :param body:                對交易或商品的描述
        :param goods_detail:        訂單包含的商品列表信息.使用make_goods_etail生成. 其它說明詳見:“商品明細說明”
        :param operator_id:         商戶操作員編號
        :param store_id:            商戶門店編號
        :param terminal_id:         商戶機具終端編號
        :param timeout_express:     該筆訂單允許的最晚付款時間,逾期將關閉交易。取值范圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天
        :param alipay_store_id:     支付寶店鋪的門店ID
        :param royalty_info:        描述分賬信息   暫時無效
        :param extend_params:       業務擴展參數	暫時無效
        :param kwargs:              公共參數可在此處暫時覆蓋
        :return:
        """
        params = copy.deepcopy(self.params)
        params['method'] = 'alipay.trade.precreate'
        total_amount = round(int(total_amount), 2)
        if discountable_amount:
            discountable_amount = round(int(discountable_amount), 2)
        if undiscountable_amount:
            undiscountable_amount = round(int(undiscountable_amount), 2)
        if discountable_amount:
            if undiscountable_amount is not None:
                if discountable_amount + undiscountable_amount != total_amount:
                    return '傳入打折金額錯誤'
        biz_content = dict(out_trade_no=out_trade_no[:64], total_amount=total_amount, seller_id=seller_id,
                           subject=subject,
                           discountable_amount=discountable_amount, undiscountable_amount=undiscountable_amount,
                           buyer_logon_id=buyer_logon_id, body=body, goods_detail=goods_detail, operator_id=operator_id,
                           store_id=store_id, terminal_id=terminal_id, timeout_express=timeout_express,
                           alipay_store_id=alipay_store_id, royalty_info=royalty_info, extend_params=extend_params)
        #print(biz_content)
        resp = self._make_request(params, dict(filter(lambda x: x[1] is not None, biz_content.items())), **kwargs)
        #print(resp)
        check = eval(resp)
        resp = json.loads(resp)['alipay_trade_precreate_response']
        if self._check_sign(check['alipay_trade_precreate_response'], check['sign']):
            return resp
        return False

    def trade_refund(self, refund_amount, out_trade_no=None, trade_no=None,
                     refund_reason=None, out_request_no=None, operator_id=None, store_id=None,
                     terminal_id=None, **kwargs):
        """

        :param refund_amount:   需要退款的金額,該金額不能大于訂單金額,單位為元,支持兩位小數
        :param out_trade_no:    商戶訂單號,不可與支付寶交易號同時為空
        :param trade_no:        支付寶交易號,和商戶訂單號不能同時為空
        :param refund_reason:   退款的原因說明
        :param out_request_no:  標識一次退款請求,同一筆交易多次退款需要保證唯一,如需部分退款,則此參數必傳。
        :param operator_id:     商戶的操作員編號
        :param store_id:        商戶的門店編號
        :param terminal_id:     商戶的終端編號
        :param kwargs:          公共參數可在此處臨時覆蓋
        :return:
        """
        params = copy.deepcopy(self.params)
        params['method'] = 'alipay.trade.refund'
        refund_amount = round(float(refund_amount), 2)

        biz_content = dict(refund_amount=refund_amount, out_trade_no=out_trade_no, trade_no=trade_no,
                           refund_reason=refund_reason, out_request_no=out_request_no, operator_id=operator_id,
                           store_id=store_id, terminal_id=terminal_id)
        resp = self._make_request(params, dict(filter(lambda x: x[1] is not None, biz_content.items())), **kwargs)
        check = eval(resp)
        resp = json.loads(resp)['alipay_trade_refund_response']
        if self._check_sign(check['alipay_trade_refund_response'], check['sign']):
            return int(resp['code']) == 10000
        return False

    def trade_query(self, out_trade_no, trade_no=None, **kwargs):
        params = copy.deepcopy(self.params)
        params['method'] = 'alipay.trade.query'

        biz_content = dict(out_trade_no=out_trade_no, trade_no=trade_no)
        resp = self._make_request(params, dict(filter(lambda x: x[1] is not None, biz_content.items())), **kwargs)
        check = eval(resp)
        resp = json.loads(resp)['alipay_trade_query_response']
        if self._check_sign(check['alipay_trade_query_response'], check['sign']) and resp['code'] == 10000:
            return resp
        return False

    def init_alipay_cfg(self):
        alipay = AliPay(
            appid=APP_ID,
            app_notify_url=None,  # 默認回調url
            app_private_key_string=private_key,
            alipay_public_key_string=public_key,  # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你自己的公鑰,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默認False ,若開啟則使用沙盒環境的支付寶公鑰
        )
        return alipay
            
          

該代碼也有幾處需要注意的地方:公鑰密鑰,appid, 特別注意自己加密形式RSA 或者 RSA2之前博主吃過大虧。

#---------------------------------------------------------------------------------------------------------------------------#

特別注意事項:

1.這個支付寶端口支持的是非java端口,使用PKCS1加密方式密匙。

2.支付寶應用公鑰,和支付寶公鑰要分清楚。本代碼中需要填寫的是支付寶公鑰!

3.其實PKCS8的小伙伴也不用悲傷,支付寶自帶格式轉換,如下圖:

Python實現支付寶二維碼支付(沙箱環境)_第4張圖片

只需要將自己的PKCS8(JAVA適用)轉換PKCS1(非JAVA適用)的密鑰,本文代碼依舊可以使用。

#---------------------------------------------------------------------------------------------------------------------------#

可以用自己的沙箱支付寶測試,是否可以支付。

附加成功示例:

Python實現支付寶二維碼支付(沙箱環境)_第5張圖片

Python實現支付寶二維碼支付(沙箱環境)_第6張圖片


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 中中文字幕乱码 | www.国产福利视频.com | 亚洲欧美v视色一区二区 | 日本综合久久 | 97视频在线观看免费播放 | 人人爱天天做夜夜爽2020麻豆 | 全黄h全肉边做边吃奶在线观看 | 在线看片福利 | 99热这里只有精 | 99久久做夜夜爱天天做精品 | 中文一区二区视频 | 国产一级一级毛片 | 精品国产一区二区三区www | 欧美精品综合一区二区三区 | 久久久毛片| 天天射天天搞 | 亚洲成a人在线播放www | 97av视频在线播放 | 豆奶视频污 | 国产人成精品综合欧美成人 | 免费一级欧美片在线观看 | 亚洲高清视频在线 | 久久国产精彩视频 | 五月开心六月伊人色婷婷 | 黄色网址在线免费 | 亚洲精品国产经典一区二区 | 一区二区三区亚洲视频 | 婷婷激情在线视频 | 九九热这里有精品 | 青青操在线观看 | 中文字幕一区二区在线视频 | 天天毛片 | 亚洲精品色一区二区三区 | 国产黄mmd在线观看免费 | 999精品国产 | 国内精品视频在线播放一区 | 欧美大屁股精品毛片视频 | 日本伊人色 | 欧美香蕉爽爽人人爽观看猫咪 | 久久综合色婷婷 | 国产边打电话边被躁视频 |