• 微信公众号开发


    微信官方文档参考地址: https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html

    1、微信公众号平台基础设置

    1-1、白名单配置

    在这里插入图片描述

    1-2、回调接口配置

    服务器地址为后端服务部署接口地址,令牌,消息加密秘钥这个自己生成,对数据进行加密需要

    2、后台服务接口

    2-1、公众号二维码生成接口

    **注意说明:**当前接口主要是生成临时二维码,调用腾讯服务器获取公众号二维码并将企业logo合成到二维码中。

    2-1-1、controller代码逻辑

     @GetMapping("qrcode")
        public Response login(HttpServletResponse response, HttpServletRequest request){
            return wxMpManager.qrcode();
        }
    
    • 1
    • 2
    • 3
    • 4

    2-1-2、service接口

    public Response qrcode() {
          Map<String,Object> showQrcodeMap = new HashMap();
            String accessToken = getAccessToken();
            String url = String.format(PUBLICACCOUNT_QRCODE_URL,accessToken);
            Map<String,Object> paramMap = new HashMap();
            paramMap.put("expire_seconds",604800);
            paramMap.put("action_name","QR_SCENE");
            Map<String,Object> sceneMap = new HashMap();
            Map<String,Object> sceneMap2 = new HashMap();
            sceneMap2.put("scene_id",IdGen.uuid());
            sceneMap.put("scene",sceneMap2);
            paramMap.put("action_info",sceneMap);
            HttpEntity httpEntity = new HttpEntity<>(new Gson().toJson(paramMap),new HttpHeaders());
            ResponseEntity<String> response  = restTemplate.postForEntity(url,httpEntity,String.class);
            JSONObject jsonObject =new JSONObject(response.getBody());
            log.info("临时二维码获取ticket,获取json:{}",jsonObject);
            String qrCodeUrl = jsonObject.getString("url");
            if(StringUtils.isEmpty(qrCodeUrl)){
                log.error("临时二维码获取ticket,获取json:{}",jsonObject);
                return ResponseUtils.returnCommonException("二维码获取失败");
            }
            try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                InputStream inputStream = getClass().getResourceAsStream(JIANMO_LOG_PATH)){
                BufferedImage bufferedImage =QRCodeUtil.createImage(qrCodeUrl,inputStream , false, QR_CODE_SIZE);
                ImageIO.write(bufferedImage,"jpg",outputStream);
                String content = new BASE64Encoder().encode(outputStream.toByteArray());
                showQrcodeMap.put("showQrcodeUrl", "data:image/jpeg;base64,"+content);
                showQrcodeMap.put("ticket",jsonObject.getString("ticket"));
            } catch (IOException e) {
                log.error(e.getMessage(),e);
            } catch (Exception e) {
               log.error(e.getMessage(),e);
            }
            return ResponseUtils.returnObjectSuccess(showQrcodeMap);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    2-2、微信回调接口

    2-2-1、微信公众号平台配置回调校验接口

    说明: 验证回调接口参数是否合法,如果合法直接返回入参中的echostr,这样公众平台中的回调校验才能正常通过。

    @RequestMapping(method ={RequestMethod.GET,RequestMethod.POST},value ="login" )
        public String login(PublicAccountCallDTO publicAccountCallDTO,HttpServletRequest request,HttpServletResponse response) {
            log.info("publicAccountCallDTO={}",publicAccountCallDTO);
            boolean flag= wxMpManager.getSignature(publicAccountCallDTO);
             return flag ? publicAccountCallDTO.getEchostr():"";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
        public boolean getSignature(PublicAccountCallDTO publicAccountCallDTO) {
            if(StringUtils.isEmpty(publicAccountCallDTO.getSignature())){
                return false;
            }
            String[] array = new String[]{wxpayConfig.getWxOpenToken() , publicAccountCallDTO.getTimestamp() , publicAccountCallDTO.getNonce()};
            StringBuilder sb = new StringBuilder();
            // 字符串排序
            Arrays.sort(array);
            for (int i = 0; i < 3; i++) {
                sb.append(array[i]);
            }
            String signature = DigestUtils.sha1Hex(sb.toString());
            return signature.equals(publicAccountCallDTO.getSignature());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2-2-2、controller业务逻辑代码接口

    注意说明: 当前接口响应公众平台回调,所以返回格式为xml文件格式,为了避免返回数据乱码,此处需要二外配置produces = “application/xml; charset=UTF-8”

     @RequestMapping(method ={RequestMethod.POST},value ="login",produces =  "application/xml; charset=UTF-8")
        public String login( @RequestBody String requestBody,PublicAccountCallDTO publicAccountCallDTO,HttpServletRequest request,
                             HttpServletResponse response) {
            log.info("body={},publicAccountCallDTO={},paramMap={}",requestBody,publicAccountCallDTO,new Gson().toJson(request.getParameterMap()));
    
            boolean flag= wxMpManager.getSignature(publicAccountCallDTO);
            if(!flag){
                log.error("非法回调,body={},publicAccountCallDTO={}",requestBody,publicAccountCallDTO);
                return "";
            }
            wxMpManager.updateUser(requestBody,publicAccountCallDTO.getOpenid(), request);
    
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
            if(outMessage!=null) {
                log.info("输出xml数据,{}",outMessage.toXml());
                return outMessage.toXml();
            }
            return "";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2-3、微信公众号扫码关注客户端消息推送

    2-3-1、公众号关注消息处理

    @Component
    @Slf4j
    public class WxMpSubscribeHandler implements WxMpMessageHandler {
        @Override
        public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
                                        WxSessionManager sessionManager) throws WxErrorException {
            log.info("wxMessage={}",wxMessage);
            return WxMpXmlOutMessage.TEXT().
                    fromUser(wxMessage.getToUser()).
                    toUser(wxMessage.getFromUser()).
                    content("欢迎关注,用户登录成功").
                    build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2-3-2、公众号取消关注消息处理

    @Component
    @Slf4j
    public class WxMpUnSubscribeHandler implements WxMpMessageHandler {
        @Override
        public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
                                        WxSessionManager sessionManager) throws WxErrorException {
            log.info("wxMessage={}",wxMessage);
            return WxMpXmlOutMessage.TEXT().
                    fromUser(wxMessage.getToUser()).
                    toUser(wxMessage.getFromUser()).
                    content("请别离开我").
                    build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2-3-3、公众号扫码场景消息处理

    @Component
    @Slf4j
    public class WxMpScanHandler implements WxMpMessageHandler {
        @Override
        public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
                                        WxSessionManager sessionManager) throws WxErrorException {
            log.info("绑定系统用户成功,wxMessage={}",wxMessage);
            return WxMpXmlOutMessage.TEXT().
                    content("用户登录成功!").
                    fromUser(wxMessage.getToUser()).
                    toUser(wxMessage.getFromUser()).
                    build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2-4、消息路由

    
    @Configuration
    public class WeChartConfig {
    
        @Resource
        private WxMpSubscribeHandler wxMpSubscribeHandler;
    
        @Resource
        private WxMpUnSubscribeHandler wxUnSubscribeHandler;
    
        @Resource
        private WxMpScanHandler wxMpScanHandler;
        @Resource
        private WeChartWxMpService weChartWxMpService;
    
        @Bean
        public WxMpMessageRouter wxMpMessageRouter(){
            WxMpMessageRouter router = new WxMpMessageRouter(weChartWxMpService);
            router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SUBSCRIBE)
                    .handler(wxMpSubscribeHandler).end();
            router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.UNSUBSCRIBE)
                    .handler(wxUnSubscribeHandler).end();
            router.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SCAN)
                    .handler(wxMpScanHandler).end();
            return router;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    公众号平台参考文档:
    1、https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
    2、https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId

    公众号接口参考信息:
    //获取accessToken
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=&secret=
    //临时二维码获取ticket
    https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s
    //公众号获取用户信息接口
    https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN

  • 相关阅读:
    10个美妙的Python装饰器
    面包屑实现
    【Cross-Direction and Progressive Network:交叉的挖掘信息】
    Python如何正确将“爬虫数据”以json格式进行保存
    2022年三网融合行业研究报告
    机器学习-SVM算法
    打破文件锁限制,以存储力量助力企业增长新动力
    wwwwwwwwwwwwwwww
    深入理解JVM虚拟机第二篇:虚拟机概念和JVM整体架构以及字节码的执行路线
    NRF52832蓝牙芯片详细介绍及应用方案
  • 原文地址:https://blog.csdn.net/u010353018/article/details/126250580