記錄django-rest-framework處理微信支付notify_url遇到的問題

mjw發表於2019-02-16

最近在做一個小程式,小程式有涉及到微信支付,說來慚愧,還是第一次自己動手去做微信支付這一塊的實現,所以過程中遇到了很多人都會踩的坑(例如mmp的微信支付各種key各種id要在哪裡找,很難找),這次使用django來開發,介面部分用django-rest-framework(下面簡稱drf)。

入入入入入正題吧。

微信支付統一下單介面,有一個叫notify_url的引數,作用我就照搬官方文件:

非同步接收微信支付結果通知的回撥地址,通知url必須為外網可訪問的url,不能攜帶引數。

吐槽:官方文件竟然不告訴我到時候是通過Get還是Post(難道是其他HTTP method)請求我,我怕我到時候措不及防,事實證明,是通過Post來請求的。

好了,我前面的支付功能都寫好了,就等微信爸爸來調我的notify_url了,測試支付完之後,屁顛屁顛跑去IDE的控制檯看debug輸出,結果有Traceback,找找裡面的關鍵資訊:Unsupported media type "text/xml" in request.,哭唧唧。

唔,聰明如我,drf可以自定義parser類,官方文件也有提到一個xml的parser,安裝了,然後為這個介面指定了parser_classes,程式碼如下:

# ...省略
class WechatNotifyView(APIView):
    """
    微信回撥介面
    """
    authentication_classes = []
    permission_classes = (AllowAny,)
    parser_classes = (XMLParser,)

    def post(self, request):
        print(request.data)
        return Response()

滿心歡喜重新測試一次,結果還是不對,追查了下,發現了關鍵所在,微信呼叫notify_url的時候,Content-Typetext/xml而不是application/xml,真是mmp,看了下XMLParser的原始碼,改起來很簡單:

# ...省略
class WechatPaymentXMLParser(XMLParser):
    media_type = `text/xml`

class WechatNotifyView(APIView):
    # ...省略
    parser_classes = (WechatPaymentXMLParser,)
    # ...省略    
    

再測試了一次,搞定,request.data列印出來的就是那個xml內容的字典形式。
吐槽:微信的東西總是有吐不完的槽,但爸爸始終是爸爸。

相關文章