前言:
最近在研究一个功能,在系统中绑定用户微信号,绑定好用户账号后,用户就可以直接扫码进入系统。讲到这里先来看一个下面这个完整的项目例子。
例子:
在系统当中的业务逻辑是这样的。
- 第一步,用户点击绑定微信,生成一个二维码。
- 第二步,用户扫完二维码后出现关注公众号的页面。
- 第三步,用户关注该公众号出现微信扫码的界面
- 第四步,用户扫完这个微信后,弹出获取微信用户信息的框。用户同意以后即可绑定成功,下次就可用微信扫码登录系统。
- 第五步,绑定成功。
业务介绍:
上面是一个完整的项目例子,但是我这边博客我会将这个功能拆分开。
一个是生成公众号的二维码 强制用户关注该公众号,关注公众号以后,就可以让用户扫描一个生成好的微信二维码,用户扫完码以后,我们可以拿到用户的昵称以及用户唯一的openId ,将取到的这俩个参数保存到数据库中,这样在登录界面的时候,我们可以与已有的用户账号关联上,当然如果该用户没有系统账号,他也可以扫描二维码,我们可以让他以一个游客身份登录,或者扫完码以后 提示他注册账号或者绑定已有账号。
1.这篇文章先给大家演示一下如何生成一个公众号的二维码。
2.下篇文章我将给大家介绍一下微信的扫码功能。
开发步骤:
步骤1:
首先我们需要生成一个带参数的二维码,关于二维码有2种,一种是临时二维码,一种是永久二维码。
- 1.临时二维码:有过期时间,最长可以设置为在二维码生成的30天(即2592000秒)后过期,生成较多数量。临时二维码主要用于帐 号绑定等不要求二维码永久保存的业务场景。
- 2.永久二维码:是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。
获取带参数的二维码的过程包括两步:
- 1.首先创建二维码ticket。
- 2.然后凭借ticket到指定URL换取二维码。
步骤2:
1. 首先创建二维码Ticket 以下是请求地址和参数。
2.通过Ticket换取二维码,以下是请求地址和请求参数内容
WechatController
@ApiOperation(value = "1.8 绑定微信账号")
@GetMapping(value = "/bindWechatAccount")
public ResultData bindWechatAccount() {
return weiService.bindWechatAccount();
}
WeiService
@Override
public ResultData bindWechatAccount() {
ResultData resultData = new ResultData();
try {
//第一步:向微信公众平台发送请求,获取Ticket
String accessToken = WeiXinParamesUtil.getAccessToken2("weixin");
String createQrCodeUrl = WeiXinParamesUtil.createQrCodeUrl;
createQrCodeUrl = createQrCodeUrl.replace("TOKEN", accessToken);
//传入参数。
String postParam = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": 123}}}";
//发送请求 获取Ticket
JSONObject jsonObject = SendRequest.sendPost(createQrCodeUrl, postParam);
System.out.println("111----" + jsonObject);
String ticket = jsonObject.getString("ticket");
// url : 二维码图片解析后的地址,开发者可根据该地址自行生成需要的二维码图片
String url = jsonObject.getString("url");
//第二步: 通过Ticket换取二维码。
String getWehatCodeUrl = WeiXinParamesUtil.getWeiQrCodeUrl;
getWehatCodeUrl = getWehatCodeUrl.replace("TICKET", ticket);
resultData.setResult("true");
resultData.setMessage("返回微信公众号二维码成功");
//返回生成的二维码图片
System.out.println("111----"+getWehatCodeUrl);
resultData.setStr(getWehatCodeUrl);
} catch (Exception e) {
resultData.setResult("false");
resultData.setMessage("返回微信公众号二维码失败");
logger.error("返回微信公众号二维码失败", e);
}
return resultData;
}
WeiXinParamesUtil
当前这个类属于微信公众平台的参数配置类,其中有很多参数是我当前这篇文章不需要的,可以自行删除。
package com.bos.util;
import com.alibaba.fastjson.JSONObject;
import com.bos.common.CommenUtil;
import com.bos.data.model.WeiUserInfoModel;
import com.bos.qiWechat.AesException;
import com.bos.qiWechat.WXBizMsgCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 微信公众平台的参数
* @param
* @return
*/
public class WeiXinParamesUtil {
private Logger logger = LoggerFactory.getLogger(WeiXinParamesUtil.class);
/**
* 获取微信公众平台accessToken
* @param
* @return
*/
public static String getWeiAccessToken ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
public static String getUserInfoList = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
public static String getUserList = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
public static String updateUserRemark = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=ACCESS_TOKEN";
public static String open_access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";
/**
* 客户接口发送消息
* @param
* @return
*/
public static String sendCustomerMsgUrl="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";
/**
* 上传临时文件素材到微信服务器上
* @param
* @return
*/
public static String uploadMaterialToWeiUrl="https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
/**
* 从微信服务器上下载临时文件素材
* @param
* @return
*/
public static String downloadMaterialFromWeiUrl="https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";
/**
* 获取access_token的接口地址(GET) 限200(次/天)
* @param
* @return
*/
public static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}";
public static String open_id = "gh_b920df4d06d0";
/**
* 微信扫码之后获取用户基本信息的地址
* @param
* @return
*/
public static String getuserinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
/**
* 发送消息给微信公众平台的url
* @param
* @return
*/
public static String sendMessageToWei_url="https://api.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";
/**
* 获取微信公众平台Ticket
*/
public static String createQrCodeUrl="https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
/**
* 生成推广的二维码
*/
public static String getWeiQrCodeUrl="https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
/**
* 生成小程序的二维码
*/
public static String CREATE_APPLET_CODE = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN";
/**
* 通过code 获取 access_token
*/
public static String GET_ACCESSTOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";
/**
* 检验AccessToken是否有效
*/
public static String CHECK_OUT_ACCESSTOKEN = "https://api.weixin.qq.com/sns/auth?access_token={access_token}&openid={open_id}";
/**
* 微信开放平台获取用户信息
*/
public static String GET_SNS_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={open_id}";
/**
* 刷新AccessToken
*/
public static String REFRESH_TOKEN = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={appid}&grant_type={refresh_token}&refresh_token={refresh_token}";
//------------微信公众平台的参数
/**
* appId
* @param
* @return
*/
public static String APPID;
/**
* secret
* @param
* @return
*/
public static String SECRET;
//----------------微信开放平台的参数
/**
* openAppid
* @param
* @return
*/
public static String OPENAPPID;
/**
* appSecret
* @param
* @return
*/
public static String OPENSECRET;
/**
* 回调地址 redirect_uri
* @param
* @return
*/
public static String REDIRECT_URI;
/**
* scope
* @param
* @return
*/
public static String SCOPE;
/**
* 模板id
* @param
* @return
*/
public static String TEMPLATEID;
public static String TOKEN="weixinEbo";
public static String ENCODEING_AES_KEY="MUPgLCxZND6ER0wON5FhdfGLtzzbOI7O5P23B2EWFrM";
/**
* 微信加密签名
*/
private String msg_signature;
/**
* 时间戳
*/
private String timestamp;
/**
* 随机数
*/
private String nonce;
static {
APPID = "替换成你的APPid";
SECRET = "替换成你的Secret";
SCOPE = "snsapi_userinfo";
REDIRECT_URI = "snsapi_userinfo";
TEMPLATEID = "********";
OPENAPPID="************";
OPENSECRET="**************";
}
}
/**
* 获取微信公众平台的access_token
* @param type
* @return
*/
public static String getAccessToken2(String type) {
String url = "";
if ("weixin".equals(type)) {
url = getWeiAccessToken.replace("APPID", WeiXinParamesUtil.APPID).replace("APPSECRET", WeiXinParamesUtil.SECRET);
}
JSONObject departmentJson = SendRequest.sendGet2(url);
return departmentJson.getString("access_token");
}
}
SendRequest
// 发送post请求(返回json)
public static JSONObject sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
JSONObject jsonObject = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// conn.addRequestProperty("Cookie", "stay_login=1 smid=DumpWzWQSaLmKlFY1PgAtURdV_u3W3beoei96zsXkdSABwjVCRrnnNBsnH1wGWI0-VIflgvMaZAfli9H2NGtJg id=EtEWf1XZRLIwk1770NZN047804");//设置获取的cookie
// 获取URLConnection对象对应的输出流(设置请求编码为UTF-8)
out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 获取请求返回数据(设置返回数据编码为UTF-8)
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
jsonObject = JSONObject.parseObject(result);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return jsonObject;
}
package com.bos.common;
import com.bos.data.model.TShowColumnModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
import java.util.Map;
/**
* @author tanghh
*/
public class ResultData {
/**
* "true" or "false"
*/
@ApiModelProperty(value = "后台返回的查询结果,true=查询成功,false=查询失败")
private String result;
/**
* 消息提示
*/
@ApiModelProperty(value = "后台返回的消息,如'保存成功'。用作前端的提示消息")
private String message;
/**
* 消息提示
*/
@ApiModelProperty(value = "一个字符串")
private String str;
/**
* 存放一个实体
*/
private Object object;
/**
* 主数据集合
*/
private PageData pageData;
/**
*其他数据
*/
private List<Map> otherData;
/**
*整形
*/
private Integer number;
/**
*存放list集合的map
*/
private Map<String, List> mapList;
/**
*
*/
private Map<Object, Object> map;
/**
*存放一个list集合
*/
private List list;
/**
*专用于存放表头字段的集合
*/
private List fieldList;
/**
*专用于存放视图集合
*/
private List viewList;
/**
*专用于存放报表集合
*/
private List reportList;
/**
* 专用于存每个页面的page
* @param
* @return
*/
private String page;
/**
* 专用于存不同页面的module
* @param
* @return
*/
private String module;
/**
* 存储当前数据的上一级数据(第一级)
* @param
* @return
*/
private String level1;
/**
* 存储当前数据的上一级的上一级数据(第二级)
* @param
* @return
*/
private String level2;
/**
* 存储当前数据的上一级的上一级的上一级数据(第三级)
* @param
* @return
*/
private String level3;
/**
* map2
*/
private Map<Object, Object> map2;
private Map<String,List<TShowColumnModel>> mapCloumnList;
public List getReportList() {
return reportList;
}
public void setReportList(List reportList) {
this.reportList = reportList;
}
public List getViewList() {
return viewList;
}
public void setViewList(List viewList) {
this.viewList = viewList;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public Map<String, List<TShowColumnModel>> getMapCloumnList() {
return mapCloumnList;
}
public void setMapCloumnList(Map<String, List<TShowColumnModel>> mapCloumnList) {
this.mapCloumnList = mapCloumnList;
}
public ResultData() {
this.message = "查询成功";
this.result = "true";
}
/**
* 用于删除成功
* @param count
*/
public ResultData(int count) {
if(count>0){
this.message = "删除成功";
this.result = "true";
}else {
this.message = "删除失败";
this.result = "false";
}
}
public ResultData(Object object) {
this.object=object;
this.message = "查询成功";
this.result = "true";
}
/**
* 用于添加删除提示
* @param type
* @param flag
*/
public ResultData(String type,boolean flag) {
if(flag==false){
//保存和修改时候的提示
if(Constant.SAVE.equals(type)){
this.message = "保存失败";
}else{
this.message = "删除失败";
}
this.result = "false";
}else {
if(Constant.SAVE.equals(type)){
this.message = "保存成功";
}else{
this.message = "删除成功";
}
this.result = "true";
}
}
public ResultData(String result, String message, PageData pageData) {
this.result = result;
this.message = message;
this.pageData = pageData;
}
public ResultData(String result, String message, PageData pageData, List<Map> otherData) {
this.result = result;
this.message = message;
this.pageData = pageData;
this.otherData = otherData;
}
public ResultData(String result, String message, PageData pageData, List<Map> otherData, Map<String, List> mapList) {
this.result = result;
this.message = message;
this.pageData = pageData;
this.otherData = otherData;
this.mapList = mapList;
}
public ResultData(String result, String message) {
this.result = result;
this.message = message;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public PageData getPageData() {
return pageData;
}
public void setPageData(PageData pageData) {
this.pageData = pageData;
}
public List<Map> getOtherData() {
return otherData;
}
public void setOtherData(List<Map> otherData) {
this.otherData = otherData;
}
public Map<String, List> getMapList() {
return mapList;
}
public void setMapList(Map<String, List> mapList) {
this.mapList = mapList;
}
public Map<Object, Object> getMap() {
return map;
}
public void setMap(Map<Object, Object> map) {
this.map = map;
}
public List getFieldList() {
return fieldList;
}
public void setFieldList(List fieldList) {
this.fieldList = fieldList;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public String getModule() {
return module;
}
public void setModule(String module) {
this.module = module;
}
public String getLevel1() {
return level1;
}
public void setLevel1(String level1) {
this.level1 = level1;
}
public String getLevel2() {
return level2;
}
public void setLevel2(String level2) {
this.level2 = level2;
}
public String getLevel3() {
return level3;
}
public void setLevel3(String level3) {
this.level3 = level3;
}
public Map<Object, Object> getMap2() {
return map2;
}
public void setMap2(Map<Object, Object> map2) {
this.map2 = map2;
}
}
ResultData
步骤3:
访问这个接口,http://localhost:8088/bindWechatAccount
getWehatCodeUrl 为一个url ,这个url可以直接在网页上展示也可以下载下来。我这里的话先在网页上访问一下。
将上面这个url 复制到 浏览器上,扫描这个二维码。
步骤4:
扫描上图中的公众号二维码 关注公众号。
到此,本篇文章就写完啦 ,如果觉得小编写的不错的话,不妨给小编一个赞吧,如果有什么问题的话,欢迎评论区留言。一起加油。