刘耀文

刘耀文

java开发者
github

微信公式アカウントでウェブサイトにログインする

要求:ウェイチャット公式アカウントでウェブサイトにログインし、ユーザー情報を取得する。

前提条件#

  1. ウェイチャット公式アカウントが認証済みであること
  2. ウェイチャットサーバーのコールバックを受け取るためのサーバーを所有していること

手順#

1、ウェイチャット公式アカウントの appid と appsecret を取得する#

2、サーバーに接続し、ウェイチャットサーバーからのコールバックを受け取るために、ドメインが必要です。内部ネットワークトンネリングツール(cpolar など)を使用できます。#

まず、リソースの準備が必要です。#

image

説明:

  • URL はウェイチャットの認証サーバーの存在を確認するために使用されます。要件に従って設定する必要があります。例えば、私の場合のアドレスは

    https://13a34511.r1.cpolar.top/api/user/wxcheck
    

    なので、自分のサービスで応答するためのインターフェースを準備する必要があります。

    //外層には/userがあります
    @GetMapping("wxcheck")
    public String  wxCheck(@RequestParam("signature") String signature,
                                        @RequestParam("timestamp") String timestamp,
                                        @RequestParam("nonce") String nonce,
                                        @RequestParam("echostr") String echostr) {
        if (userService.wxCheck(signature, timestamp, nonce, wxOpenConfig.getToken())) {
            return echostr;
        } else {
            return "error";
        }
    }
    

    ウェイチャットの要件に従ってデータを返す必要があります。要件は以下の通りです。

    1)token、timestamp、nonce の 3 つのパラメータを辞書順に並べ替えます。

    2)3 つのパラメータ文字列を 1 つの文字列に連結し、sha1 で暗号化します。

    3)開発者は暗号化された文字列を取得し、signature と比較して、リクエストがウェイチャットからのものであることを示します。

        @Override
        public Boolean wxCheck(String signature, String timestamp, String nonce, String token) {
            // ウェイチャット公式アカウントの接続確認
            // token、timestamp、nonceの3つのパラメータを辞書順に並べ替える
            String[] arr = new String[]{token, timestamp, nonce};
            Arrays.sort(arr);
            // 3つのパラメータ文字列を1つの文字列に連結し、sha1で暗号化する
            StringBuilder content = new StringBuilder();
            for (String s : arr) {
                content.append(s);
            }
            String tmpStr = MYDigestUtils.sha1DigestAsHex(content.toString());
    
            log.info("ウェイチャット公式アカウントの接続確認、signature = {}, tmpStr = {}", signature, tmpStr);
            return signature.equals(tmpStr);
        }
    

    上記のフォームを送信すると、検証が成功したというメッセージが表示されます。

3、次に、access_token を取得します。#

Mermaid Loading...
  • 要件に従って、ウェイチャットのリソースにアクセスするためのトークンを返す必要があります。ウェイチャットのリソースにアクセスするためには、このトークンが必要です。例えば、後続の QR コードなどです。
@Override
public String getAccessToken() {
    // access_tokenを取得する
    String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
                               wxOpenConfig.getAppId(), wxOpenConfig.getAppSecret());
    // リクエストを送信する
    String result = restTemplate.getForObject(url, String.class);
    log.info("access_tokenを取得する、result = {}", result);
    return result;
}

4、チケット付きの QR コードを生成する#

    @Override
    public String getQRCode(String accessToken) {
        // QRコードを取得する
        String url = String.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", accessToken);
        // 5分で有効期限が切れる
        String body = WXUtils.getQRCodeBody("300", "QR_STR_SCENE");
        String result = restTemplate.postForObject(url, body, String.class);
        log.info("QRコードを取得する、result = {}", result);
        return result;
    }

5、QR コードのチケットをフロントエンドに返し、ユーザーに QR コード画像を表示します。#

6、ユーザーがスキャンした後、イベントを上記の URL にプッシュします。GET リクエストを POST リクエストに変換するだけで、形式は次のとおりです。#

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[FromUser]]></FromUserName>
  <CreateTime>123456789</CreateTime>
  <MsgType><![CDATA[event]]></MsgType>
  <Event><![CDATA[subscribe]]></Event>
  <EventKey><![CDATA[qrscene_123123]]></EventKey>
  <Ticket><![CDATA[TICKET]]></Ticket>
</xml>

もちろん、多くのイベントタイプがあり、それぞれを個別に処理するために戦略パターンを定義できます。

@Slf4j
public class DispatchEventHandle {

    private final Map<String, EventHandle> eventHandleMap = new HashMap<>();

    {
        eventHandleMap.put("subscribe", new SubscribeEventHandle());
        eventHandleMap.put("SCAN", new ScanEventHandle());
    }

    public  void dispatch(JSONObject jsonObject) {
        String eventType = jsonObject.getJSONObject("xml").getStr(WxEventHandleConstants.EVENT_TYPE_KEY);
        log.info("イベントタイプ:{}", eventType);
        EventHandle eventHandle = eventHandleMap.get(eventType);
        if (eventHandle == null) {
            log.error("対応するイベントハンドラーが見つかりませんでした");
            return;
        }
        eventHandle.handle(jsonObject);

    }
}

リクエストを受け取るインターフェースは次のように定義されています。

    @PostMapping("wxcheck")
    public String  event(@RequestBody String xml) {
        String msgType = WXUtils.getMsgType(xml);
        if ("event".equals(msgType)) {
            DispatchEventHandle dispatchEventHandle = new DispatchEventHandle();
            dispatchEventHandle.dispatch(JSONUtil.xmlToJson(xml));
        }
        return xml;
    }

7、フロントエンドは QR コードを表示した後、サーバーをポーリングしてスキャンされたかどうかを確認する必要があります。バックエンドは処理が完了した後、チケットをキー、JWT を値としてキャッシュし、フロントエンドが問題なくログインできるようにします。#

この記事は Mix Space から xLog に同期されています。
元のリンクは https://me.liuyaowen.club/posts/default/1 です。


読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。