要求:ウェイチャット公式アカウントでウェブサイトにログインし、ユーザー情報を取得する。
前提条件#
- ウェイチャット公式アカウントが認証済みであること
- ウェイチャットサーバーのコールバックを受け取るためのサーバーを所有していること
手順#
1、ウェイチャット公式アカウントの appid と appsecret を取得する#
2、サーバーに接続し、ウェイチャットサーバーからのコールバックを受け取るために、ドメインが必要です。内部ネットワークトンネリングツール(cpolar など)を使用できます。#
まず、リソースの準備が必要です。#
説明:
-
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 コードなどです。
- 公式ドキュメント開発を開始する / アクセストークンを取得する (qq.com)
- コード:
@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 です。