微信公衆號網頁開發
授權流程
1、設置授權回調域名:微信公衆平臺-接口權限-網頁授權獲取用戶基本信息
2、自定義菜單:微信公衆平臺-自定義菜單 或者 微信公衆平臺接口調試工具-發送請求
方案一:菜單的URL設置爲 https://open.weixin.qq.com/connect/oauth2/authorize?appid=&redirect_uri=&response_type=code&scope=snsapi_userinfo#wechat_redirect
URL中包含 appId 和 授權後要跳轉到的URL(encodeURIComponent 處理後)
方案二:菜單的URL設置爲 簡單地址,後端判斷是否已授權,未授權則重定向到方案一的地址
3、引導用戶訪問以上URL,顯式授權:出現授權頁面,點擊授權;靜默授權:用戶已關注該公衆號,不出現授權頁面
4、跳轉到redirect_uri/?code=10003
5、公衆號後端請求 https://api.weixin.qq.com/sns/oauth2/access_token?appid=&secret=&code=&grant_type=authorization_code
URL中包含 appId,開發者密碼secret,從4中得到的code
得到 {"access_token":"授權憑證", "openid":"用戶標識" }
6、公衆號後端請求 https://api.weixin.qq.com/sns/userinfo?access_token=&openid=&lang=zh_CN
URL中包含 5中得到的 access_token 和 openid
得到用戶基本信息
JS-SDK調用流程
1、設置JS接口安全域名:微信公衆平臺-公衆號設置-功能設置-JS接口安全域名
2、公衆號後端請求 https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=&type=jsapi
URL中包含 access_token,得到jsapi_ticket { "ticket":""}
3、公衆號後端生產 隨機字符串noncestr, 時間戳timestamp, 當前網頁的url(不包含#及其後面部分)
4、拼接成jsapi_ticket=&noncestr=×tamp=&url=,計算sha1(拼接值),得到簽名signature,返給前端
5、前端引入JS-SDK:http://res.wx.qq.com/open/js/jweixin-1.2.0.js
6、前端調用前配置
wx.config({
debug: true,
appId: '',
timestamp: ,
nonceStr: '',
signature: '',
jsApiList: [需要使用的JS接口列表]
});
7、
wx.ready(function(){
// SDK接口調用
});
微信支付流程
一、設置支付目錄:微信商戶平臺-商戶平臺-->產品中心-->開發配置
二、下單
1、前端下單,後端調用微信支付系統下單API,得到prepay_id
2、後端生成 時間戳timestamp,隨機字符串nonceStr,支付簽名paySign,和prepay_id一起返給前端
三、支付
1、調用支付接口
wx.chooseWXPay({
timestamp: 0,
nonceStr: '',
package: '', // prepay_id
paySign: '',
success: function (res) {
// 支付成功後的回調函數
}
});
2、用戶確認支付,微信支付系統給微信客戶端返回支付信息;同時異步通知後端支付結果
四、展示支付結果
1、前端支付接口成功回調,向後端查詢支付結果,後端未有結果,則向微信支付系統查詢
2、前端展示支付結果
微信網頁對比瀏覽器網頁
微信網頁支持微信的很多能力,例如掃描二維碼、支付
微信小程序開發
對比
與微信網頁:微信網頁 給 微信提供的是 URL,小程序給微信提供的是 源代碼;微信給小程序提供了框架、組件、更多Native能力的API;小程序需要審覈才能上線;小程序被收藏後有更多入口;
與MVVM:page 接近於 vue 的單文件組件,模板、樣式、腳本完全分離,模板採用xml;檢查模型變化的方式 this.setData() 接近於 react 的 this.setState()
代碼示例
1、獲取用戶信息(暱稱、頭像、性別、省市縣)
<template>
<button open-type="getUserInfo" @getuserinfo="getUserInfoHandle"
v-show="!userInfoAuth">獲取用戶信息</button>
</template>
<script>
export default {
data() {
return {
userInfoAuth: false,
userInfo: {}
}
},
onLoad() {
this.getSetting();
},
methods: {
// 查看已有權限
getSetting() {
wx.getSetting({
success: (res) => {
let authSetting = res.authSetting;
if (authSetting['scope.userInfo']) {
this.getUserInfo();
}
}
})
},
// 已授權,直接接調用wx.getUserInfo()得到userInfo
getUserInfo() {
wx.getUserInfo({
success: (res) => {
this.analysisUserInfo(res.userInfo);
}
})
},
// 未授權,使用<button>獲得授權,並得到userInfo
getUserInfoHandle(event) {
let userInfo = event.detail.userInfo;
if (userInfo) {
this.analysisUserInfo(userInfo);
}
},
analysisUserInfo(userInfo) {
this.userInfoAuth = true;
this.userInfo = userInfo;
}
}
}
</script>
2、登錄(獲取openId,session_key、unionid)
export default {
onLoad() {
this.checkSession();
},
methods: {
// 檢查會話是否有效,即上次login得到的session_key(由後端從微信服務器獲取)是否還有效
checkSession() {
wx.checkSession({
success: ()=>{
this.fetchMe();
},
fail: () => {
this.login();
}
})
},
// 檢查會話是否還有效
fetchMe(){
wx.request({
url: 'https://test.com/me',
success:(res)=>{
console.log(res.data)
},
fail:(res)=> {
this.login();
}
})
},
login() {
wx.login({
success:(res)=> {
if (res.code) {
this.loginServer(res.code);
}
}
})
},
loginServer(code){
wx.request({
url: 'https://test.com/login',
data: {
code
},
success(res) {
console.log(res.data)
}
})
}
}
}
3、獲取手機號
前提:已登錄
<template>
<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">獲取手機號</button>
</template>
<script>
export default {
methods: {
getPhoneNumber(e) {
// 得到加密過的數據
if (e.detail.iv && e.detail.encryptedData) {
this.getPhoneNumberFromServer(e.detail);
}
},
// 發給後端解密,後端拿session_key去微信服務器解密
getPhoneNumberFromServer(detail) {
wx.request({
url: 'https://test.com/phone',
data: {
iv: detail.iv,
encryptedData: detail.encryptedData
},
success(res) {
console.log(res.data)
}
})
}
}
}
</script>
4、登錄與獲取用戶信息的結合
1、雖然登錄與獲取用戶信息可以分離,但是可以設計成 獲取用戶信息 是登錄的前提,從而能採集一些用戶信息;具體來說是,用戶觸發 getUserInfo 按鈕 後再 wx.login(),並把用戶信息保存到後端
2、用戶觸發過 getUserInfo 按鈕,即可獎獲取的信息保存到後端,但是有必要獲取用戶最新的信息,因此可以設計成每次登錄都觸發 getUserInfo
3、第一次獲取用戶信息 只能是 getUserInfo 按鈕,之後可以是 wx.getUserInfo,可以設計成 任何情況都是 getUserInfo 按鈕,從而不用區分兩種情況
4、有getUserInfo權限的情況下,使用getUserInfo 按鈕,不會彈出授權框,但能正常回調;因此,在顯式登錄的場景中,(type爲getUserInfo的登錄按鈕 + wx.login) 不會比 (登錄按鈕 + wx.getUserInfo + wx.login)給用戶帶來更多負擔;因此,在顯式登錄的場景中,無需判斷是否有getUserInfo權限,統統使用getUserInfo 按鈕
5、登錄功能可以設計成一個抽屜,能被各處調用
總結:
方案一:不要自動wx.login(),用戶要進行登錄後纔能有的操作時,彈出登錄抽屜,抽屜裏放置getUserInfo 按鈕;用戶觸發getUserInfo 按鈕後,在調用wx.login(),並將最新的用戶信息保存到後端;缺點,用戶每次都要顯式的登錄
方案二:先用wx.getSetting判斷有沒有getUserInfo權限,有的話,自動wx.getUserInfo並wx.login,並將最新的用戶信息保存到後端;還沒有getUserInfo權限的話,再按方案一
場景一:在有退出功能的小程序中,不能自動wx.login(),需要顯式的登錄,因此採用方案一
5、Cookie
小程序不支持cookie機制,但可以讀取響應頭的Set-Cookie,有Storage機制。
可以用現成的組件使得小程序支持cookie:https://github.com/charleslo1/weapp-cookie