项目中对接微信公众平台笔记整理

背景简述

项目部分需求的流程中涉及跨微信应用,需要借助微信开放平台实现应用间的对接。特整理此文档记录。

涉及的应用对象

整个项目中涉及3个应用:推广服务号、ToC的业务小程序、ToB的业务小程序

项目需求

当关注服务号的用户在使用【ToC的业务小程序】或【ToB的业务小程序】时,触发了需要后续消息通知的事件(例如:投递简历后,有进一步结果会发消息通知),会在服务号里通知用户事件进展。

单个应用梳理——获取当前应用下的用户信息

获取当前应用的凭证信息

每个应用在申请完毕后,微信会生成当前应用的AppID(该应用的唯一凭证)和 AppSecret(该应用的唯一凭证密钥)。
注:AppSecret需要自行保存,在微信后台不会像AppID那样明示。
小程序后台
公众号后台

获取接口调用凭据

在微信平台下,接口调用凭据为【access_token】,在后续调微信提供的其他接口时,绝大多数下(除:小程序登录接口不需要)都需要在接口信息里加入access_token参数,才能获取到各接口正确响应信息。
注:每个应用的接口凭证是需要单独维护的,跨应用的接口凭证是不可不共用的。

调用说明

调用方式:HTTPS 调用
接口名和方式

GET https://api.weixin.qq.com/cgi-bin/token

接口参数说明

在这里插入图片描述

接口调用注意点
  • access_token的有效期通过返回的expires_in来传达,目前是7200秒之内的值。
  • 重复获取将导致上次获取的access_token失效。
  • 建议在同一个应用下的不同业务接口调用中,将access_token做统一管理。不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务。(也就是在自己的项目中,对单个应用,根据返回的expires_in来作为过期时间,统一获取和刷新access_token)
  • 小程序应用无需配置 IP 白名单。公众号调用接口时,需要提前将服务器 IP 地址添加到 IP 白名单中,否则将无法调用成功。
    在这里插入图片描述
详见微信文档

公众号:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
小程序:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html

不同应用下获取用户信息

在单应用下,微信用户在应用中的唯一标识叫【OpenID】。
注:每个应用的用户OpenID也是需要单独管理的,跨应用的用户OpenID不互通。
下面提供公众平台下获取微信用户OpenID的方式 和 小程序里获取微信用户OpenID的方式。

公众平台下获取微信用户OpenID

微信用户关注公众号后,使得微信服务器通过事件推送的形式,通知到我们在公众号后台配置的服务器地址,从而可以获取到关注用户的信息(包括openID)。
步骤如下:

1、在微信公众号后台配置自己服务的信息。主要包括:

  • 提供一个接口地址(配置里的服务器地址),供微信在捕捉到用户事件后,调取我们接口发送用户信息。
  • 自己设置一个token,后面用作签名校验。
    注意:在开启【服务期配置】后,在公众号后台设置的菜单和自定义回复语会失效。需要通过接口形式触发回复语和设置菜单
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2、在自己项目里,编写接口接收微信发来的事件通知。请求接口的参数里会带上关注用户的openID。
在这里插入图片描述

代码如下:
例如在上步配置里填的接口地址为:http://demo.com/token/wechat


package com.demo.upms.admin.controller;

import com.demo.common.core.dto.WxServiceMsgDto;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;


@RestController
@AllArgsConstructor
@RequestMapping("/token")
@Slf4j
public class TokenController {
 
     /**
     * 公众号后台配置的token值
     */
    public static final String Token="123456";

    /**
     * 功能描述: 微信对接验证接口
     * @Param wxServiceMsgDto 用户事件信息
     * @return String 
     */
    @PostMapping(value="/wechat", produces = "application/xml;charset=utf-8")
    public String wechat(@RequestParam(value = "signature", required = false) String signature,
                         @RequestParam(value = "timestamp", required = false) String timestamp,
                         @RequestParam(value = "nonce", required = false) String nonce,
                         @RequestParam(value = "echostr", required = false) String echostr,
                         @RequestBody(required = false) WxServiceMsgDto wxServiceMsgDto) throws Exception{
        if (null != echostr && !"".equals(echostr.trim())) {
            // 用于微信校验接口存在性,必须返回echostr
            return echostr;
        }
       // 触发事件的用户openID
       String openId = wxServiceMsgDto.getFromUserName();
       
       String[] str = { Token, timestamp, nonce };
        // 字典排序
        Arrays.sort(str);
        String bigStr = str[0] + str[1] + str[2];
        // SHA1加密
        String digest = sha1(bigStr);
        // 确认请求来至微信
        if (digest.equals(signature)) {
            return echostr;
        }

        return echostr;
    }

    /**
     * SHA1加密
     * @Param data 需加密的字符串
     * @return String 
     */
    private static String sha1(String data) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA1");
        //把字符串转为字节数组
        byte[] b = data.getBytes();
        //使用指定的字节来更新我们的摘要
        md.update(b);
        //获取密文  (完成摘要计算)
        byte[] b2 = md.digest();
        //获取计算的长度
        int len = b2.length;
        //16进制字符串
        String str = "0123456789abcdef";
        //把字符串转为字符串数组
        char[] ch = str.toCharArray();
        //创建一个40位长度的字节数组
        char[] chs = new char[len*2];
        //循环20次
        for(int i=0,k=0;i<len;i++) {
            //获取摘要计算后的字节数组中的每个字节
            byte b3 = b2[i];
            // >>>:无符号右移
            // &:按位与
            //0xf:0-15的数字
            chs[k++] = ch[b3 >>> 4 & 0xf];
            chs[k++] = ch[b3 & 0xf];
        }
        //字符数组转为字符串
        return new String(chs);
    }

}

package com.demo.common.core.dto;

import lombok.Data;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
public class WxServiceMsgDto {
    @XmlElement(name = "Event")
    private String event;

    @XmlElement(name = "Content")
    private String content;

    @XmlElement(name = "MsgType")
    private String msgType;

    @XmlElement(name = "ToUserName")
    private String toUserName;

    /**
     * fromUserName为关注人的openId
     **/

    @XmlElement(name = "FromUserName")
    private String fromUserName;

    @XmlElement(name="CreateTime")
    private String createTime;
}

公众号接收事件相关接口文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html

小程序下获取微信用户OpenID

通过小程序登录获取openID。需要在小程序里通过 wx.login 接口,获得临时登录凭证 code 后,将code传到后端服务器,调用【小程序登录】接口完成登录流程。
调用方式

调用方式:HTTPS 调用
接口名和方式

GET https://api.weixin.qq.com/sns/jscode2session

接口参数说明

在这里插入图片描述

跨应用关系梳理

如果涉及跨应用实现需求,需要申请微信开放平台。将微信公众号和小程序都绑定到微信开放平台里。就可以获取单个微信用户在多应用下的唯一标识 unionid

OpenID与unionid的关系与使用

开发者可通过 OpenID 来获取用户基本信息。特别需要注意的是,如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的 unionid 来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的 unionid 是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。

理解图:
根据 toC小程序中的 openID,可以获取到 unionid,存储 unionid。
下次在数据库可以根据 unionid 查到服务号里的 openID。
在这里插入图片描述
由此,就可以借助 unionid 给关注公众号的小程序用户发送服务通知了。

不同应用下获取 unionid

前提:

  • 小程序、公众号都需要绑定到微信开放平台里。
  • 用户如果没有登录过公众号,也没有关注过公众号的情况下,是获取不到 unionid 的

小程序里

【小程序端】在调登录接口时,就可以获取到unionid。
在这里插入图片描述

公众号下

通过传用户{openID}参数,请求【获取用户信息】接口,查询用户unionid
ps. 也可以通过该接口,获取用户最新的关注状态。

调用方式:HTTPS 调用
接口名和方式

GET https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

接口参数说明

请求参数:
在这里插入图片描述
响应参数:
在这里插入图片描述

实现小程序里触发事件,在公众号下发送通知

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值