自定義微信分享標題和描述信息


概述

環境: python3.4, Django1.9.6

准備工作

首先要搞到微信公眾平台開發者ID和開發者密碼,這個在公眾號平台的公眾號開發信息里查看和修改

image

然后在IP白名單中,把服務器的IP加進去。

最后在公眾號設置--功能設置里 把域名加進去

image

 

添加域名的時候,會看到提示下載一個txt文件,放到web服務器;這里我是把它放在static目錄下,然后給它單獨做了個url,單獨寫了view訪問。

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.index),
    url(r'^MP_verify_xdl1MStBzOrk6qLu.txt', views.gettxt),
]
def gettxt(request):
    with open('MP_verify_xdl1MStBzOrk6qLu.txt', 'r') as f:
        return HttpResponse(f.read())

這樣是為了http://你的域名/MP_verify_xdl1MStBzOrk6qLu.txt可以訪問到它。

當然直接把它放到nginx根目錄下也可以,我是在IIS下配置的站點,其實不寫路由不寫views也是可以的,詳細見最后的部署

基本流程

基本流程步驟如下:

1. 通過開發者ID和密碼 獲取到 token

2. 通過token獲取到ticket

3. 拿到ticket生成簽名

4. 后台返回數據給前台js調用

注意的是token和ticket是2個小時過期,而且api每天有請求次數,所以我們要把ticket存到本地,過期后再去請求。

代碼

settings.py  我只列出比較重要的內容

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR,  'static')
TEMPLATE_DIRS = (
    os.path.join(BASE_DIR,  'templates'),
    'app',
)

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

#微信API信息
WEIXINAPI = {
    "tokenUrl": "https://api.weixin.qq.com/cgi-bin/token?",
    "ticketUrl": "https://api.weixin.qq.com/cgi-bin/ticket/getticket?",
    "appID": "開發者ID",
    "appwd": "開發者密碼"
}

#分享頁面信息
PAGEINFO = {
    "Title": "這里是標題信息",
    "Description": "這里是描述信息",
    "PicUrl": "這里是你要分享的url"
}

 

views.py

我是圖省事把所有代碼都寫在views.py里了,其實這些可以寫到別的文件里,然后import進來,views.py只寫它該寫的東西 

先寫一個獲取token的方法:

def flush_token():
    token_url = settings.WEIXINAPI["tokenUrl"]
    appID = settings.WEIXINAPI["appID"]
    appwd = settings.WEIXINAPI["appwd"]
    url = "%sgrant_type=client_credential&appid=%s&secret=%s" % (token_url, appID, appwd)
    ssl._create_default_https_context = ssl._create_unverified_context
    jsondata = urllib.request.urlopen(url).read().decode()
    json_dic = json.loads(jsondata)
    return json_dic["access_token"]

再來寫一個獲取ticket的方法

def flush_ticket(access_token):
    ticket_url = settings.WEIXINAPI["ticketUrl"]
    url = '%saccess_token=%s&type=jsapi' % (ticket_url, access_token)
    jsondata = urllib.request.urlopen(url).read().decode()
    json_dic = json.loads(jsondata)
    json_dic["expires_time"] = time.time()
    with open("ticket.txt", 'w') as f:
        json.dump(json_dic, f)
    return json_dic["ticket"]

因為每次分享的時候,ticket要先從ticket.txt中獲取,然后對比當前時間,如果超過兩個小時了,需要更新;沒有超過,則直接使用,那就寫一個get_ticket方法:

def get_ticket():
    if os.path.exists("ticket.txt"):
        with open('ticket.txt', 'r') as f:
            ticket_dic = json.load(f)
        expires_time = ticket_dic['expires_time']
        now_time = time.time()
        if now_time - expires_time >= 7200:
            #更新ticket
            access_token = flush_token()
            ticket = flush_ticket(access_token)
        else:
            ticket = ticket_dic["ticket"]
    else:
        access_token = flush_token()
        ticket = flush_ticket(access_token)
    return ticket

獲取到ticket之后,就要生成簽名信息了, 簽名信息需要幾個參數,一個是16位的隨機字符串,一個是ticket, 一個是timestamp這的單位是秒, 最后一個是你要分享的url, 然后將它們按照ASCII碼由小到大的順序以url參數方式拼接起來 用sha1加密。

先寫一個生成隨機數的方法:

def randomone(n):
    string = ''
    if n.isdigit():
        for i in range(int(n)):
            if i%2 != 0:
                tmp = random.randint(0,9)
            else:
                tmp = str(chr(random.randint(97, 122)))
            string = "%s%s" % (string, tmp)
    return string

現在再來一個生成簽名的方法:

def create_string(url):
    random_string = randomone('16')
    times = int(time.time()/1000)
    ticket = get_ticket()
    arg_string = "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s" % (ticket, random_string, times, url)
    m = hashlib.sha1()
    m.update(arg_string.encode('utf8'))
    sign = m.hexdigest()
    return times,random_string,sign

這個方法返回了三個變量,這三個變量是時間,隨機字符串,和簽名信息;這三個變量需要傳遞給前台頁面使用。

最后來寫一個index方法:

ef index(request):
    url = request.get_host() + request.get_full_path()
    url = 'http://%s' % url
    appId = settings.WEIXINAPI["appID"]
    timestamp, nonceStr, signature = create_string(url)
    title = settings.PAGEINFO["Title"]
    des = settings.PAGEINFO["Description"]
    picture = settings.PAGEINFO["PicUrl"]

    return render(request, 'index.html', locals())

注意這里,在獲取URL的時候,如果你的url只是個域名,瀏覽器會自動在域名后面加上“/”,比如http://www.qq.com/ , 最后這個”/”也是要參與加密的; 如果你的url還有參數,可能還會自動在后面加上#weixin啥的,都要去掉,具體把url打印出來看就知道了。

代碼部分到這里就結束了。下面看頁面和js.

前台頁面和js

我直接把js寫到頁面上了,你也可以寫到獨立的js文件中,用到的變量以參數形式傳過去,在頁面上調用即可。

我寫在了head標簽里

首先引一個weixin的js:

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

然后寫一下xw.config

wx.config({
            debug: false,
            appId: '{{ appId }}',
            timestamp: '{{ timestamp }}',
            nonceStr: '{{ nonceStr }}',
            signature: '{{ signature }}',
            jsApiList: [
                // 所有要調用的 API 都要加到這個列表中
                'checkJsApi',
                'openLocation',
                'getLocation',
                'onMenuShareTimeline',
                'onMenuShareAppMessage',
                'onMenuShareQQ',
                'onMenuShareWeibo'
              ]
        });

最后把各個分享方法寫到wx.ready()方法里,意思是文檔加載完后就加載它們

wx.ready(function () {

              //分享給朋友
                wx.onMenuShareAppMessage({
                  title: '{{ title }}',
                  desc: '{{ des }}',
                  link: '{{ url }}',
                  imgUrl: '{{ picture }}',
                  trigger: function (res) {
                    // 不要嘗試在trigger中使用ajax異步請求修改本次分享的內容,因為客戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回
                    //alert('用戶點擊發送給朋友');
                  },
                  success: function (res) {
                    alert('已分享');
                  },
                  cancel: function (res) {
                    alert('已取消');
                  },
                  fail: function (res) {
                    alert(JSON.stringify(res));
                  }
                });

                //分享到朋友圈
                wx.onMenuShareTimeline({
                  title: '{{ title }}',
                  link: '{{ url }}',
                  imgUrl: '{{ picture }}',
                  trigger: function (res) {
                    // 不要嘗試在trigger中使用ajax異步請求修改本次分享的內容,因為客戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回
                    //alert('用戶點擊分享到朋友圈');
                  },
                  success: function (res) {
                    alert('已分享');
                  },
                  cancel: function (res) {
                    alert('已取消');
                  },
                  fail: function (res) {
                    alert(JSON.stringify(res));
                  }
                });

                //分享到QQ
                wx.onMenuShareQQ({
                  title: '{{ title }}',
                  desc: '{{ des }}',
                  link: '{{ url }}',
                  imgUrl: '{{ picture }}',
                  trigger: function (res) {
                    // 不要嘗試在trigger中使用ajax異步請求修改本次分享的內容,因為客戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回
                    //alert('用戶點擊分享到朋友圈');
                  },
                  success: function (res) {
                    alert('已分享');
                  },
                  cancel: function (res) {
                    alert('已取消');
                  },
                  fail: function (res) {
                    alert(JSON.stringify(res));
                  }
                });

                 //分享到騰訊微博
                wx.onMenuShareWeibo({
                  title: '{{ title }}',
                  desc: '{{ des }}',
                  link: '{{ url }}',
                  imgUrl: '{{ picture }}',
                  trigger: function (res) {
                    // 不要嘗試在trigger中使用ajax異步請求修改本次分享的內容,因為客戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回
                    //alert('用戶點擊分享到朋友圈');
                  },
                  success: function (res) {
                    alert('已分享');
                  },
                  cancel: function (res) {
                    alert('已取消');
                  },
                  fail: function (res) {
                    alert(JSON.stringify(res));
                  }
                });
        });

上面那些alert() 都可以注釋掉,沒啥用,反而會影響用戶體驗,因為本身就會有個已分享的提示,不需要自己寫。

到這就寫完了,需要說的是,這個要在微信時打開鏈接,然后右上角的‘…’, 選擇分享, 效果是這樣的:

image

 

 

IIS下部署Django

安裝IIS的時候,需要把CGI裝上

image

然后安裝 wfastcgi:

pip install wfastcgi

安裝完成之后將 python的Lib\site-packages\wfastcgi.py 放到你的項目下,跟 manage.py一個目錄。

配置IIS:

選中你的站點,選擇”處理程序映射”, 添加模塊映射:

image

可執行文件寫: C:\Python34\python.exe|C:\web\jisuanqi\wfastcgi.py 中間用”|”分隔,前面是python的路徑,后面是剛才wfastcgi.py文件的路徑,然后點擊“請求限制”:

image

去掉這個 勾。

最后選中 web服務器的 fastCGI設置

image

選中新建的應用程序,點擊編輯,添加三個環境變量:

get_wsgi_application()方法的位置

Name: WSGI_HANDLER
Value: django.core.wsgi.get_wsgi_application()

 

Django項目目錄,就是manage.py所在的目錄,我的項目名稱叫jisuanqi

Name: PYTHONPATH
Value: D:\web\jisuanqi

 

這個是settings.py所在的目錄

Name: DJANGO_SETTINGS_MODULE
Value: jisuanqi.settings

 

添加完成后是這樣的:

image

 

到這就可以訪問到網站了,但是會發現靜態文件,所有的css,js,圖片全丟了,訪問不到;解決方法也很簡單,把這些文件交給IIS處理就好了。

image

選中static目錄,進入 處理程序映射。把“DjangoWebHandller”刪掉就行了。

image


結束。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM