需求
- 微信支付对接
- 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
来源:oschina
链接:https://my.oschina.net/tplinuxhyh/blog/4511719