spring boot +微信小程序项目,通过微信公众号实现指定用户消息长期推送

这篇具有很好参考价值的文章主要介绍了spring boot +微信小程序项目,通过微信公众号实现指定用户消息长期推送。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

流程

用户登录小程序,后台记录用户的小程序openId和用户唯一的UnionId。然后用户触发公众号事件(关注公众号或者发送指定消息),后台获取到用户公众号的openId,再调用接口通过公众号的openId查询用户的UnionId,再和数据库里的UnionId进行匹配,将用户的公众号openId存入数据库。此后即可通过userId找到公众号openId 实现公众号消息推送。
springboot 微信公众号存储openid并推送消息,java,spring boot

1.开通公众号

这个直接操作就好了

2.配置公众号验签接口

添加验签接口

	/**
     * 服务器有效性验证
     */
    @GetMapping("connect")
    public String verifyToken(HttpServletRequest request) {
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        log.info("signature: {} nonce: {} echostr: {} timestamp: {}", signature, nonce, echostr, timestamp);
        if (this.checkSignature(signature, timestamp, nonce)) {
            log.info("token ok");
            return echostr;
        }
        return echostr;
    }

将接口配置到公众号上
springboot 微信公众号存储openid并推送消息,java,spring boot

3.设置用户关注、取关以及发送消息事件处理

接口名称和验签接口相同 只是验签是GET请求 事件处理是POST请求

	/**
     * 用户公众号关注/取关事件回调
     */
    @PostMapping(value = "/connect")
    public void getXmlInfo(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        req.setCharacterEncoding("UTF-8"); // 接收请求时的编码。
        resp.setCharacterEncoding("UTF-8"); // 响应给浏览器的编码。
        Map<String, String> map = XMLUtil.parseXml(req);
        log.info(JSONObject.toJSONString(map));

        if ( map.get("MsgType").equals("text")){
            if (map.get("Content").equals("求购留言")){
                String result = wechatOfficialAccountService.replySubscribeInfo(map);
                resp.setCharacterEncoding("UTF-8");
                resp.getWriter().println(result);
            }
        }else {
            if (map.get("Event").equals("subscribe")){
                wechatOfficialAccountService.subscribeInfo(map);
            } else if (map.containsKey("Event") && map.get("Event").equals("unsubscribe")) {
                wechatOfficialAccountService.unSubscribeInfo(map);
            }
        }
    }

关注时给用户绑定openId

	public void subscribeInfo(Map<String, String> map){
        WeChatEventInfo eventInfo = new WeChatEventInfo()
                .setToUserName(map.get("ToUserName"))
                .setFromUserName(map.get("FromUserName"))
                .setCreateTime(map.get("CreateTime"))
                .setMsgType(map.get("MsgType"))
                .setEvent(map.get("Event"));
        String accessToken = getToken();
        log.info("accessToken:{}",accessToken);
        String unionId = getUserInfo(accessToken,eventInfo.getFromUserName());
        if(StrUtil.isNotBlank(unionId)){
            wxCustomerService.bindOfficialAccountOpenId(unionId,eventInfo.getFromUserName());
        }
    }

回复指定消息时给用户绑定openId

/**
     * 回复求购留言进行关注
     */
    public String replySubscribeInfo(Map<String, String> map) throws Exception {
        WeChatEventInfo eventInfo = new WeChatEventInfo()
                .setToUserName(map.get("ToUserName"))
                .setFromUserName(map.get("FromUserName"))
                .setCreateTime(map.get("CreateTime"))
                .setMsgType(map.get("MsgType"))
                .setContent(map.get("content"));

        String accessToken = getToken();
        log.info("accessToken:{}",accessToken);
        String unionId = getUserInfo(accessToken,eventInfo.getFromUserName());
        ReplyMessage result = new ReplyMessage()
                .setToUserName(eventInfo.getFromUserName())
                .setFromUserName(eventInfo.getToUserName())
                .setCreateTime(System.currentTimeMillis())
                .setMsgType("text");
        if(StrUtil.isNotBlank(unionId)){
            wxCustomerService.bindOfficialAccountOpenId(unionId,eventInfo.getFromUserName());
            result.setContent("已为您开通求购留言通知");
        }else {
            result.setContent("开通失败,暂未获取到您的用户信息");
        }
        return XMLUtil.textMessageToXml(result);
    }

取关时解绑用户openId

 public void unSubscribeInfo(Map<String, String> map){
        WeChatEventInfo eventInfo = new WeChatEventInfo()
                .setToUserName(map.get("ToUserName"))
                .setFromUserName(map.get("FromUserName"))
                .setCreateTime(map.get("CreateTime"))
                .setMsgType(map.get("MsgType"))
                .setEvent(map.get("Event"));
        wxCustomerService.unSubscribeInfo(eventInfo.getFromUserName());
    }

4.申请消息模板

5.给指定用户发送消息

前三步代码

依赖

		<dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>4.0.0</version>
        </dependency>

        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.1</version>
        </dependency>
        <!-- java对象转换为xml字符串 -->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.19</version>
        </dependency>

接口层

接口需要放行

@RestController
@RequestMapping("wechat")
@Slf4j
public class WeChatController {

    private final WechatOfficialAccountService wechatOfficialAccountService;
    private static final String TOKEN = "platformYz";

    public WeChatController(WechatOfficialAccountService wechatOfficialAccountService) {
        this.wechatOfficialAccountService = wechatOfficialAccountService;
    }

    /**
     * 服务器有效性验证
     */
    @GetMapping("connect")
    public String verifyToken(HttpServletRequest request) {
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        log.info("signature: {} nonce: {} echostr: {} timestamp: {}", signature, nonce, echostr, timestamp);
        if (this.checkSignature(signature, timestamp, nonce)) {
            log.info("token ok");
            return echostr;
        }
        return echostr;
    }

    /**
     * 用户公众号关注/取关事件回调
     */
    @PostMapping(value = "/connect")
    public void getXmlInfo(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        req.setCharacterEncoding("UTF-8"); // 接收请求时的编码。
        resp.setCharacterEncoding("UTF-8"); // 响应给浏览器的编码。
        Map<String, String> map = XMLUtil.parseXml(req);
        log.info(JSONObject.toJSONString(map));

        if ( map.get("MsgType").equals("text")){
            if (map.get("Content").equals("求购留言")){
                String result = wechatOfficialAccountService.replySubscribeInfo(map);
                resp.setCharacterEncoding("UTF-8");
                resp.getWriter().println(result);
            }
        }else {
            if (map.get("Event").equals("subscribe")){
                wechatOfficialAccountService.subscribeInfo(map);
            } else if (map.containsKey("Event") && map.get("Event").equals("unsubscribe")) {
                wechatOfficialAccountService.unSubscribeInfo(map);
            }
        }
    }

    private boolean checkSignature(String signature, String timestamp, String nonce) {
        String[] str = new String[]{TOKEN, timestamp, nonce};
        //排序
        Arrays.sort(str);
        //拼接字符串
        StringBuffer buffer = new StringBuffer();
        for (String s : str) {
            buffer.append(s);
        }
        //进行sha1加密
        String temp = SHA1.encode(buffer.toString());
        //与微信提供的signature进行匹对
        return signature.equals(temp);
    }
}

service层


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;


@Service
@Slf4j
public class WechatOfficialAccountService {

    private final WxCustomerService wxCustomerService;
    private final RestTemplate restTemplate;

    private final String appId;
    private final String appSecret;
    private static final String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN";
    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token";
    public WechatOfficialAccountService(WxCustomerService wxCustomerService, RestTemplate restTemplate,
                                        @Value("${wx.gzh.appId}") String appId,
                                        @Value("${wx.gzh.secret}") String appSecret) {
        this.wxCustomerService = wxCustomerService;
        this.restTemplate = restTemplate;
        this.appId = appId;
        this.appSecret = appSecret;
    }


    public void subscribeInfo(Map<String, String> map){
        WeChatEventInfo eventInfo = new WeChatEventInfo()
                .setToUserName(map.get("ToUserName"))
                .setFromUserName(map.get("FromUserName"))
                .setCreateTime(map.get("CreateTime"))
                .setMsgType(map.get("MsgType"))
                .setEvent(map.get("Event"));
        String accessToken = getToken();
        log.info("accessToken:{}",accessToken);
        String unionId = getUserInfo(accessToken,eventInfo.getFromUserName());
        if(StrUtil.isNotBlank(unionId)){
            wxCustomerService.bindOfficialAccountOpenId(unionId,eventInfo.getFromUserName());
        }
    }

    /**
     * 回复求购留言进行关注
     */
    public String replySubscribeInfo(Map<String, String> map) throws Exception {
        WeChatEventInfo eventInfo = new WeChatEventInfo()
                .setToUserName(map.get("ToUserName"))
                .setFromUserName(map.get("FromUserName"))
                .setCreateTime(map.get("CreateTime"))
                .setMsgType(map.get("MsgType"))
                .setContent(map.get("content"));

        String accessToken = getToken();
        log.info("accessToken:{}",accessToken);
        String unionId = getUserInfo(accessToken,eventInfo.getFromUserName());
        ReplyMessage result = new ReplyMessage()
                .setToUserName(eventInfo.getFromUserName())
                .setFromUserName(eventInfo.getToUserName())
                .setCreateTime(System.currentTimeMillis())
                .setMsgType("text");
        if(StrUtil.isNotBlank(unionId)){
            wxCustomerService.bindOfficialAccountOpenId(unionId,eventInfo.getFromUserName());
            result.setContent("已为您开通求购留言通知");
        }else {
            result.setContent("开通失败,暂未获取到您在玉农智链中的用户信息");
        }
        return XMLUtil.textMessageToXml(result);
    }
    private String getUserInfo(String accessToken,String openId) {
        String url = String.format(USER_INFO_URL, accessToken, openId);
        String json = restTemplate.getForObject(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(json);
        log.info("json:{}",json);
        return jsonObject.getString("unionid");
    }
    private String getToken() {
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(TOKEN_URL,new JSONObject().fluentPut("grant_type","client_credential").fluentPut("appid",appId).fluentPut("secret",appSecret).toJSONString(), JSONObject.class);
        JSONObject json = Optional.ofNullable(responseEntity.getBody()).orElse(new JSONObject());
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        log.info("access_token_json:{}",json.toJSONString());
        return json.getString("access_token");
    }

    public void unSubscribeInfo(Map<String, String> map){

        WeChatEventInfo eventInfo = new WeChatEventInfo()
                .setToUserName(map.get("ToUserName"))
                .setFromUserName(map.get("FromUserName"))
                .setCreateTime(map.get("CreateTime"))
                .setMsgType(map.get("MsgType"))
                .setEvent(map.get("Event"));
        wxCustomerService.unSubscribeInfo(eventInfo.getFromUserName());
    }
}

工具类

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class XMLUtil {

    private static final String MESSAGE_TYPE_TEXT = "text";
    public  static Map<String, String> parseXml(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();

        try(InputStream inputStream = request.getInputStream()){
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点

            List<Element> elementList = root.elements();

            // 遍历所有子节点
            for (Element e : elementList) {
                map.put(e.getName(), e.getText());
            }
        } catch (IOException |DocumentException e) {
            log.info("xml信息解析失败");
        }
        return map;
    }
    /**
     * 文本消息对象转换成xml
     *
     * @param textMessage 文本消息对象
     * @return xml
     */
    public static String textMessageToXml(ReplyMessage textMessage) {
        XSTREAM.alias("xml", textMessage.getClass());
        return XSTREAM.toXML(textMessage);
    }

    /**
     * 扩展xstream,使其支持CDATA块
     */
    private static final XStream XSTREAM = new XStream(new XppDriver() {
        @Override
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {
                // 对所有xml节点的转换都增加CDATA标记
                final boolean cdata = true;

                @Override
                protected void writeText(QuickWriter writer, String text) {
                    if (cdata) {
                        writer.write("<![CDATA[");
                        writer.write(text);
                        writer.write("]]>");
                    } else {
                        writer.write(text);
                    }
                }
            };
        }
    });
    /**
     * 获取默认文本消息
     *
     * @param receiver     接收人
     * @param officialWxid 官方微信id
     * @return 文本消息
     */
    public static ReplyMessage getDefaultReplyMessage(String receiver, String officialWxid) {
        ReplyMessage textMessage = new ReplyMessage();
        textMessage.setToUserName(receiver);
        textMessage.setFromUserName(officialWxid);
        textMessage.setCreateTime(System.currentTimeMillis());
        textMessage.setMsgType(MESSAGE_TYPE_TEXT);
        return textMessage;
    }

}

模板消息发送服务类文章来源地址https://www.toymoban.com/news/detail-773775.html


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Optional;

@Component
@Slf4j
public class WechatOfficialAccountMessageServer {

    private final String appId;
    private final String miniAppId;
    private final String appSecret;


    private final RestTemplate restTemplate;

    private  String accessToken;

    private static final String SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token";

    private WechatOfficialAccountMessageServer(@Value("${wx.gzh.appId}") String appId,
                                               @Value("${wx.xcx.appId}") String miniAppId,
                                               @Value("${wx.gzh.secret}")String appSecret) {

        this.appId = appId;
        this.appSecret = appSecret;
        this.miniAppId = miniAppId;
        this.restTemplate = new RestTemplate();
    }



    /**
     * 消息推送
     *
     * @param templateId  消息模板id
     * @param openId      用户openId
     * @param param 推送对象
     */
    public void pushMessage(String templateId, String openId, WechatOfficialAccountMessageParam param) {
        getInstance();
        param.getMessageDataList().forEach(item->{
            pushMessage(templateId,openId,item,param.getPage());
        });
    }

    private void getInstance(){
        //获取access_token
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(TOKEN_URL,new JSONObject().fluentPut("grant_type","client_credential").fluentPut("appid",appId).fluentPut("secret",appSecret).toJSONString(), JSONObject.class);
        JSONObject json = Optional.ofNullable(responseEntity.getBody()).orElse(new JSONObject());
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        this.accessToken = json.getString("access_token");
    }

    /**
     * 消息推送
     *
     * @param templateId  消息模板id
     * @param openId      用户openId
     * @param messageData 消息体
     * @param page
     */
    private void pushMessage(String templateId, String openId, JSONObject messageData, String page) {
        String url = String.format(SEND_URL, this.accessToken);
        //拼接推送的模版
        SendTemplateRequest request = new SendTemplateRequest()
                .setTouser(openId)
                .setTemplateId(templateId)
                .setData(messageData);
        if (StrUtil.isNotBlank(page)){
            JSONObject miniProgram = new JSONObject().fluentPut("appid", miniAppId)
                    .fluentPut("pagepath", page);
            request.setMiniProgram(miniProgram);
        }

        ResponseEntity<SendTemplateResponse> responseEntity = restTemplate.postForEntity(url, JSONObject.toJSONString(request), SendTemplateResponse.class);
        SendTemplateResponse response = Optional.ofNullable(responseEntity.getBody()).orElse(SendTemplateResponse.getInstance());
        if (Objects.requireNonNull(response).isSuccess()) {
            log.info("公众号推送成功");
            return;
        }
        log.error("公众号推送失败:{} {}", response.getErrcode(), response.getErrmsg());
        throw new DefaultException("公众号推送失败:" + response.getErrcode() + response.getErrmsg(), ResponseEnum.OPERATE_FAIL);
    }
}

相关实体类

import lombok.Data;
import lombok.experimental.Accessors;

/**
 * 微信公众号关注取消事件信息
 */
@Data
@Accessors(chain = true)
public class WeChatEventInfo {

    private String toUserName;
    private String fromUserName;
    private String createTime;
    private String msgType;
    private String event;
    private String content;
    private String msgId;
}
@Data
@Accessors(chain = true)
public class ReplyMessage {
    private String ToUserName;
    private String FromUserName;
    private Long CreateTime;
    private String MsgType;
    private String Content;
}
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
class SendTemplateRequest {
    /**
     * 接收者(用户)的 openid
     */
    private String touser;
    /**
     * 所需下发的模板消息的id
     */
    @JSONField(name = "template_id")
    private String templateId;
    /**
     * 模板跳转链接(海外账号没有跳转能力)
     */
    @JSONField(name = "url")
    private String url;
    /**
     * 跳小程序所需数据,不需跳小程序可不用传该数据
     * "miniprogram":{
     *              "appid":"xiaochengxuappid12345",
     *              "pagepath":"index?foo=bar"
     *            }
     * appid	必填	所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)
     * pagepath	非必填	所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏
     */
    @JSONField(name = "miniprogram")
    private Object miniProgram;
    /**
     * 模板数据
     */
    private Object data;

    /**
     * 防重入id。对于同一个openid + client_msg_id, 只发送一条消息,10分钟有效,超过10分钟不保证效果。若无防重入需求,可不填
     */
    @JSONField(name = "client_msg_id")
    private String clientMsgId;
}
import lombok.Data;
import lombok.experimental.Accessors;

/**
 * 消息推送响应对象
 *
 * @author fenglifei
 */
@Data
@Accessors(chain = true)
public class SendTemplateResponse {
    /**
     * 错误码
     * 0 ok
     * 43116 该模板因滥用被滥用过多,已被限制下发
     */
    private long errcode;
    /**
     * 错误信息
     */
    private String errmsg;
    /**
     * 错误信息
     */
    private String msgid;

    public static SendTemplateResponse getInstance(){
        return new SendTemplateResponse()
                .setErrcode(404L)
                .setErrmsg("");
    }
    public boolean isSuccess() {
        return this.errcode == 0;
    }
}


import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.util.List;

@Data
public class WechatOfficialAccountMessageParam {
    private String page;
    private List<JSONObject> messageDataList;
}

到了这里,关于spring boot +微信小程序项目,通过微信公众号实现指定用户消息长期推送的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信H5(公众号)跳转微信小程序实现及其传参

    其中:         username:目标小程序的原始id;         path : 所需跳转的小程序内页面路径及参数( 传参采取挂参的形式传递 ); ps:目标小程序接收参数时要在index的onload里面接收直接 options.XXX就可以。 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-lin

    2024年02月09日
    浏览(63)
  • NO.3--- 微信小程序项目创建之 “小程序”、“小游戏”、“代码片段”、“公众号网页项目” 版块的学习记录(游客模式)

    一、微信小程序登录界面的相关信息。 1.1、开启软件 打开已安装好的微信开发者工具。 1.2、登录界面 第一次登陆应该是弹出一个二维码框,如以下这样: 1.3、登录模式 从登陆界面可以看到有两种登陆方式,一种是微信扫描二维码登入,另一种是以 “游客模式” 登入。我

    2024年02月02日
    浏览(66)
  • Java开源项目—通用CRM管理系统(微信小程序+微信公众号+H5网页+PC管理后台)

    CRM(客户关系管理)管理系统是一种用于管理客户关系的软件系统,通过收集、组织和分析客户关系数据,帮助企业更好地了解客户,提高客户满意度,提升客户服务水平,建立长期客户关系,提升企业的销售和服务效率。 此系统是一款基于likeadmin-Java开发的客户关系管理系

    2024年02月13日
    浏览(49)
  • 微信小程序中引导用户关注公众号实现方案详细说明

        之前讲过如何利用公众号针对指定用户完成业务操作之后实时发送消息.就好比在线医院公众号中看病挂号,挂号预约成功之后微信列表中会新增一条关注的公众号预约成功消息.具体实现步骤可以看下文章如何实现:手把手教你微信公众号如何给指定用户发送消息提醒,

    2024年02月09日
    浏览(40)
  • [Spring boot] Spring boot 整合RabbitMQ实现通过RabbitMQ进行项目的连接

     🍳作者:天海奈奈 💭眼过千遍不如手锤一遍:推荐一款模拟面试,斩获大厂 o f f e r ,程序员的必备刷题平台 − − 牛客网  👉🏻点击开始刷题之旅 目录 什么是RabbitMQ   消息队列:接受并转发消息,类似于快递公司 消息队列的优点 消息队列的特性 RabbitMQ特点 RabbitMQ核

    2024年01月24日
    浏览(76)
  • 基于Spring Boot和微信小程序的智能小程序商城

    🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 基于Spring Boot和微信小程序的智能小程序商城,java项目。 eclipse和idea都能打开运行。 推荐环境配置:eclipse/idea jdk1.8 maven

    2024年02月03日
    浏览(51)
  • 微信小程序的授权登录-Java 后端 (Spring boot)

    微信开发文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 一个可以测试的微信小程序 此微信小程序的APPID和APPscret(至开发者后台获取) 从时序图我们可以了解到流程大致分为两步: 小程序端获取code后传给Java后台 Java后台获取code后向微信后台接口

    2024年02月09日
    浏览(41)
  • springboot基于spring boot的在线答题微信小程序

    :在线答题微信小程序;JAVA语言;MySQL数据库; Abstract WeChat widget for online question answering is an important part of the exam. Online question answering is the main channel for students to obtain task information. In order to facilitate students to view task information and exams on the website, a simple and portable online W

    2024年02月20日
    浏览(42)
  • 真的简单,单手用Spring Boot 开发一个微信小程序

      嗨,大家好,现在微信使用的用户很多,作为开发人员也可以建立一个自己的微信小程序,本期与大家分享一下作者建立微信小程序的开发流程。   百度搜索微信公众号平台,然后扫码登录注册一个微信公众号,   进入申请页面之后,需要及时完善小程序相关信息

    2024年02月10日
    浏览(42)
  • Spring Boot+微信小程序_保存微信登录者的个人信息

    微信小程序 开发平台,提供有一类 API ,可以让开发者获取到微信登录用户的个人数据。这类 API 统称为 开放接口 。 Tip: 微信小程序开发平台,会把微信登录用户的个人信息分为 明文数据 和 敏感数据 。 明文数据 也称为公开数据,开发者可以直接获取到,如登录者的昵称

    2024年02月10日
    浏览(32)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包