## 關于小程序平臺
小程序可以兼容以下小程序的應用框架:
* 微信小程序
* 百度小程序
* 阿里小程序
* 微信小游戲
* Web網頁應用
用戶可以將以上類型的小程序簡單改造就可以植入平臺
## 開發者如何開發小程序
下面是開發者開發小程序的時序圖

步驟如下:
1. 商戶通過"potato商戶平臺"按要求填寫資料,申請AppId、以及API Key
2. 按照上面任意框架的規范編寫小程序
3. 如果需要獲取Potato的用戶資料,調用登錄授權接口獲取權限
4. 如果需要支付功能,調用potato的支付接口
5. 把開發好的小程序上傳到Potato的商戶平臺
6. 等待Potato官方對小程序進行審核
7. 審核通過則上架,未通過則通過郵件的方式通知商戶未通過以及原因
## 本地方法調用示例
在編寫小程序的過程中,可以通過Potato提供的API,方便的進行本地調用, 示例如下:
* 注意:
* `api.call`返回的都是`JSON對象`,不是`字符串`
##### 授權服務,請求用戶登錄token
接口說明,請參考`https://www.potato.im/api/loginSDK`, 其中調用此接口的參數獲取方法如下:
1. access\_token: 在小程序中調用Potato提供的授權登錄API,`requestOAuth`
2. client\_id: 在商戶平臺注冊時返回的APP ID
3. client\_secret: 在商戶平臺注冊時返回的API Key
* 前端調起potato授權示例:
* `注意`: 此處使用window.api和window.onloadw的含義請參考`小程序初始化`部分的說明
* 調用參數
* appid : 商戶平臺分配給小程序的APP ID
~~~javascript
if (window.api) {
this.callback();
} else {
window.onloadw = function() {
this.callback();
}
}
callback: function(){
window.api.call('requestOAuth', {appid: 'abcdefghijklmn'}, function(data) {
});
}
~~~
* 返回值
~~~javascript
{
"code": 1,
"data": {
"access_token": "abcd",
"code": 1,
"expires_in": "1565177880",
"message": "ok",
"scope": "userinfo",
"success": true,
"token_type": "bearer"
},
"message": "ok"
}
~~~
#### 支付
##### [接口詳情請參考文檔《ptpay 商戶接口文檔規范》](https://developer.potato.im/#/docs/payment#summary)
* 前端調用支付頁面示例:
* 調用參數
* pcpay\_tid : 調用統一下單接口返回的訂單號`orderId`
~~~javascript
window.api.call('payment', { "pcpay_tid":'2019012921727114226' }, function(data) {
})
~~~
* 返回值
* `注意`: 此返回值只是返回是否成功`調起了支付付款頁面`,`而不是支付結果`
~~~javascript
{
"result":"true"// 此結果僅僅是返回是否成功調起了支付付款頁面,切勿用于最終支付結果業務邏輯處理
}
~~~
#### 目前支持的其他接口(使用時請注意大小寫)
launchMiniProgram 打開其他小程序
* 調用參數
* appId:要打開的小程序appId
* attach:開發者自定義的附加數據,后續可以用getAppUrl函數獲取傳遞的attach參數.
~~~javascript
window.api.call('launchMiniProgram', {appId: "abcdefghijklmn", attach: "orderNo"}, function(data) {
})
~~~
* 返回值
~~~javascript
{
"result":true
}
~~~
shareToAppMessage 分享小程序
* 在聊天框和朋友圈分享小程序,由于`客戶端原生的分享按鈕無法自定義`shareInfo分享參數,可以先通過此函數傳遞自定義的分享信息,后續再使用getAppUrl函數獲取傳遞的shareInfo參數
* `注意`:通過客戶端原生的分享按鈕分享小程序后可以通過監聽`shareActionObserved`事件得知分享結果
~~~javascript
window.native.handler('shareActionObserved', function(data) {
console.log(JSON.stringify(data)) // true or false
});
~~~
* 調用參數
* shareInfo:要分享的數據,在getAppUrl函數中原樣返回
~~~javascript
window.api.call('shareToAppMessage', { shareInfo: "abcdefg" }, function(data) {
})
~~~
* 返回值
~~~javascript
{
"result":true
}
~~~
getAppUrl 獲取打開小程序的鏈接
* 可以獲取launchMiniProgram函數里開發者自定義的附加參數信息(attach)
* 可以獲取shareToAppMessage函數里開發者自定義的分享參數信息(shareInfo)
* 調用參數
* 無
~~~javascript
window.api.call('getAppUrl', {}, function(data) {
let url = data.result;
let obj = new Object();
if (url.indexOf("?") != -1) {
let str = url.substr(1);
let strs = str.split("&");
for(let i = 0; i < strs.length; i ++) {
obj[strs[i].split("=")[0]]=(strs[i].split("=")[1]);
}
}
console.log(JSON.stringify(obj))
})
~~~
* 返回值
~~~javascript
{
"result":"webapp://game?appid=abcdefghijklmn&shareInfo=abcdefg&attach=123456789"
}
~~~
getAppVersion 獲取app版本
* 調用參數
* 無
~~~javascript
window.api.call('getAppVersion', {}, function(data) {
})
~~~
* 返回值
~~~javascript
{
"result":"version" // potato當前版本號
}
~~~
getAppLanguage 獲取當前語音
* 調用參數
* 無
~~~javascript
window.api.call('getAppLanguage', {}, function(data) {
})
~~~
* 返回值
~~~javascript
{
"result":"language" // potato當前使用的語言
}
~~~
scanQR 掃描二維碼
* 調用參數
* tips:掃描時,掃描框顯示的提示標題
~~~javascript
window.api.call('scanQR', {'tips':'掃描分享碼'}, function(data) {
})
~~~
* 返回值
~~~javascript
{
"result":"二維碼掃描結果字符串"
}
~~~
close 關閉小程序接口
* 調用參數
* 無
~~~javascript
window.api.call('close', {}, function(data) {
})
~~~
* 返回值
* 無
## 小程序初始化
#### Web頁面框架下的初始化
`api并不會`在頁面加載時就加載,api是否成功加載,可以根據`window.api`是否為true來判斷
我們為此添加了一個消息`window.onloadw`當這個消息被調用時,表示api已經就緒。
可以在代碼中用`User-Agent`來判斷是否是小程序框架`navigator.userAgent.match(/WebApp/)`.
~~~javascript
// 判斷頁面加載時,api是否成功加載
if (window.api) {
// 成功加載,立即執行callback
this.callback();
} else {
// 未成功加載,window.onloadw消息被調用后執行callback
window.onloadw = function() {
this.callback();
}
}
callback: function(){
console.log('test')
}
~~~
#### 獲取小程序的初始化參數
~~~javascript
window.onloadw = function() {
console.log(wx.getInitParams()); // getInitParams() 返回值一般是介值對
};
~~~
## 小程序開發說明
### API
小程序通用API可以通過`window`上的`wx`對象訪問,一般情況下也可以通過`mh`,`my`,`swan`對象訪問.
這些api在所有版本的應用中都能訪問到。
#### 本地數據
由于本地運行程序不會有域名,所以依靠域名的`js api`都會出現一些問題,比如`cookie`,`localStorage`等.
可以使用以下`api`代替
`wx.getStorageSync(key)`獲得本地信息
* `key`(string)存儲介
`wx.setStorageSync(key, value)`保存數據
* `key`(string)存儲介
* `value`(string)儲存值
`wx.clearStorageSync(key)`刪除數據
#### 網絡請求
在小程序使用`XMLHTTPRequest`可以滿足基礎請求限制,如果需要更加特別的請求,比如跨域等問題可以使用`request`, 或`wx.XMLHTTPRequest`;
`request(options)`網絡請求(基本和微信小程序一致)
* `options`請求參數
* `data`請求參數數據,GET中會被無視
* `dataType`請求參數類型,GET中會被無視,如果`header`中有`content-type`,會替換掉默認值
1. `arraybuffer``data`會被轉換為`Buffer`類型,默認`content-type`:`application/stream`
2. `text``data`會直接`toStirng`,默認`content-type`:`text/plain`
3. `json``data`會使用`JSON.stringify`,默認`content-type`:`application/json`
4. `urlencoded``data`會編碼為url query,默認`content-type`:`application/x-www-form-urlencoded`
5. `formdata``data`會被編碼為表單格式,默認`content-type`請不要更改。
* `header`請求headers,以介質對的方式傳入header即可。
* `responseType`返回類型
1. `text`返回值會被轉化為`String`
2. `json`返回值會被當作json轉化為對象
3. `arraybuffer`返回值會作為`Buffer`類型返回
* `success(res)`請求成功回調
* `fail(res)`請求失敗回調
* `complete(res)`請求完成回調
`wx.XMLHTTPRequest`參數與使用基本與`XMLHTTPRequest`一致。不過沒有跨域限制,使用原生實現。
#### 保存圖片到本地
~~~javascript
let req = wx.XMLHttpRequest();
req.open('GET', '/a.png');
req.responseType = 'arraybuffer';
req.onload =function() {
wx.fs.writeFileSync('tmp:///a.png', req.response);
wx.saveImageToPhotosAlbum({
filePath: 'tmp:///a.png',
success(res) {
console.log("Success " + JSON.stringify(res))
},
fail(err) {
console.log("Fail " + JSON.stringify(err))
}
})
}
req.send();
~~~
#### 打開頁面或其他應用
`api.call('open', url)`即可打開url
在Web框架中,`window.open`會調用`api.call('open', url)`
#### 監聽小程序隱藏或顯示
* 小程序切換到后臺運行,如果要處理相關業務時可以使用以下代碼.
~~~javascript
window.addEventListener('loadw', function() {
native.handler('window.state', function(state) {
if (state.action === 'appear') {
console.log("隱藏小程序時暫停背景音樂")
} else if (state.action === 'disappear') {
console.log("顯示小程序時恢復背景音樂")
}
});
});
~~~
#### 小程序獲取渠道商信息
* 本地`根目錄`新建`appletConfig.json`文件,里面可自定義配置渠道的參數.例如 :
~~~javascript
{
"channelId": 1,
"channelName ": "abc"
}
~~~
* 在小程序中使用`wx.getChanelInfoSync()`讀取返回的json對象,獲取參數.
* 提供給渠道商的時候,需要渠道商先給予相關渠道信息后覆蓋此appletConfig.json文件里面的內容
#### 配置文件
小程序支持通過一些配置,讓原生程序響應一些基礎操作.
不同類型小程序各有不同分別是`app.json`,`game.json`和`web.json`
##### 配置如下
* window
* backgroundColor`//背景色 #FFFFFF`
* navigationBarTextStyle`//導航條文字顏色(小程序) white, black`
* navigationBarTitleText`//標題文本(小程序)`
* pageOrientation`//方向,橫豎屏 landscape, portrait, auto`
* statusBarHidden`//隱藏狀態條 true,false`
* keyboardAppear`//鍵盤出現時是否改變webView大小 'none', 'resize'`
* enableBackGesture`//原生的返回手勢,會調用history.back()`
* fitSafeArea`//是否把webView移動去匹配safeArea`
~~~javascript
示例:web.json下追加以下代碼
{
"window": {
"backgroundColor": "#FFFFFF",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "最好的小程序",
"pageOrientation": "landscape",
"statusBarHidden": true,
"keyboardAppear": "resize",
"enableBackGesture": true,
"fitSafeArea": true
}
}
~~~
#### 請求更改配置
使用`wx.requireWindowFeature(feature)`可以在運行時請求動態更改配置
* 調用參數
* fullscreen`//是否全屏 true,false`
* orientation`//橫豎屏 (portrait|landscape|'auto')`
* statusBarStyle`//白色還是暗色狀態欄 (white|black)`
* enableGesture`//開啟或關閉返回手勢 true,false`
~~~javascript
wx.requireWindowFeature({
orientation: 'portrait'
})
~~~
* 返回值
* 無
#### 設備信息
`getSystemInfo`獲得設備信息,`getSystemInfoSync`是同步版方法.
* 調用參數
* 無
~~~javascript
wx.getSystemInfo({
success:function(data){
console.log(JSON.stringify(data))
}
})
~~~
* 返回值
~~~javascript
{
brand: String,
model: String,
pixelRatio: Number,
screenWidth: Number,
screenHeight: Number,
windowWidth: Number,
windowHeight: Number,
statusBarHeight: Number,
language: String,
version: String,
system: String,
platform: String,
SDKVersion: String,
safeArea: Number,
/**
* @property {Object} safeArea2
* @property {Number} safeArea2.left
* @property {Number} safeArea2.right
* @property {Number} safeArea2.top
* @property {Number} safeArea2.bottom
* @property {Number} safeArea2.width
* @property {Number} safeArea2.height
*/
safeArea2: Object,
udid: String,
idfa: String, // iOS only
}
~~~
#### 小程序
這部分對應微信小程序,百度小程序,阿里小程序部分。
只需要小程序根目錄存在`app.json`和`app.js`即判斷為小程序
小程序框架可以解析微信,百度,阿里小程序的模版,然后渲染為html。
#### Web
一般情況把`index.html`更名為`web.html`即可
需要在Web型根目錄存在`web.html`
## 上傳小程序
詳情請參考 "小程序商戶平臺"
* 注意:
* `打包一定要`在項目的`根目錄下壓縮為zip`,如果是以`Web應用`發布,一定要把`index.html`改為`web.html`

## 小程序的審核與上架
小程序上傳之后, 需要Potato官方通過審核 , 即可上線運行 。
## 快速方便的小程序分享方式
1. Potato內部通過@app機器人分享
在用戶聊天框中簡單的 @app 即可把應用方便的分享給好友,如下圖所示:
