E企盈营销工具技术服务商 热线:4006-838-530

Spr阳曲县E企盈小程序ingboot简便的配置微信小程序

Springboot简便的配置微信小程序ShareNotes最近在完成一个微信小程序项目,即将上线欢迎starGithub–ShareNotesissue写小程序接口遇到的具体情况通过openId登录。也就是所谓的微信点击直接登录。不需要输入账户密码使用微信自带的api过滤不合法的字符或者图片商户,支付接口更多issue后期遇到情况会添加微信直接登录在最早的时候我帮过朋友写过一个花店卖花的程序。最开始的时候大多数都是通过微信官方文档API找到api。然后RestTemplate来访问url。RestTemplate是Spring提供的用于访问Rest服务的客户端。@Autowirdprivate RestTemplate restTemplate;WxConfig wxConfig= restTemplate.getForObject("https://api.weixin.qq.com/xxxxx/" , WxConfig.class);

十分的烦琐引入别人写好的微信封装工具类Github-Binary Wang开始操作引入依赖dependency    groupIdcom.github.binarywang/groupId    artifactIdweixin-java-miniapp/artifactId    version3.3.0/version/dependency!--如果不需要支付功能--dependency    groupIdcom.github.binarywang/groupId    artifactIdweixin-java-pay/artifactId    version3.3.0/version/dependency

jwt的依赖dependency    groupIdcom.auth0/groupId    artifactIdjava-jwt/artifactId    version3.4.1/version/dependency

创建用户表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 '最近一次登录时间',  `last_login_ip` varchar(63) NOT NULL DEFAULT '' COMMENT '最近一次登录IP地址',  `nickname` varchar(63) NOT NULL DEFAULT '' COMMENT '用户昵称或网络名称',  `mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '用户手机号码',  `avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '用户头像图片',  `weixin_openid` varchar(63) NOT NULL DEFAULT '' COMMENT '微信登录openid',  `session_key` varchar(100) NOT NULL DEFAULT '' COMMENT '微信登录会话KEY',  `status` tinyint(3) NOT NULL DEFAULT '0' COMMENT '0 可用, 1 禁用, 2 注销',  `add_time` datetime DEFAULT NULL COMMENT '创建时间',  `update_time` datetime DEFAULT NULL COMMENT '更新时间',  `deleted` tinyint(1) DEFAULT '0' COMMENT '逻辑删除',  PRIMARY KEY (`id`),  UNIQUE KEY `user_name` (`username`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

本质是 weixin_openid,session_key。因为登录不需要账户密码。是直接登录。所以如果第一次登录创建用户的时候username和password可以设置为 weixin_openid,或者任意值。配置wxConfig。如果weixin-java-miniapp依赖已经导入完成就可以开始配置你的appid和appsecret,其在到微信开发者平台里头在之前先配置好properties(我这里是yml格式)wx:  app-id: xxxxx  app-secret: xxxxx  mch-id: xxxxxxxx  mch-key: xxxxxx  notify-url: http://www.example.com/wx/order/pay-notify  # 商户证书文件路径  # 请参考“商户证书”一节 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3  key-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@Configurationpublic class WxConfig {    @Autowired    private WxProperties properties;    @Bean    public WxMaConfig wxMaConfig() {        WxMaInMemoryConfig config = new WxMaInMemoryConfig();        config.setAppid(properties.getAppId());        config.setSecret(properties.getAppSecret());        return config;    }    @Bean    public WxMaService wxMaService(WxMaConfig maConfig) {        WxMaService service = new WxMaServiceImpl();        service.setWxMaConfig(maConfig);        return service;    }    @Bean    public 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;    }    @Bean    public WxPayService wxPayService(WxPayConfig payConfig) {        WxPayService wxPayService = new WxPayServiceImpl();        wxPayService.setConfig(payConfig);        return wxPayService;    }}

所有关于微信小程序配置都在这里了。然后我们可以使用他封装好的wxMaService了。生成(写好)对应的 实体类,mapper。User.java@Datapublic 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.javapublic 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@Datapublic 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需要放这两个方法public interface UserService {//根据openId查询public User queryByOid(String openId);//加入user表public void add(User user);

实现UserServiceImpl.java@Overridepublic User queryByOid(String openId) {//这里用了Example    UserExample example = new UserExample();    example.or().andWeixinOpenidEqualTo(openId).andDeletedEqualTo(false);    return userMapper.selectOneByExample(example);}@Overridepublic void add(User user) {    user.setAddTime(new Date());    user.setUpdateTime(new Date());    userMapper.insertSelective(user);}

ControllerWxAuthController.java@Slf4j@RestController@RequestMapping("/wx/auth")@Valid开通电商培训小程序电话:4006-838-530atedpublic class WxAuthController {    @Autowired    private UserService userService;//这里是之前添加依赖里面的方法    @Autowired    private 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();        }    }    // token    String token = UserTokenManager.generateToken(user.getId());    MapObject, Object result = new HashMapObject, Object();    result.put("token", token);    result.put("userInfo", userDto);    return ResponseUtil.ok(result);}

这里的ResponseUtil.ok(result)是我自己的返回值封装类。举个例子public static Object ok(Object data) {    MapString, Object obj = new HashMapString, Object();    obj.put("errno", 0);    obj.put("errmsg", "成功");    obj.put("data", data);    return obj;}

JWT配置接上面的 UserTokenManagerJwtHelper—- UserTokenManagerJwtHelper.javapublic 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);          MapString, Object map = new HashMapString, Object();          Date nowDate = new Date();          // 过期时间:7天2小时          Date expireDate = getAfterDate(nowDate,0,0,7,2,0,0);           map.put("alg", "HS256");           map.put("typ", "JWT");          String token = JWT.create()             // 设置头部信息 Header             .withHeader(map)             // 设置 载荷 Payload             .withClaim("userId", userId)              .withIssuer(ISSUSER)              .withSubject(SUBJECT)              .withAudience(AUDIENCE)              // 生成签名的时间               .withIssuedAt(nowDate)              // 签名过期的时间               .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);          MapString, 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.javapublic 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.jsfunction loginByWeixin(userInfo) {  return new Promise(function (resolve, reject) {    return login().then((res) = {      //这里的api.AuthLoginByWeixin 为 localhost:8080/wx/auth/login_by_weixin      util.request(api.AuthLoginByWeixin, {        code: res.code,        userInfo: userInfo      }, 'POST').then(res = {        if (res.errno === 0) {          //存储用户信息          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.jsfunction request(url, data = {}, method = "GET") {  return new Promise(function (resolve, reject) {    wx.request({      url: url,      data: data,      method: method,      header: {        'Content-Type': 'application/json',//刚刚你设置的token        'YOUR-SECRET-TOKEN': wx.getStorageSync('token')      },      success: function (res) {        if (res.statusCode == 200) {          if (res.data.errno == 501) {            // 清除登录相关内容            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('微信登录失败');});

关于登录就到这里了。可以打开我的GitHub源码其分别对应Github–ShareNotes实体类和mapper还有sqlshare-Notes-db—–sql文件夹share-Notes-db—–src–main–java–cn.sharenotes.db—-domain/mapper/modelwxconfig配置share-Notes-core—–src–main–java–cn.sharenotes.core—-configshare-Notes-core—–src–main–java–cn.sharenotes.core—-utilsshare-Notes-core—–src–main–resources—-wxconfig.properties(我这里不是yml)controller使用share-Notes-wx-api—–src–main–java–cn.sharenotes.wxapi—-webshare-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;    @Bean    public WxMaConfig wxMaConfig() {        WxMaInMemoryConfig config = new WxMaInMemoryConfig();        config.setAppid(appId);        config.setSecret(appSecret);        log.info("id"+appId);        log.info("key"+appSecret);        return config;    }    @Bean    public WxMaService wxMaService(WxMaConfig maConfig) {        WxMaService service = new WxMaServiceImpl();        service.setWxMaConfig(maConfig);        return service;    }    @Bean    public WxMaSecCheckService  wxMaSecCheckService(){        WxMaSecCheckService wxMaSecCheckService = new WxMaSecCheckServiceImpl(wxMaService(wxMaConfig()));        return wxMaSecCheckService;    }    @Bean    public开通渔夫帽小程序电话:4006-838-530 WxPayConfig wxPayConfig() {        WxPayConfig payConfig = new WxPayConfig();        payConfig.setAppId(appId);        payConfig.setTradeType("JSAPI");        payConfig.setSignType("MD5");        return payConfig;    }    @Bean开通海报定制小程序电话:4006-838-530    public WxPayService wxPayService(WxPayConfig payConfig) {        WxPayService wxPayService = new WxPayServiceImpl();        wxPayService.setConfig(payConfig);        return wxPayService;    }}

使用文字过滤  @Autowired    private WxMaSecCheckService wxMaSecCheckService;if(!wxMaSecCheckService.checkMessage(JacksonUtil.parseString(body, "name"))){            ResponseUtil.fail(500,"违法违规标题");        }

图片wxMaSecCheckService.checkImage(f)

他的方法都是返回布尔值。分析原理https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/sec-check/security.imgSecCheck.html

这里的本质是使用微信开发文档中的apiPOST https://api.weixin.qq.com/wxa/img_sec_check?access_token=ACCESS_TOKEN

通过post请求这段api返回是否是内容安全。官方文档很详细了。返回errcode和errMsg通过为0失败为87014Post的body中放图片。不过我们看一下整句api,后面有一个accessToken。这个accesstoken怎么获取呢。回到官方文档获取小程序全局唯一后台接口调用凭据(access_token)。调调用绝大多数后台接口时都需使用 access_token,开发者需要进行妥善保存。api为GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

这里需要我们的appid和appsecret。请求后可以过去accesstoken。但是请求的token只会支持2个小时,后他将重新生成。2个小时后得再次请求。tips微信官方api中关于服务端的有趣api很多,可以查阅。虽然有请求次数限制。但是已经足够了

赞(0) 打赏
未经允许不得转载:E企盈小程序开发-热线:4006-838-530 » Spr阳曲县E企盈小程序ingboot简便的配置微信小程序
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

模王系统开发

联系我们升级日志

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏