微信公衆號、微信小程序

微信公衆號網頁開發

授權流程
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=&timestamp=&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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章