
因?yàn)樯婕暗臇|西比較多,所以需要準(zhǔn)備的東西也比較雜。當(dāng)然,你得首先知道自己要做什么,畢竟這一切準(zhǔn)備和將來的勞動都將為這個產(chǎn)品服務(wù)。
開發(fā)者資質(zhì)、服務(wù)器、數(shù)據(jù)庫、域名(需要預(yù)留至少20天備案時間)、SSL證書等可以通過申請、購買獲得,工具及操作環(huán)境如下:

工具:Axure RP、putty、WinSCP、Photoshop、微信web開發(fā)者工具、Sublime Text、Zend Studio
操作環(huán)境:微信公眾平臺、騰訊云、業(yè)務(wù)服務(wù)器CentOS 7.2(nginx/1.10.1、php-fpm(PHP 5.6.26, Zend Engine v2.6.0))、會話管理服務(wù)器CentOS
7.2(PHP+Mysql+Apache)、微信小程序數(shù)據(jù)庫MySQL
整個過程會產(chǎn)生一些費(fèi)用,根據(jù)自己選擇,大概幾百元的樣子。不過別擔(dān)心,騰訊云可以滿足所有需求,其中的微信小程序解決方案,就是專門針對小程序量身定制的。
目前小程序的開放注冊范圍僅限于企業(yè)、政府、媒體和其他組織,是不開放對個人注冊的,所以首先你需要給自己一個合法的身份,我是找了個朋友的企業(yè)注冊的。申請小程序的開發(fā)權(quán)限,請移步微信公眾平臺。吐槽一句,現(xiàn)在開發(fā)者也流行繳納“入會費(fèi)”,這里需要300元。

其次是騰訊云注冊,這里可以獲得小程序用到的一切資源,包括域名、SSL證書、服務(wù)器、數(shù)據(jù)庫等。小程序畢竟是騰訊的產(chǎn)品,服務(wù)器支持肯定自家的兼容更好些,騰訊云官網(wǎng)為廣大開發(fā)者提供了微信解決方案服務(wù)器。首次購買半年需要516元,后期續(xù)費(fèi)每月91元。

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

騰訊云可以申請域名,(.com域名一般需要45元左右),審核過程會持續(xù)4-5個工作日,之后需要解析域名,在騰訊云管理中心可以直接操作(登錄騰訊云管理中心-云產(chǎn)品-域名服務(wù)-云解析)。域名備案比較耗時,要在指定背景下拍照。如果你距離指定地點(diǎn)比較近,可以到指定地點(diǎn)拍照,基本各省都有拍照點(diǎn),見拍照點(diǎn)地圖。

如果不方便,可以申請郵寄給你個背景幕布,按照要求拍照,見辦理拍照指南,備案材料提交管局審核,需要大概20個工作日(你得習(xí)慣這工作效率),所以最好提前申請域名,給備案預(yù)留出時間。

另外,域名實(shí)名認(rèn)證也需要4-5天。
在騰訊云購買小程序解決方案時需要選后臺語言,決定了分配給你的是什么系統(tǒng)及環(huán)境的服務(wù)器(有PHP、Java、Node.js、.NET四種選擇),后期可更改、重裝系統(tǒng)。云端小程序構(gòu)建完成后會得到三個服務(wù)器:業(yè)務(wù)服務(wù)器、會話管理服務(wù)器、MySQL數(shù)據(jù)庫服務(wù)器,之后以短信形式發(fā)送分配的服務(wù)器登錄密碼,用戶名統(tǒng)一是root。
在騰訊云登錄服務(wù)器后可以在彈出的黑色命令窗口輸入命令,見下圖:

之后輸入用戶名和密碼即登錄成功。這個登錄窗口是用canvas做的,不能拖動滾動條查看一屏以外的東西,相當(dāng)憋屈。所以還得有個稱手的工具,現(xiàn)在putty可以登場了。

運(yùn)行putty之后輸入公網(wǎng)IP地址,點(diǎn)擊Open,之后輸入用戶名密碼,就可以執(zhí)行各種shell命令了。

至于上傳下載文件,為了安全起見,默認(rèn)安裝的鏡像 FTP 不支持,官方推薦用WinSCP/SecureFX,這兩個都可以支持,操作跟 FTP 類似。
這里不得不說下關(guān)于三個服務(wù)器需要注意的點(diǎn),或者說是坑。系統(tǒng)雖然可以重裝,不過需謹(jǐn)慎,因?yàn)橛行┡渲弥匮b后并不能恢復(fù)成最初分配時的狀態(tài)。下圖是業(yè)務(wù)服務(wù)器重裝界面(再次提醒:重裝需謹(jǐn)慎):

關(guān)于業(yè)務(wù)服務(wù)器:我選的是PHP環(huán)境服務(wù)器,購買后默認(rèn)并不支持mysql,需要自己安裝。下面是關(guān)于PHP環(huán)境業(yè)務(wù)服務(wù)器升級支持mysql擴(kuò)展方法:
### 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
以上四行,從上到下按次序執(zhí)行或保存為一文件,如update_php.sh(見附件), 然后執(zhí)行
chmod +x update_php.sh
再執(zhí)行
./update_php.sh
即可
業(yè)務(wù)服務(wù)器配置參考這里,修改Linux - /etc/qcloud/sdk.config文件。
業(yè)務(wù)服務(wù)器的文件存放路徑/data/release/php-weapp-demo
關(guān)于會話服務(wù)器:首先查看《騰訊云小程序會話管理服務(wù)器BUG修復(fù)與升級方案》(見附件),然后如果你也重裝了會話服務(wù)器,你可能還會發(fā)現(xiàn)一個問題,官方給出的三木聊天室demo鏈接失敗。問題解決參考這里 。
1.執(zhí)行
cd /opt/lampp/htdocs/mina_auth/system/db/
vi db.ini
記下配置里的host和pass_wd值,之后ctrl+Z退出。
2.執(zhí)行
cd /opt/lampp/bin/
之后按照參考,本應(yīng)執(zhí)行
./mysql -h #ip -P #port -u #username -p #passwd(其中#ip、#port、#username、#passwd是在1.2步驟中查看到的具體信息)
但因?yàn)橹匮b系統(tǒng)默認(rèn)提供的IP和密碼不正確,需要在微信小程序數(shù)據(jù)庫MySQL賬號管理里為session_user重置密碼,見下圖:

然后用mysql內(nèi)網(wǎng)IP和新密碼執(zhí)行如下命令:
./mysql -h IP -P 3306 -u session_user -p新密碼
或直接用root賬號登錄,執(zhí)行:
mysql -h IP -P 3306 -u root -proot密碼
(IP為微信小程序數(shù)據(jù)庫MySQL內(nèi)網(wǎng)地址,用戶名和密碼為登錄數(shù)據(jù)庫服務(wù)器的賬號密碼,注意參數(shù)-p后沒有空格)
3.登錄微信公眾號打開開發(fā)設(shè)置,記下AppID(小程序ID)和AppSecret(小程序密鑰)
4.執(zhí)行(命令行后帶;設(shè)置字段值不用引號,退出mysql命令行直接輸入;回車):
use cAuth;
update cAppinfo set appid = 這里是AppID,secret =這里是 AppSecret;
5.為會話服務(wù)器云主機(jī)安全組添加默認(rèn)安全組放通全部端口,并更改優(yōu)先級在前面
6.更新/opt/lampp/htdocs/mina_auth/system/db/vi db.ini內(nèi)容為以下:
[db]
host = 數(shù)據(jù)庫MySQL內(nèi)網(wǎng)地址
port = 3306
user_name = session_user
pass_wd = 新密碼
data_base= cAuth
或
[db]
host = 數(shù)據(jù)庫MySQL內(nèi)網(wǎng)地址
port = 3306
user_name = root
pass_wd = root密碼
data_base= cAuth
會話服務(wù)器文件存放路徑/opt/lampp/htdocs
關(guān)于數(shù)據(jù)庫服務(wù)器:如果有數(shù)據(jù)表格需要導(dǎo)入,如果你要導(dǎo)入的.sql文件大于2048k,可以壓縮成zip,一般可以壓縮到原來的1/20,壓縮比率還是很可觀的。
騰訊云實(shí)名認(rèn)證后可以獲得騰訊云的代金券,還可以更好的保障你的號安全,認(rèn)證后你的騰訊云號也是獨(dú)一無二的。具體見實(shí)名認(rèn)證指引,大約1-2個工作日。

為了保護(hù)小程序應(yīng)用安全,微信官方的需求文檔要求每個微信小程序必須事先設(shè)置一個域名,并通過HTTPS請求進(jìn)行網(wǎng)絡(luò)通信,不滿足條件的域名和協(xié)議無法請求。所以需要購買或申請SSL證書。目前正規(guī)渠道購買SSL證書還是很貴的,不過如果您選的是微信小程序方案,這個SSL證書是免費(fèi)的(大約需要1個工作日審核下發(fā)),頒發(fā)后會獲得一個壓縮包,內(nèi)含安全證書。安裝ssl證書參考這里,把ssl證書壓縮包內(nèi)Nginx下的證書拷貝至/etc/nginx下
至此,環(huán)境算搭好了,剩下的就專注于你的小程序開發(fā)了。
我最初是想做一個車友會之類的小程序,但涉及車友互動發(fā)文之類,需要有互聯(lián)網(wǎng)電子公告服務(wù)許可證, 總之各種條條框框。反正我是練手,還是繞過這個限制,改做記賬本之類的小工具了,鑒于目前小程序只能匹配全名,只在個別關(guān)鍵詞開啟了模糊匹配,經(jīng)過查驗(yàn),“養(yǎng)車”和“記賬”兩個詞都可以模糊搜索,所以名字就叫“養(yǎng)車記賬本”了,可以給車主提供個專門記錄養(yǎng)車所產(chǎn)生的費(fèi)用的統(tǒng)計(jì)工具。從用戶開始訪問小程序開始,大概流程圖如下:

主要涉及以下幾個功能:增加記賬、賬單列表、賬單篩選、修改賬目、刪除賬目、賬單統(tǒng)計(jì)、車型選擇、分類設(shè)置等。
增加記賬和修改賬目可以共用同一個界面,根據(jù)實(shí)際需要,要用到賬單分類、賬單產(chǎn)生日期,再就是額度。記賬頁面操作簡單,見后面設(shè)計(jì)圖。
賬單列表頁和賬單統(tǒng)計(jì)作為一個展示模塊,需要能夠通過設(shè)置篩選條件比如時間段、類別勾選來展示指定賬目,展示方式為按時間列表,統(tǒng)計(jì)方式為餅圖。
用戶可以設(shè)置車型,可以不填。如果用戶有不止一輛車,這個必須為必填,不過第一版先不考慮多輛車這個維度,后期再加。
至于分類,我大概歸納了一下用車、養(yǎng)車過程可能產(chǎn)生費(fèi)用的方面,大概包括(停車費(fèi)、加油費(fèi)、養(yǎng)護(hù)、保險、罰款、高速、維修、購車、年檢、改裝、賠償?shù)龋?,如果不夠用可以在分類設(shè)置里增加分類,如果用不到的可以關(guān)閉,避免干擾。
再就是象征性的來個建議反饋、關(guān)于之類的。
小程序有推薦的設(shè)計(jì)規(guī)范,見微信小程序設(shè)計(jì)指南,為方便設(shè)計(jì)師進(jìn)行設(shè)計(jì),微信提供一套可供Web設(shè)計(jì)和小程序使用的基礎(chǔ)控件庫;同時提供方便開發(fā)者調(diào)用的資源。設(shè)計(jì)小程序推薦以iphone6的尺寸為標(biāo)準(zhǔn),即750px*1334px。

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

開始碼代碼了,開發(fā)分前端和后臺。
小程序在前端上的貢獻(xiàn)不得不點(diǎn)贊,wxss在css的基礎(chǔ)上擴(kuò)展了rpx(responsive pixel)單位,rpx換算px為屏幕寬度/750,px換算rpx為750/屏幕寬度。這樣就可以根據(jù)屏幕寬度進(jìn)行自適應(yīng),讓前端開發(fā)可以解放出來不用過多考慮兼容問題。使用rpx規(guī)定屏幕寬為750rpx,比如在 iPhone6 上,屏幕寬度為375px,共有750個物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。wxml是 微信 的一套標(biāo)簽語言,結(jié)合基礎(chǔ)組件、事件系統(tǒng),可以構(gòu)建出頁面的結(jié)構(gòu)。開發(fā)工具不大好用(遇到N次閃退,有個好的保存習(xí)慣還是不錯的;還有就是調(diào)試時候如果需要點(diǎn)開非默認(rèn)頁面,有時候不能刷出Wxml結(jié)構(gòu),重啟開發(fā)工具可以解決),但畢竟不是一天兩天打造完美的,相信微信團(tuán)隊(duì)一定能做更好。如果不習(xí)慣也可以用你喜歡的工具。我的頁面結(jié)構(gòu)如下:
"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"
],
如果問你,小程序放開的用戶數(shù)據(jù)夠嗎?你一定說不夠。那我們能做的就是物盡其用吧!如果你的接口涉及wx.getUserInfo當(dāng)中的 openId,接口的明文內(nèi)容將不包含這些敏感數(shù)據(jù)。如果需要獲取敏感數(shù)據(jù),需要對接口返回的加密數(shù)據(jù)( encryptedData )進(jìn)行對稱解密??蓞⒖嘉⑿判〕绦蚩蛻舳蓑v訊云增強(qiáng) SDK。
在微信登錄,解密encryptData后,可以在userInfo里可以看到用戶信息

在登錄后做了這些工作:獲取用戶信息,對照數(shù)據(jù)庫,如果庫里有該用戶,將車型和類別設(shè)置存儲到本地,以供其他頁面調(diào)用;如果沒有則保存該用戶。如果庫里有該用戶且設(shè)備信息有變化則更新設(shè)備信息,如果沒有則追加設(shè)備信息。如果用戶拒絕獲取用戶信息,授權(quán)失敗,顯示重新授權(quán)教程。篇幅有限,只截取部分代碼展示。代碼如下:
// 用戶登錄
UserLoginFn:function(){
var that = this;
// qcloud.request() 方法和 wx.request() 方法使用是一致的,不過如果用戶已經(jīng)登錄的情況下,會把用戶的會話信息帶給服務(wù)器,服務(wù)器可以跟蹤用戶
qcloud.request({
url: config.service.requestUrl, // 要請求的地址
login: true, // 請求之前是否登錄,如果該項(xiàng)指定為 true,會在請求之前進(jìn)行登錄
success(result) {
wx.setStorageSync('ThisUserInfo', result);
var usr = result.data.data.userInfo;
that.setData({
ThisUserInfo: result
});
wx.setStorageSync('OpenID', usr.openId);
// 用戶登錄(如果庫里有該用戶,將車型和類別設(shè)置存儲到本地,如果沒有則保存該用戶)
wx.request({
url: 'https://xxx.php', //這里不是真實(shí)地址
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(); // 登錄成功后為該用戶格式化表單
}
}
});
// 用戶設(shè)備信息采集
wx.getNetworkType({
success: function(res) {
// 返回網(wǎng)絡(luò)類型, 有效值:wifi/2g/3g/4g/unknown(Android下不常見的網(wǎng)絡(luò)類型)/none(無網(wǎng)絡(luò))
var networkType = res.networkType;
wx.getSystemInfo({
success: function(res) {
// 如果庫里有該用戶且設(shè)備信息有變則更新設(shè)備信息,如果沒有則追加設(shè)備信息
wx.request({
url: 'https://xxx.php', //這里不是真實(shí)地址
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: '未授權(quán)不可使用,請刪除后重新獲取養(yǎng)車記賬本。',
showCancel: false,
confirmText: '查看教程',
confirmColor: '#3CC51F',
success: function(res) {
if (res.confirm) {
wx.redirectTo({
url: '/pages/other/reLogin/reLogin'
});
}
}
});
}
});
},
前端開發(fā)過程中遇到的問題順便提一句,canvas、textarea、video等組件使用原生渲染,如果需要彈層交互的話它們會擋住彈層,解決辦法就是在彈層后將這些組件hidden屬性設(shè)置為true,彈層消失時重置為false。另外還有個問題:我想把data里的數(shù)據(jù)保存成對象格式的,如果追加key值的話,不支持a.b:'c'這樣追加,只能a:{b:'c'},但前者可以更直觀的表示某一組賦值是給一個特定對象的,尤其有時候不能確定你要追加的key值就限于你指定的那幾個的時候,但setData并不支持這種做法,不知是出于何種考慮,如果沒有特殊原因還是希望能改進(jìn)下。再有就是css不支持標(biāo)簽名選擇器,也是目前支持標(biāo)簽比較單一,所以要想美化某個組件,必須給它實(shí)實(shí)在在賦個樣式,略顯臃腫。
后臺開發(fā)語言我選的是PHP,主要是網(wǎng)上資料多,函數(shù)方法齊全。關(guān)于PHP對MySQL的增刪改查操作網(wǎng)上很容易找到。在同事的指點(diǎn)下,采取了一些措施,防止SQL注入與XSS攻擊,主要是過濾文本,做了字符串轉(zhuǎn)換、格式化等操作。在賬單查詢頁面,通過聯(lián)合查詢列出用戶表和賬單表信息,對查詢結(jié)果裝入數(shù)組,之后進(jìn)行格式化輸出供小程序使用,代碼如下:
$accountArr = array();
$MonthList = array();
$dateTemp = '';
$switch = false;
function wk($date1) {
$datearr = explode('-',$date1); //將傳來的時間使用“-”分割成數(shù)組
$year = $datearr[0]; //獲取年份
$month = sprintf('%02d',$datearr[1]); //獲取月份
$day = sprintf('%02d',$datearr[2]); //獲取日期
$hour = $minute = $second = 0; //默認(rèn)時分秒均為0
$dayofweek = mktime($hour,$minute,$second,$month,$day,$year); //將時間轉(zhuǎn)換成時間戳
$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 == ''){ // 如果沒有結(jié)果
$accountArr = array(); //返回空數(shù)組
}
$str = json_encode($accountArr); //將數(shù)組轉(zhuǎn)化為json格式的字符串
echo $str;
針對自己的項(xiàng)目,需要設(shè)計(jì)合理的數(shù)據(jù)庫表以滿足記賬的需要。關(guān)于賬單表字段設(shè)置如下:
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='賬目表';
此外還有用戶表、設(shè)備表、類別表、車型表。除了車型表獨(dú)立存在之外,其他幾個表都是以O(shè)penID字段相互關(guān)聯(lián)的,以實(shí)現(xiàn)相互間的互查。
開發(fā)者工具 集成了開發(fā)調(diào)試、代碼編輯及程序發(fā)布等功能,其中模擬器模擬微信小程序在客戶端真實(shí)的邏輯表現(xiàn),對于絕大部分的 API 均能在模擬器上呈現(xiàn)出正確的狀態(tài)。自帶的調(diào)試工具分為 6 大功能模塊:Wxml、Console、Sources、Network、Appdata、Storage,平時開發(fā)的時候及時糾錯,問題不大。馬上就要車展了,鑒于時間關(guān)系,第一版就這樣匆匆提交了。不過比較幸運(yùn),首次提交就通過審核了。

提交審核需要填一些簡單的信息,有利于用戶快速搜索出你的信息。之后可以在微信公眾平臺查看數(shù)據(jù)分析,其中的自定義分析功能強(qiáng)大(不過目前正在內(nèi)測中,暫時只支持開發(fā)者測試數(shù)據(jù)上報;6.5.4及以上微信版本支持用戶數(shù)據(jù)上報,用戶微信版本更新以前無法收集數(shù)據(jù)。新版本覆蓋全量用戶前,數(shù)據(jù)可能有缺失),可以從不同角度分析訪問者信息,為你進(jìn)一步挖掘用戶信息做足準(zhǔn)備。

隨著小程序不斷增長,越來越多的小程序滲透到網(wǎng)友生活、工作的方方面面。弱水三千只取一瓢。本著滿足客戶某項(xiàng)需求的前提下盡量做一個小而美的工具。
問題是養(yǎng)車記賬本目前只具雛形,限于時間和個人能力,班門弄斧,只完成了基礎(chǔ)功能,還有很多細(xì)節(jié)需要調(diào)整,功能也不太完善,比如篩選交互邏輯還需要進(jìn)一步優(yōu)化,每個網(wǎng)友現(xiàn)在也只能為一輛車記錄賬單,賬單統(tǒng)計(jì)還可以列出篩選具體額度以及增加趣味評價,甚至可以考慮增加位置定位等功能……也懇請大家提出寶貴意見,未來一個月比較忙,等車展過后繼續(xù)!
最后,感謝hjiang、ningtian給出的好點(diǎn)子,感謝wqcheng給出的服務(wù)器升級、部署方面的指導(dǎo),感謝lightllchen在php開發(fā)方面的幫助。