1. 业务开发

1.1. 事件推送

1.1.1. 获取带参数的二维码

net.mingsoft.mweixin.biz.impl.QrCodeBizImpl

场景二维码管理实体作为入参,每个字段都应有值,返回值是一个存储二维码图片字节和ticket

public Map qrCodeCreateTmpTicket(QrCodeEntity qrCodeEntity) {
        if (qrCodeEntity == null && StringUtils.isEmpty(qrCodeEntity.getWeixinId())) {
            throw new BusinessException("未找到配置");
        }
        //获取微信配置
        WeixinEntity weixin = (WeixinEntity)weixinBiz.getEntity(Integer.parseInt(qrCodeEntity.getWeixinId()));
        if (weixin == null) {
            throw new BusinessException("未找到配置");
        }
        PortalService service = new PortalService().build(weixin);
        WxMpQrcodeService qrcodeService = service.getQrcodeService();
        WxMpQrCodeTicket wxMpQrCodeTicket = null;
        try {
            wxMpQrCodeTicket = qrcodeService.qrCodeCreateTmpTicket(qrCodeEntity.getQrSceneStr(), qrCodeEntity.getQrExpireSeconds());
            File file = qrcodeService.qrCodePicture(wxMpQrCodeTicket);
            HashMap<String, Object> map = new HashMap<>();
            map.put("qCode",FileUtil.readBytes(file));
            map.put("key", wxMpQrCodeTicket.getTicket());
            return map;
        } catch (WxErrorException e) {
            e.printStackTrace();
            throw new BusinessException(e.getMessage());
        }
    }

[!tip] 返回值中的key可以用于前台页面检测这次二维码的状态

    <img :src="previewUrl" width="300" height="300"/>
    ···
        var codeImg = "data:image/jpeg;base64," + res.data.qCode;
    ···

1.1.2. 关注及扫码等事件处理

对于一些特殊事件,微信服务器会推送消息到系统,例如用户在扫描携带参数的二维码时,分为用户已关注再扫码和用户未关注再扫码关注两种情况。

用户已关注时扫码对应扫码事件,由net.mingsoft.mweixin.service.ScanService做处理; 用户未关注时扫码关注对应关注事件,由net.mingsoft.mweixin.service.SubscribeService做处理;

SubscribeService: 关注服务类第一步保存了关注用户的信息,用户扫码关注或者主动查询关注没有区别;第二步检测是不是带参数二维码,带参数二维码通常在关注和扫码两种事件上的业务是高度重合的, 所以当检测成功时调用扫码事件处理器去处理相关业务,开发者可以自行增加场景二维码管理,并添加与其beanName相对应的处理器;第三步是用于一二步仍不能满足开发业务需求时, 需要额外扩展的处理,只需要写一个实现类去实现net.mingsoft.mweixin.handle.ISubscribeHandle接口即可,注意和扫码处理器接口不同,关注处理器只允许一个实现类

    ···
    if (userWxInfo != null) {
      // TODO 可以添加关注用户到本地
        this.logger.debug("保存用户信息");
        int weixinId = weixinService.getWeixin().getIntId();
        weixinPeopleBiz.saveOrUpdate(userWxInfo, weixinId);
    }

    WxMpXmlOutMessage responseResult = null;
    try {
        //处理特殊请求,比如如果是扫码进来的,可以做相应处理
        this.logger.info("处理特殊请求,比如如果是扫码进来的,可以做相应处理");
        // todo 未关注扫码也获取实体的beanName走扫码事件统一处理
        IScanHandle scanHandle = scanService.getScanHandleBySceneStrAndWeixinId(wxMessage.getEventKey().replace("qrscene_", ""), weixin.getId());
        if (scanHandle!=null){
            responseResult = scanHandle.handleSpecial(wxMessage,weixinService);
        }
        // todo 如果还想在关注的时候做一些事情,请写一个类实现ISubscribeHandle
        if (subscribeHandle!=null){
            subscribeHandle.handleSpecial(wxMessage,weixinService);
        }
    } catch (Exception e) {
        logger.debug("扫码实现类或关注实现类处理异常");
        e.printStackTrace();
    }

    if (responseResult != null) {
        return responseResult;
    }
    ···

ScanService: 扫码服务类中没有统一要处理的业务代码,默认每个不同的场景二维码对应一个不同的处理器,开发者在新增场景二维码时,应在业务代码中新增具体的处理实现类。

    ···
    WeixinEntity weixin =  ((PortalService) wxMpService).getWeixin();
    PortalService weixinService = (PortalService) wxMpService;
    // 获取扫码处理对象,为null不会执行
    IScanHandle scanHandle = getScanHandleBySceneStrAndWeixinId(wxMessage.getEventKey(), weixin.getId());
    if (scanHandle!=null){
        return scanHandle.handleSpecial(wxMessage,weixinService);
    }
    return null;

    ···

1.1.3. 其余事件处理

其他不同的事件基本都有默认处理的业务代码,基本都能满足业务需求,如果有需要可以参考上面两种方式进行二次开发。

1.2. 微信消息模板

插件在微信官方的模板字段基础上统一了字段前缀规范,并且新增了两个字段,模板编码和模板关键词,在做业务开发时不需要关心微信本身的字段, 模板编码作为唯一标识,模板关键词作为参数传递;模板编码字段值全表唯一,不可重复

[!tip] 初次使用需要先同步微信消息模板,然后自定义模板编码和模板关键词,后续再同步,同一个模板的编码和关键词字段会保留

1.2.1. 定义规范

对于模板编码字段,插件没有做任何约束,命名时能见名知意即可;

模板关键词字段需要严格按照规范定义,需遵守 微信关键词顺序对应关键词参数顺序

如下图,

注意关键词中必须使用${}取参数,命名不做约束,顺序按照模板内容占位顺序依次排列,占位关键词之间以逗号隔开

1.2.2. 业务开发范例

        // 参数组装 注意微信消息已经不再发送头尾信息
        Map wordList = new HashMap();
        wordList.put("first", "这是头信息");
        wordList.put("keyword1", "这是关键词1");
        wordList.put("keyword2", "这是关键词2");
        wordList.put("remark", "这是备注信息");
        TemplateBean templateBean = new TemplateBean();
        templateBean.setTemplateCode("test-template-code");
        // openId错误会发送失败
        templateBean.setOpenIds("openId1,openId2,openId3");
        templateBean.setWordList(wordList);
        // 校验参数,组装消息,注意在实际业务中做参数和查询结果的校验
        TemplateEntity template = templateBiz.getOne(new LambdaQueryWrapper<TemplateEntity>().eq(TemplateEntity::getTemplateCode, templateBean.getTemplateCode()));
        List<WxMpTemplateData> wxMpTemplateData = TemplateMessageUtil.buildParams(template.getTemplateContent(), template.getTemplateKeyword(), templateBean.getWordList());
        String[] receives = templateBean.getOpenIds().split(",");
        // 根据模板获取微信
        WeixinEntity weixin = weixinBiz.getById(template.getWeixinId());
        PortalService service = new PortalService().build(weixin);
        TemplateMessageUtil.send(service,wxMpTemplateData,templateBean.getUrl(), template.getTemplateId(),receives);

1.3. 移动端自动授权登录

移动端登录核心点在于授权,通过授权获取到用户信息再核对进行登录

场景分为两种:1.用户访问会员层接口 2.用户访问非会员层

1.3.1. 会员层接口自动授权登录

会员层接口拥有共同特征,接口路径都是由 /people 开头,根据这个特点可以用拦截器来实现自动授权

代码片段示例参考:

    ···
        if (BasicUtil.isMobileDevice() && BasicUtil.isWechatBrowser()) {
            //组装请求参数地址
            response.sendRedirect(BasicUtil.getUrl()+"/mweixin/oauth/redirectUrl.do?weixinNo="+weixinNo+"&url="+URLUtil.encodeAll(BasicUtil.buildRequestUrl(request)));
            return true;
        }
    ···

1.3.2. 非会员层授权自动登录

如果出现非会员层也要获取用户信息的需求情况,例如菜单上有非会员层网站入口要组装成授权地址加菜单实际地址:

BasicUtil.getUrl()+"/mweixin/oauth/redirectUrl.do?weixinNo="+weixinNo+"&url="+ 任意地址(需经过url转码)

例如上面这个地址作为菜单地址,用户会经过授权再回到实际要访问的页面,这样就可以拿到用户信息了

1.4. 页面分享

1.4.1. 页面制作

页面分享首先需要引入 http://res.wx.qq.com/open/js/jweixin-1.6.0.js 用来调用微信js接口。 同时需要引入微信插件中的 /static/mweixin/weixin.js js文件来快速请求签名算法接口,在页面自定义标题描述以及图片就可以达到diy分享效果

示例:

    ···
    <#include "head-file.htm" />
    <script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
    <script src="/static/mweixin/weixin.js"></script>
    ···
    <script>
        var shareConfig = {
            weixinNo: "weixinNo",// 微信号
            title: "分享卡片标题",// 标题随意
            desc: "分享卡片描述",// 分享朋友圈没有描述
            link: location.href,// 获取签名必须要用本页面地址,不一致会导致签名失败
            imgUrl: "{ms:global.host/}template/1/default//images/bg-saas.jpg",// 图片路径必须要是绝对路径
        }
        ms.weixin.share(shareConfig);
    </script>

[!tip] 示例这段js代码通常情况不需要放到vue实例中,用js标签包裹即可

1.4.2. 数据统计

如果还需要数据统计功能,开发者需要在现有基础上进行小幅度二开

二次开发流程可以参考如下步骤:

1.增加一个会员层接口当做分享页面的入口来统计分享的点击记录(需注意参数合法性),处理完数据后再转发到实际地址

2.在获取签名时,可以将返回的签名实体中的url重新组装,将url当做参数转码拼接在分享入口的接口地址后面,这样其他用户点击的时候就会是访问分享入口

[!tip] 注意在写接口时要考虑微信重复请求的情况,解决办法就是给个返回值

微信插件基本基本的接口,具体参考 swagger 接口文档。

Copyright © mingsoft.net 2012-2022 all right reserved,powered by Gitbook该文件修订时间: 2023-08-23 17:23:18

results matching ""

    No results matching ""

    results matching ""

      No results matching ""