微信APP支付V3版本簽名 && APP下單/訂單查詢接口Python版實(shí)現(xiàn)

問題背景

最近接入微信支付,微信官方并沒有提供Python版的服務(wù)端SDK,因而只能根據(jù)文檔手動(dòng)實(shí)現(xiàn)一版,這里記錄一下微信支付的整體流程、踩坑過程與最終具體實(shí)現(xiàn)。

10余年的江蘇網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營(yíng)銷型網(wǎng)站的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整江蘇建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“江蘇網(wǎng)站設(shè)計(jì)”,“江蘇網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

微信支付APP下單流程

根據(jù)微信官方文檔: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_5_2.shtml
下單流程如下:

和支付寶不同,微信多了一個(gè)預(yù)付單的概念,這里把APP下單實(shí)際分為四大部分,其中包含請(qǐng)求微信后端需要的首次簽名和需要返回給APP的二次支付信息簽名--這里踩一個(gè)小坑,流程圖中并沒把第二次簽名支付信息需要返回給APP的步驟畫出來(即下面的步驟6.5),因而一開始誤以為只需要返回prepay_id給客戶端,導(dǎo)致校驗(yàn)失敗。
一. 對(duì)應(yīng)步驟1~4,APP 請(qǐng)求業(yè)務(wù)后端,業(yè)務(wù)后臺(tái)進(jìn)行V3簽名后,請(qǐng)求微信后端生成預(yù)付單prepay_id
二. 對(duì)應(yīng)步驟5~6.5,業(yè)務(wù)后端收到微信后端返回prepay_id,將支付相關(guān)參數(shù)打包進(jìn)行二次簽名后返回給APP,這里相比流程圖多了一個(gè)6.5--即業(yè)務(wù)后端返回簽名支付信息到APP
三. 對(duì)應(yīng)步驟7~18,APP收到業(yè)務(wù)后端返回簽名支付信息后調(diào)起SDK發(fā)起支付請(qǐng)求,收到同步消息結(jié)果通知
四. 對(duì)應(yīng)步驟19~22,APP查詢業(yè)務(wù)后端,業(yè)務(wù)后端通過回調(diào)通知或直接查詢微信后端返回最終支付結(jié)果

代碼實(shí)現(xiàn)

首次簽名邏輯

第一次請(qǐng)求生成預(yù)付單號(hào)的簽名文檔為:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml, 共5個(gè)部分參與簽名,其組成格式為:

HTTP請(qǐng)求方法\nURL\n請(qǐng)求時(shí)間戳\n請(qǐng)求隨機(jī)串\n請(qǐng)求報(bào)文主體\n

對(duì)應(yīng)簽名代碼:

class WechatPayDALBase(object):
    def __init__(self, mch_appid, mchid, v3key, serial_no, client_key):
        self.mch_appid = mch_appid
        self.mchid = mchid
        self.v3key = v3key
        # serial_no可通過openssl直接獲取, 例: openssl x509 -in __cert.pem -noout -serial
        self.serial_no = serial_no

        with open(client_key, 'r') as ifile:
            pkey = RSA.importKey(ifile.read())
        self.signer = pkcs1_15.new(pkey)

    def compute_sign_v3(self, method, url, body):
        '''
        V3簽名邏輯
        '''
        ts = int(time.time())
        nonce = self.generate_nonce()
        uparts= parse_url(url)
        ustr = uparts.path + ('?{}'.format(uparts.query) if uparts.query else '')
        content = '{}\n{}\n{}\n{}\n{}\n'.format(method, ustr, ts, nonce, body)

        digest = SHA256.new(content.encode('utf-8'))
        sign_v = base64.b64encode(self.signer.sign(digest)).decode('utf-8')
        sign_str = 'serial_no="{}",mchid="{}",timestamp="{}",nonce_str="{}",signature="{}"'.format(
                    self.serial_no, self.mchid, ts, nonce, sign_v)
        return sign_str

    def make_headers_v3(self, url, headers=None, body='', method='GET'):
        '''
        微信支付V3版本簽名header生成函數(shù)
        '''
        if not headers:
            headers = {}
        headers['Accept'] = 'application/json'
        sign = self.compute_sign_v3(method, url, body)
        auth_info = 'WECHATPAY2-SHA256-RSA2048 {}'.format(sign)
        headers['Authorization'] = auth_info
        return headers

    def generate_nonce(self):
        rnd = int(time.time()) + random.randint(, )
        nonce = hashlib.md5(str(rnd).encode()).hexdigest()[:16]
        return nonce

二次簽名邏輯

由業(yè)務(wù)后端返回給APP的二次簽名信息文檔為:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_4.shtml
共4個(gè)部分參與簽名,其組成格式為:

應(yīng)用id\n時(shí)間戳\n隨機(jī)字符串\n預(yù)支付交易會(huì)話ID\n

返回簽名支付信息的對(duì)應(yīng)代碼:

    def get_pay_sign_info(self, prepay_id):
        ts = int(time.time())
        nonce = self.generate_nonce()
        content = '{}\n{}\n{}\n{}\n'.format(self.mch_appid, ts, nonce, prepay_id)

        digest = SHA256.new(content.encode('utf-8'))
        sign_v = base64.b64encode(self.signer.sign(digest)).decode('utf-8')
        return {
            'appid': self.mch_appid,
            'partnerid': self.mchid,
            'timestamp': str(ts),
            'noncestr': nonce,
            'prepay_id': prepay_id,
            'package': 'Sign=WXPay',
            'sign': sign_v,
        }

業(yè)務(wù)后端查詢訂單詳情

文檔地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_2.shtml
代碼如下:

    def query_order(self, out_trade_no):
        '''
        查詢指定訂單信息
        '''
        url = f'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}?mchid={self.mchid}'
        headers = self.make_headers_v3(url)
        rsp = requests.get(url, headers=headers)
        pay_logger.info('out_trade_no:{}, rsp:{}|{}'.format(out_trade_no, rsp.status_code, rsp.text))
        rdct = rsp.json()
        return rdct

業(yè)務(wù)后端調(diào)用APP下單API

文檔地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
代碼如下:

    def create_order_info(self, data, callback_url):
        '''
        創(chuàng)建微信預(yù)支付訂單, 注意包含兩次簽名過程:
        首次簽名用于請(qǐng)求微信后端獲取prepay_id
        二次簽名信息返回客戶端用于調(diào)起SDK支付
        '''
        url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/app'
        ndt = datetime.now()
        out_trade_no = self.generate_partner_trade_no(ndt)
        data = {
            'mchid': self.mchid,
            'out_trade_no': out_trade_no,
            'appid': self.mch_appid,
            'description': data['subject'],
            'notify_url': callback_url,
            'amount': {
                'currency': 'CNY',
                'total': int(data['price']),
            },
            'time_expire': (ndt + timedelta(minutes=5)).strftime('%Y-%m-%dT%H:%M:%S+08:00')
        }
        jdata = json.dumps(data, separators=[',', ':'])
        headers = {'Content-Type': 'application/json'}
        # 第一次簽名, 直接請(qǐng)求微信后端
        headers = self.make_headers_v3(url, headers=headers, body=jdata, method='POST')
        rsp = requests.post(url, headers=headers, data=jdata)
        pay_logger.info('rsp:{}|{}'.format(rsp.status_code, rsp.text))
        rdct = rsp.json()
        # 第二次簽名, 返回給客戶端調(diào)用
        sign_info = self.get_pay_sign_info(rdct['prepay_id'])
        return sign_info

源碼地址

試水代碼開源,把相關(guān)代碼分享在了github:https://github.com/liuzhi67/wechat-pay-python

轉(zhuǎn)載請(qǐng)注明出處,原文地址:https://www.cnblogs.com/AcAc-t/p/wechat_pay_by_python.html

文章標(biāo)題:微信APP支付V3版本簽名 && APP下單/訂單查詢接口Python版實(shí)現(xiàn)
網(wǎng)頁路徑:http://m.kartarina.com/article4/dsoghie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)App設(shè)計(jì)動(dòng)態(tài)網(wǎng)站、關(guān)鍵詞優(yōu)化品牌網(wǎng)站制作App開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
主站蜘蛛池模板: 亚洲AV无码一区二区二三区软件 | 少妇性饥渴无码A区免费| 日韩乱码人妻无码中文字幕| 亚洲午夜无码毛片av久久京东热| 国产精品无码一区二区在线观| 国产成人无码精品久久久久免费| 成人无码AV一区二区| 无码永久免费AV网站| 国产成人无码一区二区三区在线 | 亚洲最大av资源站无码av网址| 午夜寂寞视频无码专区| 日韩欧国产精品一区综合无码| 亚洲精品无码专区| 国产午夜无码精品免费看动漫| 亚洲啪AV永久无码精品放毛片| 国产∨亚洲V天堂无码久久久| 无码人妻精品内射一二三AV| 亚洲av无码无在线观看红杏| 蜜臀亚洲AV无码精品国产午夜. | 国产亚洲?V无码?V男人的天堂| 精品人妻大屁股白浆无码| 国产成人亚洲综合无码| 在线看片无码永久免费视频| 亚洲AV无码久久精品狠狠爱浪潮| 亚洲午夜无码片在线观看影院猛| 无码夫の前で人妻を侵犯| 国产aⅴ无码专区亚洲av| 国产激情无码一区二区三区| 丰满少妇人妻无码专区| 在线观看无码不卡AV| 久久人妻av无码中文专区| 精品久久久久久无码中文字幕| 内射精品无码中文字幕| 精品久久久无码人妻中文字幕豆芽| 无码AV片在线观看免费| 国产精品视频一区二区三区无码| 国产亚洲AV无码AV男人的天堂 | 亚洲久热无码av中文字幕| 久久久亚洲精品无码| 无码人妻少妇色欲AV一区二区| 亚洲精品无码久久久久sm|