時間:2017-11-01 11:00javascript
前面作過 HG 項目的微信端,裏面用到微信掃碼、支付、圖片選取、拍照、分享的功能。用到 weixin-js-sdk 和 WeixinJSBridge。php
前端開發以Vue代碼爲例,後端以NodeJS爲例。後端開發還需詳細閱讀開發者文檔。html
用於開發和測試環境,產品經理需準備前端
步驟:vue
登陸【公衆號平臺】 → 側邊欄開發選擇【開發者工具】→ 進入【公衆平臺測試賬號】→ 掃碼確認 → 成功java
==注意:測試號的配置都在此頁面==web
如圖:ajax
保存 appID
、appSecret
和 測試號二維碼算法
==注意:及時保存,以避免須要的時候找不到==npm
修改受權回調頁面地址
==注意:用戶確認受權後重定向的地址==
修改接口配置信息、JS接口安全域名
==注意:調用 weixin-js-sdk
功能或調用 WeixinJSBridge
頁面所在域名==
修改JS安全域名:
公衆號主頁側邊欄設置選擇【公衆號設置】→ 選擇上面第二個tab
【功能設置】第三項
若是有支付功能須要配置受權目錄
==注意:這個須要在商戶平臺修改,不是在公衆平臺==
舉例:
如今須要在 http://www.behuntergatherer.com/pay/payment 頁面進行支付,就須要設置一個受權目錄爲 http://www.behuntergatherer.com/pay/ 。在支付頁面路由的前一個目錄。
建議:
統一一個頁面進行支付。好比 http://www.behuntergatherer.com/pay/payment 是支付頁面,我在 http://www.behuntergatherer.com/vip/order 頁面須要支付,則生成好訂單後跳轉 http://www.behuntergatherer.com/pay/payment 頁面進行支付。
下載安裝【Web開發者工具】
==注意:開發同窗準備,下載地址==
目的:
注意事項:
##二、簡單config封裝
==注意:須要調用微信JSAPI接口的頁面,不能使用h5 pushState進行跳轉,會形成無效的簽名問題。請使用location.href。==
// utils.js
// 微信配置接口通用方法
const ALL_API_LIST = [
'scanQRCode',
'...'
]
export function configWxApi (jsApiList = ALL_API_LIST) {
return new Promise((resolve, reject) => {
// 使用當前的href獲取簽名,後端返回配置接口所須要的參數
get('/mdm2/api/getSignature.do', {
url: encodeURIComponent(window.location.href),
})
.then(data => {
wx.config({
debug: process.env.NODE_ENV !== 'production',
appId: data.appId,
timestamp: Number(data.timestamp), // 秒數,不是毫秒
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList,
})
wx.error(function (res) {
Toast('調用微信jsapi返回的狀態:' + res.errMsg)
reject()
})
wx.ready(resolve)
})
})
}
複製代碼
// utils.js
export function checkWxBridge () {
return new Promise((resolve, reject) => {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', resolve, false)
} else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', resolve)
document.attachEvent('onWeixinJSBridgeReady', resolve)
}
} else {
resolve()
}
})
}
複製代碼
==注意事項:==
// 採用Promise封裝有兩種使用方法,統一選擇一個
// app.js
import { configWxApi } from 'utils'
// Promise寫法
mounted () {
configWxApi()
.then(res => {
// 配置完成
wx.chooseImage()
})
.catch(err => {
// 配置失敗
})
}
// 同步函數寫法
async mounted () {
try {
const configResult = await queryWxApi(['scanQRCode'])
// 成功處理
} catch (err) {
// 錯誤處理
}
}
複製代碼
==注意事項:==
JS-SDK
的的接口都必須 checkWxBridge
// someComponent.js
import { checkWxBridge } from 'utils'
checkWxBridge().then(() => {
WeixinJSBridge.call('hideOptionMenu')
WeixinJSBridge.invoke('getBrandWCPayRequest')
})
複製代碼
後端一兩個常見例子說明
==這是微信開發中最基礎的東西,詳情見官方文檔== 詳細文檔 => 任意門
這是什麼東西?
access_token是公衆號的==全局惟一==接口調用憑據,公衆號調用各接口時都需使用access_token
有什麼屬性?
怎麼獲取?
==調用接口時,請登陸「微信公衆平臺-開發-基本配置」提早將服務器IP地址添加到IP白名單中,點擊查看設置方法,不然將沒法調用成功。==
https請求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
複製代碼
參數說明
參數 | 是否必須 | 說明 |
---|---|---|
grant_type | 是 | 獲取access_token填寫client_credential |
appid | 是 | 第三方用戶惟一憑證 |
secret | 是 | 第三方用戶惟一憑證密鑰,即appsecret |
返回說明
正常狀況下,微信會返回下述JSON數據包給公衆號:
{"access_token":"ACCESS_TOKEN","expires_in":7200}
複製代碼
開發建議:統一獲取和刷新Access_token,不該該各自去刷新,不然容易形成衝突,致使access_token覆蓋而影響業務。
// accessToken.js
module.exports = {
getToken: function (callback) {
// 判斷token是否過時,若是過時就重取,未過時就返回
var tokenPath = path.join(__dirname, './token.json')
var token = JSON.parse(fs.readFileSync(tokenPath))
var currTime = utils.getTimeStamp().second
var isExpired = currTime > token.timestamp
if(isExpired) fetchToken(callback)
else callback(token.value)
},
updateToken: function (callback) {
fetchToken(callback)
},
}
function fetchToken (callback) {
var configPath = path.join(__dirname, './config.json')
var config = JSON.parse(fs.readFileSync(configPath))
var param = {
grant_type: 'client_credential',
appid: config.appId,
secret: config.secret,
}
var paramStr = utils.obj2Params(param)
var url = `https://api.weixin.qq.com/cgi-bin/token?${paramStr}`
request(url, function(err, res, body) {
// 記錄獲取token時間,兩小時後過時重取
try {
var resReult = JSON.parse(body);
var newToken = {
value: resReult.access_token,
timestamp: utils.getTimeStamp().second + 7200,
}
var filePath = path.join(__dirname, 'token.json')
fs.writeFileSync(filePath, JSON.stringify(newToken))
callback(newToken.value)
} catch (e) {
console.log('獲取token出錯,', e)
callback()
}
})
}
// somejs.js
import { getToken } from 'accessToken'
getToken(function(token) {
// 其餘業務
})
複製代碼
公衆號開發中常見的需求 詳細文檔 => 任意門
openid是啥?
是加密後的微信號,==每一個用戶==對==每一個公衆號==的OpenID是惟一的。對於不一樣公衆號,同一用戶的openid不一樣。
openid能幹啥?
公衆號可經過本接口來根據OpenID獲取用戶基本信息,包括暱稱、頭像、性別、所在城市、語言和關注時間
提示:
用戶頭像連接http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0
修改連接最後一個數字也是就是0
,能獲取不一樣尺寸的頭像,(有0、4六、6四、9六、132數值可選,0表明640*640正方形頭像)。
{
"subscribe": 1, // 用戶是否訂閱該公衆號 0:未關注 1:已關注
"openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
"nickname": "Band", // 用戶的暱稱
"sex": 1, // 性別,1:男性,2:女性,0:未知
"language": "zh_CN", // 用戶的語言,簡體中文爲zh_CN
"city": "廣州",
"province": "廣東",
"country": "中國",
"headimgurl": "LINK_URL", // 用戶頭像圖片連接
"subscribe_time": 1382694957,// 關注公衆號時間
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL", //
"remark": "", // 公衆號運營者對粉絲的備註
"groupid": 0, // 用戶所在的分組ID(兼容舊的用戶分組接口)
"tagid_list":[128,2] // 用戶被打上的標籤ID列表
}
複製代碼
怎麼拿到openid?
兩種獲取的方法(相同接口所帶參數不一樣而已):
snsapi_base
,==體驗較好,獲取到的數據較少==snsapi_userinfo
,==體驗較差,用戶可能拒絕,獲取到的數據多====注意:對於已關注公衆號的用戶,若是用戶從公衆號的會話或者自定義菜單進入本公衆號的網頁受權頁,即便是scope爲snsapi_userinfo,也是靜默受權,用戶無感知。==
==簽名在微信開發過程當中扮演了一個很是重要的角色,很容易出錯== 詳細文檔 => 任意門
簽名是啥?
公衆號用於調用微信接口的臨時票據
怎麼獲取?
官方文檔說明 詳細文檔 => 任意門
官方詳細文檔 => 任意門
微信是反對引導關注的,可是,爲了能留住訪客。we have to。使用的連接是公衆號詳情頁面下【歷史消息】頁面。能夠點進頁面,而後右上角【點點點】點擊而後複製連接獲取。
官方詳細文檔 => 任意門
==注意事項==
package
內容是"prepay_id=" 是預訂單id(統一下單任意門)paySign
是 params
全部參數根據微信簽名規則生成import { checkWxBridge } from 'utils'
someFunction () {
get('/wx/fetchSign').then(data => {
// data 須要的數據
// appId, timeStamp, nonceStr, package, paySign
const params = Object.assign(data, {signType: 'MD5'})
checkWxBridge().then(() => {
WeixinJSBridge.invoke('getBrandWCPayRequest', params, res => {
// res 數據結構 {err_msg: 'get_brand_wcpay_request:ok'}
// err_msg 可能的值 ok、fail、cancel
})
})
})
}
複製代碼
測試號是沒有支付功能,須要用正式的公衆號,並且須要有支付權限的公衆號(我的公衆號不可支付)。在測試環境使用正式環境的openid去實現支付。
var openIdMap = {
'測試公衆號openId': '正式公衆號openId',
'正式公衆號openId': '測試公衆號openId',
}
// 測試環境
1. 【前端】購買請求
2. 【後端】用戶購買(測試公衆號openId)
3. 【後端】統一下單用(openIdMap[測試公衆號openId])
4. 【前端】拿到prepay_id,WeixinJSBridge.invoke('getBrandWCPayRequest')支付
5. 【前端】用戶支付請求 => 微信
6. 【後端】收到支付成功或回調(可異步或同步),通知前端
7. 【後端】保存相應數據到(openIdMap[正式公衆號openId])
複製代碼
CRMWeb 項目使用的 VueJS,使用的是npm
相關包 vue-croppa
頁面簽名
import { queryWxApi } from 'utils'
mounted () {
queryWxApi().then(res => this.wxConfSucc = true)
}
複製代碼
選擇本地圖片或拍照,獲取到 localId
wx.chooseImage({
count: 1, // 可選擇張數
sizeType: ['original', 'compressed'],
sourceType: [
'album', // 從相冊選
'camera',// 拍照
],
success: (res) => {
let localId = res.localIds[0]
},
})
複製代碼
經過 localId 上傳到微信服務器拿到 serverId(只能保存3天)
wx.uploadImage({
localId: localId, // 本地ID
isShowProgressTips: 1, // 是否顯示上傳進度
success: res => {
const serverId = res.serverId
},
})
複製代碼
服務端經過 serverId 下載圖片到本身服務器,並返回圖片連接給前端
croppa(
v-model="croppa",
:width="coroppaStyle.width"
:height="coroppaStyle.height"
:disable-click-to-choose="false"
:show-remove-button="false"
:initial-position="position"
)
img(
:src="showImgUrl"
slot="initial"
)
複製代碼
調用 config 接的時候傳入參數 debug: true 能夠開啓 debug 模式,頁面會 alert 出錯誤信息。如下爲常見錯誤及解決方法:
當前頁面所在域名與使用的 corpid 沒有綁定(可在該企業號的應用可信域名中配置域名)。
簽名錯誤,建議按以下順序檢查:
這個錯誤是由於 config 沒有正確執行,或者是調用的 JSAPI 沒有傳入 config 的 jsApiList 參數中。建議按以下順序檢查:
該企業號沒有權限使用這個 JSAPI(部分接口須要認證以後才能使用)
當前客戶端版本不支持該接口,請升級到新版體驗。
由於6.0.2版本以前沒有作權限驗證,因此 config 都是ok,但這並不意味着你 config 中的簽名是 ok 的,請在6.0.2檢驗是否生成正確的簽名以保證 config 在高版本中也 ok。
請確認企業號已經認證,只有認證的企業號才具備分享相關接口權限,若是確實已經認證,則要檢查監聽接口是否在wx.ready回調函數中觸發)
由於 access_token 和 jsapi_ticket 必需要在本身的服務器緩存,不然上線後會觸發頻率限制。請確保必定對token 和 ticket 作緩存以減小服務器請求,不只能夠避免觸發頻率限制,還加快大家本身的服務速度。目前爲了方便測試提供了1w的獲取量,超過閥值後,服務將再也不可用,請確保在服務上線前必定全局緩存 access_toke和 jsapi_ticket,二者有效期均爲7200秒(以返回結果中的 expires_in 爲準),不然一旦上線觸發頻率限制,服務將再也不可用。
目前只支持一次上傳一張,多張圖片需等前一張圖片上傳以後再調用該接口。
chooseImage 接口自己就支持預覽,不須要額外支持。
這是因爲傳入的 config 參數不全致使,請確保傳入正確 appId、timestamp、nonceStr、signature 和須要使用的 jsApiList。
此問題已在Android6.2中修復。在IOS中此問題依然存在。
Android6.2 會解決此問題,若需支持低版本能夠把調用 uploadImage 放在 setTimeout 中延遲 100ms 解決。
由於 getLocation 返回的是gps座標,openLocation 打開的騰訊地圖爲火星座標,須要第三方本身作轉換,6.2 版本開始已經支持直接獲取火星座標。
經過 snsapi_base 方式獲取未關注公衆號的用戶 openid。測試號是不能夠的。
[
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone',
'startRecord',
'stopRecord',
'onVoiceRecordEnd',
'playVoice',
'pauseVoice',
'stopVoice',
'onVoicePlayEnd',
'uploadVoice',
'downloadVoice',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'translateVoice',
'getNetworkType',
'openLocation',
'getLocation',
'hideOptionMenu',
'showOptionMenu',
'hideMenuItems',
'showMenuItems',
'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem',
'closeWindow',
'scanQRCode',
]
複製代碼
[
// 類型一
'hideOptionMenu', // 隱藏右上角按鈕
'showOptionMenu', // 顯示右上角按鈕
'hideToolbar', // 隱藏底部工具欄
'showToolbar', // 顯示底部工具欄
// 類型二
'getNetworkType', // 獲取網絡狀態
'getBrandWCPayRequest', // 調用支付
]
// 類型一
WeixinJSBridge.call('hideToolbar')
// 類型二
WeixinJSBridge.invoke('getBrandWCPayRequest')
複製代碼
[
// 基本類
'menuItem:exposeArticle' // 舉報
'menuItem:setFont' // 調整字體
'menuItem:dayMode' // 日間模式
'menuItem:nightMode' // 夜間模式
'menuItem:refresh' // 刷新
'menuItem:profile' // 查看公衆號(已添加)
'menuItem:addContact' // 查看公衆號(未添加)
// 傳播類
'menuItem:share:appMessage' // 發送給朋友
'menuItem:share:timeline' // 分享到朋友圈
'menuItem:share:qq' // 分享到QQ
'menuItem:share:weiboApp' // 分享到Weibo
'menuItem:favorite' // 收藏
'menuItem:share:facebook' // 分享到FB
// 保護類
'menuItem:jsDebug' // 調試
'menuItem:editTag' // 編輯標籤
'menuItem:delete' // 刪除
'menuItem:copyUrl' // 複製連接
'menuItem:originPage' // 原網頁
'menuItem:readMode' // 閱讀模式
'menuItem:openWithQQBrowser' // 在QQ瀏覽器中打開
'menuItem:openWithSafari' // 在Safari中打開
'menuItem:share:email' // 郵件
'menuItem:share:brand' // 一些特殊公衆號
]
複製代碼