見出し画像

WeChatソーシャルログインの使い方

「Facebookでログイン」や「LINEでログイン」と言ったソーシャルログインを実装しているウェブサイトを良く見かけますが、WeChatでもソーシャルログインが利用可能です。また、WeChatのソーシャルログインを利用する事で外部のサイトやネイティブアプリでもWeChatユーザーのOpenIDやUnionIDを取得する事が出来るようになるので、外部リソースをWeChatエコシステムへ組み込む事が出来ます。

WeChatには2種類のソーシャルログインが存在する

WeChatエコシステムが提供するソーシャルログインは2種類あります。1つは我々が一般的に想像するソーシャルログインで、自社のサービスに対してログインしてもらう手段の一つとしてWeChat用のQRコードを表示して、それをWeChatアプリでスキャンさせる方法です。
もう一つはWeChatブラウザで開く事を前提としてWeChatユーザーだけに提供するサービスを外部に構築する場合です。
ここでは便宜的に前者を「WeChatソーシャルログイン」、後者を「WeChatOpenID連携」と呼びます。
ここでは「WeChatソーシャルログイン」の使い方を紹介します。
「WeChatOpenID連携」の使い方についてはもう一つの記事をご覧ください。

WeChatソーシャルログインを利用する為の準備

WeChatソーシャルログインの実装を始める為には以下の2つの作業が必要です。

①WeChatオープンプラットフォームのアカウントを取得する

WeChatソーシャルログインにはWeChatオープンプラットフォームのアカウントが必要です。また、WeChatオープンプラットフォームのアカウントを作成するには公式アカウントと同様の企業認証が必要です。
企業認証済みの公式アカウントと同じ名義であっても改めて企業認証が必要となります。(ミニプログラムアカウントの様に公式アカウントの企業認証情報を流用したアカウント開設は出来ません)
【WeChatオープンプラットフォーム】
https://open.weixin.qq.com/

②ウェブサイトを追加する

WeChatオープンプラットフォームのアカウントが取得出来たら管理画面へログインして「管理中心」にある「网站应用」を開き、「创建网站应用」ボタンからウェブサイトを追加します。

WeChatオープンプラットフォームの管理画面

ウェブサイト追加の際にURLや会社名などの色々な情報を入力しますが、最終的にWordファイルの申請書に必要事項を記入後に印刷して捺印した書類のスキャン画像をアップロードします。
この印鑑は恐らく企業認証をした際に使った印鑑である必要があると思われるので、会社や組織・部署の代表印になると思います。(自分は企業認証で使った印鑑以外で申請した事がありません)
試しにやってみるにはちょっとハードルが高いですね。

申請書のWordファイル

ちなみに申請時にソーシャルログインを利用するサービスのURLを記入しますが、ソーシャルログインを使う際に指定するコールバックURLのドメインと一致している必要はありません。サイト自体は開発中でも申請は通りますが、404などのエラーで正常に表示出来ないURLを指定すると申請が通らない場合もあるようです。「UnderConstruction」だけを表示する状態でも良いので申請したURLには正常にアクセス出来るようにしておきましょう。

③追加したサイトのAppID、AppSecretを確認する

サイトの追加が正常に完了すると追加したサイトに対してAppIDが発行されます。また、管理画面でこのサイトのAppSecretを発行出来るようになります。AppIDの確認とAppSecretの発行はサイトの詳細画面で行います。サイトの詳細画面はWeChatオープンプラットフォームにログインして「管理中心」にある「网站应用」で表示されるサイト一覧から「查看」をクリックする事で開く事が出来ます。

サイト一覧画面

サイトの詳細画面を開くと上部にAppIDが表示されています。また、その下にAppSecretの発行リンクがあります。

サイト詳細画面

AppSecretは発行した際に画面に表示されますが、その後は管理画面上で表示する事は出来ませんので、必ずコピーして大切に保管しましょう。

④サービスドメインを設定する

WeChatソーシャルログインを設置する際にコールバックURIを指定しますが、そのコールバックURIのドメインは事前に登録したサービスドメインに限られます。後述する通りWeChatソーシャルログインでユーザーが情報提供に同意した場合に戻って来るコールバックURIやサイトのAppIDはAPIに対してGETパラメータで指定する為、外部からも見えてしまいます。
その為第三者がコールバックURIを自分のサイトに書き換えて情報を盗もうとするかも知れません。
それを防ぐ為にコールバックURIに指定するドメインを管理画面上で事前設定しておく必要があります。設定はサイト詳細画面の下部にある「开发信息」の項目で行います。

サービスドメインの設定

右側にある「修改」をクリックするとドメイン設定画面が開きますので、コールバック処理をするドメインを指定しましょう。(初めて設定する場合は「修改」ではなく「开启」になっているかも知れません)

WeChatソーシャルログインの利用方法

サービスドメインの設定とAppIDAppSecretの確認が完了するとWeChatソーシャルログインを使う事が出来ます。
WeChatソーシャルログインの大まかな処理の流れは以下の通りです。

  1. WeChatソーシャルログイン用のリンクを準備

  2. ユーザーに対してQRコードを表示

  3. ユーザーがWeChatアプリでQRコードをスキャン

  4. コールバックURLでチケットを受け取る

  5. チケットを利用してアクセストークンを取得

  6. アクセストークンを使ってユーザー情報を取得

①WeChatソーシャルログイン用のリンクを準備する

WeChatソーシャルログイン用のQRコードはWeChatシステムのサイトへ飛ばした上でQRコードを表示する方法と、自分のサイト上にQRコードを表示する2つの方法があります。
基本的な処理は同じなのでここではWeChatシステムのページでQRコードを表示する方法で手順を説明します。
実装は簡単で、下記APIに正しいパラメータを設定してユーザーにリンクをクリックしてもらうだけです。(もちろんシステム的にリダイレクトしてもOKです)

https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect

上記URLの中で自分で設定するパラメータは以下の通りです。

  • APPID
    WeChatオープンプラットフォーム上で追加したサイトのAppIDを指定します。

  • REDIRECT_URI
    ユーザーが情報提供を許可した場合に戻ってくるコールバックURLです。このURLのドメインはWeChatオープンプラットフォーム上で設定したサービスドメインと一致している必要があります。また、このパラメータで指定するURLはURLエンコードする必要があります。

  • STATE
    このパラメータを指定するとコールバックの際に指定した値がそのまま戻されます。設定するかどうかは任意ですが、テンセントのドキュメントではコールバックURLに対するクロスサイトリクエストフォージェリ対策として使う事を推奨しています。
    ここでリクエストしているAPIはソーシャルログインに使う為のチケットを取得する為のAPIであり、攻撃者が有効なチケットを送りつけて来る事はあり得ないですが、デタラメなチケットを大量に送り付けられてアクセストークンを取得するAPIを叩きまくるのも不健全ですので、このSTATEを設定しておいてコールバックが飛んで来た時に本当に自分のシステムがリダイレクトさせたリクエストかどうかを検証するのも良いでしょう。

②ユーザーに対してQRコードを表示する

手順①のAPIリンクでユーザーがWeChatシステムへ遷移すると以下のような画面が表示されます。

WeChatソーシャルログインの画面例

この例はテンセントのドキュメントに例として記載されている「一号会员店」という中国のECサイトのソーシャルログインURLを開いたところです。テンセントのサイトへリダイレクトしているのでアドレス欄のドメインが「open.wechat.qq.com」というWeChatオープンプラットフォームのドメインになっているのが分かります。
この画面に表示されている「一号会员店」という文字列はWeChatオープンプラットフォーム上でサイトを追加する際に設定したサイト名になります。パラメータなどでこの文字列を変更する事は出来ないので、サイト追加の際にはここで表示される事を意識したサイト名を設定しましょう。(中国語表記にするなど)

③ユーザーがQRコードをWeChatアプリでスキャンする

ユーザーがQRコードをWeChatアプリでスキャンすると、スマホ上では以下のような画面に遷移します。ウェブサイトに対して提供する情報が表示され、情報提供に同意するかどうかの選択肢が出てきます。

QRコードをスキャンすると表示される画面例

現在WeChatソーシャルログインでWeChatシステムからサイトへ提供されるユーザー情報は「ニックネーム」「プロフィール画像」「OpenID」「UnionID」に限定されています。以前は性別やWeChatに登録している居住地などの情報も提供されていましたが、2021年10月頃から提供されなくなりました。これは2021年11月1日から施行された中国の新しい個人情報保護法に適応する為の対応と思われます。

根据相关法律法规,为进一步规范开发者调用用户信息相关接口或功能,保障用户合法权益,平台将对用户信息相关功能及接口进行调整,具体如下:

一、相关接口调整:
1、小程序与小游戏获取用户信息相关接口:不再返回用户性别及地区信息;
2、 公众号用户信息获取接口:不再返回用户性别及地区信息;
3、 Open平台授权接口:包括App授权登录、公众号H5授权登录、网站扫码授权登录,不再返回用户性别及地区信息;

WeChatプラットフォームのユーザー情報に関するAPI変更に関するお知らせ

④コールバックURLでチケットを受け取る

上記画面でユーザーが情報提供に同意するとコールバックURLに以下のような形式でアクセストークンを取得する為のチケットが送られて来ます。
(リダイレクトする際のパラメータ「REDIRECT_URI」を「https://wechat.example.com/wc_login.php」と設定した場合)


https://wechat.example.com/wc_login.php?code=CODE&state=STATE

GET文字列として送られ来るCODEがアクセストークンを取得する為のチケットです。STATEはリダイレクトの際に指定した値がそのまま返って来ます。
ちなみにユーザーがQRコードをスキャンした後で情報提供を拒否すると画面上は以下のような表示に変わります。

ユーザーがスマホ側でログインを拒否した場合の画面例

アドレスバーのドメインがまだ「open.wechat.qq.com」ですので、ユーザーが拒否してもサイトの方には戻って来ていない事が分かります。また、コールバックURLへの通知もありませんので、サイト側がユーザーが拒否した事を知る術はありません。

⑤チケットを利用してアクセストークンを取得する

ユーザーが情報提供へ同意したらコールバックURLにチケットが送られて来ます。このチケットを使ってWeChatエコシステムのAPIを呼び出す時に必要なアクセストークンを取得します。具体的には以下のAPIを呼び出します。

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

このAPIに渡すパラメータは以下の3つです。

  • APPID
    WeChatオープンプラットフォーム上で追加したサイトのAppIDを指定します。QRコードを表示する為にリダイレクトさせた時に指定したAppIDと同じものを指定します。

  • SECRET
    WeChatオープンプラットフォーム上で発行したサイトのAppSecretを指定します。

  • CODE
    コールバックURLに送られて来たチケット(CODE)をそのまま指定します。

設定したパラメータに間違いがなく、リクエストが正常に受理されるとWeChatシステムは以下のようなJSONデータを返して来ます。

{ 
  "access_token":"ACCESS_TOKEN", 
  "expires_in":7200, 
  "refresh_token":"REFRESH_TOKEN",
  "openid":"OPENID", 
  "scope":"SCOPE",
  "unionid": "UNIONID"
}

返って来るJSONデータの各要素の意味は以下の通りです。

  • access_token
    WeChatエコシステムのAPIを利用する為のトークンです。と言ってもソーシャルログインで得られるチケットから取得出来るトークンの利用範囲は大変狭く、ユーザーのプロフィール画像とニックネームを取得する事しか出来ません。

  • expires_in
    このトークンの有効期限(秒単位)です。通常は7200秒(2時間)です。

  • refresh_token
    このトークンの有効期限を延長したり新しい「access_token」を取得する際に使うトークンです。使い方は後述します。

  • openid
    情報提供を許可したユーザーのOpenIDです。

  • scope
    このトークンに許可された権限です。WeChatソーシャルログインの流れでは「snsapi_userinfo」という文字列だけが返されるはずです。
    今回の手順で呼び出したAPI(/sns/oauth2/access_token)はWeChatソーシャルログインだけでなく、その他のWeChatエコシステムのSNSAPIを使う場面でも利用されるAPIですので、このような要素が必要となります。
    ソーシャルログインだけを使う場合はこの要素の内容を気にする必要はありません。

  • unionid
    情報提供を許可したユーザーのUnionIDです。WeChatソーシャルログインはWeChatオープンプラットフォームの機能ですので、必ずUnionIDが取得出来ます。上記OpenIDとの違いはこちらの記事をご覧ください。

⑥アクセストークンを使ってユーザー情報を取得する

アクセストークンを使ってユーザー情報を取得するには以下のAPIを利用します。

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

APIに指定する各パラメータの意味は以下の通りです。

  • ACCESS_TOKEN
    手順⑤で取得したアクセストークンを指定します。

  • OPENID
    アクセストークンと一緒に送られて来たOpenIDを指定します。実は一緒に送られて来たものとは違う別のOpenIDを指定してもエラーにはなりません。それどころかデタラメな文字列を送り付けても、アクセストークンさえ正しければリクエストは成功します。(何も指定しないとさすがにエラーになります)

APIのリクエストが成功すると以下のようなJSONデータが返って来ます。

{
   "openid":"OPENID",
   "nickname":"NICKNAME",
   "sex":0,
   "province":"",
   "city":"",
   "country":"",
   "headimgurl": "https://thirdwx.qlogo.cn/mmopen/vi_32/xxxxxxxxxxxxxxxxxxxxx/132",
   "privilege":[
      "PRIVILEGE1",
      "PRIVILEGE2"
   ],
   "unionid": "UNIONID"
}

JSONデータの各項目の意味は以下の通りです。

  • openid
    情報提供を許可したユーザーのOpenIDです。API呼び出し時にパラメータ「OPENID」に指定した文字列とは無関係に情報提供を許可したユーザーのOpenIDが戻されます。

  • nickname
    情報提供を許可したユーザーのWeChat上でのニックネームです。ニックネームはユーザーが頻繁に変える可能性がありますし、WeChatエコシステム内でユニークでもありませんのでログインIDには使えませんが、WeChatソーシャルログインを利用するサイトでニックネームを設定できる場合はこの値を初期値として入れておいてあげると親切です。

  • sex,province,city,country
    元々は情報提供を許可したユーザーの性別や居住地の情報がこれらの要素に入っていましたが、2021年10月頃からこれらの値は常に0や空文字列となっています。

  • headimgurl
    情報提供を許可したユーザーがWeChatで設定しているプロフィール画像へのURLです。末尾の数字は画像サイズを表しており、自分で書き換える事で「0」「46」「64」「96」「132」の5種類が指定可能です。「0」を指定した場合はWeChatシステムが保持している一番大きなサイズの画像が表示され、それ以外の数値は数値がそのままピクセル数となります。(例えば132を指定すると縦132px横132pxの画像が表示されます)
    ユーザーがプロフィール画像を変更するとこのURLが無効になる事に注意しましょう。ユーザーがいつプロフィール画像を変更するか分からないので、APIでURLを取得したらすぐに画像をサーバへダウンロードして保存しておく事をお勧めします。

  • privilege
    情報提供を許可したユーザーに与えられている特権情報がリストで提供されるみたいですが、私はここに値が入っているユーザーを見たことがありません。基本的に無視して良いでしょう。

  • unionid
    情報提供を許可したユーザーのUnionIDです。

お気づきの通りニックネームとプロフィール画像以外の情報は意味が無いか、手順⑤でのアクセストークン取得時に既に手に入っているものになります。ユーザーの識別に使えるOpenIDUnionIDがあれば十分という事であればこの手順⑥は実施しなくてOKです。

アクセストークンを保持し続ける意味はあるのか

さて、アクセストークンを取得した際に「refresh_token」というものが一緒に送られて来ました。
このリフレッシュトークンは、アクセストークンの有効期限(2時間)を延長したり、新しいアクセストークンを取得する為のものです。
以下のAPIで利用する事が出来ます。

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

APPIDには自分のAppIDを、REFRESH_TOKENにはアクセストークンと一緒に送られて来た「refresh_token」を指定します。
このAPI呼び出しが成功すると、アクセストークンの有効期限が2時間延長されます。また、もし既にアクセストークンの有効期限が切れていた場合は新たにアクセストークン(有効期限は同じく2時間)が発行されます。
いずれの場合もJSONデータとしてアクセストークンが返されます。
なお、リフレッシュトークン自体の有効期限は30日間で延長は出来ません。つまり、ユーザーが一度情報提供を許可すると、30日間はサイト側がアクセストークンを延長・再取得する事が可能で、その間はユーザーの情報へアクセス可能となりますが、得られる情報がニックネームとプロフィール画像だけである事、ユーザーが再度サイトを訪れてWeChatソーシャルログインを利用してログインした場合は新たにアクセストークンを取得出来る事を勘案するとこのリフレッシュトークンを利用してアクセストークンを保持し続ける意味は無いかと思います。
(ソーシャルログインにおいては意味がないですが、WeChatオープンプラットフォームのサードパーティ授権機能を使う際には、このリフレッシュトークンは重要なファクターになって来ます)

QRコードを自サイトに表示する方法

APIリンクでユーザーをWeChatシステムへ遷移させる方法は実装が簡単ですが、リダイレクトした先でQRコードが表示される画面は白地にサイト名とQRコードがポツンと配置された非常に寂しいデザインしかありません。その為、実際にWeChatソーシャルログインを実装している中国のサイトでは自サイトへQRコードを埋め込む方法を採用している場合がほとんどです。
サイト側でQRコードを表示したいページで以下のライブラリを読み込みます。

https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js

次にQRコードを表示したい場所をdivタグなどで指定します。(タグのidは任意に決めてOKです)

<div id="wx_login_container"></div>

最後にWxLoginオブジェクトを生成します。

var obj = new WxLogin({
        self_redirect: false,
        id:"wx_login_container", 
        appid: "APPID", 
        scope: "snsapi_login", 
        redirect_uri: "https%3A%2F%2Fwechat.example.com%2Flogin.php",
        state: "",
        style: "black",
        href: ""
});

WxLoginオブジェクトのコンストラクタに渡しているパラメータの意味は以下の通りです。

  • self_redirect
    コールバックURLをiframe内に読み込むかトップウィンドウに読み込むかの設定です。「true」を指定するとiframe内に読み込み、「false」を設定するとトップウィンドウに読み込みます。

  • id
    QRコードを表示する位置を指定したタグのidを指定します。

  • appid
    サイトのAppIDを指定します。

  • scope
    要求する権限スコープを指定します。ソーシャルログインの場合は「snsapi_login」で固定です。

  • redirect_uri
    ユーザーが情報提供に同意した場合に呼び出されるコールバックURLを指定します。このURLはURLエンコードされている必要があります。

  • state
    チケットと一緒にコールバックURLに渡される値です。指定しなくても良いですが、都度ランダムな文字列を指定しておいてコールバックURL側でチェックするようにするとより安全です。

  • style
    QRコードの上下に表示されるテキストの色を「black」(黒)か「white」(白)で指定出来ます。デフォルトの文字色は黒なのでサイトの背景色が黒だと文字が読めません。そういう場合は「white」を指定すると文字色が白になって読みやすくなります。

  • href
    QRコードを表示する際のスタイルシートを上書きしたい場合に、cssファイルのURLを指定します。相対パスは使えません。また、URLはURLエンコードする必要があります。

例えば自サイト上にQRコードをのみを表示したい場合は以下の様に記述します。
【QRコードを表示するhtml】

<html>
   <head>
      <title>欢迎加入!</title>
      <script src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
   </head>
   
   <body>
      <div id="wx_login_container"></div>
      <script>
         var obj = new WxLogin({
            self_redirect: false,
            id:"wx_login_container", 
            appid: "wxaaaaaaaaaaaaaaaa", 
            scope: "snsapi_login", 
            redirect_uri: "https%3A%2F%2Fwechat.example.com%2Flogin.php",
            state: "",
            style: "white",
            href: "https%3A%2F%2Fwechat.example.com%2Fnotext.css"
         });
      </script>
   </body>
</html>

【QRコード以外の表示を消すcss(notext.css)】

.impowerBox .title {display: none;}
.impowerBox .info {display: none;}

参考ドキュメント

【网站应用微信登录开发指南】
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

この記事が気に入ったらサポートをしてみませんか?