diff --git a/.gitbook/assets/wechat-account-id.png b/.gitbook/assets/wechat-account-id.png
deleted file mode 100644
index fa2ba06..0000000
Binary files a/.gitbook/assets/wechat-account-id.png and /dev/null differ
diff --git a/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (2).png b/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (2).png
deleted file mode 100644
index 2f8be46..0000000
Binary files a/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (2).png and /dev/null differ
diff --git a/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (9).png b/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (9).png
deleted file mode 100644
index 2f8be46..0000000
Binary files a/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (9).png and /dev/null differ
diff --git a/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (5) (2).png b/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (5) (2).png
deleted file mode 100644
index 2f8be46..0000000
Binary files a/.gitbook/assets/wechat-development-information (5) (5) (5) (5) (5) (2).png and /dev/null differ
diff --git a/.gitbook/assets/wechat-mobile-app-id.png b/.gitbook/assets/wechat-mobile-app-id.png
deleted file mode 100644
index e903f65..0000000
Binary files a/.gitbook/assets/wechat-mobile-app-id.png and /dev/null differ
diff --git a/.gitbook/assets/wechat-mobile-appid.png b/.gitbook/assets/wechat-mobile-appid.png
new file mode 100644
index 0000000..b99ffb3
Binary files /dev/null and b/.gitbook/assets/wechat-mobile-appid.png differ
diff --git a/.gitbook/assets/wechat-mobile-appsecret.png b/.gitbook/assets/wechat-mobile-appsecret.png
new file mode 100644
index 0000000..77caed6
Binary files /dev/null and b/.gitbook/assets/wechat-mobile-appsecret.png differ
diff --git a/.gitbook/assets/wechat-mobile-play-store-keystore-md5.png b/.gitbook/assets/wechat-mobile-play-store-keystore-md5.png
new file mode 100644
index 0000000..37d4adf
Binary files /dev/null and b/.gitbook/assets/wechat-mobile-play-store-keystore-md5.png differ
diff --git a/.gitbook/assets/wechat-open-platform-account-id.png b/.gitbook/assets/wechat-open-platform-account-id.png
new file mode 100644
index 0000000..ac815ac
Binary files /dev/null and b/.gitbook/assets/wechat-open-platform-account-id.png differ
diff --git a/.gitbook/assets/wechat-sandbox-account-id.png b/.gitbook/assets/wechat-sandbox-account-id.png
deleted file mode 100644
index 6aac3c8..0000000
Binary files a/.gitbook/assets/wechat-sandbox-account-id.png and /dev/null differ
diff --git a/.gitbook/assets/wechat-web-appid.png b/.gitbook/assets/wechat-web-appid.png
new file mode 100644
index 0000000..760c201
Binary files /dev/null and b/.gitbook/assets/wechat-web-appid.png differ
diff --git a/.gitbook/assets/wechat-web-appsecret.png b/.gitbook/assets/wechat-web-appsecret.png
new file mode 100644
index 0000000..08501e1
Binary files /dev/null and b/.gitbook/assets/wechat-web-appsecret.png differ
diff --git a/SUMMARY.md b/SUMMARY.md
index cf8aab9..f67c257 100644
--- a/SUMMARY.md
+++ b/SUMMARY.md
@@ -68,7 +68,8 @@
* [Connect Apps to Facebook](authentication-and-access/social-enterprise-login-providers/social-login-providers/facebook.md)
* [Connect Apps to GitHub](authentication-and-access/social-enterprise-login-providers/social-login-providers/github.md)
* [Connect Apps to LinkedIn](authentication-and-access/social-enterprise-login-providers/social-login-providers/linkedin.md)
- * [Connect Apps to WeChat](authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat.md)
+ * [Connect Mobile Apps to WeChat](authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-mobile.md)
+ * [Connect Websites to WeChat](authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-web.md)
* [Enterprise Login Providers](authentication-and-access/social-enterprise-login-providers/enterprise-login-providers/README.md)
* [Connect Apps to Azure Active Directory](authentication-and-access/social-enterprise-login-providers/enterprise-login-providers/azureadv2.md)
* [Connect Apps to Microsoft AD FS](authentication-and-access/social-enterprise-login-providers/enterprise-login-providers/adfs.md)
diff --git a/authentication-and-access/social-enterprise-login-providers/README.md b/authentication-and-access/social-enterprise-login-providers/README.md
index a8a66e0..bb60529 100644
--- a/authentication-and-access/social-enterprise-login-providers/README.md
+++ b/authentication-and-access/social-enterprise-login-providers/README.md
@@ -16,5 +16,5 @@ Authgear supports the following social and enterprise identity providers. Please
* [Azure Active Directory](enterprise-login-providers/azureadv2.md)
* [Azure AD B2C](enterprise-login-providers/azureadb2c.md)
* [Microsoft AD FS](enterprise-login-providers/adfs.md)
-* [WeChat](social-login-providers/wechat.md)
-
+* [Mobile application with WeChat Login](social-login-providers/wechat-mobile.md)
+* [Website with WeChat Login](social-login-providers/wechat-web.md)
diff --git a/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-mobile.md b/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-mobile.md
new file mode 100644
index 0000000..4fe4812
--- /dev/null
+++ b/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-mobile.md
@@ -0,0 +1,1040 @@
+# Connect Mobile Apps to WeChat
+
+{% hint style="info" %}
+**WeChat Open Platform account (微信开放平台账号)** is different from **WeChat Official account (微信公众平台账号)**. Authgear supports integrating WeChat Login with a WeChat Open Platform account.
+{% endhint %}
+
+## Prerequisite
+
+- Register a WeChat Open Platform account (微信开放平台账号).
+- Register a Mobile Application (移动应用).
+ - For **iOS**, WeChat Open Platform requires your app to support Associated Domains and Universal Links. See [the official documentation](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content/) from Apple for details.
+ - For **Android**, WeChat Open Platform requires you to tell them the MD5 fingerprint of the signing keystore.
+
+## Get the information from WeChat Open Platform
+
+- Get the `appid` (**Client ID**).
+
+where to find appid
+
+- Get the `appsecret` (**Client Secret**). It will only be shown once. You need to re-generate if you lose it.
+
+where to find appsecret
+
+- Get the `原始ID` (**Account ID**) of your WeChat Open Platform account.
+
+where to find account ID
+
+## Configure Sign in with WeChat in the Authgear portal
+
+1. Sign in to the Authgear portal.
+2. Select your project.
+3. In the navigation menu, go to **Authentication > Social / Enterprise Login**.
+4. Click **Add Connection**.
+5. Select **WeChat Mobile / 移动应用**.
+6. Fill in **Client ID** with the `appid`.
+7. Fill in **Client Secret** with the `appsecret`.
+8. Fill in **Account ID** with the `原始ID`.
+9. Add a WeChat Redirect URI. This is typically a custom URI with the scheme being your iOS bundle identifier or your Android package name. For example, `com.myapp://authgear/open_wechat_app`.
+10. Save.
+
+## Integrate the WeChat SDK into your iOS app
+
+{% hint style="info" %}
+You can skip this section if you do not have an iOS app.
+{% endhint %}
+
+{% hint style="info" %}
+This section assumes you install the WeChat SDK with [CocoaPods](https://cocoapods.org/).
+{% endhint %}
+
+To integrate the WeChat SDK into your iOS app, you have to read [the official integration guide](https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/iOS.html).
+
+This section reminds you some of the important points that you may miss in the official integration guide.
+
+### Install the latest version of the WeChat SDK for iOS
+
+```
+pod "WechatOpenSDK-XCFramework", "~> 2.0.4"
+```
+
+The latest version can be found at [this URL](https://cocoapods.org/pods/WechatOpenSDK)
+As of the time of writing, the latest version is `2.0.4`.
+
+### Specify your WeChat `appid` in Info.plist
+
+```
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ weixin
+ CFBundleURLSchemes
+
+ wxYOUR_WECHAT_APPID
+
+
+
+```
+
+### Specify LSApplicationQueriesSchemes in Info.plist
+
+```
+ LSApplicationQueriesSchemes
+
+ weixin
+ weixinULAPI
+ weixinURLParamsAPI
+
+```
+
+In case you have other schemes, you need to make sure the WeChat ones are the first 50 items.
+
+### Make sure `OTHER_LDFLAGS` contains `-ObjC`
+
+{% hint style="info" %}
+If you fail to do so, you will encounter [this error](https://developers.weixin.qq.com/community/develop/article/doc/000e8e316d4590c7ef92ec1a366c13).
+{% endhint %}
+
+The WeChat SDK for iOS depends on the Objective-C runtime. Therefore, your app has to link to the Objective-C runtime. To do so, you need to make sure `OTHER_LDFLAGS` contains `-ObjC`.
+
+The `-ObjC` flag is so special in CocoaPods that you **CANNOT** add it with CocoaPods [post_install](https://guides.cocoapods.org/syntax/podfile.html#post_install) hook.
+
+If your iOS app is written in [React Native](https://reactnative.dev/), the app is likely to have `OTHER_LDFLAGS` including `-ObjC` already, as React Native depend on the Objective-C runtime.
+
+In other case, you need to manually edit your Build Settings to include the `-ObjC` flag.
+
+### Add the integration code for the WeChat SDK for iOS
+
+{% tabs %}
+{% tab title="Swift WeChat SDK" %}
+
+In your `AppDelegate.swift`
+
+```swift
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Insert this line to register your WeChat mobile application.
+ WXApi.registerApp("wxYOUR_WECHAT_APPID", universalLink: "https://myapp.com/wechat/")
+ return true
+ }
+
+ func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
+ // Forward the URL to the WeChat SDK.
+ // If the URL is about WeChat integration, onResp will be called.
+ WXApi.handleOpen(url, delegate: self)
+ return true
+ }
+
+ func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
+ // Forward the URL to the WeChat SDK.
+ // If the URL is about WeChat integration, onResp will be called.
+ WXApi.handleOpen(url, delegate: self)
+ return true
+ }
+
+ func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
+ // Forward the NSUserActivity to the WeChat SDK.
+ // If the NSUserActivity is about WeChat integration, onResp will be called.
+ WXApi.handleOpenUniversalLink(userActivity, delegate: self)
+ return true
+ }
+
+ // Implements WXApiDelegate.
+ // You need not do any thing special in this method.
+ func onReq(_ req: BaseReq) {}
+
+ // The WeChat SDK will call this method if the forwarded callbacks are about WeChat.
+ func onResp(_ resp: BaseResp) {
+ guard let authResp = resp as? SendAuthResp else {
+ return
+ }
+
+
+ let errCode = WXErrCode(rawValue: authResp.errCode)
+ if errCode == WXSuccess {
+ let state = authResp.state
+ let code = authResp.code
+ // Forward code to Authgear SDK.
+ } else {
+ // Handle the error returned by the WeChat SDK properly to deliver good user experience.
+ }
+ }
+}
+```
+
+In your `SceneDelegate` (if you have one)
+
+```swift
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+ func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
+ // Assume your AppDelegate is the single point of handling WeChat callback,
+ // you need to get it back.
+ let appDelegate = UIApplication.shared.delegate as? AppDelegate
+
+ // Forward the NSUserActivity to the WeChat SDK.
+ // If the NSUserActivity is about WeChat integration, onResp on AppDelegate will be called.
+ WXApi.handleOpenUniversalLink(userActivity, delegate: appDelegate)
+ }
+}
+```
+
+{% endtab %}
+{% tab title="Objective-C WeChat SDK" %}
+
+In your `AppDelegate.h`
+
+```objc
+// Import the WeChat SDK header file.
+#import
+
+// Declare your AppDelegate to be a WXApiDelegate.
+@interface AppDelegate : UIResponder
+
+@end
+```
+
+In your `AppDelegate.m`
+
+```objc
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ // Insert this line to register your WeChat mobile application.
+ [WXApi registerApp:@"wxYOUR_WECHAT_APPID" universalLink:@"https://myapp.com/wechat/"];
+ return true;
+}
+
+- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
+ // Forward the URL to the WeChat SDK.
+ // If the URL is about WeChat integration, onResp will be called.
+ [WXApi handleOpenURL:url delegate:self];
+ return true;
+}
+
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
+ // Forward the URL to the WeChat SDK.
+ // If the URL is about WeChat integration, onResp will be called.
+ [WXApi handleOpenURL:url delegate:self];
+ return true;
+}
+
+- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray> * __nullable restorableObjects))restorationHandler {
+ // Forward the NSUserActivity to the WeChat SDK.
+ // If the NSUserActivity is about WeChat integration, onResp will be called.
+ [WXApi handleOpenUniversalLink:userActivity delegate:self];
+ return true;
+}
+
+// Implements WXApiDelegate.
+// You need not do any thing special in this method.
+-(void) onReq:(BaseReq*)req
+{
+}
+
+// The WeChat SDK will call this method if the forwarded callbacks are about WeChat.
+-(void) onResp:(BaseResp*)resp
+{
+ if([resp isKindOfClass:[SendAuthResp class]]) {
+ SendAuthResp *sendAuthResp = (SendAuthResp*)resp;
+ if (sendAuthResp.errCode == WXSuccess) {
+ NSString *state = sendAuthResp.state;
+ NSString *code = sendAuthResp.code;
+ // Forward code to Authgear SDK.
+ } else {
+ // Handle the error returned by the WeChat SDK properly to deliver good user experience.
+ }
+ }
+}
+
+@end
+```
+
+In your `SceneDelegate.m` (if you have one)
+
+```objc
+@implementation SceneDelegate
+
+- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
+ // Assume your AppDelegate is the single point of handling WeChat callback,
+ // you need to get it back.
+ AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
+
+ // Forward the NSUserActivity to the WeChat SDK.
+ // If the NSUserActivity is about WeChat integration, onResp on AppDelegate will be called.
+ [WXApi handleOpenUniversalLink:userActivity delegate:appDelegate];
+}
+
+@end
+```
+
+{% endtab %}
+{% endtabs %}
+
+## Integrate the WeChat SDK into your Android app
+
+{% hint style="info" %}
+You can skip this section if you do not have an Android app.
+{% endhint %}
+
+To integrate the WeChat SDK into your Android app, you have to read [the official integration guide](https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/Android.html).
+
+This section reminds you some of the important points that you may miss in the official integration guide.
+
+### Install the latest version of the WeChat SDK for Android
+
+```
+implementation "com.tencent.mm.opensdk:wechat-sdk-android:6.8.34"
+```
+
+The latest version can be found at [this URL](https://central.sonatype.com/artifact/com.tencent.mm.opensdk/wechat-sdk-android)
+As of the time of writing, the latest version is `6.8.34`.
+
+### Declare `` in your `AndroidManifest.xml`
+
+You need to declare in your `AndroidManifest.xml` that your app is supposed to query the existence of the WeChat app at runtime.
+
+Add this to your `AndroidManifest.xml`.
+
+```xml
+
+
+
+```
+
+### Declare your callback Activity in your `AndroidManifest.xml`
+
+The WeChat SDK opens the Activity `PACKAGE_NAME.wxapi.WXEntryActivity`. You need to implement that Activity and declare it in your `AndroidManifest.xml`.
+
+```xml
+
+ android:name="com.myapp.wxapi.WXEntryActivity"
+
+ android:exported="true"
+
+ android:launchMode="singleTask"
+
+ android:taskAffinity="com.myapp"
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
+
+```
+
+### Implement the callback Activity
+
+The full Java name of the Activity must be `PACKAGE_NAME.wxapi.WXEntryActivity`. If the package name you tell WeChat Open Platform is `com.myapp`, then the full Java name of the Activity must be `com.myapp.wxapi.WXEntryActivity`.
+
+Here is an example implementation that is based on BroadcastReceiver:
+
+```java
+import com.tencent.mm.opensdk.constants.ConstantsAPI;
+import com.tencent.mm.opensdk.modelbase.BaseReq;
+import com.tencent.mm.opensdk.modelbase.BaseResp;
+import com.tencent.mm.opensdk.modelmsg.SendAuth;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
+ private IWXAPI api;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ api = WXAPIFactory.createWXAPI(this, "wxYOUR_WECHAT_APPID", true);
+ api.registerApp("wxYOUR_WECHAT_APPID");
+
+ try {
+ Intent intent = getIntent();
+ api.handleIntent(intent, this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+ api.handleIntent(intent, this);
+ }
+
+ @Override
+ public void onReq(BaseReq req) {
+ }
+
+ @Override
+ public void onResp(BaseResp resp) {
+ String error = null;
+
+ switch (resp.errCode) {
+ case BaseResp.ErrCode.ERR_OK:
+ break;
+ case BaseResp.ErrCode.ERR_USER_CANCEL:
+ error = "errcode_cancel";
+ break;
+ case BaseResp.ErrCode.ERR_AUTH_DENIED:
+ error = "errcode_deny";
+ break;
+ case BaseResp.ErrCode.ERR_UNSUPPORT:
+ error = "errcode_unsupported";
+ break;
+ default:
+ error = "errcode_unknown";
+ break;
+ }
+
+ if (resp.getType() == ConstantsAPI.COMMAND_SENDAUTH) {
+ SendAuth.Resp authResp = (SendAuth.Resp)resp;
+
+ String state = authResp.state;
+ Intent intent = new Intent(state);
+ intent.putExtra("state", state);
+
+ intent.setPackage(this.getApplicationContext().getPackageName());
+ if (error != null) {
+ intent.putExtra("error", error);
+ } else {
+ intent.putExtra("code", authResp.code);
+ }
+
+ this.getApplicationContext().sendBroadcast(intent);
+ }
+ finish();
+ }
+}
+```
+
+### Make sure your Android app is signed by the keystore you tell WeChat Open Platform
+
+On WeChat Open Platform, you need to tell it the MD5 fingerprint of the keystore you use to sign your Android app.
+
+If you use Google Play Console to distribute your Android app, it is likely that you are using [Play App Signing](https://support.google.com/googleplay/android-developer/answer/9842756?hl=en). With Play App Signing, you tell Google the fingerprint of the keystore you originally sign your app. Google removes the signature and uses its managed keystore to sign the app before distributing the app to Play Store. The final app running on the device of course bears the signature of the managed keystore. This is also the signature the WeChat SDK sees when it validates the signature.
+
+To get the MD5 fingerprint of the managed keystore, refer to the following screenshot:
+
+where to find the MD5 fingerprint of the managed keystore
+
+Note that the MD5 fingerprint you see on Google Play Console is a **colon-delimited uppercase hex string**, while WeChat Open Platform expects you to provide a **plain lowercase hex string**.
+
+For example, suppose the MD5 fingerprint you get from Google Play Console is `D4:1D:8C:D9:8F:00:B2:04:E9:80:09:98:EC:F8:42:7E`, you can use the following shell command to do the conversion.
+
+```sh
+$ echo "D4:1D:8C:D9:8F:00:B2:04:E9:80:09:98:EC:F8:42:7E" | sed 's/://g' | tr 'A-Z' 'a-z'
+d41d8cd98f00b204e9800998ecf8427e
+```
+
+The output `d41d8cd98f00b204e9800998ecf8427e` is in the expected WeChat Open Platform format.
+
+For those of you who produce the final signature of your app using your own keystore, you can use the following shell command to output the MD5 fingerprint.
+
+```sh
+keytool -exportcert -keystore "$STORE_FILE" -storepass "$STORE_PASSWORD" -alias "$KEY_ALIAS" -rfc | openssl x509 -noout -fingerprint -md5
+```
+
+Where
+- `STORE_FILE` is an environment variable pointing to the keystore file on your machine, for example, `./mykeystore.jks`.
+- `STORE_PASSWORD` is an environment variable containing the password of the keystore.
+- `KEY_ALIAS` is an environment variable indicating which key in the keystore to use.
+
+## Configure Authgear SDK for WeChat
+
+You have 2 actions to take:
+
+1. Switch to `WebKitWebViewUIImplementation` when you initialize the Authgear SDK.
+2. Implement the callback / delegate of `WebKitWebViewUIImplementation`.
+
+### Switch to `WebKitWebViewUIImplementation`
+
+{% tabs %}
+{% tab title="iOS WebKitWebViewUIImplementation" %}
+
+```swift
+import Authgear
+
+let uiImplementation = WKWebViewUIImplementation()
+// Put the WeChat redirect URI you added in the Authgear portal here.
+uiImplementation.wechatRedirectURI = URL(string: "com.myapp://authgear/open_wechat_app")!
+// You need to implement the delegate to bridge between the WeChat SDK and the Authgear SDK.
+uiImplementation.authgearDelegate = self
+
+self.authgear = Authgear(
+ clientId: "AUTHGEAR_CLIENT_ID",
+ endpoint: "https://myapp.authgear.cloud",
+ uiImplementation: uiImplementation
+)
+```
+
+{% endtab %}
+{% tab title="Android WebKitWebViewUIImplementation" %}
+
+```java
+WebKitWebViewUIImplementation impl = new WebKitWebViewUIImplementation();
+impl.setWechatRedirectURI(Uri.parse("com.myapp://authgear/open_wechat_app"));
+impl.setAuthgearDelegate(this);
+boolean isSsoEnabled = false;
+boolean isPreAuthenticatedURLEnabled = false;
+
+this.mAuthgear = new Authgear(
+ this.getApplicationContext(),
+ "AUTHGEAR_CLIENT_ID",
+ "https://myapp.authgear.cloud",
+ new TransientTokenStorage(),
+ impl,
+ isSsoEnabled,
+ isPreAuthenticatedURLEnabled,
+ null,
+ null
+);
+```
+
+{% endtab %}
+{% tab title="React Native WebKitWebViewUIImplementation" %}
+
+```typescript
+import authgear, {
+ WebKitWebViewUIImplementation,
+} from '@authgear/react-native';
+
+authgear.configure({
+ clientID: "AUTHGEAR_CLIENT_ID",
+ endpoint: "https://myapp.authgear.cloud",
+ uiImplementation: new WebKitWebViewUIImplementation({
+ ios: {
+ wechatRedirectURI: "com.myapp://authgear/open_wechat_app",
+ },
+ android: {
+ wechatRedirectURI: "com.myapp://authgear/open_wechat_app",
+ },
+ // You need to implement this callback to bridge between the WeChat SDK and the Authgear SDK.
+ sendWechatAuthRequest,
+ }),
+})
+```
+
+{% endtab %}
+{% tab title="Flutter WebKitWebViewUIImplementation" %}
+
+```dart
+import 'package:flutter_authgear/flutter_authgear.dart';
+
+var authgear = Authgear(
+ clientID: "AUTHGEAR_CLIENT_ID",
+ endpoint: "https://myapp.authgear.cloud",
+ uiImplementation: WebKitWebViewUIImplementation(
+ options: WebKitWebViewUIImplementationOptions(
+ ios: WebKitWebViewUIImplementationOptionsIOS(
+ wechatRedirectURI: "com.myapp://authgear/open_wechat_app",
+ ),
+ android: WebKitWebViewUIImplementationOptionsAndroid(
+ wechatRedirectURI: "com.myapp://authgear/open_wechat_app",
+ ),
+ // You need to implement this callback to bridge between the WeChat SDK and the Authgear SDK.
+ sendWechatAuthRequest: sendWechatAuthRequest,
+ ),
+ ),
+)
+```
+
+{% endtab %}
+{% endtabs %}
+
+### Implement the callback / delegate of `WebKitWebViewUIImplementation`
+
+{% hint style="info" %}
+This section assume you have integrated the WeChat SDK according to
+
+- [Add the integration code for the WeChat SDK for iOS](#add-the-integration-code-for-the-wechat-sdk-for-ios)
+- [Implement the callback Activity](#implement-the-callback-activity)
+
+In particular,
+
+- On iOS, you implement `WXApiDelegate` on your `AppDelegate`.
+- On Android, your `WXEntryActivity` sends a broadcast with `state` being the Intent action.
+{% endhint %}
+
+{% tabs %}
+{% tab title="iOS Authgear WeChat" %}
+
+In your `AppDelegate.swift`
+
+```swift
+import Authgear
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate, AuthgearDelegate {
+ // authgear is assumed to be initialised somewhere else.
+ var authgear: Authgear!
+
+ // Implements AuthgearDelegate
+ func sendWechatAuthRequest(_ state: String) {
+ // Open WeChat using the WeChat SDK.
+ let req = SendAuthReq()
+ req.scope = "snsapi_userinfo"
+ req.state = state
+ WXApi.send(req)
+ }
+
+ // Implements WXApiDelegate
+ func onResp(_ resp: BaseResp) {
+ guard let authResp = resp as? SendAuthResp else {
+ return
+ }
+
+ let errCode = WXErrCode(rawValue: authResp.errCode)
+ if errCode == WXSuccess {
+ let state = authResp.state
+ let code = authResp.code
+ // Forward code to Authgear SDK.
+ self.authgear?.wechatAuthCallback(code: code, state: state) { result in
+ switch result {
+ case .success():
+ // The code was sent to Authgear successfully.
+ // The end-user will proceed the login in the WebView.
+ // You do not need to do anything here.
+ break
+ case let .failure(error):
+ // Handle the error returned by the Authgear SDK properly to deliver good user experience.
+ }
+ }
+ } else {
+ // Handle the error returned by the WeChat SDK properly to deliver good user experience.
+ }
+ }
+}
+```
+
+{% endtab %}
+{% tab title="Android Authgear WeChat" %}
+
+In your `MainActivity.java`
+
+```java
+public class MainActivity extends AppCompatActivity implements AuthgearDelegate {
+ private IWXAPI mWeChatAPI;
+ // mAuthgear is assumed to be initialised somewhere else.
+ private Authgear mAuthgear;
+
+ @Override
+ public void sendWechatAuthRequest(String state) {
+ if (!this.mWeChatAPI.isWXAppInstalled()) {
+ // Handle WeChat not installed.
+ return;
+ }
+
+ Context ctx = this.getApplicationContext();
+
+ IntentFilter intentFilter = new IntentFilter(state);
+ BroadcastReceiver br;
+ br = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String state_ = intent.getStringExtra("state");
+ if (state_ != null && state_.equal(state)) {
+ ctx.unregisterReceiver(br);
+
+ String code = intent.getStringExtra("code");
+ String error = intent.getStringExtra("error");
+ if (code != null) {
+ mAuthgear.wechatAuthCallback(code, state, new OnWechatAuthCallbackListener() {
+ @Override
+ public void onWechatAuthCallback() {
+ // No need to do anything here.
+ }
+
+ @Override
+ public void onWechatAuthCallbackFailed(Throwable throwable) {
+ // Handle error.
+ }
+ });
+ } else {
+ // Handle error.
+ }
+ }
+ }
+ }
+ ContextCompat.registerReceiver(ctx, br, intentFilter, ContextCompat.RECEIVER_NOT_EXPORTED);
+
+ SendAuth.Req req = new SendAuth.Req();
+ req.scope = "snsapi_userinfo";
+ req.state = state;
+ this.mWeChatAPI.sendReq(req);
+ }
+}
+```
+
+{% endtab %}
+{% tab title="React Native Authgear WeChat" %}
+
+In your React Native TypeScript code
+
+```typescript
+import {
+ NativeModules,
+} from "react-native";
+import authgear from '@authgear/react-native';
+
+// This is the callback you pass to WebKitWebViewUIImplementation.
+async function sendWechatAuthRequest(state: string) {
+ // MyWeChatModule is the Native Module you need to implement yourselves to bridge
+ // between the WeChat SDK and the Authgear SDK.
+ const { code } = await NativeModules.MyWeChatModule.sendWechatAuthRequest(state);
+ await authgear.wechatAuthCallback(code, state);
+}
+```
+
+In your iOS Native Module `MyWeChatModule.h`
+
+```objc
+#import
+
+static NSString *const kMyWeChatModuleNotification = @"MyWeChatModuleNotification";
+
+@interface MyWeChatModule : NSObject
+@end
+```
+
+In your iOS Native Module `MyWeChatModule.m`
+
+```objc
+#import "MyWeChatModule.h"
+#import
+#import
+
+@interface MyWeChatModule()
+@property (nonatomic, strong) RCTPromiseResolveBlock sendWechatAuthResolve;
+@property (nonatomic, strong) RCTPromiseRejectBlock sendWechatAuthReject;
+@end
+
+@implementation MyWeChatModule
+
+RCT_EXPORT_MODULE(MyWeChatModule);
+
+- (instancetype)init
+{
+ if ((self = [super init])) {
+ // Listen to the notification posted by your WXApiDelegate.
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(handleWechatAuthResult:)
+ name:kMyWeChatModuleNotification
+ object:nil];
+ }
+ return self;
+}
+
+RCT_EXPORT_METHOD(sendWechatAuthRequest:(NSString *)state
+ resolve:(RCTPromiseResolveBlock)resolve
+ reject:(RCTPromiseRejectBlock)reject)
+{
+ self.sendWechatAuthResolve = resolve;
+ self.sendWechatAuthReject = reject;
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ SendAuthReq* req = [[SendAuthReq alloc] init];
+ req.scope = @"snsapi_userinfo";
+ req.state = state;
+ [WXApi sendReq:req completion:nil];
+ });
+}
+
+- (void)handleWechatAuthResult:(NSNotification *)notification
+{
+ if (notification.userInfo[@"code"]) {
+ self.sendWechatAuthResolve(notification.userInfo);
+ } else {
+ NSString *error = notification.userInfo[@"error"];
+ self.sendWechatAuthReject(RCTErrorUnspecified, error, error);
+ }
+ [self cleanup];
+}
+
+- (void)cleanup
+{
+ self.sendWechatAuthResolve = nil;
+ self.sendWechatAuthReject = nil;
+}
+
+@end
+```
+
+In your `WXApiDelegate`
+
+```objc
+-(void) onResp:(BaseResp*)resp
+{
+ if ([resp isKindOfClass:[SendAuthResp class]]) {
+ SendAuthResp *sendAuthResp = (SendAuthResp*)resp;
+ NSDictionary *payload;
+ if (sendAuthResp.errCode == WXSuccess) {
+ payload = @{
+ @"code": sendAuthResp.code,
+ @"state": sendAuthResp.state,
+ };
+ } else {
+ NSString *error;
+ switch (resp.errCode) {
+ case WXErrCodeUserCancel:
+ error = @"errcode_cancel";
+ break;
+ case WXErrCodeAuthDeny:
+ error = @"errcode_deny";
+ break;
+ case WXErrCodeUnsupport:
+ error = @"errcode_unsupported";
+ break;
+ default:
+ error = @"errcode_unknown";
+ break;
+ }
+ payload = @{
+ @"error": error,
+ };
+ }
+ // Send the notification to your MyWeChatModule.
+ [[NSNotificationCenter defaultCenter] postNotificationName:kMyWeChatModuleNotification
+ object:nil
+ userInfo:payload];
+ }
+}
+```
+
+In your Android Native Module `MyWeChatModule`
+
+```java
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.IntentFilter;
+import androidx.core.content.ContextCompat;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.tencent.mm.opensdk.openapi.IWXAPI;
+import com.tencent.mm.opensdk.openapi.WXAPIFactory;
+
+public class MyWeChatModule extends ReactContextBaseJavaModule {
+ private IWXAPI wechatAPI;
+
+ WechatAuthModule(ReactApplicationContext context) {
+ super(context);
+
+ wechatAPI = WXAPIFactory.createWXAPI(context, "wxYOUR_WECHAT_APPID", true);
+ wechatAPI.registerApp("wxYOUR_WECHAT_APPID");
+ }
+
+ @Override
+ public String getName() {
+ return "MyWeChatModule";
+ }
+
+ @ReactMethod
+ public void sendWechatAuthRequest(String state, Promise promise) {
+ if (!wechatAPI.isWXAppInstalled()) {
+ promise.reject(new Exception("You have not installed the WeChat client app"));
+ return;
+ }
+
+ Context ctx = this.getReactApplicationContext();
+
+ IntentFilter intentFilter = new IntentFilter(state);
+ BroadcastReceiver br;
+ br = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String state_ = intent.getStringExtra("state");
+ if (state_ != null && state_.equal(state)) {
+ ctx.unregisterReceiver(br);
+
+ String code = intent.getStringExtra("code");
+ String error = intent.getStringExtra("error");
+ if (code != null) {
+ WritableMap result = new WritableNativeMap();
+ result.putString("code", code);
+ result.putString("state", state);
+ promise.resolve(result);
+ } else {
+ promise.reject(error, error);
+ }
+ }
+ }
+ }
+ ContextCompat.registerReceiver(ctx, br, intentFilter, ContextCompat.RECEIVER_NOT_EXPORTED);
+
+ SendAuth.Req req = new SendAuth.Req();
+ req.scope = "snsapi_userinfo";
+ req.state = state;
+ wechatAPI.sendReq(req);
+ }
+}
+```
+
+{% endtab %}
+{% tab title="Flutter Authgear WeChat" %}
+
+In your Flutter code
+
+```dart
+import 'package:flutter/services.dart';
+import 'package:flutter_authgear/flutter_authgear.dart';
+
+// authgear is assumed to be initialised somewhere else.
+var authgear;
+
+const _nativeMethodChannel = MethodChannel("MyWeChatMethodChannel");
+
+// This is the callback you pass to WebKitWebViewUIImplementation.
+Future sendWechatAuthRequest(String state) async {
+ try {
+ final code = await _nativeMethodChannel.invokeMethod("sendWechatAuthRequest", {
+ "state": state,
+ });
+ await authgear.wechatAuthCallback(state: state, code: code);
+ } on PlatformException catch (e) {
+ print("exception: $e");
+ }
+}
+```
+
+In your `AppDelegate.swift`
+
+```swift
+import Flutter
+
+@main
+@objc class AppDelegate: FlutterAppDelegate, WXApiDelegate {
+
+ private var wechat = [String: FlutterResult]()
+
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ let controller = window?.rootViewController as! FlutterViewController
+ let channel = FlutterMethodChannel(name: "MyWeChatMethodChannel", binaryMessenger: controller.binaryMessenger)
+ channel.setMethodCallHandler {
+ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
+ let arguments = call.arguments as! Dictionary
+ let state = arguments["state"] as! String
+ self.wechat[state] = result
+ let req = SendAuthReq()
+ req.scope = "snsapi_userinfo"
+ req.state = state
+ WXApi.send(req)
+ }
+
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+
+ override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
+ WXApi.handleOpen(url, delegate: self)
+ return super.application(app, open: url, options: options)
+ }
+
+ override func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
+ WXApi.handleOpen(url, delegate: self)
+ return super.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
+ }
+
+ override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
+ WXApi.handleOpenUniversalLink(userActivity, delegate: self)
+ return super.application(application, continue: userActivity, restorationHandler: restorationHandler)
+ }
+
+ @objc
+ func onReq(_ req: BaseReq) {
+ }
+
+ @objc
+ func onResp(_ resp: BaseResp) {
+ guard let authResp = resp as? SendAuthResp else {
+ return
+ }
+
+ guard let state = authResp.state else {
+ return
+ }
+
+ guard let result = wechat.removeValue(forKey: state) else {
+ return
+ }
+
+ var error: String
+ switch WXErrCode(rawValue: authResp.errCode) {
+ case WXErrCodeUserCancel:
+ error = "errcode_cancel"
+ case WXErrCodeAuthDeny:
+ error = "errcode_deny"
+ case WXErrCodeUnsupport:
+ error = "errcode_unsupported"
+ default:
+ error = "errcode_unknown"
+ }
+
+ switch WXErrCode(rawValue: authResp.errCode) {
+ case WXSuccess:
+ let code = authResp.code
+ result(code)
+ default:
+ result(FlutterError(code: error, message: error, details: nil))
+ }
+ }
+}
+```
+
+In your `MainActivity.kt`
+
+```kotlin
+class MainActivity: FlutterFragmentActivity() {
+
+ private var api: IWXAPI? = null
+
+ override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
+ super.configureFlutterEngine(flutterEngine)
+
+ MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "MyWeChatMethodChannel").setMethodCallHandler { call, result ->
+ handleMethodCall(call, result)
+ }
+ }
+
+ private fun handleMethodCall(call: MethodCall, result: MethodChannel.Result) {
+ val api = api!!
+ if (!api.isWXAppInstalled) {
+ result.error("errcode_not_installed", "errcode_not_installed", null)
+ return
+ }
+
+ val state = call.argument("state")!!
+ val req = SendAuth.Req()
+ req.scope = "snsapi_userinfo"
+ req.state = state
+
+ var broadcastReceiver: BroadcastReceiver?
+ broadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ val state_ = intent.getStringExtra("state")
+ if (state_ == state) {
+ this@MainActivity.applicationContext.unregisterReceiver(broadcastReceiver)
+
+ val code = intent.getStringExtra("code")
+ val error = intent.getStringExtra("error")
+ if (code != null) {
+ result.success(code)
+ } else {
+ result.error(error, error, nil)
+ }
+ }
+ }
+ }
+ val intentFilter = IntentFilter(state)
+ ContextCompat.registerReceiver(this.applicationContext, broadcastReceiver, intentFilter, ContextCompat.RECEIVER_NOT_EXPORTED)
+ api.sendReq(req)
+ }
+}
+```
+
+{% endtab %}
+{% endtabs %}
diff --git a/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-web.md b/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-web.md
new file mode 100644
index 0000000..dbd74df
--- /dev/null
+++ b/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat-web.md
@@ -0,0 +1,44 @@
+# Connect Websites to WeChat
+
+{% hint style="info" %}
+**WeChat Open Platform account (微信开放平台账号)** is different from **WeChat Official account (微信公众平台账号)**. Authgear supports integrating WeChat Login with a WeChat Open Platform account.
+{% endhint %}
+
+## Prerequisite
+
+- Register a WeChat Open Platform account (微信开放平台账号).
+- Register a Website Application (网站应用).
+
+{% hint style="info" %}
+The 授权回调域 is the domain of your Authgear project, e.g. `myapp.authgear.cloud`. It is without URL scheme. If you ever change your Authgear project domain, you **MUST** update 授权回调域.
+{% endhint %}
+
+## Get the information from WeChat Open Platform
+
+- Get the `appid` (**Client ID**)
+
+where to find appid
+
+- Get the `appsecret` (**Client Secret**). It will only be shown once. You need to re-generate if you lose it.
+
+where to find appid
+
+- Get the `原始ID` (**Account ID**) of your WeChat Open Platform account.
+
+where to find account ID
+
+## Configure Sign in with WeChat in the Authgear portal
+
+1. Sign in to the Authgear portal.
+2. Select your project.
+3. In the navigation menu, go to **Authentication > Social / Enterprise Login**.
+4. Click **Add Connection**.
+5. Select **WeChat Web / 网站应用**.
+6. Fill in **Client ID** with the `appid`.
+7. Fill in **Client Secret** with the `appsecret`.
+8. Fill in **Account ID** with the `原始ID`.
+9. Save.
+
+## Done!
+
+No further changes are needed. The Sign in with WeChat button should be shown in the signup / login page now.
diff --git a/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat.md b/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat.md
deleted file mode 100644
index 033ff91..0000000
--- a/authentication-and-access/social-enterprise-login-providers/social-login-providers/wechat.md
+++ /dev/null
@@ -1,634 +0,0 @@
-# Connect Apps to WeChat
-
-## Web
-
-### Prerequisite
-
-To create a website application in WeChat, you can choose to setup a website application and wait for approval or a sandbox account for testing.
-
-### Setup the Website Application (网站应用)
-
-* Register an account in [WeChat Open Platform](https://open.weixin.qq.com).
-* Create Website Application (网站应用), fill in information and wait for approval (It may take few days).
-* View the application detail page, obtain the "AppID" and "AppSecret" on the top of the application page.
-* Go to Account Center > Basic information, to obtain the "原始ID".
-
-
-
-### Setup the Sandbox Application (微信公众平台接口测试帐号)
-
-* Use your WeChat app to login in [微信公众平台接口测试帐号申请](https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login).
-* Obtain the "appID", "appSecret" and "原始ID". The "原始ID" is the "微信号" in the top right corner.
-
-
-
-* Fill in 接口配置信息. The URL must be pointing at a publicly reachable server. The token is a string of your choice.
-* Implement the 接口配置信息 server. Here is an example written in Golang.
-
-```go
-package main
-
-import (
- "crypto/sha1"
- "crypto/subtle"
- "encoding/hex"
- "fmt"
- "io"
- "net/http"
- "sort"
- "strings"
-)
-
-type WechatVerifyHandler struct {
- Token string
-}
-
-func (h *WechatVerifyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- err := r.ParseForm()
- if err != nil {
- http.Error(w, err.Error(), http.StatusBadRequest)
- return
- }
-
- signature := r.Form.Get("signature")
- timestamp := r.Form.Get("timestamp")
- nonce := r.Form.Get("nonce")
- echostr := r.Form.Get("echostr")
-
- token := h.Token
-
- tmpArr := []string{token, timestamp, nonce}
- sort.Strings(tmpArr)
-
- tmpStr := strings.Join(tmpArr, "")
-
- hasher := sha1.New()
- io.WriteString(hasher, tmpStr)
- computedHash := hasher.Sum(nil)
- computedhashInHex := hex.EncodeToString(computedHash)
-
- if subtle.ConstantTimeCompare([]byte(signature), []byte(computedhashInHex)) == 1 {
- w.Write([]byte(echostr))
- return
- }
-
- http.Error(w, fmt.Sprintf("%v != %v", signature, computedhashInHex), http.StatusBadRequest)
-}
-
-func main() {
- http.Handle("/", &WechatVerifyHandler{
- Token: "TOKEN", // Change this value to the value you told Wechat!
- })
- http.ListenAndServe(":9999", nil)
-}
-```
-
-* Fill in JS接口安全域名. The value is your Authgear domain name plus port, e.g. `192.168.2.88:3000` or `myapp.authgear.cloud`
-* Fill in 网页授权获取用户基本信息. The value is your Authgear domain name plus port, e.g. `192.168.2.88:3000` or `myapp.authgear.cloud`
-* Look for an QR code in the sandbox settings page. You must scan it with your Wechat app and follow the sandbox account.
-
-### Configure Sign in with WeChat through the Authgear portal
-
-In the portal, do the following:
-
-1. In the portal, go to **Authentication > Social / Enterprise Login**.
-2. Enable **Sign in with WeChat (Web/网站应用)**.
-3. Fill in **Client ID** with the **AppID**.
-4. Fill in **Client Secret** with the **AppSecret**.
-5. Fill in **原始 ID** with the **原始 ID**.
-6. Check the checkbox **Is Sandbox account** if you are using sandbox account.
-7. **Save** the settings.
-
-## Mobile app (Native iOS app, Native Android app, React Native, and Flutter)
-
-### Overview of Setting Up Wechat
-
-Wechat integration is a bit more complicated then other social login, here are the overview of what needs to be done:
-
-* Register an account and create mobile application in WeChat Open Platform. Approval is needed in this process.
-* Enable and configure WeChat Login in Authgear portal.
-* Include Authgear SDK on your app.
-* Implement a delegate function to be triggered when user clicks the "Login with WeChat" button during authorization. You need to integrate WeChat SDK to open WeChat app to perform authentication in the delegate function (we have sample code below). After obtaining the authorization code from WeChat, call the Authgear callback with the auth code and complete the "Login With WeChat" process.
-
-Here are the detailed steps for iOS, Android, React Native, and Flutter.
-
-### Prerequisite - Setup the Mobile Application (移动应用)
-
-* Register an account in [WeChat Open Platform](https://open.weixin.qq.com).
-* Create Mobile Application (移动应用), fill in information and wait for approval (It may take few days).
-* View the application detail page, obtain the `AppID` and `AppSecret` on the top of the page.
-
-
-
-* Go to Account Center > Basic information, to obtain the "原始ID".
-
-
-
-* Save those values, we will need them in the section below.
-
-### Update code based on platform
-
-#### Native iOS application
-
-* Setup Authgear iOS SDK.
-* Follow [iOS接入指南](https://developers.weixin.qq.com/doc/oplatform/Mobile\_App/Access\_Guide/iOS.html) to setup WeChat SDK. For the coding part, we will further explain in the below steps.
-* `WechatOpenSDK` is Objective-C library. If you are using swift. You will need to create bridging header. To setup bridge header, please check [Importing Objective-C into Swift](https://developer.apple.com/documentation/swift/imported\_c\_and\_objective-c\_apis/importing\_objective-c\_into\_swift). Here is the example `WechatOpenSDK-Bridging-Header.h`.
-
- ```
- #ifndef WechatOpenSDK_Bridging_Header_h
- #define WechatOpenSDK_Bridging_Header_h
-
- #import "WXApiObject.h"
- #import "WXApi.h"
-
- #endif
- ```
-* After setting up the `WechatOpenSDK`, universal link should be enabled in your application. We will need two links for the setup. One is for the WeChat SDK used, another is for the Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here are the suggestion of the links.
- * **WECHAT\_UNIVERICAL\_LINK**: `https://{YOUR_DOMAIN}/wechat`
- * **WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR**: `https://{YOUR_DOMAIN}/open_wechat_app`
-* Login WeChat Open platform, open the application detail page, update the development information iOS section.
-
- (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (9).png>)
-
-* Fill in "Bundle ID" field with your app bundle id.
-* Fill in "Universal Links" with "WECHAT\_UNIVERICAL\_LINK" above.
-* Go to Authgear portal, do the following:
- * In the portal, go to **Authentication > Social / Enterprise Login**.
- * Enable **Sign in with WeChat (Mobile/移动应用)**.
- * Fill in **Client ID** with the **AppID**.
- * Fill in **Client Secret** with the **AppSecret**.
- * Fill in **原始 ID** with the **原始 ID**.
- * Add **WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR** above in **WeChat redirect URIs**.
- * **Save** the settings.
-* Update the code
- * Setup WeChat SDK when app launch
-
- ```swift
- // Replace WECHAT_APP_ID with wechat app id
- // Replace WECHAT_UNIVERICAL_LINK with the link defined above
- WXApi.registerApp("WECHAT_APP_ID", universalLink: "WECHAT_UNIVERICAL_LINK")
- WXApi.startLog(by: .detail) { log in
- print(#line, "wechat sdk wxapi: " + log)
- }
- ```
- * Setup Authgear delegate and call WeChat SDK when `sendWechatAuthRequest` is triggered
-
- ```swift
- // Replace self with the object that you implement the AuthgearDelegate
- authgear.delegate = self
-
- // Replace WECHAT_APP_ID with wechat app id
- extension MyClass: AuthgearDelegate {
- func sendWechatAuthRequest(_ state: String) {
- let req = SendAuthReq()
- req.openID = "WECHAT_APP_ID"
- req.scope = "snsapi_userinfo"
- req.state = state
- WXApi.send(req)
- }
- }
- ```
- * Handle universal link
-
- ```swift
- // Update App Delegate
- func application(_ application: NSApplication,
- continue userActivity: NSUserActivity,
- restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool {
- // wechat sdk handle, replace self with object implement WXApiDelegate
- WXApi.handleOpenUniversalLink(userActivity, delegate: self)
- // authgear sdk handle
- return authgear.application(application, continue: userActivity, restorationHandler: restorationHandler)
- }
-
- // If your app has opted into Scenes, Update Scene Delegate
- func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
- // wechat sdk handle, replace self with object implement WXApiDelegate
- WXApi.handleOpenUniversalLink(userActivity, delegate: self)
-
- // authgear sdk handle
- authgear.scene(scene, continue: userActivity)
- }
-
- // Implement WXApiDelegate
- extension MyClass: WXApiDelegate {
- func onReq(_ req: BaseReq) {}
- func onResp(_ resp: BaseResp) {
- // Receive code from WeChat, send callback to authgear
- // by calling `authgear.wechatAuthCallback`
- if resp.isKind(of: SendAuthResp.self) {
- if resp.errCode == 0 {
- let _resp = resp as! SendAuthResp
- if let code = _resp.code, let state = _resp.state {
- authgear.wechatAuthCallback(code: code, state: state) { result in
- switch result {
- case .success():
- // send wechat auth callback to authgear successfully
- case let .failure(error):
- // failed to send wechat auth callback to authgear
- }
- }
- }
- } else {
- // failed to obtain code from wechat sdk
- }
- }
- }
- }
- ```
- * Provide `wechatRedirectURI` when calling `authenticate` and `promoteAnonymousUser` in authgear sdk
-
- ```swift
- // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
- container?.authenticate(
- redirectURI: "REDIRECT_URI",
- prompt: "login",
- wechatRedirectURI: "WECHAT_REDIRECT_URI_FOR_AUTHGEAR"
- ) { result in
- }
-
- // For anonymous user support only
- // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
- container?.promoteAnonymousUser(
- redirectURI: "REDIRECT_URI",
- wechatRedirectURI: "WECHAT_REDIRECT_URI_FOR_AUTHGEAR"
- ) { result in
- }
-
- // Open setting page
- // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
- container?.open(
- page: .settings,
- wechatRedirectURI: "WECHAT_REDIRECT_URI_FOR_AUTHGEAR"
- )
- ```
-* Here is the completed [example](https://github.com/authgear/authgear-sdk-ios/tree/master/example).
-
-#### Native Android application
-
-* Setup Authgear iOS SDK.
-* Follow [Android接入指南](https://developers.weixin.qq.com/doc/oplatform/Mobile\_App/Access\_Guide/Android.html) to setup Wechat SDK. For the coding part, we will further explain in the below steps.
-* Login WeChat Open platform, open the application detail page, update the development information Android section.
-
- (5) (5) (5) (1) (1) (1) (1) (1) (1) (1) (1) (2).png>)
-
-* Fill in application signature, you can obtain it with command `keytool -list -v -keystore YOUR_KEYSTORE_FILE_PATH`. WeChat needs the certificate fingerprint in MD5, remove `:` in the fingerprint. It should be string in length 32.
-* Fill in your package name
-* We will need to define a custom url for Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here is the example, you should update it with your own scheme.
- * **"WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR"**: `com.myapp://host/open_wechat_app`
-* Go to Authgear portal, do the following:
- * In the portal, go to **Authentication > Social / Enterprise Login**.
- * Enable **Sign in with WeChat (Mobile/移动应用)**.
- * Fill in **Client ID** with the **AppID**.
- * Fill in **Client Secret** with the **AppSecret**.
- * Fill in **原始 ID** with the **原始 ID**.
- * Add **WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR** above in **WeChat redirect URIs**.
- * **Save** the settings.
-* Update the code
- * Update application `AndroidManifest.xml`
-
- ```markup
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ```
- * Configure WeChat SDK
-
- ```java
- private IWXAPI wechatAPI;
-
- private setupWechatSDK() {
- wechatAPI = WXAPIFactory.createWXAPI(app, YOUR_WECHAT_APP_ID, true);
- wechatAPI.registerApp(YOUR_WECHAT_APP_ID);
- }
- ```
- * Setup Authgear delegate
-
- ```java
- mAuthgear.setDelegate(new AuthgearDelegate() {
- @Override
- public void sendWechatAuthRequest(String state) {
- if (!wechatAPI.isWXAppInstalled()) {
- // User have not installed WeChat app, show them the error
- return;
- }
- SendAuth.Req req = new SendAuth.Req();
- req.scope = "snsapi_userinfo";
- req.state = state;
- wechatAPI.sendReq(req);
- }
- });
- ```
- * Create wxapi directory in the directory named after your package name and create `WXEntryActivity` activity. In `WXEntryActivity`, pass the received intent and the object that implements IWXAPIEventHandler API to the `handleIntent` method of the `IWXAPI` API, as shown below:
-
- ```java
- api.handleIntent(getIntent(), this);
- ```
-
- You will be able to receive the authentication code and state in `onResp` method, call Authgear `wechatAuthCallback` with `code` and `state`.
-
- ```java
- mAuthgear.wechatAuthCallback(code, state, new OnWechatAuthCallbackListener() {
- @Override
- public void onWechatAuthCallback() {
- }
-
- @Override
- public void onWechatAuthCallbackFailed(Throwable throwable) {
- }
- });
- ```
- * Provide `wechatRedirectURI` when calling `authorize` and `promoteAnonymousUser` in Authgear SDK.
-
- ```java
- // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
- AuthenticateOptions options = new AuthenticateOptions(AUTHGEAR_REDIRECT_URI);
- options.setWechatRedirectURI(WECHAT_REDIRECT_URI_FOR_AUTHGEAR);
- mAuthgear.authenticate(options, new OnAuthenticateListener() {
- @Override
- public void onAuthenticated(@Nullable UserInfo userInfo) {
- }
-
- @Override
- public void onAuthenticationFailed(@NonNull Throwable throwable) {
- }
- });
-
- // For anonymous user support only
- // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
- PromoteOptions options = new PromoteOptions(AUTHGEAR_REDIRECT_URI);
- options.setWechatRedirectURI(WECHAT_REDIRECT_URI_FOR_AUTHGEAR);
- mAuthgear.promoteAnonymousUser(options, new OnPromoteAnonymousUserListener() {
- @Override
- public void onPromoted(@NonNull UserInfo userInfo) {
- }
-
- @Override
- public void onPromotionFailed(@NonNull Throwable throwable) {
- }
- });
-
- // Open setting page
- // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
- SettingOptions options = new SettingOptions();
- options.setWechatRedirectURI(WECHAT_REDIRECT_URI_FOR_AUTHGEAR);
- mAuthgear.open(Page.Settings, options);
- ```
-* Here is the completed [example](https://github.com/authgear/authgear-sdk-android/tree/main/javasample).
-
-#### React Native
-
-* Setup Authgear SDK
-* Follow [iOS接入指南](https://developers.weixin.qq.com/doc/oplatform/Mobile\_App/Access\_Guide/iOS.html) and [Android接入指南](https://developers.weixin.qq.com/doc/oplatform/Mobile\_App/Access\_Guide/Android.html) to setup WeChat SDK. For the coding part, we will further explain in the below steps.
-* In iOS, after setting up the WechatOpenSDK, universal link should be enabled in your application. We will need two links for the setup. One is for the WeChat SDK used, another is for the Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here are the suggestion of the links.
- * **IOS\_WECHAT\_UNIVERSAL\_LINK**: `https://{YOUR_DOMAIN}/wechat`
- * **IOS\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR**: `https://{YOUR_DOMAIN}/open_wechat_app`
-* In android, you need to sign your app to use WeChat SDK. Obtain your application signature by running command `keytool -list -v -keystore YOUR_KEYSTORE_FILE_PATH` with your keystore file. WeChat needs the certificate fingerprint in MD5, remove `:` in the fingerprint. It should be string in length 32.
-* Login WeChat Open platform, open the application detail page, update the development information iOS and Android sections.
-
- (5) (5) (5) (5) (2).png>)
-
-* In iOS
- * Fill in "Bundle ID" field with your app bundle id.
- * Fill in "Universal Links" with "IOS\_WECHAT\_UNIVERSAL\_LINK" above.
-* In Android
- * Fill in application signature.
- * Fill in your package name
-* For android, we will need to define a custom url for Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here is the example, you should update it with your own scheme.
- * **ANDROID\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR**: `com.myapp://host/open_wechat_app`
-* Login Authgear portal, go to "Single-Sign On" page, then do the following:
- * Enable "Sign in with WeChat (Mobile/移动应用)"
- * Fill in "Client ID" with the WeChat "AppID".
- * Fill in "Client Secret" with the WeChat "AppSecret".
- * Fill in "原始 ID" with the WeChat "原始 ID".
- * Add "IOS\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR" and "ANDROID\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR" above into "WeChat redirect URIs"
- * Click save.
-* Update the code
- * In Android, Update application `AndroidManifest.xml`.
-
- ```markup
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ```
- * In iOS, update your App Delegate
-
- ```
- - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
- [WXApi handleOpenUniversalLink:userActivity delegate:self];
- [AGAuthgearReactNative application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
- return YES;
- }
- ```
- * Provide `wechatRedirectURI` when calling Authgear SDK `authorize` and `promoteAnonymousUser` in js
-
- ```javascript
- // REPLACE IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR and ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR
- const wechatRedirectURI = Platform.select({
- android: 'ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR',
- ios: 'IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR',
- });
-
- authgear
- .authenticate({
- redirectURI: "REDIRECT_URI",
- wechatRedirectURI: wechatRedirectURI
-
- });
-
- // For anonymous user support only
- authgear
- .promoteAnonymousUser({
- redirectURI: "REDIRECT_URI",
- wechatRedirectURI: wechatRedirectURI
- });
-
- // Open setting page
- authgear
- .open(Page.Settings, {
- wechatRedirectURI: wechatRedirectURI,
- })
- ```
- * Setup Authgear delegate and open WeChat SDK when sendWechatAuthRequest is triggered
-
- ```javascript
- authgear.delegate = {
- sendWechatAuthRequest: (state) => {
- // User click login with WeChat
- // Implement native modules to use WeChat SDK to open
- // WeChat app for authorization.
- // After obtaining authorization code, call Authgear.wechatAuthCallback
- // to complete the authorization.
- const {WechatAuth} = NativeModules;
- WechatAuth.sendWechatAuthRequest(state)
- .then((result: {code: string; state: string}) => {
- // Native module sending back the code after login with
- // WeChat app. Call Authgear.wechatAuthCallback
- return authgear.wechatAuthCallback(result.code, result.state);
- })
- .then(() => {
- // Send WeChat callback to authgear successfully
- })
- .catch((err: Error) => {
- // error ocurred
- });
- }
- }
- ```
- * Implement the NativeModules to use WeChat SDK to open WeChat app for authorization. Here is the completed [example](https://github.com/authgear/authgear-sdk-js/tree/master/example/reactnative).
-
-#### Flutter
-
-* Setup Authgear SDK
-* Follow [iOS接入指南](https://developers.weixin.qq.com/doc/oplatform/Mobile\_App/Access\_Guide/iOS.html) and [Android接入指南](https://developers.weixin.qq.com/doc/oplatform/Mobile\_App/Access\_Guide/Android.html) to setup WeChat SDK. For the coding part, we will further explain in the below steps.
-* In iOS, after setting up the WechatOpenSDK, universal link should be enabled in your application. We will need two links for the setup. One is for the WeChat SDK used, another is for the Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here are the suggestion of the links.
- * **IOS\_WECHAT\_UNIVERSAL\_LINK**: `https://{YOUR_DOMAIN}/wechat`
- * **IOS\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR**: `https://{YOUR_DOMAIN}/open_wechat_app`
-* In android, you need to sign your app to use WeChat SDK. Obtain your application signature by running command `keytool -list -v -keystore YOUR_KEYSTORE_FILE_PATH` with your keystore file. WeChat needs the certificate fingerprint in MD5, remove `:` in the fingerprint. It should be string in length 32.
-* Login WeChat Open platform, open the application detail page, update the development information iOS and Android sections.
-
- (5) (5) (5) (5) (2).png>)
-
-* In iOS
- * Fill in "Bundle ID" field with your app bundle id.
- * Fill in "Universal Links" with "IOS\_WECHAT\_UNIVERSAL\_LINK" above.
-* In Android
- * Fill in application signature.
- * Fill in your package name
-* For android, we will need to define a custom url for Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here is the example, you should update it with your own scheme.
- * **ANDROID\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR**: `com.myapp://host/open_wechat_app`
-* Login Authgear portal, go to "Single-Sign On" page, then do the following:
- * Enable "Sign in with WeChat (Mobile/移动应用)"
- * Fill in "Client ID" with the WeChat "AppID".
- * Fill in "Client Secret" with the WeChat "AppSecret".
- * Fill in "原始 ID" with the WeChat "原始 ID".
- * Add "IOS\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR" and "ANDROID\_WECHAT\_REDIRECT\_URI\_FOR\_AUTHGEAR" above into "WeChat redirect URIs"
- * Click save.
-* Update the code
- * In Android, Update application `AndroidManifest.xml`.
-
- ```markup
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ```
- * Provide `wechatRedirectURI`.
-
- ```dart
- // REPLACE IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR and ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR
- var wechatRedirectURI = "";
- if (Platform.isIOS) {
- wechatRedirectURI = 'IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR';
- } else if (Platform.isAndroid) {
- wechatRedirectURI = 'ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR';
- }
-
- await authgear.authenticate(redirectURI: "REDIRECT_URI", wechatRedirectURI: wechatRedirectURI);
-
- // For anonymous user support only
- await authgear.promoteAnonymousUser(redirectURI: "REDIRECT_URI", wechatRedirectURI: wechatRedirectURI);
-
- // Open setting page
- await authgear.open(SettingsPage.settings, wechatRedirectURI: wechatRedirectURI);
- ```
- * Provide sendWechatAuthRequest
-
- ```dart
- final authgear = Authgear(
- sendWechatAuthRequest: sendWechatAuthRequest,
- );
-
- Future sendWechatAuthRequest(state: String) async {
- // Implement your platform specific code to use WeChat SDK to open WeChat app.
- // After success, pass the code back to Authgear.
- await authgear.wechatAuthCallback(state: state, code: code);
- }
- ```
- * Implement the platform specific code to use WeChat SDK to open WeChat app for authorization. Here is the completed [example](https://github.com/authgear/authgear-sdk-flutter/tree/main/example).