国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Flask 微信卡券小項目:從開發(fā)到上線

作者:KBdancer

來源:https://www.92ez.com/

前言

博主上周接了一個小單子,是關(guān)于微信卡券,博主原來主要精力和工作內(nèi)容屬于前端開發(fā),后來學習了Python后發(fā)現(xiàn)自己居然也會寫后端了,于是一發(fā)不可收拾,自學Django和Flask之后發(fā)現(xiàn)還是寫后端比較有意思,業(yè)余時間也接一些小的外包單子掙點零花。外包項目多數(shù)是跟微信相關(guān),但是關(guān)于微信卡券,博主還真是第一次開發(fā),遇到的坑不少,做此記錄,也給初學Python web的萌新一些入門知識。

眾所周知,微信官方的開發(fā)者文檔寫的非常的爛,至于有多爛,同學們可以自行谷歌微信文檔的坑,如果說你打算完全參考官方的文檔進行開發(fā),可能你永遠都無法開發(fā)出來你想要的項目,so?老老實實參考第三方的民間文檔吧,以免浪費寶貴的開發(fā)時間。

說明

這個項目實際開發(fā)時間為1.5天,其中被微信文檔坑掉的時間大概占到了三分之二,所以說經(jīng)驗很重要。博主之前做過比較多基于微信的項目,在微信授權(quán)和jssdk應用上面還是比較熟悉的,這個項目的功能非常簡單:

微信授權(quán)獲取用戶信息保存到數(shù)據(jù)庫,保存成功之后調(diào)用微信的jssdk喚起微信的卡券領(lǐng)取頁面,用戶領(lǐng)取成功之后更新數(shù)據(jù)庫記錄標示已領(lǐng)取。

早前博主使用的是PHP開發(fā)過微信授權(quán),用了第三方寫的一個庫,生成各種簽名都是簡單調(diào)用封裝好的方法,簡單易用,但是這次使用Python開發(fā),雖然Gayhub上有很多第三方開源的封裝庫,但是我這里只需要簡單的微信授權(quán)和卡券功能,并不需要那么強大,所以還是自己動手寫個比較方便,溫故而知新,再復習一下舊的知識也是相當不錯的。

開發(fā)

此項目前端頁面使用了如下開源庫:

vuejs 這個就不用說了,最近很火

weui.js 微信官方團隊開源的微信生態(tài)UI組件庫

axios.js vue推薦的前端ajax方案,使用起來很棒

后端:Flask(Flask, render_template, request, session, jsonify, redirect)

數(shù)據(jù)庫:Mysql

由于項目很小,這里就沒有使用前后完全分離開發(fā),直接使用了Flask的Jinja2模板引擎進行頁面的渲染,Jinja2的頁面渲染識別符號是{{ }},由于vuejs也是使用的{{ }}作為識別符,為了避免沖突,我這里將Jinja2的識別符修改成了[[ ]],也是挺好看的。使用如下代碼進行設置

  1. app.jinja_env.variable_start_string = '[[ '

  2. app.jinja_env.variable_end_string = ' ]]'

項目里面生成微信Token之類的需要跟微信的服務器進行交互,所以用到了 requests 庫,生成簽名用的是sha1算法,用的庫是 hashlib,為了防止csrf攻擊,生成隨機字符串需要用到 random,對數(shù)據(jù)進行json轉(zhuǎn)換的操作用 json 庫,生成數(shù)據(jù)報表用xlwt庫來操作excel文件,使用time庫生成時間戳,微信簽名也需要用到它,獲取當前項目路徑用sys庫,os庫用來判斷文件或者路徑是否存在。

Flask里面對Mysql數(shù)據(jù)庫操作用的是Flask-Mysql,當然也可以使用Python-Mysql,這個取決于個人需要,使用方法都差不多,總結(jié)一下用到的庫,大概就是下面這些了

  1. from flask import Flask, render_template, request, session, jsonify, redirect

  2. from flaskext.mysql import MySQL

  3. import requests

  4. import hashlib

  5. import random

  6. import json

  7. import xlwt

  8. import time

  9. import sys

  10. import os

Flask項目里面使用session的話需要有一段隨機字符串作為安全密鑰,比如說我這里寫的是

  1. app.secret_key = 'A0Zr98j/3yX R~XHH!jmNT'

這個自己生成就好了,如果沒有這玩意 session 就沒法用。

為了方便對數(shù)據(jù)庫的操作,我這里寫了通用的類

  1. mysql_object = MySQL()

  2. app.config['MYSQL_DATABASE_USER'] = 'user'

  3. app.config['MYSQL_DATABASE_PASSWORD'] = 'sadjni3u8asnd3'

  4. app.config['MYSQL_DATABASE_DB'] = 'wanshang_coupon'

  5. app.config['MYSQL_DATABASE_HOST'] = '127.0.0.1'

  6. mysql_object.init_app(app)

  7. class Database:

  8.    def __init__(self):

  9.        self.connection = mysql_object.connect()

  10.        self.cursor = self.connection.cursor()

  11.    def insert(self, query, params):

  12.        try:

  13.            self.cursor.execute(query, params)

  14.            self.connection.commit()

  15.        except Exception as e:

  16.            print(e)

  17.            self.connection.rollback()

  18.    def query(self, query, params):

  19.        self.cursor.execute(query, params)

  20.        return self.cursor.fetchall()

  21.    def __del__(self):

  22.        self.connection.close()

項目比較小,query和insert夠用了,insert也可用于update。關(guān)于項目的完整代碼就不貼出來了,也沒啥用,下面就說一些關(guān)鍵點吧。

首先用戶進入首頁,會進行微信的授權(quán),代碼如下

  1. @app.route('/')

  2. def index():

  3.    appid = 'wx*************'

  4.    redirect_uri = 'http%3A%2F%2Fcoupon.abc.com%2Fauthorization'

  5.    csrf_state = str(random.randint(0, 10000)) + ''.join(random.sample('abcdefghijk', 5))

  6.    session['csfr_token'] = csrf_state

  7.    wx_code_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=%s#wechat_redirect' % (appid, redirect_uri, csrf_state)

  8.    return redirect(wx_code_url)

微信的授權(quán)是分步驟進行的,上面的代碼是獲取一個code,有了這個code才能去拿token,上面代碼中需要注意的是 redirecturi 這個變量一定要進行url編碼,否則微信會報異常,csrfstate 變量是生成一個隨機字符串,用于防止csrf跨站攻擊,微信文章說不加也可以,為了安全起見,咱們還是加上去吧,誰叫咱們是搞安全的呢。

這個csrf_state會在獲取到code后微信重定向回來時帶在url后面,所以下一步是可以拿到這個參數(shù)的。

session['csfrtoken'] = csrfstate 這個就很簡單了,把這個隨機字符串寫入到session,這樣在下一步操作的時候會去檢查進行比對。

這里我要說明一下為何需要這個 csrf_state 參數(shù),微信授權(quán)在獲取code的時候,請求是通過前端的URL進行跳轉(zhuǎn),url跳轉(zhuǎn)很明顯的一個問題就是明文傳輸,明文傳輸?shù)臅r候arp攻擊是很容易拿到請求鏈接的,如果說我們實現(xiàn)已經(jīng)在服務器上的session里面存儲了那個隨機字符串,微信回調(diào)回來的時候服務器拿到參數(shù)進行比對,如果這個參數(shù)值跟session里面的一致,則認為是正常的請求,否則這個請求就是偽造的,比如典型的請求重放攻擊,在這里就用不了了,就算被arp拿到了鏈接,發(fā)過去服務器也會認為請求非法所以我還是建議加上這個參數(shù)。

Flask跳轉(zhuǎn)使用redirect方法。

下面是關(guān)鍵的授權(quán)部分,獲取授權(quán)Token的回調(diào)鏈接在上一步已經(jīng)給出,微信會自動回調(diào)到這個頁面,相關(guān)注釋我直接在代碼里面寫了

  1. @app.route('/authorization')

  2. def authorization():

  3.    page_status = '1'

  4.    wx_code = request.args.get('code')  # Flask 獲取 get請求的值用request.args,獲取post請求用request.form,獲取前端ajax的json數(shù)據(jù)用request.data,這里的code是微信回調(diào)的時候加上去的

  5.    csrf_state = request.args.get('state') # 這個state是微信回調(diào)回來的時候帶上去的,是之前我們自己生成的隨機字符串

  6.    if session['csfr_token'] != csrf_state: # 隨機字符串的校驗,校驗失敗就跳轉(zhuǎn)首頁

  7.        return redirect('http://coupon.abc.com')

  8.    else:

  9.        appid = 'wx****************'

  10.        app_secret = '*********************'

  11.        wx_login_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code' % (appid, app_secret, wx_code)

  12.        try:

  13.            wx_login_token = requests.get(url=wx_login_token_url, timeout=15).json() # 獲取一個token

  14.            session['openid'] = wx_login_token['openid'] # 微信返回的openid,同時返回了一個授權(quán)用的Token,這個授權(quán)token是沒有次數(shù)限制的,區(qū)別于基礎(chǔ)功能的access_token,這里把openid作為session來全局判斷登錄狀態(tài)

  15.            access_token = get_access_token(appid, app_secret)  # 單獨寫了一個獲取基礎(chǔ)功能access_tokende 的方法,這個是有次數(shù)限制的,每天2000次,用完就gg了,所以需要做特殊的緩存操作,下面會詳細說

  16.            jsapi = get_ticket(access_token['access_token'], 'jsapi')  # 這個單獨的方法是獲取通用jssdk需要的ticket方法,ticket的使用也有次數(shù)限制,所以也需要做緩存

  17.            jsapi_ticket = jsapi['ticket']

  18.            jsapi_timestamp = int(time.time())

  19.            jsapi_current_url = request.url

  20.            jsapi_noncestr = createNonceStr()

  21.            before_string = 'jsapi_ticket=%s&noncestr=%s×tamp=%s&url=%s' % (jsapi_ticket, jsapi_noncestr, jsapi_timestamp, jsapi_current_url)

  22.            sha = hashlib.sha1(before_string.encode('utf8'))

  23.            jsapi_signature = sha.hexdigest()

  24.            jssdk_data = {

  25.                'appId': appid,

  26.                'timestamp': str(jsapi_timestamp),

  27.                'nonceStr': jsapi_noncestr,

  28.                'signature': jsapi_signature,

  29.            }

  30.            # 以上這一段是生成jssdk用的簽名等參數(shù),這些參數(shù)用于基礎(chǔ)jssdk的各種功能調(diào)用

  31.            card_id = 'p1NnvjhhcMvSHx××××××××××××××'

  32.            card_ticket = get_ticket(access_token['access_token'], 'wx_card') # 這個單獨的方法是獲取卡券專用ticket方法,這個跟上面那個ticket是有區(qū)別的,官方文檔也有詳細說明原因,此ticket的使用也有次數(shù)限制,所以也需要做緩存

  33.            cardapi_ticket = card_ticket['ticket']

  34.            card_timestamp = str(int(time.time()))

  35.            card_noncestr = createNonceStr()

  36.            fuck_dic_list = sorted([cardapi_ticket, card_timestamp, card_id, card_noncestr])

  37.            card_string = '%s%s%s%s' % (fuck_dic_list[0], fuck_dic_list[1], fuck_dic_list[2], fuck_dic_list[3])

  38.            sha_card = hashlib.sha1(card_string.encode('utf8'))

  39.            card_signature = sha_card.hexdigest()

  40.            card_data = {

  41.                'timestamp': card_timestamp,

  42.                'nonce_str': card_noncestr,

  43.                'signature': card_signature

  44.            }

  45.            # 以上這一段是生成卡券用的簽名等參數(shù),這些參數(shù)用于卡券的功能調(diào)用

  46.            # 獲取用戶信息接口,注意,此接口使用的是微信登錄所拿到的token,微信還有個獲取用戶信息的接口,可以獲取微信是否關(guān)注公眾號,那個接口使用的是基礎(chǔ)access_token,有次數(shù)限制,具體使用哪個要看個人業(yè)務需求

  47.            # 最開始的時候客戶是要根據(jù)用戶是否關(guān)注公眾號來判斷用戶是否可以參與活動,后面跟我說不要這個需求了,所以下面的變量寫了follow就沒有改

  48.            wx_userinfo_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s' % (wx_login_token['access_token'], session['openid'])

  49.            follow_response = json.loads(requests.get(url=wx_userinfo_url, timeout=15).content.decode('utf8'))

  50.            wx_openid = session['openid']

  51.            wx_nickname = follow_response['nickname']

  52.            wx_headimgurl = follow_response['headimgurl']

  53.            wx_sex = follow_response['sex']

  54.            wx_hostip = request.headers['Remote-Host'] # 獲取一個請求的IP,不一定準確,需要配合下面的參數(shù)使用

  55.            wx_xip = request.headers['X-Forwarded-For']  # flask 獲取用戶的真實IP,有時候這個地方有兩個值,一個是wifi的ip,一個是4G的ip,但是都有可能被用戶偽造

  56.            mysql_db = Database()

  57.            query_sql = 'SELECT addcard FROM wx_users WHERE `openid`=%s'

  58.            query_result = mysql_db.query(query_sql, [session['openid']])

  59.            if len(query_result) > 0:

  60.                if query_result[0][0] == 0:

  61.                    page_status = '1'

  62.                else:

  63.                    page_status = '2'

  64.            else:

  65.                insert_sql = 'INSERT INTO wx_users (`openid`,`nickname`,`headimgurl`,`sex`,`hostip`,`x-for-ip`) VALUES (%s,%s,%s,%s,%s,%s)'

  66.                mysql_db.insert(insert_sql, [wx_openid, wx_nickname, wx_headimgurl, wx_sex, wx_hostip, wx_xip])

  67.                page_status = '1'

  68.            return render_template('index.html', status=page_status, jssdk=jssdk_data, cardId=card_id, cardExt=card_data)

  69.        except Exception as e:

  70.            return redirect('http://coupon.abc.com')

代碼里面涉及到的兩個單獨方法如下,第一個獲取基礎(chǔ)access_token

  1. def get_access_token(appid, app_secret):

  2.    access_token_file = sys.path[0] + '/access_token.json' # 將獲取到的token緩存到本地文件,上面說過這個token是有使用次數(shù)限制的

  3.    wx_access_token_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s' % (appid, app_secret)

  4.    try:

  5.        if os.path.exists(access_token_file): # 緩存文件存在的時候就直接讀緩存

  6.            access_token = open(access_token_file).readline()

  7.            token_string = access_token.split('|')[0]

  8.            last_time = int(access_token.split('|')[1])

  9.            current_time = int(time.time())

  10.            if current_time > last_time: # 判斷是否達到了過期時間,原本過期時間為7200秒,我寫了6000,提前一點重新獲取

  11.                token_string = requests.get(url=wx_access_token_url, timeout=15).content.decode('utf8')

  12.                signa_expire_time = str(int(time.time() + 6000))

  13.                with open(access_token_file, 'wb') as f:

  14.                    f.write(str.encode(token_string + '|' + signa_expire_time))

  15.                    f.flush()

  16.                    f.close()

  17.        else: # 沒有緩存文件的時候就去微信服務器獲取

  18.            token_string = requests.get(url=wx_access_token_url, timeout=15).content.decode('utf8')

  19.            signa_expire_time = str(int(time.time() + 6000))

  20.            with open(access_token_file, 'wb') as f:

  21.                f.write(str.encode(token_string + '|' + signa_expire_time))

  22.                f.flush()

  23.                f.close()

  24.        return json.loads(token_string)

  25.    except Exception as e:

  26.        return jsonify({'code': -1, 'msg': str(e)}) # jsonify 方法可以直接轉(zhuǎn)換成json很方便,也可以用json庫進行轉(zhuǎn)換,常用的有json.loads(str)和json.dump(json)方法

第二個單獨方法是獲取ticket,請求的方式一樣,唯獨參數(shù)值不一樣

  1. def get_ticket(access_token, ticket_type):

  2.    if ticket_type == 'wx_card':

  3.        ticket_file = sys.path[0] + '/jsapi_signa_ticket.json'

  4.    else:  # jsapi

  5.        ticket_file = sys.path[0] + '/jsapi_ticket.json'

  6.    wx_ticket_url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=%s' % (access_token, ticket_type)

  7.    try:

  8.        if os.path.exists(ticket_file):

  9.            ticket = open(ticket_file).readline()

  10.            ticket_string = ticket.split('|')[0]

  11.            last_time = int(ticket.split('|')[1])

  12.            current_time = int(time.time())

  13.            if current_time > last_time:

  14.                ticket_string = requests.get(url=wx_ticket_url, timeout=15).content.decode('utf8')

  15.                signa_expire_time = str(int(time.time() + 6000))

  16.                with open(ticket_file, 'wb') as f:

  17.                    f.write(str.encode(ticket_string + '|' + signa_expire_time))

  18.                    f.flush()

  19.                    f.close()

  20.        else:

  21.            ticket_string = requests.get(url=wx_ticket_url, timeout=15).content.decode('utf8')

  22.            signa_expire_time = str(int(time.time() + 6000))

  23.            with open(ticket_file, 'wb') as f:

  24.                f.write(str.encode(ticket_string + '|' + signa_expire_time))

  25.                f.flush()

  26.                f.close()

  27.        return json.loads(ticket_string)

  28.    except Exception as e:

  29.        return jsonify({'code': -1, 'msg': str(e)})

這兩個方法獲取回來的數(shù)據(jù)都需要進行緩存。

前端頁面在加載的時候需要初始化微信分享和卡券的相關(guān)簽名參數(shù)等,所以需要把前面生成的簽名數(shù)據(jù)傳過去,通過render就可以輕松傳到前端,render這個東西不要覺得有多神秘,搞過nodejs和thinkphp的估計也都見過,如下代碼

  1. return render_template('index.html', status=page_status, jssdk=jssdk_data, cardId=card_id, cardExt=card_data)

前端拿數(shù)據(jù)也是非常簡單,如下

  1. <> class='mainBody'>

  2.        {% if status == '1' %}

  3.            <> class='page_index'>

  •            <> class='page_info'>

  •                <> class='formbox'>

  •                    

    <>
    src='/static/img/text-index.png'>

  •                    

    <>
    src='/static/img/input-name.png'><> type='text' v-model='username' maxlength='30'>

  •                    

    <>
    src='/static/img/input-carnum.png'><> type='text' v-model='carnumber' maxlength='8'>

  •                    

    <>
    src='/static/img/input-carmod.png'><> type='text' v-model='carmodal' maxlength='30'>

  •                    

    <>
    src='/static/img/input-phone.png'><> type='tel' v-model='userphone' maxlength='11'>

  •                    <> href='javascript:;' @click='postData'><> src='/static/img/button-save.png'>

  •                

  •            

  •        {% elif status == '2' %}

  •            <> class='page_finish'><> src='/static/img/page4.png'>

  •        {% endif %}

  • JInja2使用了{% %}識別邏輯判斷等,看起來是不是很像jsp或者thinkphp?其實寫起來都差不多,直接輸出數(shù)據(jù)如下

    1. wx.config({

    2.            debug: false,

    3.            appId: '[[ jssdk.appId ]]',

    4.            timestamp: '[[ jssdk.timestamp ]]',

    5.            nonceStr: '[[ jssdk.nonceStr ]]',

    6.            signature: '[[ jssdk.signature ]]',

    7.            jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage','addCard']

    8.        });

    9.        wx.ready(function () {

    10.            wxSetShare();

    11.        });

    12.        function wxSetShare(){

    13.            //朋友圈分享

    14.            wx.onMenuShareTimeline({

    15.                title: wx_shareTitle,

    16.                link:  wx_shareurl,

    17.                imgUrl: wx_imgUrl,

    18.                success: function () {},

    19.                cancel: function () {console.log('share cancel')}

    20.            });

    21.            //發(fā)送給朋友

    22.            wx.onMenuShareAppMessage({

    23.                title: wx_shareTitle,

    24.                desc:  wx_shareContent,

    25.                link:  wx_shareurl,

    26.                imgUrl: wx_imgUrl,

    27.                type: 'link',

    28.                dataUrl: '',

    29.                success: function () {},

    30.                cancel: function () {console.log('share cancel')}

    31.            });

    32.        }

    33.        var cardExtString = '{'timestamp':'[[ cardExt.timestamp ]]','nonce_str':'[[ cardExt.nonce_str ]]','signature':'[[ cardExt.signature ]]'}';

    34.        function addCoupon() {

    35.            wx.addCard({

    36.                cardList: [{

    37.                    cardId: '[[ cardId ]]',

    38.                    cardExt: cardExtString

    39.                    }],

    40.                success: function (res) {

    41.                    axios.post('/addCard').then(function (response) {

    42.                        if(response.data.code === 0){

    43.                            window.location.reload(true)

    44.                        }else{

    45.                            weui.alert(response.data.msg);

    46.                        }

    47.                    }).catch(function (error) {

    48.                        weui.alert(error);

    49.                    });

    50.                }

    51.            });

    52.        }

    在[[ ]]里面直接就輸出了數(shù)據(jù),這里有個大坑,看下面這段代碼

    1. var cardExtString = '{'timestamp':'[[ cardExt.timestamp ]]','nonce_str':'[[ cardExt.nonce_str ]]','signature':'[[ cardExt.signature ]]'}';

    2.        function addCoupon() {

    3.            wx.addCard({

    4.                cardList: [{

    5.                    cardId: '[[ cardId ]]',

    6.                    cardExt: cardExtString

    7.                    }],

    8.                success: function (res) {

    9.                    axios.post('/addCard').then(function (response) {

    10.                        if(response.data.code === 0){

    11.                            window.location.reload(true)

    12.                        }else{

    13.                            weui.alert(response.data.msg);

    14.                        }

    15.                    }).catch(function (error) {

    16.                        weui.alert(error);

    17.                    });

    18.                }

    19.            });

    20.        }

    里面有個

    1. cardExt: cardExtString

    微信官方的寫法是

    1. wx.addCard({

    2.    cardList: [{

    3.        cardId: '[[ cardId ]]',

    4.        cardExt: {

    5.        timestamp:'×××××',

    6.        nonce_str:'×××××',

    7.        signature:'×××××'

    8.        }

    9.        }],

    10.    success: function (res) {

    11.        axios.post('/addCard').then(function (response) {

    12.        if(response.data.code === 0){

    13.            window.location.reload(true)

    14.        }else{

    15.            weui.alert(response.data.msg);

    16.        }

    17.        }).catch(function (error) {

    18.        weui.alert(error);

    19.        });

    20.    }

    21. });

    如果替換掉Jinja2的識別符應該就是

    1. wx.addCard({

    2.    cardList: [{

    3.        cardId: '[[ cardId ]]',

    4.        cardExt: {

    5.        timestamp:'[[ cardExt.timestamp ]]',

    6.        nonce_str:'[[ cardExt.nonce_str ]]',

    7.        signature:'[[ cardExt.signature ]]'

    8.        }

    9.        }],

    10.    success: function (res) {

    11.        axios.post('/addCard').then(function (response) {

    12.        if(response.data.code === 0){

    13.            window.location.reload(true)

    14.        }else{

    15.            weui.alert(response.data.msg);

    16.        }

    17.        }).catch(function (error) {

    18.        weui.alert(error);

    19.        });

    20.    }

    21. });

    在自己安卓手機上測試通過,發(fā)給客戶,客戶一直說他的手機不行,提示簽名錯誤,我就郁悶了,我這里測試很多遍都可以啊,要求客戶發(fā)截圖,截圖發(fā)來看看確實簽名錯誤,神奇了。仔細一看,客戶用的是IPhone,難道是安卓可以ios不行,經(jīng)過長達4個小時的不斷嘗試,終于給解決問題了,開啟微信jssdk的調(diào)試模式后在安卓和ios上都會彈窗提示普通jssdk的簽名正確,安卓上面領(lǐng)取優(yōu)惠券成功后會顯示優(yōu)惠券相關(guān)信息,仔細一看發(fā)現(xiàn)雙引號被轉(zhuǎn)義各種斜杠,但是是成功的,然而iphone不行,此時我才想起這個坑我之前就遇到過,因為ios解析json的時候認為{}里面的是一個json對象,會把一些字符轉(zhuǎn)義,導致簽名字符串不一致,所以簽名錯誤,而安卓則認為{}是一個字符串,正常的處理,就不會報錯。

    于是就有了上面那個

    1. var cardExtString = '{'timestamp':'[[ cardExt.timestamp ]]','nonce_str':'[[ cardExt.nonce_str ]]','signature':'[[ cardExt.signature ]]'}';

    直接定義成一個字符串,這樣安卓和ios識別就會一致的認為這個變量為字符串類型,不會做特殊處理,至此BUG解決。

    這里順便說下axios,使用方法如下代碼

    1. axios.post('/addCard').then(function (response) {

    2.                        if(response.data.code === 0){

    3.                            window.location.reload(true)

    4.                        }else{

    5.                            weui.alert(response.data.msg);

    6.                        }

    7.                    }).catch(function (error) {

    8.                        weui.alert(error);

    9.                    });

    簡單易用,通俗易懂。

    部署

    項目上線部署到阿里云上,使用的是系統(tǒng)是CentOS 7,Python3 + virtualenv + supervisor + gunicorn + nginx 具體部署方法我之前也專門寫文章講過,關(guān)于部署這塊如果有同學不懂或者不清楚部署方法的話可以郵箱聯(lián)系我。

    后記

    遇到問題多谷歌,經(jīng)驗真的很重要?。。?!


    題圖:pexels,CC0 授權(quán)。

    本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
    打開APP,閱讀全文并永久保存 查看更多類似文章
    猜你喜歡
    類似文章
    微信JSSDK說明文檔
    java微信分享config:invalid signature,自定義右上角菜單(只保留分享給好友和朋友圈)
    微信開發(fā)(六)微信分享接入
    《程序員》:當微軟牛津計劃遇到微信App ——微信實現(xiàn)部分
    微信JSSDK分享功能詳解
    微信分享
    更多類似文章 >>
    生活服務
    分享 收藏 導長圖 關(guān)注 下載文章
    綁定賬號成功
    后續(xù)可登錄賬號暢享VIP特權(quán)!
    如果VIP功能使用有故障,
    可點擊這里聯(lián)系客服!

    聯(lián)系客服