您的位置:首页 > 编程语言 > Python开发

【python】巧用SAE搭建微信本地调试环境

2013-10-31 22:21 344 查看
巧用SAE搭建微信本地调试环境


随着移动互联网时代的到来,微信——一个改变着我们生活的产品悄悄走近了我们的生活。我们不得不觉得自己很幸运,自己能在这个世界上遇到像QQ、微博、微信这样优秀的产品,同时,也不得不感叹这些产品的强大之处。就拿微信来说吧,我们可以文字聊天、发语音、报告位置、甚至是发视频、对讲机等功能,确实为我们平时的沟通大大降低了成本,譬如以前生日祝福等都是打电话、发短信,可在微信时代我们只要发文字或者是发一段语音就好了——省钱、简单、好用。

移动互联网的时代,你不一定需要你自己的移动APP,而且自己外包给别人做成本也比较高,小小的创业公司,就算你有了自己的移动APP,还要自己去发展用户(不同性质的公司需求不一样,举个例子而已),而且还要花大量的时间和精力在移动APP的维护上。基于不同的平台需要不同的人开发,譬如安卓版、IOS版、WP版等。因此,选择在微信上做二次开发是中小企业的不二选择。也有不少企业也有了自己的公众账号,甚至是服务号。

关于订阅号、服务号有哪些优点和缺点以及怎么使用,楼主在这里就不再赘述了,因为已经有最好的了。参考链接:http://www.zhongyaofang.cn/combat_power/weixin_jiaocheng_vol1.html

基于公众账号的二次开发,楼主选择的是最简单易懂的Python语言,结合Python一个轻量级的框架Django开发,操作比较简单,简单两下就能学会。由于业务发展需要,最近楼主也为自己所在的公司从事微信相关开发。因此将开发中遇到的问题及解决方案总结出来与大家,共同进步、共同成长。

需求描述:

楼主所在的公司是一家微型金融机构,有自己的网站,现在要将网站上的一部分功能(譬如放贷、购买理财产品等)在微信端实现,这样方便微信用户的操作,顺便也从微信用户中导一份流量到自己的网站。

首先,我们来了解一下微信通信的原理。现在假设你也接到和楼主相同的需求。举个简单的流程:在微信端实现放贷的流程。 第一步,用户在微信端发送放贷请求到微信服务器,请求格式由你自己决定,只要能解析就行;

第二步,微信服务器接受到请求信息,将信息转发到你自己的网站;

第三步,在你自己的网站处理完业务逻辑,反馈结果发送到微信服务器;

第四步,微信服务器将反馈结果转发给用户。

简单四步,完成了整个通讯,详细的流程如下图:


上图中,已经清晰的描述了通讯的原理,但是在开发过程中,我们大多都在本地,一般都是局域网,怎样才能和微信服务器实现通讯呢?当然你可以选择在服务器提供商买一台服务器,在那上面做开发。不过,细细盘算下来,成本确实有点高,所以我们要选择最简便有效的方法来解决我们的问题。在这里,楼主用到了SAE,当然你也可以用GAE, 在本地(局域网内)搭建了一个开发环境。当然,其原理还是跟上图很类似,只是稍微复杂了一点点:

第一步,用户在微信端发送放贷请求到微信服务器;

第二步,微信服务器接受到请求信息,将信息转发SAE(需要自己配置);

第三步,SAE将请求转发到指定位置(需要自己配置,还需要提供域名),我们暂且命名为“中转站”;

第四步,指定位置(“中转站”)将请求转发到你的路由;

第五步,路由通过映射转发到你的内网IP(即你的本地服务器);

第六步,你本地服务器处理完成后发送反馈到路由器;

第七步,路由器转发到指定位置(中转站);

第八步,指定位置(中转站)转发到SAE;

第九步,SAE转发到微信服务器;

第十步,微信服务器将反馈结果转发给用户。

看起来,确实有一点点复杂,不急,先看看图,且听我细细道来。



具体思路我们已经很清楚了,现阶段,我们只需要解决各个节点中的问题即可了。

我们从简单的开始:

(1) 配置路由器映射。可能不是所有的路由器都有这个功能,其目的是为了在外网能访问你本地的IP。一般在你上网的时候,都会对应有一个IP地址,可以通过在百度中输入IP来查询你的外网IP(见下图)。由于外网IP没有给用户开放80端口(如果开放了大家的机器都可以当服务器用了),所以你需要自己打开一个端口,让外网可以访问。我在本地我指定的是9000端口,假设我现在的IP地址是192.168.0.99,外网IP经查得是116.77.5.229,那么当你本地开启网络服务后,通过访问116.77.5.229:9000地址,就可以和你本机进行通信了。


(2) 配置“中转站”。通常,我们上网的 外网IP都是随机分配的,也就是说,我们每次上网时的外网IP都是不一样的,所以在与微信端通信的时候就比较麻烦了。在这里我们用到的"中转站"就是为了解决这一问题——让你的域名可以顺利解析到你本地的外网IP。因此,我们需要找一个DNS供应商,在这里,楼主找到了免费的DNSPod:https://www.dnspod.cn/
,不过需要你在这上面注册一个用户,然后将你在域名提供商购买的域名配置为DNSPod的DNS地址,如图:


除此之外,我们还要配置一个子域名如:wx.xxxx.com(xxxx是你的域名),记录值那一栏就是你外网的IP,但是这样你每次都要查询你的外网IP,然后将IP更改过来来。是不是很繁琐?有没有一劳永逸的办法?

答案是:当然有。楼主整来了下面一段代码,将你在DNSPod上的用户名和密码写入,在本地配上Python环境就可以使用喔:

#!/usr/bin/env python
# coding: utf-8

import httplib, urllib, urllib2
import time
import sys,os
import re
import json

username = 'yima1006@qq.com'  #账号
password = 'password'  #密码
format = 'json'

domain = [u'wx.xxxxx.com']  #要解析的域名

def get_domain_info(domain):
    domain_split = domain.split('.')
    domain_split_len = len(domain_split)
    maindomain = domain_split[domain_split_len - 2] + '.' + domain_split[domain_split_len - 1]
    return maindomain,domain

params = {'login_email':username,'login_password':password,'format':format}

def request(action, params, method = 'POST'):
    headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/json"}
    conn = httplib.HTTPSConnection("dnsapi.cn")
    conn.request(method, '/' + action, urllib.urlencode(params), headers)
    response = conn.getresponse()
    data = response.read()
    conn.close()
    if response.status == 200:
        return data
    else:
        return None

def get_my_domain_id():
    data = request('Domain.List',params)
    data = json.loads(data)
    domainlist = data.get('domains')
    domaninfo = {}
    for d in domainlist:
        domaninfo[d.get('name')]  = d.get('id')
    return domaninfo

def get_my_domain_record_id(domain_id):
    params['domain_id'] = domain_id
    data = request('Record.List',params)
    data = json.loads(data)
    if data.get('code') == '10':
        return None
    domainname = data.get('domain').get('name')
    record_list = data.get('records')
    record = {}
    for r in record_list:
        if r.get('type') == 'A':
            key = r.get('name') != '@' and r.get('name') + '.' + domainname or domainname
            record[key] = {'id':r.get('id'),'value':r.get('value')}
    print record
    return  record

def changerecord(domain,domain_id,record_id,ip):
    params['domain_id'] = domain_id
    params['record_id'] = record_id
    params['record_type'] = 'A'
    params['record_line'] = '默认'
    params['sub_domain'] = domain
    params['ttl'] = 600
    params['value'] = ip
    data = request('Record.Modify',params)

def getip():
    url = 'http://iframe.ip138.com/ic.asp'
    response = urllib2.urlopen(url)
    text = response.read()
    ip = re.findall(r'\d+.\d+.\d+.\d+', text)
    print '外网IP:%s'%ip[0]
    return ip[0] or None

def updatedomaininfo(domain):
    m,sub_m = get_domain_info(domain)
    domain_id = my_domain_id_list.get(m)
    record_list = get_my_domain_record_id(domain_id)
    if record_list == None:
        return None
    rocord_info = record_list.get(sub_m)
    record_ip = rocord_info.get('value')
    record_id = rocord_info.get('id')
    return sub_m,record_ip,record_id,domain_id

if __name__ == '__main__':
    my_domain_id_list = get_my_domain_id()
    try:
        for dm in domain:
            domaindata = updatedomaininfo(dm)
            if domaindata == None:
                continue
            dnsdomain,dnsdmainip,record_id,domain_id = domaindata
            domain_name = dnsdomain.split('.')[0]
            ip = getip()
            if ip == dnsdmainip:
                continue
            else:
                changerecord(domain_name,domain_id,record_id,ip)
    except:
        pass


这样,通过访问http://wx.xxxx.com:9000端口就能找到你本地的服务器了。



(3)配置SAE应用。在SAE上,我们只需要做一个简单的代理就行,即将微信服务器转发过来的请求按照原来的方式转发到你的“中转站”就好了。在这里,我们用到了一个Python机器轻量级的web框架——web.py。我们可以在SAE上直接创建一个Python项目,然后在index.wsgi文件中贴如如下一段代码就行了。

#/usr/bin/python
#coding:utf-8

import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import web
import urllib2
try:
    import sae
except:
    pass

urls = (
    '/weixin/?', 'weixin',
)

web.config.debug = True
app = web.application(urls, globals())

class weixin:
    def GET(self):
	""" GET 请求转发"""
        url = "http://wx.xxxx.com:9000/weixin/?"    # 转发地址,与你的路由器端口映射
        d = web.input()        # 读取参数
        data = []
        for i in d:
            data.append(i + '=' + d[i])
        url = url + '&'.join(data)      # 拼接参数
        req = urllib2.Request(url=url)
        res = urllib2.urlopen(req )
        return res.read()

    def POST(self):
	""" POST请求转发 """
        data = web.data()     # 转发参数
        url = "http://wx.xxxx.com:9000/weixin/?"     # 转发地址,与你的路由器端口映射
        req = urllib2.Request(url=url, data=data)
        res = urllib2.urlopen(req, timeout=10 )
        return res.read()

if __name__ =="__main__":
    app.run()
else:
    try:
        app = web.application(urls, globals()).wsgifunc()
        application = sae.create_wsgi_app(app)
        #application = sae.create_wsgi_app(ShellMiddleware(app))
    except:
        pass


这样,我们本地的开发环境搭建已经基本完成,只需要稍作配置就可以开发了。

感谢您的关注,更多详细,请听下回为您分解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: