PythonはWeChatカード決済(バーコード支払い)MicroPayを実現します。

30525 ワード

転載は原文の住所を明記してください。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,'')