Django + Apache + 树莓派 搭建内网微信公众号服务器

  其实早在微信开放公众号开发平台时就想弄一个自己的公众号服务器,奈何对web服务器搭建和开发一窍不通,只是注册了一下开发者帐号,并没有采取行动,万恶的拖延症。

前一年,开始接触python,打开了神奇世界的大门,以前都是用C,C++写程序,开发一个程序就像安装一台机器,有严格的说明书,一步一步不能有差。而用python开发,特别是

自己用的助手程序,怎么说呢,就像飞在空中一般,广阔天空,任尔发挥。python的精彩在这里不做赘述,自己也只是学了一点皮毛,还有更好玩的在后面等着去学,继续努力哈。

  最初学python,是看的《python基础教程》,对我而言是本不错的书,第15章就是介绍python web开发,只需要简单的代码就可以搭建一个简单的服务器,并且也知道了python的

网络框架Django,再后来开始看《Django Web开发指南》,加上自己有一些需求,想定制自己的微信公众号,给自己提供特定的功能,就有了用Django搭建自己的微信公众号服务器的念头。

  Django和Apache 搭建web服务器,是比较简单的,《Django Web 开发指南》上有,推荐到这个网站上去看一下 

http://www.ziqiangxuetang.com/django/django-deploy.html

这个网址专门讲了Django开发,从初级到实践,作者讲的很好。这里只是建议在开发阶段把Django 的Debug 设置成True(默认就是True),这样在访问服务器出错时,可以在浏览器上看到出错在哪里,

当然,在linux上,查看/var/log/apache2/error.log 也可以查看出错的日志。

  对于服务器来说,一般是不关机的,对我来说,一直开着台式机好像有点浪费电,因为现在服务只提供给个人,在网上买个云服务器也划不来,刚好有块闲置的树莓派二代,就想把服务器搭在pi上面,平时只要

用手机充电器供电即可。

  搭建内网服务器,最主要的问题是如何让外网能访问家里的内网,我用的是在花生壳(http://hsk.oray.com/)上注册一个帐号,它会免费提供一个动态域名,家里用的是TP_Link路由器,在“动态DNS”设置里面

  填写注册的帐号和密码,登录,正常就会显示连接成功,下面的域名信息就可以用作你服务器的域名。接下来就是配置外网访问内网的端口号,通过配置路由器的转发规则可以进行映射

 上面的IP地址就是内网服务器的IP地址,服务器端口号就是外网访问时的端口号,内部端口号就是映射到内网服务器监听的端口号,就这样外网可以通过域名访问内网的服务器了,可以通过浏览器加端口号访问测试,如

http://xxx.xicp.net/:443/

  服务器访问配置基本就这些了,接下来就是把服务器的信息添加到微信公众号开发平台上,在自己的开发帐号中,开发--》基本配置 中,填写服务器配置 URL就填写上面的域名 http://xxx.xicp.net(下面会对这个进行修改),

Token(令牌),随便填写一个,在服务器端填成一致就可以了,消息加解密方式,开发阶段填成明文模式就可以了,提交,显示URl访问超时!!! 这里是碰到的第一只拦路虎,一开始不明白为什么会访问超时,因为查看其他人的教程,

都是这么配置的,并且用浏览器访问服务器都是好的,当出现问题时,不要着急去网上找资料,先自己想想,查看一下配置步骤,看看官方的开发文档。终于,看到微信公众号平台支持两个端口号80和443,如果在路由器上映射80端口的话,

会提示80端口被占用,是被电信占用了,没办法,只能映射443端口了,这就需要搭建apache ssl访问了,因为443端口就是对应的https访问。

  apache 上搭建https访问(谢谢网上的分享者):

1.sudo a2enmod ssl

2.sudo apt-get install openssl  //安装openssl (如果已经安装了openssl,就不用安装了,派上面应该已经安装了)

3.openssl genrsa -des3 -out server.key 1024  //创建CA签名, 会提示输入密码,密码在后面启动服务器时需要输入

4.openssl req -new -key server.key -out server.csr //创建CSR

5.openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt  //自己签发证书

6.sudo cp server.crt /etc/ssl/certs  //拷贝文件到ssl的目录下

7.sudo cp server.key /etc/ssl/private

然后在apache服务器配置里面,需要添加一些东西,在/etc/apache2/sites-available/ 这个目录下,有我的之前的apache配置web.conf,这个是自己创建的,

我的配置如下

<VirtualHost *:443> #修改成443

ServerName you.xicp.net  #你的服务器域名
ServerAlias you.xicp.net
ServerAdmin admin
SSLEngine On
SSLOptions +StrictRequire
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key

#下面的配置和你的Django工程有关,配置说明参照 http://www.ziqiangxuetang.com/django/django-deploy.html


Alias /media/ /home/pi/project/media/
Alias /static/ /home/pi/project/static/

<Directory /home/pi/project/media>
Require all granted
</Directory>

<Directory /home/pi/project/static>
Require all granted
</Directory>

WSGIScriptAlias / /home/pi/project/wsgi.py

<Directory /home/pi/project/app>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>

红色的是配置https访问加上的内容

然后

sudo a2ensite web.conf #让自己的配置生效

sudo /etc/init.d/apache2 restart #重启apache服务器
重启apache服务器后,会让你输入密码,就是一开始创建CA签名时输入的密码

在Django工程代码中添加url访问 

url(r'^$',comm_view.index),
comm_view.index 是你自己的view访问函数,我的代码如下
#coding=utf-8

from django.shortcuts import render

from django.http import HttpResponse
# Create your views here.

import hashlib
import json

from django.utils.encoding import smart_str
from django.views.decorators.csrf import csrf_exempt

WX_TOKEN = "yourtoken"

@csrf_exempt
def index(request):

    print("wx request")

    if request.method == "GET":

        signature = request.GET.get("signature",None)
        timestamp = request.GET.get("timestamp",None)
        nonce     = request.GET.get("nonce",None)
        echostr   = request.GET.get("echostr",None)
        token     = WX_TOKEN
        tmp_list =[token,timestamp,nonce]
        tmp_list.sort()
        tmp_str = "%s%s%s" % tuple(tmp_list)
        tmp_str = hashlib.sha1(tmp_str.encode("unicode_escape")).hexdigest()

        if tmp_str == signature:
            return HttpResponse(echostr)
        else:return HttpResponse("sucess")

再去微信公众号开发平台上配置服务器配置,URL这时候要改成https://xxx.xicp.net,其他配置不变,提交后,服务器正常工作的话,就会提示成功!!!。然后 在“修改配置”的边上点击“启用”配置。

这样微信公众号这边也就配置完成了。

再回到上面的代码,上面的代码可以看到是一个“GET”请求,是微信公众号访问我们的服务器验证,如果订阅的人提交消息给我们的公众号,则微信服务器会把消息POST给我们的服务器,我们服务器要做的

就是对POST请求进行处理,返回结果给微信公众号服务器再显示到用户微信上。

一开始,我是这样写的 (接上面代码)

elif request.method == "POST":
    HttpResponse("ok,hello")

用自己的微信进行测试时提示“该公众号暂时无法提供服务,请稍候再试”,但是用浏览器访问又是正常的,用开发平台提供的怎么都没想明白,只能继续看开发文档,公众号的开发文档还是写的很好的(十分感谢),看到文档给的例子是接收时对xml进行解析,返回时组成xml格式,在想是不是一定要组成xml格式文档才行,用开发文档提供的例子(https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1472017492_58YV5&token=&lang=zh_CN),返回时组成xml格式,再试试,成功了!!当然也不是一次就成功的~~,这中间把收到的ToUserName和FromUserName 赋值给了返回的ToUserName和FromUserName,导致用开发平台的工具(http://mp.weixin.qq.com/debug)调试时,能正常收到回应,而用自己的微信号发送消息还是失败,后来仔细检查了一下代码才发现,收到消息时的ToUserName赋值给了回应消息时的FromUserName,这样微信公众号不混乱才怪,互调之后,终于成功。看着微信上回应"OK KO",虽然只是简单的一句话,但内心还是深深的满足感,这也许就是程序员的小满足。

  写这份记录,是对这个过程的一个笔记,用于自己日后查看,第二就是在搭建过程中网上查到的资料和自己的一些体会整理一下,希望能给有相同需求的同学给予一点点帮助。好了,属于自己的服务器搭好了,借着微信的强大平台,定制自己的服务吧!

 

posted on 2016-11-13 20:00    阅读(2736)  评论(0编辑  收藏  举报

导航