硅谷课堂笔记(中)
文章目錄
- 復(fù)習(xí)SpringCloud
- 后臺開發(fā)-訂單管理模塊
- 整合網(wǎng)關(guān)Gateway
- 網(wǎng)關(guān)bug
- 網(wǎng)關(guān)Gateway解決跨域
- 修改前端配置文件
- 后臺開發(fā)-訂單管理模塊
- 需求概述
- 基礎(chǔ)環(huán)境搭建
- 開發(fā)訂單列表接口
- 集成訂單前端頁面
- 啟動測試
- 后臺開發(fā)-營銷管理模塊
- 基礎(chǔ)環(huán)境搭建
- 創(chuàng)建用戶模塊
- 創(chuàng)建遠(yuǎn)程調(diào)用模塊
- 開發(fā)相關(guān)接口
- 整合營銷管理前端頁面
- 微信公眾號
- 測試公眾號(重要)
- 開發(fā)業(yè)務(wù)介紹
- 后臺管理系統(tǒng)-公眾號菜單管理
- 需求分析
- 管理頁面
- 后端基礎(chǔ)環(huán)境搭建
- 公眾號管理接口開發(fā)
- 公眾號菜單同步
- 同步菜單(獲取access_token)
- 文檔查看
- service_wechat添加配置
- 添加工具類
- 復(fù)制相關(guān)工具類
- 添加Menucontroller方法
- 同步菜單(功能實(shí)現(xiàn))
- 添加配置類
- 同步方法編寫
- 整合前端
- 測試
- 公眾號普通消息
- 需求分析
- 后臺消息接入
- 消息接入
- 后端接口開發(fā)
- 消息校驗(yàn)接口
- 消息接收接口
- 配置內(nèi)網(wǎng)穿透
- 何為內(nèi)網(wǎng)穿透
- 配置內(nèi)網(wǎng)穿透ngrok(不好用)
- 免費(fèi)內(nèi)網(wǎng)穿透花生殼(用這個)
- 內(nèi)網(wǎng)穿透測試
- 后臺開發(fā)-消息業(yè)務(wù)實(shí)現(xiàn)
- 業(yè)務(wù)流程
- 開發(fā)接口
- 遠(yuǎn)程調(diào)用模塊構(gòu)建
- 公眾號模塊引入遠(yuǎn)程調(diào)用
- 測試
- 公眾號模板消息
- 正式公眾號模板申請
- 查看模板樣式
- 公眾號測試號申請模板消息
- 公眾號后臺設(shè)置
- 后端相應(yīng)接口
- 測試
- 微信授權(quán)登陸
- 需求分析
- 授權(quán)登錄介紹
- 公眾號正式號配置
- 公眾號測試號配置
- 部署前端頁面
- 前端處理
- 授權(quán)登錄接口開發(fā)
- 測試
- Token(重要)
- JWT介紹
- JWT原理
- 看看Token長什么樣子
- 整合JWT
- 公眾號點(diǎn)播課程
- 需求分析
- 分頁展示接口開發(fā)
- 整合前端
- 點(diǎn)播視頻播放接口開發(fā)
- 整合前端
- 付費(fèi)觀看點(diǎn)播課程接口
- Feign創(chuàng)建獲取課程信息接口
- Feign創(chuàng)建獲取優(yōu)惠卷操作接口
- 獲取當(dāng)前用戶id
- 生成訂單
復(fù)習(xí)SpringCloud
也是這里篇幅比較多,我單獨(dú)開一篇去復(fù)習(xí)
復(fù)習(xí)SpringCloud
SpringCloud系列學(xué)習(xí):
Spring Cloud 上
Spring Cloud 中
Spring Cloud 下 (SpringCloud alibaba)
后臺開發(fā)-訂單管理模塊
引入Nacos,把之前的注解打開
配置Nacos客戶端的pom依賴
提前引入微服務(wù)相關(guān)依賴,具體的版本控制:
配置service_vod
配置application.properties,在客戶端微服務(wù)中添加注冊Nacos服務(wù)的配置信息
添加Nacos客戶端注解
在service_vod微服務(wù)啟動類中添加注解
@EnableDiscoveryClient
再次啟動服務(wù)就會發(fā)現(xiàn),新的服務(wù)已經(jīng)注冊進(jìn)入Nacos了
整合網(wǎng)關(guān)Gateway
網(wǎng)關(guān)也是一種服務(wù),所以這里也要建設(shè)一個模塊,整合網(wǎng)關(guān)服務(wù)
POM文件
<dependencies><!--工具服務(wù)引入,包括里面的全局異常處理等--><dependency><groupId>com.cc</groupId><artifactId>service_utils</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- 網(wǎng)關(guān) --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- 服務(wù)注冊 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies>創(chuàng)建啟動類并且添加注解
網(wǎng)關(guān)bug
網(wǎng)關(guān)啟動類要和跨域配置類放在一個包下,而且啟動網(wǎng)關(guān)一定要提前啟動nacos,不然啟動不起來
把配置文件寫一下,application.properties
# 服務(wù)端口 server.port=8333# 服務(wù)名 spring.application.name=service-gateway# nacos服務(wù)地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848#使用服務(wù)發(fā)現(xiàn)路由 spring.cloud.gateway.discovery.locator.enabled=true#service-vod模塊配置 #設(shè)置路由id,也就是Nacos里面注冊的服務(wù)名字 spring.cloud.gateway.routes[0].id=service-vod #設(shè)置路由的uri lb:load Balance 負(fù)載均衡 spring.cloud.gateway.routes[0].uri=lb://service-vod #設(shè)置路由斷言,代理servicerId為auth-service的/auth/路徑 #實(shí)際上斷言就是路徑匹配 /a/vod/b/c/d... spring.cloud.gateway.routes[0].predicates= Path=/*/vod/**網(wǎng)關(guān)Gateway解決跨域
跨域概述
跨域本質(zhì)是瀏覽器對于ajax請求的一種安全限制:一個頁面發(fā)起的ajax請求,只能是與當(dāng)前頁域名相同的路徑,這能有效的阻止跨站攻擊。因此:跨域問題 是針對ajax的一種限制。但是這卻給我們的開發(fā)帶來了不便,而且在實(shí)際生產(chǎn)環(huán)境中,肯定會有很多臺服務(wù)器之間交互,地址和端口都可能不同。
之前我們通過服務(wù)器添加注解實(shí)現(xiàn),現(xiàn)在我們跨域通過網(wǎng)關(guān)來解決跨域問題。
創(chuàng)建配置類
這里配置好了跨域,之前的跨域注解一定去掉,如果沒去掉就相當(dāng)于跨域跨進(jìn)去了再跨出來,就相當(dāng)于沒跨
**注意:**目前我們已經(jīng)在網(wǎng)關(guān)做了跨域處理,那么service服務(wù)就不需要再做跨域處理了,將之前在controller類上添加過@CrossOrigin標(biāo)簽的去掉==
修改前端配置文件
找到那個開發(fā)文件配置
修改接口為網(wǎng)關(guān)地址,讓服務(wù)請求先打到網(wǎng)關(guān)上
后臺開發(fā)-訂單管理模塊
需求概述
這個模塊很簡單,只有一個訂單的分頁處理,把已有的訂單展示一下就好了
基礎(chǔ)環(huán)境搭建
在網(wǎng)關(guān)模塊的配置文件中,把訂單模塊劃入網(wǎng)關(guān)進(jìn)行治理
相關(guān)表數(shù)據(jù)庫:
訂單信息
訂單詳情
這倆表是一對一的關(guān)系
創(chuàng)建訂單模塊
service模塊下創(chuàng)建service_order模塊
用MP的代碼生成器生成一下相關(guān)表的內(nèi)容,就用之前模塊下面的代碼生成器就可以了,改一遍包路徑和表
生成相關(guān)代碼和啟動類
記得在service父模塊把子模塊的信息添加進(jìn)去,要不然沒依賴
在訂單模塊里,也要改一下,不改默認(rèn)是吧最頂層的onlineClass作為父模塊依賴
添加配置文件application.properties
# 服務(wù)端口 server.port=8302# 服務(wù)名 spring.application.name=service-order# 環(huán)境設(shè)置:dev、test、prod spring.profiles.active=dev# mysql數(shù)據(jù)庫連接 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3307/glkt_order?characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=123456#返回json的全局時間格式 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8#mybatis日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImplmybatis-plus.mapper-locations=classpath:com/service_order/mapper/xml/*.xml分頁插件配置類
到這,基礎(chǔ)環(huán)境搭建完畢,開始開發(fā)
開發(fā)訂單列表接口
Controller位置:
ServiceImpl位置:
用Map封裝的結(jié)果數(shù)據(jù)
前端解析好的數(shù)據(jù)
集成訂單前端頁面
在API目錄下,新建Order文件夾,創(chuàng)建Order.js
把路由創(chuàng)建好
最后整合頁面
創(chuàng)建views -> order -> orderInfo -> list.vue
CV樣式
啟動測試
先啟動nacos
三個服務(wù)也都啟動
后臺開發(fā)-營銷管理模塊
基礎(chǔ)環(huán)境搭建
相關(guān)數(shù)據(jù)庫
coupon info 優(yōu)惠卷信息
coupon use 優(yōu)惠卷使用情況
新建工程
父工程依賴修改
子模塊POM
代碼生成器生成相關(guān)類
創(chuàng)建配置文件
GateWay網(wǎng)關(guān)注冊相關(guān)信息
創(chuàng)建分頁配置類
因?yàn)樯婕暗絻?yōu)惠卷的使用情況,所以要把用戶信息拿到,才能知道這個優(yōu)惠卷的使用情況如何。所以需要Nacos管理服務(wù)+Fegin遠(yuǎn)程接口調(diào)用
創(chuàng)建用戶模塊
這個模塊只負(fù)責(zé)遠(yuǎn)程調(diào)用
用戶表
創(chuàng)建模塊、生成代碼、配置文件、配置網(wǎng)關(guān),這些就不多贅述了,弄好之后是這樣的
這里已經(jīng)寫好了關(guān)于用戶返回的Controller,可以注意到,已經(jīng)不是返回Result了,已經(jīng)是返回UserInfo了
這寫完了,就得創(chuàng)建遠(yuǎn)程調(diào)用的模塊了
創(chuàng)建遠(yuǎn)程調(diào)用模塊
次級父模塊service_client的依賴如下
創(chuàng)建完就是這樣的
創(chuàng)建遠(yuǎn)程調(diào)用接口,和被調(diào)用接口進(jìn)行講解
最后,把這個模塊在需要被調(diào)用的接口通過pom進(jìn)行引入,最好是把他放在服務(wù)的父工程中,這樣下面的下屬子模塊就不需要去再重復(fù)引入依賴了
能這么調(diào)用的前提是,你在對應(yīng)的pom里有這樣一段標(biāo)簽,相當(dāng)于這個模塊被調(diào)用時的 “標(biāo)簽” ,否則調(diào)用不了
還要在需要進(jìn)行調(diào)用的模塊主啟動類上加入注解
現(xiàn)在就可以進(jìn)行遠(yuǎn)程調(diào)用了
配好了直接注入就能用!
最好是在Service模塊把這個遠(yuǎn)程調(diào)用模塊的接口整體注入進(jìn)父模塊下,這樣就不用Service下屬子模塊都跟著引入相關(guān)依賴了,非常的方便~
開發(fā)相關(guān)接口
Controller位置:
ServiceImpl位置:
這里解釋一下,有個繼承類
其他參數(shù)就是擴(kuò)展類
優(yōu)惠卷這個實(shí)體類在最后的一步有個集成用戶信息的步驟,就是通過實(shí)體類擴(kuò)展實(shí)現(xiàn)的,getParam也就對應(yīng)了BaseMapper中的para Map屬性
具體可以在代碼查看,這里篇幅有限
這些都寫完,記得把這個服務(wù)注冊進(jìn)路由
#service-activity模塊配置 #設(shè)置路由id spring.cloud.gateway.routes[4].id=service-activity #設(shè)置路由的uri spring.cloud.gateway.routes[4].uri=lb://service-activity #設(shè)置路由斷言,代理servicerId為auth-service的/auth/路徑 spring.cloud.gateway.routes[4].predicates= Path=/*/activity/**整合營銷管理前端頁面
定義JS的API
創(chuàng)建api -> activity -> couponInfo.js**
把路由修改好
router -> index.js定義路由
定義好的樣式
粘貼頁面樣式
最終頁面效果
微信公眾號
簡介
微信公眾平臺:https://mp.weixin.qq.com/
硅谷課堂要求基于H5,具有微信支付等高級功能的,因此需要注冊服務(wù)號,訂閱號不具備支付功能。
注冊步驟參考官方注冊文檔:https://kf.qq.com/faq/120911VrYVrA151013MfYvYV.html
注冊過程僅做了解,有公司運(yùn)營負(fù)責(zé)申請與認(rèn)證。
如果只是日常簡單的推送文章,就像我們關(guān)注的大多數(shù)公眾號一樣,那確實(shí)不需要技術(shù)人員去開發(fā);但是,如果你想將你們的網(wǎng)站嵌入進(jìn)去公眾號菜單里(這里指的是把前端項(xiàng)目的首頁鏈接配置在自定義菜單),并且實(shí)現(xiàn)微信端的獨(dú)立登錄認(rèn)證、獲取微信用戶信息、微信支付等高級功能,或者覺得UI交互的配置方式無法滿足你的需求,你需要更加自由、隨心所欲的操作,那么我們就必須啟用開發(fā)者模式了,通過技術(shù)人員的手段去靈活控制公眾號。
這里有一點(diǎn)需要注意,如果我們決定技術(shù)人員開發(fā)公眾號,必須啟用服務(wù)器配置,而這將導(dǎo)致UI界面設(shè)置的自動回復(fù)和自定義菜單失效!
我們在 設(shè)置與開發(fā) - 基本配置 - 服務(wù)器配置 中點(diǎn)擊啟用:
測試公眾號(重要)
前面說了,個人無法去申請服務(wù)號,必須企業(yè),但是我們可以通過測試賬戶進(jìn)行學(xué)習(xí)
微信公眾平臺接口測試帳號:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login&token=399029368&lang=zh_CN
查看測試號管理
(1)其中appID和appsecret用于后面菜單開發(fā)使用
(2)其中URL是開發(fā)者用來接收微信消息和事件的接口URL。Token可由開發(fā)者可以任意填寫,用作生成簽名(該Token會和接口URL中包含的Token進(jìn)行比對,從而驗(yàn)證安全性)。本地測試,url改為內(nèi)網(wǎng)穿透地址。
關(guān)注公眾號
開發(fā)業(yè)務(wù)介紹
硅谷課堂涉及的微信公眾號功能模塊:自定義菜單、消息、微信支付、授權(quán)登錄等
后臺管理系統(tǒng)-公眾號菜單管理
需求分析
微信自定義菜單說明
微信自定義菜單文檔地址:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
微信自定義菜單注意事項(xiàng):
在線課堂自定義菜單
一級菜單:直播、課程、我的
二級菜單:根據(jù)一級菜單動態(tài)設(shè)置二級菜單,直播(近期直播課程),課程(課程分類),我的(我的訂單、我的課程、我的優(yōu)惠券及關(guān)于我們)
說明:
? 1、二級菜單可以是網(wǎng)頁類型,點(diǎn)擊跳轉(zhuǎn)H5頁面
? 2、二級菜單可以是消息類型,點(diǎn)擊返回消息
數(shù)據(jù)格式
自定義菜單通過后臺管理設(shè)置到數(shù)據(jù)庫表,數(shù)據(jù)配置好后,通過微信接口推送菜單數(shù)據(jù)到微信平臺。
管理頁面
如圖所示
(1)頁面功能“列表、添加、修改與刪除”是對menu表的操作
(2)頁面功能“同步菜單與刪除菜單”是對微信平臺接口操作
后端基礎(chǔ)環(huán)境搭建
表結(jié)構(gòu)(menu):
新建模塊
這里就不多說了,文件夾,注冊網(wǎng)關(guān),主啟動類,代碼生成、修改POM這些上面都有
配置文件
# 服務(wù)端口 server.port=8305 # 服務(wù)名 spring.application.name=service-wechat# 環(huán)境設(shè)置:dev、test、prod spring.profiles.active=dev# mysql數(shù)據(jù)庫連接 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3307/glkt_wechat?characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=123456#返回json的全局時間格式 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8#mybatis日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImplmybatis-plus.mapper-locations=classpath:src/main/java/com/service_wechat/mapper/xml/*.xml# nacos服務(wù)地址 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848#公眾號id和秘鑰 # 硅谷課堂微信公眾平臺appId wechat.mpAppId: wx09f201e9013e81d8 # 硅谷課堂微信公眾平臺api秘鑰 wechat.mpAppSecret: 6c999765c12c51850d28055e8b6e2eda公眾號管理接口開發(fā)
除了常見的接口以外,這里有兩個比較重要的接口
一個是獲取一級菜單
另一個是獲取全部菜單
位置:
公眾號菜單同步
同步菜單(獲取access_token)
文檔查看
(1)進(jìn)行菜單同步時候,需要獲取到公眾號的access_token,通過access_token進(jìn)行菜單同步
接口文檔:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
(2)調(diào)用方式
service_wechat添加配置
這個是老師的測試號,當(dāng)然可以換成自己的!
# 硅谷課堂微信公眾平臺appId wechat.mpAppId: wx09f201e9013e81d8 # 硅谷課堂微信公眾平臺api秘鑰 wechat.mpAppSecret: 6c999765c12c51850d28055e8b6e2eda添加工具類
讀取公眾號API的工具
@Component public class ConstantPropertiesUtil implements InitializingBean {@Value("${wechat.mpAppId}")private String appid;@Value("${wechat.mpAppSecret}")private String appsecret;public static String ACCESS_KEY_ID;public static String ACCESS_KEY_SECRET;@Overridepublic void afterPropertiesSet() throws Exception {ACCESS_KEY_ID = appid;ACCESS_KEY_SECRET = appsecret;} }復(fù)制相關(guān)工具類
添加Menucontroller方法
在Controller中添加方法,返回token使用
同步菜單(功能實(shí)現(xiàn))
接口文檔:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html
接口調(diào)用請求說明
http請求方式:POST(請使用https協(xié)議) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
weixin-java-mp是封裝好了的微信接口客戶端,使用起來很方便,后續(xù)我們就使用weixin-java-mp處理微信平臺接口。
添加配置類
添加微信相關(guān)配置類
同步方法編寫
還是在Controller
要求的數(shù)據(jù)格式
service實(shí)現(xiàn)層
為什么直接用了JSON數(shù)組,是因?yàn)檫@里直接對接公眾號的數(shù)據(jù)
不再有Controller的JSON轉(zhuǎn)換解析,所以這里直接做成JSON
一層一層向上封裝的
/*** 說明:* 自定義菜單最多包括3個一級菜單,每個一級菜單最多包含5個二級菜單。* 一級菜單最多4個漢字,二級菜單最多8個漢字,多出來的部分將會以“...”代替。* 創(chuàng)建自定義菜單后,菜單的刷新策略是,在用戶進(jìn)入公眾號會話頁或公眾號profile頁時,* 如果發(fā)現(xiàn)上一次拉取菜單的請求在5分鐘以前,就會拉取一下菜單,如果菜單有更新,就會刷新客戶端的菜單。* 測試時可以嘗試取消關(guān)注公眾賬號后再次關(guān)注,則可以看到創(chuàng)建后的效果。* 實(shí)際上就是把自己菜單的JSON格式轉(zhuǎn)換成微信認(rèn)識的格式*/@SneakyThrows@Overridepublic void syncMenu() {List<MenuVo> menuVoList = this.findMenuInfo();//菜單,創(chuàng)建一個JSON格式數(shù)組,這里為什么用了JSON數(shù)組,是因?yàn)檫@里直接對接公眾號//不再有Controller的JSON轉(zhuǎn)換解析,所以這里直接做成JSONJSONArray buttonList = new JSONArray();//一級菜單for(MenuVo oneMenuVo : menuVoList) {JSONObject one = new JSONObject();//name是一級菜單的固定名稱one.put("name", oneMenuVo.getName());//二級菜單JSONArray subButton = new JSONArray();for(MenuVo twoMenuVo : oneMenuVo.getChildren()) {JSONObject view = new JSONObject();//type是二級菜單的固定名稱view.put("type", twoMenuVo.getType());//根據(jù)type的值進(jìn)行判斷,是按鈕還是關(guān)鍵詞觸發(fā)返回信息if(twoMenuVo.getType().equals("view")) {view.put("name", twoMenuVo.getName());view.put("url", "http://ggkt2.vipgz1.91tunnel.com/#"+twoMenuVo.getUrl());} else {view.put("name", twoMenuVo.getName());view.put("key", twoMenuVo.getMeunKey());}subButton.add(view);}//封裝二級菜單,固定叫sub_buttonone.put("sub_button", subButton);//封裝一級菜單buttonList.add(one);}//菜單整體封裝,一級+二級 一起叫buttonJSONObject button = new JSONObject();button.put("button", buttonList);this.wxMpService.getMenuService().menuCreate(button.toJSONString());}整合前端
src -> router -> index.js添加路由
src -> api -> wechat -> menu.js定義接口
創(chuàng)建views -> wechat -> menu -> list.vue CV頁面
最終樣式
測試
關(guān)注測試公眾號,電腦登陸公眾號,就可以進(jìn)行測試了
數(shù)據(jù)就同步上來了
如果更換了配置信息,就要在這里同步一下,不同步菜單的話數(shù)據(jù)上不來,因?yàn)槲⑿殴娞柺遣粫鲃诱埱蟾碌?#xff0c;需要咱們主動數(shù)據(jù)推送
公眾號普通消息
需求分析
輸入特定詞語,返回消息
1、“硅谷課堂”公眾號實(shí)現(xiàn)根據(jù)關(guān)鍵字搜索相關(guān)課程,如:輸入“java”,可返回java相關(guān)的一個課程;
2、“硅谷課堂”公眾號點(diǎn)擊菜單“關(guān)于我們”,返回關(guān)于我們的介紹
3、關(guān)注或取消關(guān)注等
后臺消息接入
消息接入
參考文檔:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
接入微信公眾平臺開發(fā),開發(fā)者需要按照如下步驟完成:
1、填寫服務(wù)器配置
2、驗(yàn)證服務(wù)器地址的有效性
3、依據(jù)接口文檔實(shí)現(xiàn)業(yè)務(wù)邏輯
公眾號服務(wù)器配置
在測試管理 -> 接口配置信息,點(diǎn)擊“修改”按鈕,填寫服務(wù)器地址(URL)和Token,其中URL是開發(fā)者用來接收微信消息和事件的接口URL。Token可由開發(fā)者可以任意填寫,用作生成簽名(該Token會和接口URL中包含的Token進(jìn)行比對,從而驗(yàn)證安全性)
說明:本地測試,url改為內(nèi)網(wǎng)穿透地址,這個內(nèi)網(wǎng)穿透在后面會仔細(xì)講解
驗(yàn)證來自微信服務(wù)器消息
(1)概述
開發(fā)者提交信息后,微信服務(wù)器將發(fā)送GET請求到填寫的服務(wù)器地址URL上,GET請求攜帶參數(shù)如下表所示:
| signature | 微信加密簽名,signature結(jié)合了開發(fā)者填寫的token參數(shù)和請求中的timestamp參數(shù)、nonce參數(shù)。 |
| timestamp | 時間戳 |
| nonce | 隨機(jī)數(shù) |
| echostr | 隨機(jī)字符串 |
開發(fā)者通過檢驗(yàn)signature對請求進(jìn)行校驗(yàn)(下面有校驗(yàn)方式)。若確認(rèn)此次GET請求來自微信服務(wù)器,請原樣返回echostr參數(shù)內(nèi)容,則接入生效,成為開發(fā)者成功,否則接入失敗。加密/校驗(yàn)流程如下:
1、將token、timestamp、nonce三個參數(shù)進(jìn)行字典序排序
2、將三個參數(shù)字符串拼接成一個字符串進(jìn)行sha1加密
3、開發(fā)者獲得加密后的字符串可與signature對比,標(biāo)識該請求來源于微信
消息接收流程
后端接口開發(fā)
消息校驗(yàn)接口
實(shí)際上就是接收四個參數(shù),而且使用HttpRequest對象來接收
接口位置
定義好Token,方便和微信后臺設(shè)置的內(nèi)容校驗(yàn)
兩個方法名
/*** 服務(wù)器有效性驗(yàn)證* @param request* @return*/public String verifyToken(HttpServletRequest request) {private boolean checkSignature(String signature, String timestamp, String nonce)完成之后,我們的校驗(yàn)接口就算是開發(fā)完成了。接下來就可以開發(fā)消息接收接口了。
消息接收接口
接下來我們來開發(fā)消息接收接口,消息接收接口和上面的服務(wù)器校驗(yàn)接口地址是一樣的,都是我們一開始在公眾號后臺配置的地址。只不過消息接收接口是一個 POST 請求。
在公眾號后臺配置的時候,消息加解密方式選擇了明文模式,這樣在后臺收到的消息直接就可以處理了。微信服務(wù)器給我發(fā)來的普通文本消息格式如下:
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId> </xml>| ToUserName | 開發(fā)者微信號 |
| FromUserName | 發(fā)送方帳號(一個OpenID) |
| CreateTime | 消息創(chuàng)建時間 (整型) |
| MsgType | 消息類型,文本為text |
| Content | 文本消息內(nèi)容 |
| MsgId | 消息id,64位整型 |
看到這里,大家心里大概就有數(shù)了,當(dāng)我們收到微信服務(wù)器發(fā)來的消息之后,我們就進(jìn)行 XML 解析,提取出來我們需要的信息,去做相關(guān)的查詢操作,再將查到的結(jié)果返回給微信服務(wù)器。
這里我們先來個簡單的,我們將收到的消息解析并打印出來:
還是在同一個Controller里
配置內(nèi)網(wǎng)穿透
何為內(nèi)網(wǎng)穿透
前面已經(jīng)說過了,要微信服務(wù)器和本地的服務(wù)器進(jìn)行通信。
我們可以找到微信服務(wù)器,但是微信服務(wù)器找不到我們的本地主機(jī)
這個時候就需要內(nèi)網(wǎng)穿透幫忙了
所謂的開通一個隧道,就是申請一個域名,讓微信服務(wù)器可以通過這個域名(隧道)訪問到你本地
配置內(nèi)網(wǎng)穿透ngrok(不好用)
注冊用戶
網(wǎng)址:https://ngrok.cc/login/register
實(shí)名認(rèn)證
(1)注冊成功之后,登錄系統(tǒng),進(jìn)行實(shí)名認(rèn)證,認(rèn)證費(fèi)2元,認(rèn)證通過后才能開通隧道
開通隧道
(1)選擇隧道管理 -> 開通隧道
最后一個是免費(fèi)服務(wù)器,建議選擇付費(fèi)服務(wù)器,10元/月,因?yàn)槊赓M(fèi)服務(wù)器使用人數(shù)很多,經(jīng)常掉線
(2)點(diǎn)擊立即購買 -> 輸入相關(guān)信息
(3)開通成功后,查看開通的隧道
這里開通了兩個隧道,一個用于后端接口調(diào)用,一個用于公眾號前端調(diào)用
啟動隧道
(1)下載客戶端工具
(2)選擇windows版本
(3)解壓,找到bat文件,雙擊啟動
(4)輸入隧道id,多個使用逗號隔開,最后回車就可以啟動
tnnd,連不上
正常如果連上了應(yīng)該是這個樣子
免費(fèi)內(nèi)網(wǎng)穿透花生殼(用這個)
花生殼官網(wǎng) 花生殼打錢!
注冊下載什么的我就不說了,安裝好配置一下
這樣就可以使用了!
一共要生成兩個,一個給前端做隧道,另一個給后端做穿透
畢竟兩個項(xiàng)目都在本地跑,想讓外網(wǎng)訪問不用隧道穿透肯定是不行的
但是如果想用HTTP服務(wù)必須花錢,再開一個,如果是學(xué)生的話可以免費(fèi)開通
我認(rèn)證了一下,就可以免費(fèi)用兩個HTTP了,TCP連前端連不上
快說,謝謝花生殼~
回到公眾號這里,再來捋一遍,先看看自己的公眾測試號
微信公眾平臺測試號后臺
URL就不說了,就是配置好的內(nèi)網(wǎng)穿透地址+后端服務(wù)器有效性驗(yàn)證 的路徑
Token可以看后端代碼
內(nèi)網(wǎng)穿透測試
向測試公眾號里發(fā)一個消息,看看后臺是否可以接收到
可以看到,已經(jīng)接受到了結(jié)構(gòu)化的數(shù)據(jù)了
后臺開發(fā)-消息業(yè)務(wù)實(shí)現(xiàn)
業(yè)務(wù)流程
開發(fā)接口
根據(jù)課程名稱返回課程信息,就是根據(jù)課程名稱進(jìn)行模糊查詢
service_vod模塊創(chuàng)建接口
(1)創(chuàng)建CourseApiController方法,根據(jù)課程關(guān)鍵字查詢課程信息
遠(yuǎn)程調(diào)用模塊構(gòu)建
創(chuàng)建模塊定義接口
service_client下創(chuàng)建子模塊service_course_client,改Pom之類的就不多說了
把課程查詢的遠(yuǎn)程調(diào)用整合到一個單獨(dú)的遠(yuǎn)程調(diào)用子模塊中
公眾號模塊引入遠(yuǎn)程調(diào)用
主啟動類
service_wechat引入更改寫好的遠(yuǎn)程調(diào)用依賴
<dependency><artifactId>service_course_client</artifactId><groupId>com.courseFeginService</groupId><version>0.0.1-SNAPSHOT</version></dependency>創(chuàng)建消息處理接口
將微信模塊的MessageController方法進(jìn)行更改,根據(jù)關(guān)鍵字內(nèi)容進(jìn)行校驗(yàn)
具體的消息結(jié)果處理在MessageServiceImpl,根據(jù)關(guān)鍵字返回比較固定,把這個基本代碼改改就可以用了
測試
把Nacos、內(nèi)網(wǎng)隧道、服務(wù)都啟動
(1)點(diǎn)擊個人 -> 關(guān)于我們,返回關(guān)于我們的介紹
(2)在公眾號輸入關(guān)鍵字,返回搜索的課程信息
公眾號模板消息
正式公眾號模板申請
這種是非測試公眾號的申請,測試公眾號則不需要
實(shí)現(xiàn)目標(biāo)
購買課程支付成功微信推送消息
模板消息實(shí)現(xiàn)
接口文檔:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html
申請模板消息
首先我們需要知道,模板消息是需要申請的。
但是我們在申請時還是有一些東西要注意,這個在官方的文檔有非常詳細(xì)的說明。
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Operation_Specifications.html
這個大家好好看看。選擇行業(yè)的時候可要謹(jǐn)慎些,因?yàn)檫@個一個月只可以修改一次。
下面看看在哪里申請,硅谷課堂已經(jīng)申請過,忽略
申請之后就耐心等待,審核通過之后就會出現(xiàn)“廣告與服務(wù)”模板消息的菜單。
添加模板消息
審核通過之后,我們就可以添加模板消息,進(jìn)行開發(fā)了。
我們點(diǎn)擊模板消息進(jìn)入后,直接在模板庫中選擇你需要的消息模板添加就可以了,添加之后就會在我的模板中。會有一個模板id,這個模板id在我們發(fā)送消息的時候會用到。
模板消息如下:
查看模板樣式
模板樣式在一個word里面,下載下來
這里是截取一部分的內(nèi)容
公眾號測試號申請模板消息
模板消息長這個樣子
公眾號后臺設(shè)置
點(diǎn)擊新增模板
從上面的模板示例中,拿到需要使用的模板,填寫進(jìn)去
添加成功就是這個樣子
后端相應(yīng)接口
MessageController
添加方法
service接口
MessageService
service接口實(shí)現(xiàn)
(1)MessageServiceImpl類
(2)openid值和模板Id
測試
訪問一下這個接口,直接讓他在公眾號里推送模板信息
測試通過,推送成功
微信授權(quán)登陸
需求分析
根據(jù)流程圖通過菜單進(jìn)入的頁面都要授權(quán)登錄
授權(quán)登錄介紹
接口文檔:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
說明:
? 1、嚴(yán)格按照接口文檔實(shí)現(xiàn);
? 2、應(yīng)用授權(quán)作用域scope:scope為snsapi_userinfo
配置授權(quán)回調(diào)域名
公眾號正式號配置
這個是有企業(yè)注冊了公眾號的情況,個人是看不到這個頁面的,只能拿本地測試玩玩
在微信公眾號請求用戶網(wǎng)頁授權(quán)之前,開發(fā)者需要先到公眾平臺官網(wǎng)中的“設(shè)置與開發(fā) - 接口權(quán)限 - 網(wǎng)頁服務(wù) - 網(wǎng)頁帳號 - 網(wǎng)頁授權(quán)獲取用戶基本信息”的配置選項(xiàng)中,修改授權(quán)回調(diào)域名。請注意,這里填寫的是域名(是一個字符串),而不是URL,因此請勿加 http:// 等協(xié)議頭;
本地測試配置內(nèi)網(wǎng)穿透地址
公眾號測試號配置
這樣的話就可以把本地服務(wù)器上運(yùn)行的前端頁面在公網(wǎng)進(jìn)行訪問了,也就是公眾號開啟新頁面,可以訪問
部署前端頁面
直接復(fù)制進(jìn)工程中,資料里的前端頁面叫
修改訪問路徑到你的內(nèi)網(wǎng)隧道
啟動公眾號頁面項(xiàng)目 這個直接運(yùn)行就可以了 npm run serve
如果啟動的時候報錯看看這個文章
https://blog.csdn.net/m0_37629753/article/details/125199185
跑起來的樣子
前端處理
(1)全局處理授權(quán)登錄,處理頁面:/src/App.vue
說明1:訪問頁面時首先判斷是否有token信息,如果沒有跳轉(zhuǎn)到授權(quán)登錄接口
說明2:通過localStorage存儲token信息
在HTML5中,加入了一個localStorage特性,這個特性主要是用來作為本地存儲來使用的,解決了cookie存儲空間不足的問題(cookie中每條cookie的存儲空間很小,只有幾K),localStorage中一般瀏覽器支持的是5M大小,這個在不同的瀏覽器中l(wèi)ocalStorage會有所不同。它只能存儲字符串格式的數(shù)據(jù),所以最好在每次存儲時把數(shù)據(jù)轉(zhuǎn)換成json格式,取出的時候再轉(zhuǎn)換回來。
(2)前端代碼實(shí)現(xiàn)
wechatLogin() {// 處理微信授權(quán)登錄let token = this.getQueryString('token') || '';if(token != '') {window.localStorage.setItem('token', token);}// 所有頁面都必須登錄,兩次調(diào)整登錄,這里與接口返回208狀態(tài)token = window.localStorage.getItem('token') || '';if (token == '') {let url = window.location.href.replace('#', 'guiguketan')window.location = 'http://glkt.atguigu.cn/api/user/wechat/authorize?returnUrl=' + url}console.log('token2:'+window.localStorage.getItem('token'));},授權(quán)登錄接口開發(fā)
操作模塊:service-user
引入微信依賴
在配置文件中添加配置
#公眾號id和秘鑰 # 硅谷課堂微信公眾平臺appId wechat.mpAppId: wx09f201e9013e81d8 ## 硅谷課堂微信公眾平臺api秘鑰 wechat.mpAppSecret: 6c999765c12c51850d28055e8b6e2eda # 授權(quán)回調(diào)獲取用戶信息接口地址 wechat.userInfoUrl: http://內(nèi)網(wǎng)隧道地址/api/user/wechat/userInfo添加了一個工具類來讀取配置文件的賬戶密碼信息
另一個是微信的配置類
測試
我這里實(shí)在連不上內(nèi)網(wǎng)穿透了…
沒做出來…
希望有小伙伴能留言給我講講QAQ
Token(重要)
通過token傳遞用戶信息
JWT介紹
JWT工具
JWT(Json Web Token)是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn)。
JWT的聲明一般被用來在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源。比如用在用戶登錄上
JWT最重要的作用就是對 token信息的防偽作用。
JWT原理
一個JWT由三個部分組成:公共部分、私有部分、簽名部分。最后由這三者組合進(jìn)行base64編碼得到JWT。
(1)公共部分
主要是該JWT的相關(guān)配置參數(shù),比如簽名的加密算法、格式類型、過期時間等等。
(2)私有部分
用戶自定義的內(nèi)容,根據(jù)實(shí)際需要真正要封裝的信息。
userInfo{用戶的Id,用戶的昵稱nickName}
(3)簽名部分
SaltiP: 當(dāng)前服務(wù)器的Ip地址!{linux 中配置代理服務(wù)器的ip}
主要用戶對JWT生成字符串的時候,進(jìn)行加密{鹽值}
base64編碼,并不是加密,只是把明文信息變成了不可見的字符串。但是其實(shí)只要用一些工具就可以把base64編碼解成明文,所以不要在JWT中放入涉及私密的信息。
看看Token長什么樣子
一個長Token一共三部分,每部分都用點(diǎn).來分割
整合JWT
(1)在service_utils模塊添加依賴
<dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId></dependency> </dependencies>(2)添加JWT工具類
公眾號點(diǎn)播課程
由于從微信用不了了,所以我這里就用本地前端工程做了
需求分析
點(diǎn)擊 去看看,進(jìn)入課程詳情頁面
分頁展示接口開發(fā)
在VOD模塊下
創(chuàng)建CourseApiController
編寫CourseService
編寫CourseServiceImpl
這里用到了Mapper,因?yàn)橐啾聿樵?br /> 值得注意的點(diǎn):
拿一個左外連接查詢來說,這種重復(fù)性的SQL是可以進(jìn)行復(fù)用的
用一個標(biāo)簽來進(jìn)行復(fù)用
<sql id="唯一id">course cLEFT JOIN teacher t ON c.teacher_id = t.idLEFT JOIN subject s1 ON c.subject_parent_id = s1.idLEFT JOIN subject s2 ON c.subject_id = s2.id</sql>怎么用?
在需要使用復(fù)用標(biāo)簽的地方加入這個標(biāo)簽
整合前端
修改路由
創(chuàng)建js文件定義接口
編寫頁面
點(diǎn)播視頻播放接口開發(fā)
還是在VOD模塊下,新建VodApi控制器,來接收前端的請求
在配置文件中加入
application.properties添加tencent.video.appid=騰訊云播放器ID
如圖找ID
整合前端
整合點(diǎn)播視頻播放前端
創(chuàng)建js定義接口
courseInfo.vue修改play方法
index.html引入文件
把播放器樣式引入
創(chuàng)建play.vue頁面
付費(fèi)觀看點(diǎn)播課程接口
提交訂單接口
創(chuàng)建Controller對象
編寫OrderInfoService和OrderInfoServiceImpl
OrderInfoService
//生成點(diǎn)播課程訂單 Long submitOrder(OrderFormVo orderFormVo);不過這里得等等,因?yàn)橄掠唵芜@個操作需要聯(lián)動優(yōu)惠卷和課程ID,所以還需要遠(yuǎn)程調(diào)用一下接口 一個是根據(jù)當(dāng)前課程ID來拿到課程
另一個是操作優(yōu)惠卷的(獲取+優(yōu)惠卷使用更新)
Feign創(chuàng)建獲取課程信息接口
先獲取課程信息
操作service_vod模塊
添加課程信息獲取方法
遠(yuǎn)程調(diào)用接口你把上面的根據(jù)ID拿課程的接口定義好
Feign創(chuàng)建獲取優(yōu)惠卷操作接口
操作service_activity模塊
提前把要操作的接口準(zhǔn)備好
對應(yīng)的Service,更改為1就代表這個優(yōu)惠卷已經(jīng)被使用了
為上面的優(yōu)惠卷接口創(chuàng)建一個遠(yuǎn)程調(diào)用接口,建Module過程我就不多說了,一遍又一遍的沒必要多說了
到這里遠(yuǎn)程調(diào)用就算結(jié)束了,一會會回到上面的課程接口信息
獲取當(dāng)前用戶id
(1)common模塊引入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency><!-- spring2.X集成redis所需common-pool2--> <dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.6.0</version> </dependency>拷貝相關(guān)工具類
之前不是說過,LocalStorage是前端的一種存儲方式,所以就可以從前端的LocalStorage里拿到對象ID
前端實(shí)現(xiàn)方式
生成訂單
回到訂單模塊
所有準(zhǔn)備工作完成,準(zhǔn)備接上面的內(nèi)容,調(diào)用相關(guān)遠(yuǎn)程服務(wù)接口生成微服務(wù)
service_order引入依賴
這三個都是遠(yuǎn)程Feign調(diào)用的
訂單業(yè)務(wù)具體工程實(shí)現(xiàn) OrderInfoServiceImpl
@Autowired private CourseFeignClient courseFeignClient;@Autowired private UserInfoFeignClient userInfoFeignClient;@Autowired private CouponInfoFeignClient couponInfoFeignClient;//生成點(diǎn)播課程訂單 @Override public Long submitOrder(OrderFormVo orderFormVo) {Long userId = AuthContextHolder.getUserId();Long courseId = orderFormVo.getCourseId();Long couponId = orderFormVo.getCouponId();//查詢當(dāng)前用戶是否已有當(dāng)前課程的訂單LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(OrderDetail::getCourseId, courseId);queryWrapper.eq(OrderDetail::getUserId, userId);OrderDetail orderDetailExist = orderDetailService.getOne(queryWrapper);if(orderDetailExist != null){return orderDetailExist.getId(); //如果訂單已存在,則直接返回訂單id}//查詢課程信息Course course = courseFeignClient.getById(courseId);if (course == null) {throw new GlktException(ResultCodeEnum.DATA_ERROR.getCode(),ResultCodeEnum.DATA_ERROR.getMessage());}//查詢用戶信息UserInfo userInfo = userInfoFeignClient.getById(userId);if (userInfo == null) {throw new GlktException(ResultCodeEnum.DATA_ERROR.getCode(),ResultCodeEnum.DATA_ERROR.getMessage());}//優(yōu)惠券金額BigDecimal couponReduce = new BigDecimal(0);if(null != couponId) {CouponInfo couponInfo = couponInfoFeignClient.getById(couponId);couponReduce = couponInfo.getAmount();}//創(chuàng)建訂單OrderInfo orderInfo = new OrderInfo();orderInfo.setUserId(userId);orderInfo.setNickName(userInfo.getNickName());orderInfo.setPhone(userInfo.getPhone());orderInfo.setProvince(userInfo.getProvince());orderInfo.setOriginAmount(course.getPrice());orderInfo.setCouponReduce(couponReduce);orderInfo.setFinalAmount(orderInfo.getOriginAmount().subtract(orderInfo.getCouponReduce()));orderInfo.setOutTradeNo(OrderNoUtils.getOrderNo());orderInfo.setTradeBody(course.getTitle());orderInfo.setOrderStatus("0");this.save(orderInfo);OrderDetail orderDetail = new OrderDetail();orderDetail.setOrderId(orderInfo.getId());orderDetail.setUserId(userId);orderDetail.setCourseId(courseId);orderDetail.setCourseName(course.getTitle());orderDetail.setCover(course.getCover());orderDetail.setOriginAmount(course.getPrice());orderDetail.setCouponReduce(new BigDecimal(0));orderDetail.setFinalAmount(orderDetail.getOriginAmount().subtract(orderDetail.getCouponReduce()));orderDetailService.save(orderDetail);//更新優(yōu)惠券狀態(tài)if(null != orderFormVo.getCouponUseId()) {couponInfoFeignClient.updateCouponInfoUseStatus(orderFormVo.getCouponUseId(), orderInfo.getId());}return orderInfo.getId(); }到這里期內(nèi)容就結(jié)束了~
來我主頁看看下一部分把~
硅谷課堂筆記下
總結(jié)
- 上一篇: nodejs+vue+elementui
- 下一篇: 百度文库和豆丁网的在线文档阅读功能