一、第一步,先获取openId
先上前端代码,刷新页面即可获取到openid,点击头像获取到微信用户个人信息
app.js页面
// app.js
App({
onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
if (res.code) {
console.log("code==" + res.code);
wx.request({
url: 'http://127.0.0.1:9090/api/wechatlogin.do', //这里是我本地的url
method: 'POST',
data: {
code: res.code
},
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success(res) {
//访问成功即可成功打印openid等信息
console.log("res.data:" + JSON.stringify(res.data));
if (res.data.openid != "" || res.data.openid != null) {
// 登录成功
wx.setStorageSync("openid", res.data.openid);//将用户id保存到缓存中
wx.setStorageSync("session_key", res.data.session_key);//将session_key保存到缓存中
} else {
// 登录失败
// TODO 跳转到错误页面,要求用户重试
console.log("登录失败,请重新登录");
return false;
}
}
})
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
})
},
globalData: {
userInfo: null
}
})
app.json
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
index.js 需要修改的是tmplIds的内容,改成自己的
// index.js
// 获取应用实例
const app = getApp()
Page({
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
canIUseGetUserProfile: false,
canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false
},
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad() {
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: false
})
}
},
getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log("eeee==============" + JSON.stringify(e.detail.encryptedData))
console.log("res==" + JSON.stringify(res))
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
getUserInfo(e) {
// 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
console.log(e)
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
getPhoneNumber (e) {
console.log(e.detail.errMsg)
console.log(e.detail.iv)
console.log(e.detail.encryptedData)
},
setPhoto:function(){
wx.requestSubscribeMessage({
tmplIds: ['5aoiQO173x-B1RyN8d0d4lpgNtOl_qms4d8d'],
success (res) {
console.log(res);
},
fail (fail) {
console.log(fail);
}
})
},
sendMsg:function(e){
wx.requestSubscribeMessage({
tmplIds: ['oY-JaD0ACkSRFoi86MANqMBVZvHSXONLMyPNiwpIQFM'],
success(res){
console.log("方法是否调用成功!" + JSON.stringify(res));
}
})
}
})
index.wxml
想着获取手机号,暂时还没能实现
<!--index.wxml-->
<view class="container">
<view class="userinfo">
<block wx:if="{{canIUseOpenData}}" calss="userinfo-opendata">
<view class="userinfo-avatar" bindtap="getUserProfile">
<open-data type="userAvatarUrl"></open-data>
</view>
<open-data type="userNickName"></open-data>
</block>
<block wx:elif="{{!hasUserInfo}}">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
<button wx:elif="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
<view wx:else> 请使用1.4.4及以上版本基础库 </view>
</block>
<block wx:else>
<image bindtap="getUserProfile" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
<button type="default" bindtap="sendMsg">点击订阅消息</button>
</view>
前端效果图
好了,前端代码已经上传完成,前端代码只是获取个人头像微信名等信息、点击订阅的例子,只能作为参考测试功能使用
二、该是java后端代码了,用的是springboot
先获取openid,本来项目上用的是分层,想着上传起来太麻烦了,自己看着迷糊,读者也容易迷糊,就合到一起吧,可以down下来自行拆解
WechatController.java
package com.bots.mcst.wechat.web;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.bots.mcst.wechat.entity.OpenIdJson;
import com.bots.mcst.wechat.entity.WechatUserInfo;
import com.bots.mcst.wechat.exception.NotEmptyStyle;
import com.bots.mcst.wechat.service.WechatUserInfoService;
import com.fasterxml.jackson.databind.ObjectMapper;
@RestController
@RequestMapping("api")
public class WechatController {
@SuppressWarnings({"unchecked"})
@PostMapping("wechatlogin.do")
public Map wechatlogin(@RequestParam("code") String code) throws Exception {
Map<String, Object> context = new HashMap<>();
String appID = ""; //自己小程序的appid
String appSecret = ""; //自己小程序的秘钥,可以在自己的微信小程序官网查看
String result = "";
try {
result = HttpUtil.doGet("https://api.weixin.qq.com/sns/jscode2session?
appid="+ appID + "&secret="+ appSecret +
"&js_code=" + code +
"&grant_type=authorization_code",null);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("result==" + result);
ObjectMapper mapper = new ObjectMapper();
OpenIdJson openIdJson = mapper.readValue(result,OpenIdJson.class);
context.put("result", openIdJson);
return context;
}
HttpUtil.java直接复制
package com.bots.mcst.wechat.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.http.HttpStatus;
public class HttpUtil {
public static String doGet(String urlPath, HashMap<String, Object> params) throws Exception {
StringBuilder sb = new StringBuilder(urlPath);
if (params != null && !params.isEmpty()) { // 说明有参数
sb.append("?");
Set<Entry<String, Object>> set = params.entrySet();
for (Entry<String, Object> entry : set) { // 遍历map里面的参数
String key = entry.getKey();
String value = "";
if (null != entry.getValue()) {
value = entry.getValue().toString();
// 转码
value = URLEncoder.encode(value, "UTF-8");
}
sb.append(key).append("=").append(value).append("&");
}
sb.deleteCharAt(sb.length() - 1); // 删除最后一个&
}
// System.out.println(sb.toString());
URL url = new URL(sb.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(10000); // 5s超时
conn.setRequestMethod("GET");
if (conn.getResponseCode() == HttpStatus.SC_OK) {// HttpStatus.SC_OK ==
// 200
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sbs = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sbs.append(line);
}
return sbs.toString();
}
return null;
}
}
OpenIdJson.java实体类
package com.bots.mcst.wechat.entity;
/*
* OpenIdJson实体类
* wlw 20210707
*/
public class OpenIdJson {
private String openid;
private String session_key;
private String access_token;
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getSession_key() {
return session_key;
}
public void setSession_key(String session_key) {
this.session_key = session_key;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
}
以上是获取openid的全部代码
下面是发送订阅消息的功能
WechatSendController.java
此处需要修改的是openId,改成前端页面获取到的,下面的是我自己的,templateId需要写自己的模板id,APPID和APPSECRET对应自己的小程序,thing1和thing2对应模板给的参数,根据模板进行修改
package com.bots.mcst.wechat.web;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bots.mcst.wechat.entity.TemplateData;
import com.bots.mcst.wechat.entity.WeChatBean;
import com.bots.mcst.wechat.entity.WxMssVo;
import com.bots.mcst.wechat.service.WechatSendService;
@RestController
@RequestMapping("api")
public class WechatSendController {
@GetMapping("pushNotification.do")
public String pushNotification() {
String openId = "ob6Di4o11gmAp3fnH49sgYGWFE_0";
//String push = wechatSendService.wechatAppletSend(openId);
return wechatAppletSend(openId);
}
public String wechatAppletSend(String openId) {
RestTemplate restTemplate = new RestTemplate();
//这里简单起见我们每次都获取最新的access_token(时间开发中,应该在access_token快过期时再重新获取)
String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + getAccessToken();
System.out.println("");
//拼接推送的模版
String templateId = ""; //添加自己微信小程序官网的订阅消息模板id
WxMssVo wxMssVo = new WxMssVo();
wxMssVo.setTouser(openId);//用户的openId(要发送给那个用户,通常这里应该动态传进来的)
wxMssVo.setTemplate_id(templateId );//订阅消息模板id
wxMssVo.setPage("https://blog.youkuaiyun.com/weixin_42460570/article/details/103347322");
Map<String, TemplateData> m = new HashMap<>(3);
m.put("thing1", new TemplateData("个人小程序推送"));
m.put("thing2", new TemplateData("收到奖品请查收"));
wxMssVo.setData(m);
ResponseEntity<String> responseEntity =
restTemplate.postForEntity(url, wxMssVo, String.class);
return responseEntity.getBody();
}
@GetMapping("getAccessToken.do")
public String getAccessToken() {
String appID = ""; //自己小程序的appid
String appSecret = ""; //自己小程序的秘钥,可以在自己的微信小程序官网查看
RestTemplate restTemplate = new RestTemplate();
Map<String, String> params = new HashMap<>();
params.put("APPID", appID);
params.put("APPSECRET", appSecret);
System.out.println("params===" + params);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={APPID}&secret={APPSECRET}", String.class, params);
String body = responseEntity.getBody();
JSONObject object = JSON.parseObject(body);
String Access_Token = object.getString("access_token");
String expires_in = object.getString("expires_in");
System.out.println("有效时长expires_in:" + expires_in);
return Access_Token;
}
}
WxMssVo.java
package com.bots.mcst.wechat.entity;
import java.util.Map;
import lombok.Data;
/*
* 服务通知参数实体类
* wlw 20210719
*/
@Data
public class WxMssVo {
private String touser;// 用户openId
private String template_id;// 订阅消息模版id
private String page = "pages/index/index";// 默认跳到小程序首页
private Map<String, TemplateData> data;// 推送文字
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public String getTemplate_id() {
return template_id;
}
public void setTemplate_id(String template_id) {
this.template_id = template_id;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public Map<String, TemplateData> getData() {
return data;
}
public void setData(Map<String, TemplateData> data) {
this.data = data;
}
}
这个是我添加的模板
基本就是这些代码,测试推送功能可以在开发者工具上上传一下代码,发布体验版然后微信扫码即可,切记一定要在弹出的通知申请出选择允许,否则无法收到通知。服务通知推送可以用postman工具请求pushNotification.do接口即可
体验版前端代码发布
postman请求成功返回值:
手机微信收到的服务通知,Page是跳转到某一页面,体验版的服务通知无法实现跳转,发布成功后即可