java后端实现 微信订阅消息

一、第一步,先获取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是跳转到某一页面,体验版的服务通知无法实现跳转,发布成功后即可

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值