日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Springboot简便的配置微信小程序

發(fā)布時(shí)間:2024/3/13 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Springboot简便的配置微信小程序 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Springboot簡(jiǎn)便的配置微信小程序

ShareNotes

最近在完成一個(gè)微信小程序項(xiàng)目,即將上線
歡迎star
Github–ShareNotes

issue

寫小程序接口遇到的具體情況

  • 通過openId登錄。也就是所謂的微信點(diǎn)擊直接登錄。不需要輸入賬戶密碼
  • 使用微信自帶的api過濾不合法的字符或者圖片
  • 商戶,支付接口
  • 更多issue后期遇到情況會(huì)添加

微信直接登錄

在最早的時(shí)候我?guī)瓦^朋友寫過一個(gè)花店賣花的程序。
最開始的時(shí)候大多數(shù)都是通過
微信官方文檔API
找到api。然后RestTemplate來訪問url。
RestTemplate是Spring提供的用于訪問Rest服務(wù)的客戶端。

@Autowird private RestTemplate restTemplate;WxConfig wxConfig= restTemplate.getForObject("https://api.weixin.qq.com/xxxxx/" , WxConfig.class);

十分的煩瑣

引入別人寫好的微信封裝工具類

Github-Binary Wang

開始操作

引入依賴

<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-miniapp</artifactId><version>3.3.0</version> </dependency> <!--如果不需要支付功能--> <dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-pay</artifactId><version>3.3.0</version> </dependency>

jwt的依賴

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.1</version> </dependency>

創(chuàng)建用戶表

DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(63) NOT NULL COMMENT '用戶名稱',`password` varchar(63) NOT NULL DEFAULT '' COMMENT '用戶密碼',`gender` tinyint(3) NOT NULL DEFAULT '0' COMMENT '性別:0 未知, 1男, 1 女',`birthday` date DEFAULT NULL COMMENT '生日',`last_login_time` datetime DEFAULT NULL COMMENT '最近一次登錄時(shí)間',`last_login_ip` varchar(63) NOT NULL DEFAULT '' COMMENT '最近一次登錄IP地址',`nickname` varchar(63) NOT NULL DEFAULT '' COMMENT '用戶昵稱或網(wǎng)絡(luò)名稱',`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '用戶手機(jī)號(hào)碼',`avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '用戶頭像圖片',`weixin_openid` varchar(63) NOT NULL DEFAULT '' COMMENT '微信登錄openid',`session_key` varchar(100) NOT NULL DEFAULT '' COMMENT '微信登錄會(huì)話KEY',`status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '0 可用, 1 禁用, 2 注銷',`add_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',`update_time` datetime DEFAULT NULL COMMENT '更新時(shí)間',`deleted` tinyint(1) DEFAULT '0' COMMENT '邏輯刪除',PRIMARY KEY (`id`),UNIQUE KEY `user_name` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='用戶表';

本質(zhì)是 weixin_openid,session_key。

因?yàn)榈卿洸恍枰~戶密碼。是直接登錄。所以如果第一次登錄創(chuàng)建用戶的時(shí)候username和password可以設(shè)置為 weixin_openid,或者任意值。

配置wxConfig。

如果weixin-java-miniapp依賴已經(jīng)導(dǎo)入完成就可以開始配置你的appid和appsecret,其在到微信開發(fā)者平臺(tái)里頭

在之前先配置好properties(我這里是yml格式)

wx:app-id: xxxxxapp-secret: xxxxxmch-id: xxxxxxxxmch-key: xxxxxxnotify-url: http://www.example.com/wx/order/pay-notify# 商戶證書文件路徑# 請(qǐng)參考“商戶證書”一節(jié) https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3key-path: xxxxx

獲取properties的值

@Configuration @ConfigurationProperties(prefix = "wx") public class WxProperties {private String appId;private String appSecret;private String mchId;private String mchKey;private String notifyUrl;private String keyPath;public String getNotifyUrl() {return notifyUrl;}public void setNotifyUrl(String notifyUrl) {this.notifyUrl = notifyUrl;}public String getMchKey() {return mchKey;}public void setMchKey(String mchKey) {this.mchKey = mchKey;}public String getAppId() {return this.appId;}public void setAppId(String appId) {}public String getAppSecret() {return appSecret;}}}this.keyPath = keyPath;public void setKeyPath(String keyPath) {}return keyPath;public String getKeyPath() {}this.mchId = mchId;public void setMchId(String mchId) {}return mchId;public String getMchId() {}this.appSecret = appSecret;public void setAppSecret(String appSecret) {

配置wxConfig

@Configuration public class WxConfig {@Autowiredprivate WxProperties properties;@Beanpublic WxMaConfig wxMaConfig() {WxMaInMemoryConfig config = new WxMaInMemoryConfig();config.setAppid(properties.getAppId());config.setSecret(properties.getAppSecret());return config;}@Beanpublic WxMaService wxMaService(WxMaConfig maConfig) {WxMaService service = new WxMaServiceImpl();service.setWxMaConfig(maConfig);return service;}@Beanpublic WxPayConfig wxPayConfig() {WxPayConfig payConfig = new WxPayConfig();payConfig.setAppId(properties.getAppId());payConfig.setMchId(properties.getMchId());payConfig.setMchKey(properties.getMchKey());payConfig.setNotifyUrl(properties.getNotifyUrl());payConfig.setKeyPath(properties.getKeyPath());payConfig.setTradeType("JSAPI");payConfig.setSignType("MD5");return payConfig;}@Beanpublic WxPayService wxPayService(WxPayConfig payConfig) {WxPayService wxPayService = new WxPayServiceImpl();wxPayService.setConfig(payConfig);return wxPayService;} }

所有關(guān)于微信小程序配置都在這里了。
然后我們可以使用他封裝好的wxMaService了。

生成(寫好)對(duì)應(yīng)的 實(shí)體類,mapper。

User.java

@Data public class User { private Integer id; private String username; private String password; private Byte gender; private Date birthday; private Date lastLoginTime; private String lastLoginIp; private String nickname; private String mobile; private String avatar; private String weixinOpenid; private String sessionKey; private Byte status; private Date addTime; private Date updateTime; private Boolean deleted; }

WxLoginInfo.java

public class WxLoginInfo {private String code;private UserDto userInfo;public String getCode() {return code;}public void setCode(String code) {this.code = code;}public UserDto getUserInfo() {return userInfo;}public void setUserInfo(UserDto userInfo) {this.userInfo = userInfo;} }

UserDto.java

@Data public class UserDto {private String nickName;private String avatarUrl;private String country;private String province;private String city;private String language;private Byte gender;

UserService.java
需要放這兩個(gè)方法

public interface UserService { //根據(jù)openId查詢 public User queryByOid(String openId); //加入user表 public void add(User user);

實(shí)現(xiàn)
UserServiceImpl.java

@Override public User queryByOid(String openId) { //這里用了ExampleUserExample example = new UserExample();example.or().andWeixinOpenidEqualTo(openId).andDeletedEqualTo(false);return userMapper.selectOneByExample(example); } @Override public void add(User user) {user.setAddTime(new Date());user.setUpdateTime(new Date());userMapper.insertSelective(user); }

Controller

WxAuthController.java

@Slf4j @RestController @RequestMapping("/wx/auth") @Validated public class WxAuthController {@Autowiredprivate UserService userService;//這里是之前添加依賴?yán)锩娴姆椒?#64;Autowiredprivate WxMaService wxService;@PostMapping("login_by_weixin") public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {String code = wxLoginInfo.getCode();UserDto userDto = wxLoginInfo.getUserInfo();if (code == null || userDto == null) {return ResponseUtil.badArgument();}String sessionKey = null;String openId = null;try {WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);sessionKey = result.getSessionKey();openId = result.getOpenid();} catch (Exception e) {e.printStackTrace();}if (sessionKey == null || openId == null) {return ResponseUtil.fail();}User user = userService.queryByOid(openId);if (user == null) {user = new User();user.setUsername(openId);user.setPassword(openId);user.setWeixinOpenid(openId);user.setAvatar(userDto.getAvatarUrl());user.setNickname(userDto.getNickName());user.setGender(userDto.getGender());user.setStatus((byte) 0);user.setLastLoginTime(new Date());user.setLastLoginIp(IpUtil.getIpAddr(request));user.setSessionKey(sessionKey);userService.add(user);} else {user.setLastLoginTime(new Date());user.setLastLoginIp(IpUtil.getIpAddr(request));user.setSessionKey(sessionKey);if (userService.updateById(user) == 0) {return ResponseUtil.updatedDataFailed();}}// tokenString token = UserTokenManager.generateToken(user.getId());Map<Object, Object> result = new HashMap<Object, Object>();result.put("token", token);result.put("userInfo", userDto);return ResponseUtil.ok(result); }

這里的ResponseUtil.ok(result)是我自己的返回值封裝類。
舉個(gè)例子

public static Object ok(Object data) {Map<String, Object> obj = new HashMap<String, Object>();obj.put("errno", 0);obj.put("errmsg", "成功");obj.put("data", data);return obj; }

JWT配置

接上面的 UserTokenManager
JwtHelper----> UserTokenManager

JwtHelper.java

public class JwtHelper {// 秘鑰static final String SECRET = "YOUR-SECRET-TOKEN";// 簽名是有誰生成static final String ISSUSER = "SECRET";// 簽名的主題static final String SUBJECT = "this is you token";// 簽名的觀眾static final String AUDIENCE = "MINIAPP";public String createToken(Integer userId){try {Algorithm algorithm = Algorithm.HMAC256(SECRET);Map<String, Object> map = new HashMap<String, Object>();Date nowDate = new Date();// 過期時(shí)間:7天2小時(shí)Date expireDate = getAfterDate(nowDate,0,0,7,2,0,0);map.put("alg", "HS256");map.put("typ", "JWT");String token = JWT.create()// 設(shè)置頭部信息 Header.withHeader(map)// 設(shè)置 載荷 Payload.withClaim("userId", userId).withIssuer(ISSUSER).withSubject(SUBJECT).withAudience(AUDIENCE)// 生成簽名的時(shí)間 .withIssuedAt(nowDate)// 簽名過期的時(shí)間 .withExpiresAt(expireDate)// 簽名 Signature.sign(algorithm);return token;} catch (JWTCreationException exception){exception.printStackTrace();}return null;}public Integer verifyTokenAndGetUserId(String token) {try {Algorithm algorithm = Algorithm.HMAC256(SECRET);JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSUSER).build();DecodedJWT jwt = verifier.verify(token);Map<String, Claim> claims = jwt.getClaims();Claim claim = claims.get("userId");return claim.asInt();} catch (JWTVerificationException exception){ // exception.printStackTrace();} return 0;}public Date getAfterDate(Date date, int year, int month, int day, int hour, int minute, int second){if(date == null){date = new Date();} Calendar cal = new GregorianCalendar(); cal.setTime(date);if(year != 0){cal.add(Calendar.YEAR, year);}if(month != 0){cal.add(Calendar.MONTH, month);}if(day != 0){cal.add(Calendar.DATE, day);}if(hour != 0){cal.add(Calendar.HOUR_OF_DAY, hour);}if(minute != 0){cal.add(Calendar.MINUTE, minute);}if(second != 0){cal.add(Calendar.SECOND, second);}return cal.getTime();} }

UserTokenManager.java

public static String generateToken(Integer id) {JwtHelper jwtHelper = new JwtHelper();return jwtHelper.createToken(id); } public static Integer getUserId(String token) {JwtHelper jwtHelper = new JwtHelper();Integer userId = jwtHelper.verifyTokenAndGetUserId(token);if(userId == null || userId == 0){return null;}return userId; }

小程序前端

user.js

function loginByWeixin(userInfo) {return new Promise(function (resolve, reject) {return login().then((res) => {//這里的api.AuthLoginByWeixin 為 localhost:8080/wx/auth/login_by_weixinutil.request(api.AuthLoginByWeixin, {code: res.code,userInfo: userInfo}, 'POST').then(res => {if (res.errno === 0) {//存儲(chǔ)用戶信息wx.setStorageSync('userInfo', res.data.userInfo);wx.setStorageSync('token', res.data.token);resolve(res);} else {reject(res);}}).catch((err) => {reject(err);});}).catch((err) => {reject(err);})}); }

utils.js

function request(url, data = {}, method = "GET") {return new Promise(function (resolve, reject) {wx.request({url: url,data: data,method: method,header: {'Content-Type': 'application/json', //剛剛你設(shè)置的token'YOUR-SECRET-TOKEN': wx.getStorageSync('token')},success: function (res) {if (res.statusCode == 200) {if (res.data.errno == 501) {// 清除登錄相關(guān)內(nèi)容try {wx.removeStorageSync('userInfo');wx.removeStorageSync('token');} catch (e) {// Do something when catch error}// 切換到登錄頁面wx.navigateTo({url: '/pages/ucenter/index/index'});} else {resolve(res.data);}} else {reject(res.errMsg);}},fail: function (err) {reject(err)}})}); }

小程序頁面js的使用

user.loginByWeixin(e.detail.userInfo).then(res => {app.globalData.hasLogin = true;this.onShow(); }).catch((err) => {app.globalData.hasLogin = false;util.showErrorToast('微信登錄失敗'); });

關(guān)于登錄就到這里了。可以打開我的GitHub源碼其分別對(duì)應(yīng)

Github–ShareNotes

  • 實(shí)體類和mapper還有sql
    share-Notes-db----->sql文件夾
    share-Notes-db----->src–>main–>java–>cn.sharenotes.db---->domain/mapper/model

  • wxconfig配置
    share-Notes-core----->src–>main–>java–>cn.sharenotes.core---->config
    share-Notes-core----->src–>main–>java–>cn.sharenotes.core---->utils
    share-Notes-core----->src–>main–>resources---->wxconfig.properties(我這里不是yml)

  • controller使用

share-Notes-wx-api----->src–>main–>java–>cn.sharenotes.wxapi---->web
share-Notes-wx-api----->src–>main–>java–>cn.sharenotes.wxapi---->service

  • 微信小程序
    shareNotes---->config—>api.js 地址配置
    shareNotes---->utils—>user.js /utils工具類
    shareNotes---->page---->uncenter---->index—>index.js 登錄js

用binarywang的工具類使用過濾

我們回到wxconfig中

重新添加上wxmaSecCheckService

@Slf4j @Configuration @PropertySource(value = "classpath:wxconf.properties") public class WxConfig {@Value("${APP_ID}")private String appId;@Value("${APP_SERCET}")private String appSecret;@Beanpublic WxMaConfig wxMaConfig() {WxMaInMemoryConfig config = new WxMaInMemoryConfig();config.setAppid(appId);config.setSecret(appSecret);log.info("id"+appId);log.info("key"+appSecret);return config;}@Beanpublic WxMaService wxMaService(WxMaConfig maConfig) {WxMaService service = new WxMaServiceImpl();service.setWxMaConfig(maConfig);return service;}@Beanpublic WxMaSecCheckService wxMaSecCheckService(){WxMaSecCheckService wxMaSecCheckService = new WxMaSecCheckServiceImpl(wxMaService(wxMaConfig()));return wxMaSecCheckService;}@Beanpublic WxPayConfig wxPayConfig() {WxPayConfig payConfig = new WxPayConfig();payConfig.setAppId(appId);payConfig.setTradeType("JSAPI");payConfig.setSignType("MD5");return payConfig;}@Beanpublic WxPayService wxPayService(WxPayConfig payConfig) {WxPayService wxPayService = new WxPayServiceImpl();wxPayService.setConfig(payConfig);return wxPayService;} }

使用

文字過濾

@Autowiredprivate WxMaSecCheckService wxMaSecCheckService;if(!wxMaSecCheckService.checkMessage(JacksonUtil.parseString(body, "name"))){ResponseUtil.fail(500,"違法違規(guī)標(biāo)題");}

圖片

wxMaSecCheckService.checkImage(f)

他的方法都是返回布爾值。

分析原理

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.imgSecCheck.html

這里的本質(zhì)是使用微信開發(fā)文檔中的api

POST https://api.weixin.qq.com/wxa/img_sec_check?access_token=ACCESS_TOKEN

通過post請(qǐng)求這段api返回是否是內(nèi)容安全。

官方文檔很詳細(xì)了。返回errcode和errMsg
通過為0失敗為87014
Post的body中放圖片。
不過我們看一下整句api,后面有一個(gè)accessToken。
這個(gè)accesstoken怎么獲取呢。
回到官方文檔

獲取小程序全局唯一后臺(tái)接口調(diào)用憑據(jù)(access_token)。調(diào)調(diào)用絕大多數(shù)后臺(tái)接口時(shí)都需使用 access_token,開發(fā)者需要進(jìn)行妥善保存。

api為

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

這里需要我們的appid和appsecret。
請(qǐng)求后可以過去accesstoken。但是請(qǐng)求的token只會(huì)支持2個(gè)小時(shí),后他將重新生成。2個(gè)小時(shí)后得再次請(qǐng)求。

tips

微信官方api中關(guān)于服務(wù)端的有趣api很多,可以查閱。雖然有請(qǐng)求次數(shù)限制。但是已經(jīng)足夠了

總結(jié)

以上是生活随笔為你收集整理的Springboot简便的配置微信小程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。