養車記帳本小程序開發實例

前言

自微信6.5.3版本開始,小程序正式跟你們見面了。最近利用業餘時間作了個小程序,命名「養車記帳本」。做爲IT狗,經歷了從註冊開發者資質開始到正式上線的全過程,微信小程序官方 文檔 、 快速構建具有彈性伸縮能力的微信小程序 等不在這次敘述之列。本實例所用資源爲騰訊雲購買的微信小程序解決方案,選的其中的PHP環境。php

準備工做

由於涉及的東西比較多,因此須要準備的東西也比較雜。固然,你得首先知道本身要作什麼,畢竟這一切準備和未來的勞動都將爲這個產品服務。css

開發者資質、服務器、數據庫、域名(須要預留至少20天備案時間)、SSL證書等能夠經過申請、購買得到,工具及操做環境以下:html

工具:Axure RP、putty、WinSCP、Photoshop、微信web開發者工具、Sublime Text、Zend Studio前端

操做環境:微信公衆平臺、騰訊雲、業務服務器CentOS 7.2(nginx/1.10.一、php-fpm(PHP 5.6.26, Zend Engine v2.6.0))、會話管理服務器CentOS
7.2(PHP+Mysql+Apache)、微信小程序數據庫MySQL
  
整個過程會產生一些費用,根據本身選擇,大概幾百元的樣子。不過別擔憂,騰訊雲能夠知足全部需求,其中的微信小程序解決方案,就是專門針對小程序量身定製的。mysql

申請資源

目前小程序的開放註冊範圍僅限於企業、政府、媒體和其餘組織,是不開放對我的註冊的,因此首先你須要給本身一個合法的身份,我是找了個朋友的企業註冊的。申請小程序的開發權限,請移步微信公衆平臺。吐槽一句,如今開發者也流行繳納「入會費」,這裏須要300元。nginx

其次是騰訊雲註冊,這裏能夠得到小程序用到的一切資源,包括域名、SSL證書、服務器、數據庫等。小程序畢竟是騰訊的產品,服務器支持確定自家的兼容更好些,騰訊雲官網爲廣大開發者提供了微信解決方案服務器。首次購買半年須要516元,後期續費每個月91元。git

見到下面這個界面,就申請成功了。github

域名(申請、解析、備案)

騰訊雲能夠申請域名,(.com域名通常須要45元左右),審覈過程會持續4-5個工做日,以後須要解析域名,在騰訊雲管理中心能夠直接操做(登陸騰訊雲管理中心-雲產品-域名服務-雲解析)。域名備案比較耗時,要在指定背景下拍照。若是你距離指定地點比較近,能夠到指定地點拍照,基本各省都有拍照點,見拍照點地圖。web

若是不方便,能夠申請郵寄給你個背景幕布,按照要求拍照,見辦理拍照指南,備案材料提交管局審覈,須要大概20個工做日(你得習慣這工做效率),因此最好提早申請域名,給備案預留出時間。sql

另外,域名實名認證也須要4-5天。

建立微信小程序服務器

在騰訊雲購買小程序解決方案時須要選後臺語言,決定了分配給你的是什麼系統及環境的服務器(有PHP、Java、Node.js、.NET四種選擇),後期可更改、重裝系統。雲端小程序構建完成後會獲得三個服務器:業務服務器、會話管理服務器、MySQL數據庫服務器,以後以短信形式發送分配的服務器登陸密碼,用戶名統一是root。

在騰訊雲登陸服務器後能夠在彈出的黑色命令窗口輸入命令,見下圖:

以後輸入用戶名和密碼即登陸成功。這個登陸窗口是用canvas作的,不能拖動滾動條查看一屏之外的東西,至關憋屈。因此還得有個稱手的工具,如今putty能夠登場了。

運行putty以後輸入公網IP地址,點擊Open,以後輸入用戶名密碼,就能夠執行各類shell命令了。

至於上傳下載文件,爲了安全起見,默認安裝的鏡像 FTP 不支持,官方推薦用WinSCP/SecureFX,這兩個均可以支持,操做跟 FTP 相似。

這裏不得不說下關於三個服務器須要注意的點,或者說是坑。系統雖然能夠重裝,不過需謹慎,由於有些配置重裝後並不能恢復成最初分配時的狀態。下圖是業務服務器重裝界面(再次提醒:重裝需謹慎):

關於業務服務器:我選的是PHP環境服務器,購買後默認並不支持mysql,須要本身安裝。下面是關於PHP環境業務服務器升級支持mysql擴展方法:

### Update php and install php-mysql extension
wget 'https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi.repo' -O /etc/yum.repos.d/remi.repo
yum --enablerepo=remi-php56 -y update php
yum --enablerepo=remi-php56 -y install php-mysql
service php-fpm restart

以上四行,從上到下按次序執行或保存爲一文件,如update_php.sh(見附件), 而後執行

chmod +x update_php.sh

再執行

./update_php.sh

便可

業務服務器配置參考這裏,修改Linux - /etc/qcloud/sdk.config文件。
業務服務器的文件存放路徑/data/release/php-weapp-demo

關於會話服務器:首先查看《騰訊雲小程序會話管理服務器BUG修復與升級方案》(見附件),而後若是你也重裝了會話服務器,你可能還會發現一個問題,官方給出的三木聊天室demo連接失敗。問題解決參考這裏 。

1.執行

cd /opt/lampp/htdocs/mina_auth/system/db/
vi db.ini

記下配置裏的host和pass_wd值,以後ctrl+Z退出。

2.執行

cd /opt/lampp/bin/

以後按照參考,本應執行

./mysql -h #ip -P #port -u #username -p #passwd(其中#ip、#port、#username、#passwd是在1.2步驟中查看到的具體信息)

但由於重裝系統默認提供的IP和密碼不正確,須要在微信小程序數據庫MySQL帳號管理裏爲session_user重置密碼,見下圖:

而後用mysql內網IP和新密碼執行以下命令:

./mysql -h IP -P 3306 -u session_user -p新密碼

或直接用root帳號登陸,執行:

mysql -h IP -P 3306 -u root -proot密碼

(IP爲微信小程序數據庫MySQL內網地址,用戶名和密碼爲登陸數據庫服務器的帳號密碼,注意參數-p後沒有空格)

3.登陸微信公衆號打開開發設置,記下AppID(小程序ID)和AppSecret(小程序密鑰)

4.執行(命令行後帶;設置字段值不用引號,退出mysql命令行直接輸入;回車):

use cAuth;
update cAppinfo set appid = 這裏是AppID,secret =這裏是 AppSecret;

5.爲會話服務器雲主機安全組添加默認安全組放通所有端口,並更改優先級在前面

6.更新/opt/lampp/htdocs/mina_auth/system/db/vi db.ini內容爲如下:

[db]
host = 數據庫MySQL內網地址
port = 3306
user_name = session_user
pass_wd = 新密碼
data_base= cAuth

[db]
host = 數據庫MySQL內網地址
port = 3306
user_name = root
pass_wd = root密碼
data_base= cAuth

會話服務器文件存放路徑/opt/lampp/htdocs

關於數據庫服務器:若是有數據表格須要導入,若是你要導入的.sql文件大於2048k,能夠壓縮成zip,通常能夠壓縮到原來的1/20,壓縮比率仍是很可觀的。

騰訊雲實名認證

騰訊雲實名認證後能夠得到騰訊雲的代金券,還能夠更好的保障你的號安全,認證後你的騰訊雲號也是獨一無二的。具體見實名認證指引,大約1-2個工做日。

SSL證書

爲了保護小程序應用安全,微信官方的需求文檔要求每一個微信小程序必須事先設置一個域名,並經過HTTPS請求進行網絡通訊,不知足條件的域名和協議沒法請求。因此須要購買或申請SSL證書。目前正規渠道購買SSL證書仍是很貴的,不過若是您選的是微信小程序方案,這個SSL證書是免費的(大約須要1個工做日審覈下發),頒發後會得到一個壓縮包,內含安全證書。安裝ssl證書參考這裏,把ssl證書壓縮包內Nginx下的證書拷貝至/etc/nginx下

至此,環境算搭好了,剩下的就專一於你的小程序開發了。

小程序策劃

我最初是想作一個車友會之類的小程序,但涉及車友互動發文之類,須要有互聯網電子公告服務許可證, 總之各類條條框框。反正我是練手,仍是繞過這個限制,改作記帳本之類的小工具了,鑑於目前小程序只能匹配全名,只在個別關鍵詞開啓了模糊匹配,通過查驗,「養車」和「記帳」兩個詞均可以模糊搜索,因此名字就叫「養車記帳本」了,能夠給車主提供個專門記錄養車所產生的費用的統計工具。從用戶開始訪問小程序開始,大概流程圖以下:

主要涉及如下幾個功能:增長記帳、帳單列表、帳單篩選、修改帳目、刪除帳目、帳單統計、車型選擇、分類設置等。

增長記帳和修改帳目能夠共用同一個界面,根據實際須要,要用到帳單分類、帳單產生日期,再就是額度。記帳頁面操做簡單,見後面設計圖。

帳單列表頁和帳單統計做爲一個展現模塊,須要可以經過設置篩選條件好比時間段、類別勾選來展現指定帳目,展現方式爲按時間列表,統計方式爲餅圖。

用戶能夠設置車型,能夠不填。若是用戶有不止一輛車,這個必須爲必填,不過初版先不考慮多輛車這個維度,後期再加。

至於分類,我大概概括了一下用車、養車過程可能產生費用的方面,大概包括(停車費、加油費、養護、保險、罰款、高速、維修、購車、年檢、改裝、賠償等),若是不夠用能夠在分類設置裏增長分類,若是用不到的能夠關閉,避免干擾。

再就是象徵性的來個建議反饋、關於之類的。

小程序設計

小程序有推薦的設計規範,見微信小程序設計指南,爲方便設計師進行設計,微信提供一套可供Web設計和小程序使用的基礎控件庫;同時提供方便開發者調用的資源。設計小程序推薦以iphone6的尺寸爲標準,即750px*1334px。

其中圖標我用的鋼筆工具,選擇的2像素路徑描邊,無填充色。一共分兩種狀態:選中狀態和未選中狀態。未選中狀態描邊色# 7a7e83,背景色# f5f5f5;選中狀態描邊色#ffffff,背景色# 1aad19 。

小程序開發

開始碼代碼了,開發分前端和後臺。

小程序在前端上的貢獻不得不點贊,wxss在css的基礎上擴展了rpx(responsive pixel)單位,rpx換算px爲屏幕寬度/750,px換算rpx爲750/屏幕寬度。這樣就能夠根據屏幕寬度進行自適應,讓前端開發能夠解放出來不用過多考慮兼容問題。使用rpx規定屏幕寬爲750rpx,好比在 iPhone6 上,屏幕寬度爲375px,共有750個物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。wxml是 微信 的一套標籤語言,結合基礎組件、事件系統,能夠構建出頁面的結構。開發工具不大好用(遇到N次閃退,有個好的保存習慣仍是不錯的;還有就是調試時候若是須要點開非默認頁面,有時候不能刷出Wxml結構,重啓開發工具能夠解決),但畢竟不是一天兩天打造完美的,相信微信團隊必定能作更好。若是不習慣也能夠用你喜歡的工具。個人頁面結構以下:

"pages":[
    "pages/add/index/index",
    "pages/statistics/index/index",
    "pages/my/index/index",
    "pages/my/autoBrand/autoBrand",
    "pages/my/autoSerial/autoSerial",
    "pages/my/autoModel/autoModel",
    "pages/my/sort/sort",
    "pages/my/feedback/feedback",
    "pages/my/about/about",
    "pages/other/reLogin/reLogin"
  ],

若是問你,小程序放開的用戶數據夠嗎?你必定說不夠。那咱們能作的就是物盡其用吧!若是你的接口涉及wx.getUserInfo當中的 openId,接口的明文內容將不包含這些敏感數據。若是須要獲取敏感數據,須要對接口返回的加密數據( encryptedData )進行對稱解密。可參考微信小程序客戶端騰訊雲加強 SDK。

在微信登陸,解密encryptData後,能夠在userInfo裏能夠看到用戶信息

在登陸後作了這些工做:獲取用戶信息,對照數據庫,若是庫裏有該用戶,將車型和類別設置存儲到本地,以供其餘頁面調用;若是沒有則保存該用戶。若是庫裏有該用戶且設備信息有變化則更新設備信息,若是沒有則追加設備信息。若是用戶拒絕獲取用戶信息,受權失敗,顯示從新受權教程。篇幅有限,只截取部分代碼展現。代碼以下:

// 用戶登陸
UserLoginFn:function(){
    var that = this;
    // qcloud.request() 方法和 wx.request() 方法使用是一致的,不過若是用戶已經登陸的狀況下,會把用戶的會話信息帶給服務器,服務器能夠跟蹤用戶
    qcloud.request({
        url: config.service.requestUrl, // 要請求的地址
        login: true, // 請求以前是否登陸,若是該項指定爲 true,會在請求以前進行登陸
        success(result) {
            wx.setStorageSync('ThisUserInfo', result);
            var usr = result.data.data.userInfo;
            that.setData({
                ThisUserInfo: result
            });
            wx.setStorageSync('OpenID', usr.openId);
            // 用戶登陸(若是庫裏有該用戶,將車型和類別設置存儲到本地,若是沒有則保存該用戶)
            wx.request({
                url: 'https://xxx.php', //這裏不是真實地址
                data: {
                    OpenID: usr.openId,
                    NickName: usr.nickName,
                    AvatarUrl: usr.avatarUrl,
                    Gender: usr.gender,
                    Country: usr.country,
                    Province: usr.province,
                    City: usr.city
                },
                success: function(res) {
                    if(res.data){
                        wx.setStorageSync('ThisUserInfoModelID', res.data.ModelID);
                        wx.setStorageSync('ThisUserInfoSortIDList', res.data.sortIDList);
                        that.sortFormat(); // 登陸成功後爲該用戶格式化表單
                    }
                }
            });
            // 用戶設備信息採集
            wx.getNetworkType({
                success: function(res) {
                    // 返回網絡類型, 有效值:wifi/2g/3g/4g/unknown(Android下不常見的網絡類型)/none(無網絡)
                    var networkType = res.networkType;
                    wx.getSystemInfo({
                        success: function(res) {
                            // 若是庫裏有該用戶且設備信息有變則更新設備信息,若是沒有則追加設備信息
                            wx.request({
                                url: 'https://xxx.php', //這裏不是真實地址
                                data: {
                                    OpenID: usr.openId,
                                    Model: res.model,
                                    System: res.system,
                                    Language: res.language,
                                    Version: res.version,
                                    Platform: res.platform,
                                    Network: networkType,
                                    WindowWidth: res.windowWidth,
                                    WindowHeight: res.windowHeight,
                                    DevicePixelRatio: res.pixelRatio
                                }
                            });
                        }
                    })
                }
            });
        },
        fail(error) {
            wx.showModal({
                title: '提示',
                content: '未受權不可以使用,請刪除後從新獲取養車記帳本。',
                showCancel: false,
                confirmText: '查看教程',
                confirmColor: '#3CC51F',
                success: function(res) {
                    if (res.confirm) {
                        wx.redirectTo({
                            url: '/pages/other/reLogin/reLogin'
                        });
                    }
                }
            });
        }
    });
},

前端開發過程當中遇到的問題順便提一句,canvas、textarea、video等組件使用原生渲染,若是須要彈層交互的話它們會擋住彈層,解決辦法就是在彈層後將這些組件hidden屬性設置爲true,彈層消失時重置爲false。另外還有個問題:我想把data裏的數據保存成對象格式的,若是追加key值的話,不支持a.b:'c'這樣追加,只能a:{b:'c'},但前者能夠更直觀的表示某一組賦值是給一個特定對象的,尤爲有時候不能肯定你要追加的key值就限於你指定的那幾個的時候,但setData並不支持這種作法,不知是出於何種考慮,若是沒有特殊緣由仍是但願能改進下。再有就是css不支持標籤名選擇器,也是目前支持標籤比較單一,因此要想美化某個組件,必須給它實實在在賦個樣式,略顯臃腫。

後臺開發語言我選的是PHP,主要是網上資料多,函數方法齊全。關於PHP對MySQL的增刪改查操做網上很容易找到。在同事的指點下,採起了一些措施,防止SQL注入與XSS攻擊,主要是過濾文本,作了字符串轉換、格式化等操做。在帳單查詢頁面,經過聯合查詢列出用戶表和帳單表信息,對查詢結果裝入數組,以後進行格式化輸出供小程序使用,代碼以下:

$accountArr = array();
$MonthList = array();
$dateTemp = '';
$switch = false;
function wk($date1) {
    $datearr = explode('-',$date1); //將傳來的時間使用「-」分割成數組
    $year = $datearr[0]; //獲取年份
    $month = sprintf('%02d',$datearr[1]); //獲取月份 
    $day = sprintf('%02d',$datearr[2]); //獲取日期
    $hour = $minute = $second = 0; //默認時分秒均爲0
    $dayofweek = mktime($hour,$minute,$second,$month,$day,$year); //將時間轉換成時間戳
    $shuchu = date('w',$dayofweek); //獲取星期值
    $weekarray = array('星期日','星期一','星期二','星期三','星期四','星期五','星期六'); 
    return $weekarray[$shuchu]; 
}
while($row = mysql_fetch_array($result,MYSQL_ASSOC)){
    if( $switch && (substr($dateTemp,0,7) != substr($row['Date'],0,7)) ){
        $monthTemp = array( 
            'Month' => substr($dateTemp,0,7),
            'MonthList' => $MonthList
        );
        $accountArr[] = $monthTemp;
        $MonthList = array();
    }
    $temp = array( 
        'ID' => $row['ID'],
        'Date' => $row['Date'],
        'DateWk' => substr($row['Date'],8,2).'日 ('.wk($row['Date']).')',
        'SortID' => $row['SortID'],
        'Name' => $row['Name'],
        'Mony' => preg_replace('/^0+/','',$row['Mony'])
    );
    $MonthList[] = $temp;
    $dateTemp = $row['Date'];
    $switch = true;
}
$monthTemp = array( 
    'Month' => substr($dateTemp,0,7),
    'MonthList' => $MonthList
);
$accountArr[] = $monthTemp;
if($dateTemp == ''){ // 若是沒有結果
    $accountArr = array(); //返回空數組
}
$str = json_encode($accountArr); //將數組轉化爲json格式的字符串
echo $str;

針對本身的項目,須要設計合理的數據庫表以知足記帳的須要。關於帳單表字段設置以下:

CREATE TABLE `user_account` (
  `ID` int(10) UNSIGNED NOT NULL COMMENT '指針',
  `OpenID` varchar(32) NOT NULL COMMENT '用戶ID',
  `SortID` int(10) UNSIGNED NOT NULL COMMENT '類別ID',
  `Mony` decimal(11,2) UNSIGNED ZEROFILL NOT NULL DEFAULT '000000000.00' COMMENT '金額',
  `Date` date NOT NULL COMMENT '添加日期'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='帳目表';

此外還有用戶表、設備表、類別表、車型表。除了車型表獨立存在以外,其餘幾個表都是以OpenID字段相互關聯的,以實現相互間的互查。

小程序測試、發佈、監測

開發者工具 集成了開發調試、代碼編輯及程序發佈等功能,其中模擬器模擬微信小程序在客戶端真實的邏輯表現,對於絕大部分的 API 均能在模擬器上呈現出正確的狀態。自帶的調試工具分爲 6 大功能模塊:Wxml、Console、Sources、Network、Appdata、Storage,平時開發的時候及時糾錯,問題不大。立刻就要車展了,鑑於時間關係,初版就這樣匆匆提交了。不過比較幸運,首次提交就經過審覈了。

提交審覈須要填一些簡單的信息,有利於用戶快速搜索出你的信息。以後能夠在微信公衆平臺查看數據分析,其中的自定義分析功能強大(不過目前正在內測中,暫時只支持開發者測試數據上報;6.5.4及以上微信版本支持用戶數據上報,用戶微信版本更新之前沒法收集數據。新版本覆蓋全量用戶前,數據可能有缺失),能夠從不一樣角度分析訪問者信息,爲你進一步挖掘用戶信息作足準備。

結語

隨着小程序不斷增加,愈來愈多的小程序滲透到網友生活、工做的方方面面。弱水三千只取一瓢。本着知足客戶某項需求的前提下儘可能作一個小而美的工具。

問題是養車記帳本目前只具雛形,限於時間和我的能力,班門弄斧,只完成了基礎功能,還有不少細節須要調整,功能也不太完善,好比篩選交互邏輯還須要進一步優化,每一個網友如今也只能爲一輛車記錄帳單,帳單統計還能夠列出篩選具體額度以及增長趣味評價,甚至能夠考慮增長位置定位等功能……也懇請你們提出寶貴意見,將來一個月比較忙,等車展事後繼續!

相關文章
相關標籤/搜索