微信小程序云端增強(qiáng) SDK接入
【引自第九程序的博客】一、XpmJS 是啥
XpmJS可以鏈接任何云端資源,為小程序、移動(dòng)應(yīng)用提供云資源通道和后端能力。降低開(kāi)發(fā)門(mén)檻,提升小程序的開(kāi)發(fā)效率。無(wú)需編寫(xiě)后端代碼,即可實(shí)現(xiàn)用戶登錄、WebSocket 通信、微信支付、云端數(shù)據(jù)表格、文件存儲(chǔ)等功能。雖然 PHP 是最好的編程語(yǔ)言, 但是使用 XpmJS 后, 無(wú)需學(xué)習(xí)包括 PHP 在內(nèi)的任何后端語(yǔ)言,用 Javascript 即可搞定一切,NodeJS 也不用!
二、為啥 XpmJS
從代碼結(jié)構(gòu)上看 XpmJS 更優(yōu)雅!因?yàn)槭褂昧?Promise!
XpmJS 封裝了常用后端操作,還提供一個(gè)管理后臺(tái),微信支付只要一行代碼就可以實(shí)現(xiàn)!
后端部署在你的云主機(jī)上!你可以完全掌控?cái)?shù)據(jù)。
方法1: 一鍵安裝
推薦使用騰訊云一鍵安裝鏈接 ( 訪問(wèn)微信接口快, 可以免費(fèi)申請(qǐng) Https 證書(shū) )
方法2: 安裝腳本
安裝前,先提前申請(qǐng) Docker Hub 鏡像 申請(qǐng)地址 https://www.daocloud.io/mirror
- # 請(qǐng)采用 Ubuntu 14.04 64位 LTS
 - curl -sSL http://tuanduimao.com/xpmjs-server.sh | sh -s yourdomain.com http://<your id>.m.daocloud.io
 
方法3: 使用 Docker 安裝
- # 安裝 Docker
 - curl -sSL https://get.daocloud.io/docker | sh
 - # 啟動(dòng)容器
 - docker run -d --name=xpmjs-server \
 - -e "HOST=yourdomain.com" \
 - -v /host/data:/data \
 - -v /host/apps:/apps \
 - -v /host/config:/config \
 - -p 80:80 -p 443:443 \
 - tuanduimao/xpmjs-server:1.0
 
XpmJS Server 升級(jí)
第一步: 下載代碼:
- curl http://xpmjs-1252011659.costj.myqcloud.com/xpmjs-server-1.0.tar.gz
 
第二步: 解壓并更新:
- tar xvfz xpmjs-server-1.0.tar.gz
 - cd 1.0 && docker cp . xpmjs-server:/code
 
三、XpmJS 咋用
1. 用戶 ( User )
用戶登錄 login()
- var user = app.xpm.require('User');
 - user.login().then( function( userInfo ) {
 - console.log( '用戶登錄成功', userInfo );
 - app.session.set('loginUser', userInfo );
 - })
 - .catch( function( excp ) {
 - console.log('用戶登錄失敗', excp );
 - });
 
用戶退出 logout()
- var user = app.xpm.require('User');
 - user.logout().then( function( userInfo ) {
 - console.log( '用戶注銷(xiāo)成功', userInfo );
 - })
 - .catch( function( excp ) {
 - console.log('用戶注銷(xiāo)失敗', excp );
 - });
 
讀取資料 get()
來(lái)自微信客戶端的用戶信息 ( 非云端數(shù)據(jù) )
- var user = app.xpm.require('User');
 - user.get().then( function( userInfo ) {
 - console.log( '讀取成功', userInfo );
 - })
 - .catch( function( excp ) {
 - console.log('讀取失敗', excp );
 - });
 
2. 信道( Wss )
使用 Websocket 信道,可以實(shí)現(xiàn)雙向?qū)崟r(shí)通信。
打開(kāi)信道 open()
- var wss = app.xpm.require('Wss');
 - wss.open('/wxapp').then(function( res ) {
 - console.log( '信道連接成功', res );
 - })
 - .catch( function( excp ) {
 - console.log('信道連接失敗', excp );
 - });
 
在線用戶 liveUsers ()
- var wss = app.xpm.require('Wss');
 - wss.liveUsers().then(function( users ) {
 - console.log( '讀取在線用戶成功', users );
 - })
 - .catch( function( excp ) {
 - console.log('讀取在線用戶失敗', excp );
 - });
 
用戶信息數(shù)據(jù)結(jié)構(gòu)
| 字段 | 中文 | 說(shuō)明 | 
|---|---|---|
| id | 客戶端ID | |
| _id | 用戶ID | |
| nickName | 微信昵稱 | |
| gender | 性別 | |
| avatarUrl | 頭像 | |
| language | 語(yǔ)言 | |
| group | 用戶組 | |
| isadmin | 是否是管理員 | 0 非管理員 1 管理員 | 
檢查用戶是否在線 isOnline ( xpmjs-server 1.0rc4+ )
- var user = app.xpm.require('User');
 - var wss = app.xpm.require('Wss');
 - user.login().then( function( userInfo ) {
 - return wss.isOnline( userInfo['_id'] )
 - }).then function( isOnline ) {
 - if ( isOnline ) {
 - console.log( '用戶在線');
 - } else {
 - console.log( '用戶離線');
 - }
 - })
 - .catch( function( excp ) {
 - console.log('出錯(cuò)啦', excp );
 - });
 
監(jiān)聽(tīng)指令 listen()
小程序僅提供 WebSocket 客戶端 API,所以小程序本身無(wú)法實(shí)現(xiàn) WebSocket服務(wù)器。 wss.listen() 方法并非啟動(dòng) WebSocket Server, 而是用來(lái)接收云端信道轉(zhuǎn)發(fā)的指令。
- var wss = app.xpm.require('Wss');
 - wss.listen('payment', function( res, status ){
 - // 當(dāng)接收到 payment 指令后運(yùn)行
 - if ( status != 'success') return ;
 - console.log( res, status );
 - });
 
發(fā)送指令 send()
- var wss = app.xpm.require('Wss');
 - wss.liveUsers().then(function( users ) {
 - console.log( '讀取在線用戶成功', users );
 - // 向第一個(gè)用戶發(fā)送 payment 指令
 - if ( users.length > 0 ) {
 - return wss.send('payment', users[0], users[0]['id'] )
 - } else {
 - return {code:404, message:'no live user'};
 - }
 - }).then( function( res ){
 - console.log('發(fā)送完畢', res);
 - });
 - .catch( function( excp ) {
 - console.log('出錯(cuò)了', excp );
 - });
 
綁定事件 bind()
接收并處理 websocket 服務(wù)器事件,有效值 ( open/close/message/error )
- var wss = app.xpm.require('Wss');
 - wss.bind('open', function(event) {
 - console.log('信道服務(wù)器開(kāi)啟', event );
 - });
 - wss.bind('close', function(event) {
 - console.log('信道服務(wù)器關(guān)閉', event );
 - });
 
3. 會(huì)話 ( Session )
Session 會(huì)話分為客戶端和服務(wù)端兩部分,客戶端與服務(wù)端會(huì)話ID相同,客戶端保存用戶信息資料,服務(wù)端保存用戶 openid 等敏感信息。與服務(wù)端通信,使用Sesssion ID 鑒權(quán),通過(guò)服務(wù)器端驗(yàn)證后,請(qǐng)勿將 Session ID 發(fā)送給第三方。
啟用會(huì)話 start()
啟用會(huì)話后,會(huì)自動(dòng)創(chuàng)建一個(gè)會(huì)話ID
- var session = app.xpm.require('session');
 - session.start();
 
會(huì)話 ID id()
- var session = app.xpm.require('session');
 - var sid = app.id();
 - console.log( sid );
 
客戶端會(huì)話數(shù)據(jù)管理 set() & get()
- var session = app.xpm.require('session');
 - session.set('hello', 'world');
 - console.log( session.get('hello') );
 
4. 云端表格 ( Table )
可以使用云端表格接口,將數(shù)據(jù)保存在 MySQL 中,可以通過(guò) SQL 查詢數(shù)據(jù)。
創(chuàng)建數(shù)據(jù)表 _schema()
僅管理員帳號(hào)擁有創(chuàng)建數(shù)據(jù)表權(quán)限 ( 登錄管理后臺(tái),打開(kāi)用戶表,將開(kāi)發(fā)者對(duì)應(yīng)帳號(hào)記錄的 isadmin 字段數(shù)值設(shè)置為 1 )
- var table = app.xpm.require('Table', 'hello');
 - table._schema(
 - [
 - {name:"name", type:'string', option:{length:80, require:true }, acl:"rwd:r:-" },
 - {name:"company", type:'string', option:{length:100}, acl:"w:-:-" }
 - ],
 - { record:"rwd:rw:-", table:"rwd:-:-", field:'rwd:r:-', user:'admin', group:'member' }
 - , true ).then( function( data ) {
 - console.log('數(shù)據(jù)表創(chuàng)建成功', data );
 - })
 - .catch( function( excp ) {
 - console.log('數(shù)據(jù)表創(chuàng)建失敗', excp );
 - });
 
字段配置參數(shù)
| 參數(shù) | 中文 | 說(shuō)明 | 
|---|---|---|
| name | 字段名稱 | |
| type | 字段類(lèi)型 | string/integer/text/boolean 等 | 
| option | 字段參數(shù) | index:true 索引 unique:true 唯一索引 length:80 字段長(zhǎng)度 | 
| acl | 字段鑒權(quán) | rw:rw:rw r: 讀取 w: 寫(xiě)入 -:無(wú) user:group:other | 
數(shù)據(jù)增刪改查 get() create() update() remove()
- var table = app.xpm.require('Table', 'hello');
 - // 創(chuàng)建
 - table.create(
 - {name:'張藝謀', company:'中國(guó)電影制片廠'}
 - ).then(function(data) { // 更新
 - return table.update(data['_id'], {name:'馮小剛'});
 - }).then(function(data) { // 讀取
 - return table.get(data['_id']);
 - }).then(function(data) { // 刪除
 - return table.remove(data['name'], 'name' );
 - }).then(function(resp) {
 - console.log( 'remove success', resp );
 - }).catch( function( excp ) {
 - console.log('出錯(cuò)了', excp );
 - });
 
數(shù)據(jù)查詢 query()
- var table = app.xpm.require('Table', 'hello');
 - table.query()
 - .where('name', '=', '馮小剛')
 - .orderby('name', 'asc')
 - .limit(2) // 僅查詢 2條
 - .fetch('name','company').then(function(data) {
 - console.log( '查詢結(jié)果', data );
 - })
 - table.query()
 - .where('name', '=', '馮小剛')
 - .orderby('name', 'asc')
 - .paginate(3, 2) // 分3頁(yè),當(dāng)前顯示第 2頁(yè)
 - .fetch('name','company').then(function(data) {
 - console.log( '查詢結(jié)果', data );
 - });
 
聯(lián)合查詢 join(), leftjoin(), rightjoin() (xpmjs-server 1.0rc4+)
Table 1: User
| id | name | title | 
|---|---|---|
| 1 | 張三 | 產(chǎn)品經(jīng)理 | 
| 2 | 李四 | 工程師 | 
| 3 | 王五 | 運(yùn)維工程師 | 
Table 2: Project
| id | name | uid | 
|---|---|---|
| 1 | 小程序開(kāi)發(fā)組 | 1 | 
| 2 | 網(wǎng)頁(yè)開(kāi)發(fā)組 | 3 | 
- var table = app.xpm.require('Table', 'Project');
 - table.query()
 - .join('User', 'User.id', '=', 'Project.uid' ) // leftjoin / rightjoin
 - .limit(1)
 - .fetch('User.id as userid', 'User.name as username', 'Project.*').then(function(data) {
 - console.log( '查詢結(jié)果', data );
 - })
 
返回值
- [
 - {
 - "id":1,
 - "name":"小程序開(kāi)發(fā)組"
 - "userid":1,
 - "username":"產(chǎn)品經(jīng)理"
 - }
 - ]
 
inWhere 查詢 inWhere()
Table 1: User
| id | name | title | 
|---|---|---|
| 1 | 張三 | 產(chǎn)品經(jīng)理 | 
| 2 | 李四 | 工程師 | 
| 3 | 王五 | 運(yùn)維工程師 | 
Table 2: Project
| id | name | users | 
|---|---|---|
| 1 | 小程序開(kāi)發(fā)組 | ["1","2","3"] | 
| 2 | 網(wǎng)頁(yè)開(kāi)發(fā)組 | ["1", "3"] | 
- var table = app.xpm.require('Table', 'Project');
 - table.query()
 - .inWhere('users', 'User', 'id', '*' )
 - .limit(1)
 - .fetch('User.id as userid', 'User.name as username', 'Project.*').then(function(data) {
 - console.log( '查詢結(jié)果', data );
 - })
 
返回值
- [
 - {
 - "id":1,
 - "name":"小程序開(kāi)發(fā)組"
 - "users":[
 - {
 - "id":1,
 - "name":"張三",
 - "title":"產(chǎn)品經(jīng)理"
 - }
 - ...
 - ]
 - }
 - ]
 
5. 微信支付 ( Pay )
發(fā)起支付 request();
- var pay = app.xpm.require('Pay');
 - pay.request({
 - total_fee:500, // 單位分
 - body:'算命、服務(wù)器開(kāi)光',
 - attach:'HELLO XpmJS.com',
 - detail:'{id:888,desp:"算命,抽SSR,贈(zèng)送服務(wù)器開(kāi)光"}'
 - }).then(function( data ){
 - console.log('Request Pay Success', data );
 - }).catch( function( excp){
 - console.log('Request Pay Failure', excp );
 - });
 
云端事件 before(), success(), fail(), complete() (xpmjs-server 1.0rc4+)
- pay.before('create', { // 創(chuàng)建充值記錄 (統(tǒng)一下單成功后, 發(fā)起支付前, 在云端運(yùn)行 )
 - 'table':'income',
 - 'data': {
 - sn:'{{sn}}',
 - order_sn: data.order.sn,
 - uid:data.order.uid,
 - amount:data.order.sale_price,
 - amount_free:0,
 - status:'PENDING',
 - status_tips:"F請(qǐng)求付款"
 - }
 - })
 - .order({ // 生成訂單 ( 統(tǒng)一下單接口, 僅設(shè)定并不發(fā)送請(qǐng)求 )
 - total_fee:data.order.sale_price, // 單位分
 - body:data.order.show_name,
 - attach:'attach user is ' + mid, // 應(yīng)該是當(dāng)前登錄用戶的 ID
 - detail:data
 - })
 - .success('update', { // 更新充值記錄 ( 支付成功后回調(diào),在云端運(yùn)行 )
 - 'table':'income',
 - 'data': {
 - sn:'{{sn}}',
 - status:'DONE',
 - status_tips:"income status_tips field"
 - },
 - 'unique':'sn'
 - })
 - .success('app', { // 調(diào)用APP 示例 ( 支付成功后回調(diào),在云端運(yùn)行 )
 - 'name':'xapp',
 - 'api':['ticket','index',{sn:'{{sn}}','status_tips':"{{0.status_tips}}"}],
 - 'data': {
 - sn:'{{sn}}',
 - status:'DONE'
 - }
 - })
 - .success('update', { // 更新訂單狀態(tài) ( 支付成功后回調(diào),在云端運(yùn)行 )
 - 'table':'order',
 - 'data': {
 - _id:oid,
 - status:'PENDING'
 - }
 - })
 - .success('create', { // 創(chuàng)建消費(fèi)記錄 ( 支付成功后回調(diào),在云端運(yùn)行 )
 - 'table':'payout',
 - 'data': {
 - sn:'{{sn}}',
 - order_sn: data.order.sn,
 - uid:data.order.uid,
 - amount:data.order.sale_price,
 - amount_free:0,
 - status:'DONE',
 - status_tips:"F請(qǐng)求付款"
 - }
 - })
 - .request().then(function( payResp ) { // 發(fā)起請(qǐng)求
 - console.log( payResp );
 - })
 
6. 本地存儲(chǔ) ( Stor )
- var stor = app.xpm.require('Stor');
 - stor.setSync('key','value');
 - console.log(stor.getSync('key'));
 - stor.setMapSync('map_name', 'key', 'value');
 - console.log(stor.getMapSync('map_name','key'));
 
7. 云端應(yīng)用 ( App ) (xpmjs-server 1.0rc3+)
調(diào)用示例
- var xapp = app.xpm.require('App', 'xapp' ); // xapp 應(yīng)用名稱
 - xapp.api( 'ticket', 'available' ) // ticket 控制器 available 方法名
 - .post({
 - 'train_date':'2017-01-26',
 - 'from_station':'BJP',
 - 'to_station':'SHH'
 - })
 - .then( function( resp ) {
 - console.log('POST RESP:', resp );
 - })
 - .catch( function( excp ) {
 - console.log('POST EXCP:', excp );
 - });
 
XpmJS 云端應(yīng)用開(kāi)發(fā)
參考云端應(yīng)用 Demo <火車(chē)票余票查詢接口實(shí)現(xiàn)>
https://git.oschina.net/xpmjs/xapp
8. 云端隊(duì)列 ( Que.js ) (xpmjs-server 1.0rc4+)
- var que = app.xpm.require('Que', 'hello');
 - que.select('world').push('create', { // 增加數(shù)據(jù)
 - table:'payout',
 - data: {
 - sn:'200193',
 - order_sn:'test29993',
 - amount:100,
 - status:'DONE'
 - }
 - }).push('update', { // 更新數(shù)據(jù)
 - table:'order',
 - data: {
 - sn:'148457330261256',
 - status_tips:'{{0.sn}} {{0.status}}'
 - },
 - unique:'sn'
 - }).push('app', { // 調(diào)用APP 示例
 - 'name':'xapp',
 - 'api':['ticket','index',{sn:'{{0.sn}}'}],
 - 'data': {
 - sn:'{{0.sn}} {{1.sn}}',
 - status:'DONE'
 - }
 - }).run().then(function(resp){
 - console.log( 'Response', resp );
 - })
 - .catch(function(excp){
 - console.log( 'Error', excp );
 - })
 
9. 文件上傳 Utils.upload & App.upload (xpmjs-server 1.0+)
上傳文件到騰訊云對(duì)象存儲(chǔ)
- var qcloud = app.xpm.require('app', 'xqcloud');
 - qcloud.api("cos",'upload')
 - .upload( tempFilePaths[0] )
 - .then(function(data){
 - that.setData({
 - 'rs.corver':data.access_url,
 - 'rs.images':[data.access_url]
 - });
 - })
 - .catch( function(excp){
 - console.log('Upload Fail', excp );
 - });
 
10. 常用方法 ( Utils )
請(qǐng)求網(wǎng)址 ( Utils.fetch ) (xpmjs-server 1.0rc3+)
- var utils = app.xpm.require('Utils' );
 - utils.fetch( 'http://qcloud.com' ).then( function( resp ) {
 - console.log('FETCH RESP:', resp );
 - })
 - .catch( function( excp ) {
 - console.log('FETCH EXCP:', excp );
 - });
 
生成二維碼圖片 ( Utils.qrImageUrl ) (xpmjs-server 1.0+)
返回二維碼圖片地址
- var utils = app.xpm.require('Utils' );
 - var url = utils.qrImageUrl('hello world', {size:200});
 - console.log( url );
 
生成小程序頁(yè)面二維碼 ( Utils.qrcode ) ( xpmjs-server 1.0 )
- var utils = app.xpm.require('Utils' );
 - var url = utils.qrcode('/page/detail?id=1');
 - console.log( url );
 
三、微信小程序 Demo
四、安裝配置
1. 云端配置
【安裝后端程序】
推薦使用騰訊云( 訪問(wèn)微信接口快, 可以免費(fèi)申請(qǐng) Https 證書(shū) )
方法1: 使用腳本安裝 ( 目前僅支持 Ubuntu 14.04 64 LTS 操作系統(tǒng) )
創(chuàng)建一臺(tái)云服務(wù)器,選擇 Ubuntu 14.04 64 LTS 操作系統(tǒng)。 登錄服務(wù)器運(yùn)行以下腳本。
安裝前,先提前申請(qǐng) Docker Hub 鏡像 申請(qǐng)地址 https://www.daocloud.io/mirror
- curl -sSL http://tuanduimao.com/xpmjs-server.sh | sh -s yourdomain.com http://<your id>.m.daocloud.io
 
方法2: 使用 Docker 安裝
- docker run -d --name=xpmjs-server \
 - -e "HOST=yourdomain.com" \
 - -v /host/data:/data \
 - -v /host/apps:/apps \
 - -v /host/config:/config \
 - -p 80:80 -p 443:443 \
 - tuanduimao/xpmjs-server:1.0
 
【設(shè)置管理員名稱和密碼】
訪問(wèn): http://yourdomian.com/setup.php
1、填寫(xiě)后臺(tái)信息
2、填寫(xiě)管理員信息
【上傳 HTTPS 證書(shū) & 微信支付證書(shū)】
訪問(wèn):http://yourdomian.com/baas-admin/cert/index 上傳 HTTPS 證書(shū)和證書(shū)密鑰; 如已申請(qǐng)微信支付,建議盡量上傳支付證書(shū),用于雙向驗(yàn)證證書(shū)和密鑰,確保支付安全。
上傳好證書(shū)后,登錄服務(wù)器,重啟容器。
- docker restart xpmjs-server
 
訪問(wèn): https://yourdomian.com ( 有 "S", 檢查證書(shū)是否生效 )
【設(shè)置小程序配置信息】
訪問(wèn): https://yourdomian.com/baas-admin/conf/index ( 有 "S", 填寫(xiě)小程序和微信支付的信息 )
2. 使用 XpmJS
【下載代碼】
使用 Git Bash , 進(jìn)入小程序項(xiàng)目目錄, 運(yùn)行 git clone 拉去代碼。(也可以 使用 Git 等客戶端 Clone 代碼 )
- git clone https://git.oschina.net/xpmjs/xpmjs.git xpmjs
 
克隆成功后的目錄結(jié)構(gòu)為:
【編寫(xiě)配置信息】
編輯 app.js 將域名更換為你的域名。( 必須配置好 Https 證書(shū) )
- App({
 - onLaunch: function () {
 - var that = this;
 - // 創(chuàng)建 xpm 對(duì)象
 - this.xpm = require('xpmjs/xpm.js').option({
 - 'app':1, // 對(duì)應(yīng)后臺(tái) APP 配置,支持5個(gè)
 - 'host':'yourdomian.com',
 - 'https':'yourdomian.com',
 - 'wss': 'yourdomian.com/ws-server',
 - 'table.prefix': 'demo',
 - 'user.table':'user'
 - });
 - // 創(chuàng)建全局對(duì)象
 - this.wss = this.xpm.require('wss'); // 信道
 - this.session = this.xpm.require('session'); // 會(huì)話
 - this.stor = this.xpm.require('stor'); // 存儲(chǔ)
 - },
 - xpm:null,
 - session:null,
 - stor:null,
 - wss:null
 - })
 
建議將 xpm、wss、session、stor 設(shè)定為全局變量。

























 
 
 












 
 
 
 