DRF parsers: 微信支付对接相关工具函数

╄→гoц情女王★ 提交于 2020-08-19 13:13:57

需求

  • 微信支付对接
  • xml数据解析

todo 整理流程细节

  • 支付流程
  • 退款流程
  • 订单取消逻辑 微信文档 views需要自己指定解析器和渲染器

view.py

class WeChatNotifyPayView(APIView):
    """
    微信支付回调接口
    """
    authentication_classes = []
    permission_classes = (AllowAny,)
    parser_classes = (WeChatPaymentXMLParser, )
    renderer_classes = (WeChatPayXMLRender, )
    # serializer_class = PayRecordSerializer

    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)
        logger.info(request.body)

        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

WeChatPaymentXMLParser

parsers.py

from rest_framework_xml.parsers import XMLParser


class WeChatPaymentXMLParser(XMLParser):
    media_type = 'text/xml'

WeChatPayXMLRender

renders.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.utils import six
from django.utils.encoding import force_text
from django.utils.six import StringIO
from rest_framework_xml.renderers import XMLRenderer
from django.utils.xmlutils import SimplerXMLGenerator


class WeChatPayXMLRender(XMLRenderer):
    """
    https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7
    <xml>
        <return_code><![CDATA[SUCCESS]]></return_code>
        <return_msg><![CDATA[OK]]></return_msg>
    </xml>
    """
    root_tag_name = 'xml'
    return_code_tag_name = 'return_code'
    return_msg_tag_name = 'return_msg'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        """
        Renders `data` into serialized XML.
        """
        if data is None:
            return ''

        stream = StringIO()

        xml = SimplerXMLGenerator(stream, self.charset)
        # xml.startDocument()
        xml.startElement(self.root_tag_name, {})

        self._to_xml(xml, data)

        xml.endElement(self.root_tag_name)
        xml.endDocument()
        return stream.getvalue()

    def _to_xml(self, xml, data):
        if isinstance(data, dict):
            for key, value in six.iteritems(data):
                xml.startElement(key, {})
                # value 也当成标签写入
                xml.startElement(value, {})
                # self._to_xml(xml, value)
                xml.endElement(key)

        elif data is None:
            # Don't output any value
            pass
        else:
            xml.characters(force_text(data))

sign 签名

def get_nonce_str():
    # 微信支付:生成随机字符串
    data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP"
    nonce_str = ''.join(random.sample(data, 30))
    return nonce_str


def get_sign(params=None, mch_key=''):
    """

   params = {
            "appId": settings.APP_ID,
            "timeStamp": timestamp,
            "nonceStr": nonce_str,
            "signType": "MD5",
            "package": 'shijingli',
        }

    :param params: 统一下单参数
    :param mch_key: 商户api_key
    :return:
    """
    tmp_sign = '&'.join([
            '{}={}'.format(key, params.get(key)) for key in sorted(
                params.keys()) if params.get(key)
        ]) + "&key={}".format(mch_key)
    pay_sign = hashlib.md5(tmp_sign.encode("utf-8")).hexdigest().upper()
    return pay_sign
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!