Python實現微信刷卡支付(條碼支付)MicroPay


    轉載請注明原文地址:http://www.cnblogs.com/ygj0930/p/7686765.html

    一:資料閱讀

    場景介紹:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=5_1

    支付流程:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=5_4

    提交刷卡支付:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1

    查詢訂單支付結果:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2

 

    二:配置信息准備

# ========支付相關配置信息===========
    _APP_ID = "";  # 公眾賬號appid
    _MCH_ID = "";  # 商戶號
    _API_KEY = "";  # 微信商戶平台(pay.weixin.qq.com) -->賬戶設置 -->API安全 -->密鑰設置,設置完成后把密鑰復制到這里
    _host_name = socket.gethostname()
    _ip_address = socket.gethostbyname(_host_name)
    _CREATE_IP = _ip_address;  # 發起支付ip

    # 有關url
    _MICROPAY_URL = "https://api.mch.weixin.qq.com/pay/micropay"; #刷卡支付api
    _QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery"; #查詢訂單支付結果api

    

    三:編寫刷卡支付工具類

    1:輔助函數

    def get_sign_for_wx(self, para, key):
        '''
        根據算法, 生成微信支付簽名
        :param cr:
        :param uid:
        :param para:
        :param context:
        :return:
        '''
        keylist = list(para.keys())
        keylist.sort()
        s = ''
        for i in range(len(keylist)):
            s += str(keylist[i]) + '=' + str(para[keylist[i]])
            if i != len(keylist) - 1:
                s += '&'
        s += '&key=' + key
        signmd5 = hashlib.md5()
        signmd5.update(s)
        sign = (signmd5.hexdigest()).upper()
        return sign

    #拼接xml字符串
    def get_xml_data(self, doc, para):
        root = doc.createElement('xml')
        doc.appendChild(root)
        for key, value in sorted(para.items()):
            new_node = doc.createElement(key)
            node_value = doc.createTextNode(str(value))
            new_node.appendChild(node_value)
            root.appendChild(new_node)
        return doc

 

    2:提交刷卡支付

    def do_micropay(self,orderid,goodsName,goodsPrice,authCode,**kwargs):
        '''
        刷卡支付
        '''
        appid = self._APP_ID
        mch_id = self._MCH_ID
        key = self._API_KEY
        nonce_str = str(int(round(time.time() * 1000))) + str(random.randint(1, 999)) + string.join(random.sample(
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
             'v', 'w', 'x', 'y', 'z'], 5)).replace(" ", "")
        spbill_create_ip = self._CREATE_IP

        params = {}
        params['appid'] = appid
        params['mch_id'] = mch_id
        params['nonce_str'] = nonce_str
        params['out_trade_no'] = orderid.encode('utf-8')  # 客戶端生成並傳過來,參數必須用utf8編碼,否則報錯
        params['total_fee'] = goodsPrice  # 單位是分,必須是整數
        params['spbill_create_ip'] = spbill_create_ip
        params['body'] = goodsName.encode('utf-8')  # 中文必須用utf-8編碼,否則xml格式錯誤
        params['auth_code'] = authCode

        doc = dom.Document()
        self.get_xml_data(doc, params)
        sign = self.get_sign_for_wx(params, self._API_KEY)
        params['sign'] = sign
        signnode = doc.createElement('sign')
        signvalue = doc.createTextNode(sign)
        signnode.appendChild(signvalue)
        doc.getElementsByTagName('xml')[0].appendChild(signnode)

        # 向微信刷卡支付發出請求
        req = urllib2.Request(self._MICROPAY_URL)
        req.headers['Content-Type'] = 'text/xml'
        req.data = doc.toprettyxml()
        res_data = urllib2.urlopen(req)

        # 提取支付結果
        res_read = res_data.read()
        doc = xmltodict.parse(res_read)
        return_code = doc['xml']['return_code']

        # 結果分析
        # 此字段是通信標識,非交易標識,交易是否成功需要查看result_code來判斷
        if return_code == 'SUCCESS':
            result_code = doc['xml']['result_code']
            # 業務結果
            if result_code == 'SUCCESS':
                    buyer = doc['xml']['openid'] #支付者id
                    return (True, 'SUCCESS', u'支付成功 ',buyer)
            elif result_code == 'FAIL':
                error_code =  doc['xml']['err_code']
                error_code_des =  doc['xml']['err_code_des']
                return (False, error_code, error_code_des,'')
        else:
            return_msg = doc['xml']['return_msg']
            return (False, return_code, return_msg,'')

 

    3:根據訂單號查詢支付結果

    def do_micropay_query(self,orderid):
        appid = self._APP_ID
        mch_id = self._MCH_ID
        key = self._API_KEY
        out_trade_no = orderid.encode('utf-8')  # 客戶端生成並傳過來,參數必須用utf8編碼,否則報錯
        nonce_str = str(int(round(time.time() * 1000))) + str(random.randint(1, 999)) + string.join(random.sample(
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
             'v', 'w', 'x', 'y', 'z'], 5)).replace(" ", "")

        params = {}
        params['appid'] = appid
        params['mch_id'] = mch_id
        params['nonce_str'] = nonce_str
        params['out_trade_no'] = out_trade_no

        doc = dom.Document()
        self.get_xml_data(doc, params)
        sign = self.get_sign_for_wx(params, self._API_KEY)
        params['sign'] = sign
        signnode = doc.createElement('sign')
        signvalue = doc.createTextNode(sign)
        signnode.appendChild(signvalue)
        doc.getElementsByTagName('xml')[0].appendChild(signnode)

        # 發出查詢請求
        req = urllib2.Request(self._QUERY_URL)
        req.headers['Content-Type'] = 'text/xml'
        req.data = doc.toprettyxml()
        res_data = urllib2.urlopen(req)

        # 返回查詢結果
        res_read = res_data.read()
        doc = xmltodict.parse(res_read)
        return_code = doc['xml']['return_code']

        if return_code == 'SUCCESS':
            result_code = doc['xml']['result_code']
            # 業務結果
            if result_code == 'SUCCESS':
                trade_state = doc['xml']['trade_state']
                #支付成功
                if trade_state == 'SUCCESS':
                    buyer = doc['xml']['openid']
                    return (True, 'SUCCESS', u'支付成功 ',buyer)
                #未支付、支付中
                elif trade_state == 'NOTPAY':
                    return (False, 'NOTPAY', u'未支付','')
                elif trade_state == 'USERPAYING':
                    return (False, 'USERPAYING', u'支付中','')
                #支付關閉、撤銷、失敗
                elif trade_state == 'CLOSED':
                    return (False, 'CLOSED', u'支付關閉','')
                elif trade_state == 'REVOKED':
                    return (False, 'REVOKED', u'支付撤銷','')
                elif trade_state == 'PAYERROR':
                    return (False, 'PAYERROR', u'支付失敗','')
            else:
                error_code =  doc['xml']['err_code']
                error_code_des =  doc['xml']['err_code_des']
                return (False, error_code, error_code_des,'')
        else:
            return_msg = doc['xml']['return_msg']
            return (False, return_code, return_msg,'')

 

    

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM