React-native 钉钉登录

很久没写了 我们来改个钉钉登录吧
网上文章很少
目前测试已经跑通了
服务端还没对接
大家自己看吧

iOS:

钉钉官网
https://open.dingtalk.com/document/orgapp/procedures-for-authorized-logon-to-ios-applications

image.png

其他的按照步骤走就行了

image.png

这东西一定要导入到工程 官方Demo 里是有的
你也可以通过pod 下载
下面是具体代码:

//appdelegate.m
#import <DTShareKit/DTOpenKit.h>
#import "RNDingTalkShareModule.h"//这个文件是自己的 我后面会贴出来

//在下面方法区添加
//钉钉登录配置

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//...
   [DTOpenAPI registerApp:@"这里是你钉钉的key"];
//...
}

- (BOOL)application:(UIApplication *)application
            openURL:(nonnull NSURL *)url
  sourceApplication:(nullable NSString *)sourceApplication
         annotation:(nonnull id)annotation {
  if ([DTOpenAPI handleOpenURL:url delegate:self]) {
        return YES;
    }
    return NO;
}

- (void)onResp:(DTBaseResp *)resp {
  RCTPromiseResolveBlock resolver = [RNDingTalkShareModule getSendLoginResolverStatic];
    RCTPromiseRejectBlock rejecter = [RNDingTalkShareModule getSendLoginRejecterStatic];
    if (resp.errorCode == DTOpenAPISuccess) {
        DTAuthorizeResp *authResp = (DTAuthorizeResp *)resp;
      //WeChat_Resp
    
        NSString *accessCode = authResp.accessCode;
      resolver([NSDictionary dictionaryWithObjectsAndKeys:accessCode,@"code", nil]);
    } else {
      
    }
}


下面文件创建好后添加到你的项目
这个是和 RN通讯的文件

RNDingTalkShareModule.h

#if __has_include("RCTBridge.h")
#import "RCTBridge.h"
#else
#import <React/RCTBridge.h>
#endif

#if __has_include("DTOpenKit.h")
#import "DTOpenKit.h"
#else
#import <DTShareKit/DTOpenKit.h>
#endif

@interface RNDingTalkShareModule : NSObject <RCTBridgeModule, DTOpenAPIDelegate>
+ (RCTPromiseResolveBlock)getSendLoginResolverStatic;

+ (RCTPromiseRejectBlock) getSendLoginRejecterStatic;

@end

//RNDingTalkShareModule.m


#import <React/RCTEventDispatcher.h>
#import <React/RCTBridge.h>
#import "RNDingTalkShareModule.h"

// 登录
static RCTPromiseResolveBlock sendLoginResolverStatic = nil;

static RCTPromiseRejectBlock sendLoginRejecterStatic = nil;

static NSString *const DING_TALK_NOT_INSTALLED_CODE = @"NOT_INSTALLED";
static NSString *const DING_TALK_NOT_SUPPORTED_CODE = @"NOT_SUPPORTED";
static NSString *const DING_TALK_SHARE_FAILED_CODE = @"SHARE_FAILED";

@interface RNDingTalkShareModule ()

@property (nonatomic, strong) NSString *appId;
@property (nonatomic, copy) RCTPromiseResolveBlock resolveBlock;
@property (nonatomic, copy) RCTPromiseRejectBlock rejectBlock;

@end

@implementation RNDingTalkShareModule

RCT_EXPORT_MODULE()

- (dispatch_queue_t)methodQueue {
    return dispatch_get_main_queue();
}

+ (RCTPromiseResolveBlock)getSendLoginResolverStatic {
    return sendLoginResolverStatic;
}

+ (RCTPromiseRejectBlock) getSendLoginRejecterStatic {
    return sendLoginRejecterStatic;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [self initDingTalkShare];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(handleOpenURLNotification:)
                                                     name:@"RCTOpenURLNotification"
                                                   object:nil];
    }
    return self;
}

RCT_EXPORT_METHOD(isInstalled
                  : (RCTPromiseResolveBlock)resolve
                  : (RCTPromiseRejectBlock)reject) {
    resolve(@([DTOpenAPI isDingTalkInstalled]));
}

RCT_EXPORT_METHOD(isSupported
                  : (RCTPromiseResolveBlock)resolve
                  : (RCTPromiseRejectBlock)reject) {
    resolve(@([DTOpenAPI isDingTalkSupportOpenAPI]));
}

RCT_EXPORT_METHOD(registerApp
                  : (NSString *)appId
                  : (NSString *)appDescription
                  : (RCTPromiseResolveBlock)resolve
                  : (RCTPromiseRejectBlock)reject) {
    BOOL result;
    if (appDescription) {
        result = [DTOpenAPI registerApp:appId appDescription:appDescription];
    } else {
        result = [DTOpenAPI registerApp:appId];
    }
    resolve(@(result));
}

RCT_EXPORT_METHOD(shareImage
                  : (NSString *)image
                  : (RCTPromiseResolveBlock)resolve
                  : (RCTPromiseRejectBlock)reject) {
    self.resolveBlock = resolve;
    self.rejectBlock = reject;
    if (![self checkSupport]) {
        return;
    }
    DTSendMessageToDingTalkReq *sendMessageReq = [[DTSendMessageToDingTalkReq alloc] init];
    DTMediaMessage *mediaMessage = [[DTMediaMessage alloc] init];
    DTMediaImageObject *imageObject = [[DTMediaImageObject alloc] init];
    imageObject.imageURL = image;
    mediaMessage.mediaObject = imageObject;
    sendMessageReq.message = mediaMessage;

    if (![DTOpenAPI sendReq:sendMessageReq]) {
        reject(DING_TALK_SHARE_FAILED_CODE, @"分享失败", nil);
    }
}

RCT_EXPORT_METHOD(shareWebPage
                  : (NSString *)url
                  : (NSString *)thumbImage
                  : (NSString *)title
                  : (NSString *)content
                  : (RCTPromiseResolveBlock)resolve
                  : (RCTPromiseRejectBlock)reject) {
    self.resolveBlock = resolve;
    self.rejectBlock = reject;
    if (![self checkSupport]) {
        return;
    }
    DTSendMessageToDingTalkReq *sendMessageReq = [[DTSendMessageToDingTalkReq alloc] init];
    DTMediaMessage *mediaMessage = [[DTMediaMessage alloc] init];
    DTMediaWebObject *webObject = [[DTMediaWebObject alloc] init];
    webObject.pageURL = url;
    mediaMessage.title = title;
    mediaMessage.thumbURL = thumbImage;
    mediaMessage.messageDescription = content;
    mediaMessage.mediaObject = webObject;
    sendMessageReq.message = mediaMessage;

    if (![DTOpenAPI sendReq:sendMessageReq]) {
        reject(DING_TALK_SHARE_FAILED_CODE, @"分享失败", nil);
    }
}

RCT_EXPORT_METHOD(getAuthCode
                  : (RCTPromiseResolveBlock)resolve
                  : (RCTPromiseRejectBlock)reject) {
  __weak __typeof(self)weakSelf = self;
  weakSelf.resolveBlock = resolve;
  weakSelf.rejectBlock = reject;
  sendLoginResolverStatic = resolve;
    sendLoginRejecterStatic = reject;
    if (![self checkSupport]) {
        return;
    }
  
    DTAuthorizeReq *authReq = [DTAuthorizeReq new];
    authReq.bundleId = [[NSBundle mainBundle] bundleIdentifier];

    if (![DTOpenAPI sendReq:authReq]) {
        reject(DING_TALK_SHARE_FAILED_CODE, @"获取授权码失败", nil);
    }
}

#pragma mark - DTOpenAPIDelegate

/**
 收到一个来自钉钉的请求, 第三方APP处理完成后要调用 +[DTOpenAPI sendResp:] 将处理结果返回给钉钉.
 
 @param req 来自钉钉具体的请求.
 */
- (void)onReq:(DTBaseReq *)req {
}

/**
 第三方APP使用 +[DTOpenAPI sendReq:] 向钉钉发送消息后, 钉钉会处理完请求后会回调该接口.
 
 @param resp 来自钉钉具体的响应.
 */
- (void)onResp:(DTBaseResp *)resp {
 
    if (resp.errorCode == DTOpenAPISuccess) {
        DTAuthorizeResp *authResp = (DTAuthorizeResp *)resp;
        NSString *accessCode = authResp.accessCode;
      self.resolveBlock([NSDictionary dictionaryWithObjectsAndKeys:accessCode,@"code", nil]);
    } else {
        self.rejectBlock([NSString stringWithFormat:@"%@", @(resp.errorCode)], resp.errorMessage, nil);
    }
}

#pragma mark - Private

- (void)initDingTalkShare {
    NSArray *urlTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
    for (id type in urlTypes) {
        NSArray *urlSchemes = [type objectForKey:@"CFBundleURLSchemes"];
        for (id scheme in urlSchemes) {
            if ([scheme isKindOfClass:[NSString class]]) {
                NSString *value = (NSString *)scheme;
                if ([value hasPrefix:@"ding"] && (nil == _appId)) {
                    _appId = value;
                    [DTOpenAPI registerApp:_appId];
                    break;
                }
            }
        }
    }
}

- (void)handleOpenURLNotification:(NSNotification *)notification {
    NSURL *url = [NSURL URLWithString:[notification userInfo][@"url"]];
    NSString *schemaPrefix = _appId;
    if ([url isKindOfClass:[NSURL class]] && [[url absoluteString] hasPrefix:[schemaPrefix stringByAppendingString:@"://"]]) {
        [DTOpenAPI handleOpenURL:url delegate:self];
    }
}

- (BOOL)checkSupport {
    if (![DTOpenAPI isDingTalkInstalled] && self.rejectBlock) {
        self.rejectBlock(DING_TALK_NOT_INSTALLED_CODE, @"请安装钉钉客户端", nil);
        return NO;
    }
    if (![DTOpenAPI isDingTalkSupportOpenAPI] && self.rejectBlock) {
        self.rejectBlock(DING_TALK_NOT_INSTALLED_CODE, @"请升级钉钉客户端", nil);
        return NO;
    }
    return YES;
}

@end

记得添加这个:


image.png

Android

安卓文档在这 自己去看,看不懂的话我也帮不了你
https://open.dingtalk.com/document/orgapp/android-platform-application-authorization-login-access

这些要做好


image.png

build.gradle文件里添加

dependencies{

implementation 'com.alibaba.android:ddsharesdk:1.1.0'//钉钉  1.5.0.8貌似不好用
}

新建文件路径(小白的话自己研究怎么穿件package)
首先在工程中创建 ddshare 的 package,然后在在该 package 下创建 DDShareActivity

//DDShareActivity.java

import android.app.Activity;
import android.os.Bundle;

import com.android.dingtalk.share.ddsharemodule.IDDShareApi;
import com.vyungapps.rn.vy.Native.DingTalkShareModule;

public class DDShareActivity extends Activity{
    private IDDShareApi mIDDShareApi;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            DingTalkShareModule.handleIntent(getIntent());
        } catch (Exception e) {
            e.printStackTrace();
        }
        finish();
    }

}

再创建DingTalkShareModule.java


import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

import com.android.dingtalk.share.ddsharemodule.DDShareApiFactory;
import com.android.dingtalk.share.ddsharemodule.IDDAPIEventHandler;
import com.android.dingtalk.share.ddsharemodule.IDDShareApi;
import com.android.dingtalk.share.ddsharemodule.message.BaseReq;
import com.android.dingtalk.share.ddsharemodule.message.BaseResp;
import com.android.dingtalk.share.ddsharemodule.message.DDImageMessage;
import com.android.dingtalk.share.ddsharemodule.message.DDMediaMessage;
import com.android.dingtalk.share.ddsharemodule.message.DDWebpageMessage;
import com.android.dingtalk.share.ddsharemodule.message.SendMessageToDD;
import com.android.dingtalk.share.ddsharemodule.message.SendAuth;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;

public class DingTalkShareModule extends ReactContextBaseJavaModule implements IDDAPIEventHandler {
    private static final String TAG = "DingTalkShare";

    private static final String NOT_INSTALLED_CODE = "NOT_INSTALLED";
    private static final String NOT_SUPPORTED_CODE = "NOT_SUPPORTED";
    private static final String SHARE_FAILED_CODE = "SHARE_FAILED";
    static final String DING_SCOPE = SendAuth.Req.SNS_LOGIN;

    private static DingTalkShareModule mInstance;
    // 不能在构造方法里初始化,因为构造方法获取不到需要的 Activity.
    private static IDDShareApi mDDShareApi;
    private Promise mPromise;

    public DingTalkShareModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    public static IDDShareApi getDdShareApi(Context context) {
        if (mDDShareApi == null) {
            String appId = getAppID(context);
            mDDShareApi = DDShareApiFactory.createDDShareApi(context, appId, true);
        }
        return mDDShareApi;
    }

    public static DingTalkShareModule getInstance(ReactApplicationContext reactContext) {
        if (mInstance == null) {
            mInstance = new DingTalkShareModule(reactContext);
        }
        return mInstance;
    }

    @Override
    public String getName() {
        return "RNDingTalkShareModule";
    }

    @ReactMethod
    public void isInstalled(Promise promise) {
        IDDShareApi ddShareApi = getDdShareApi(getCurrentActivity());
        promise.resolve(ddShareApi.isDDAppInstalled());
    }

    @ReactMethod
    public void isSupported(Promise promise) {
        IDDShareApi ddShareApi = getDdShareApi(getCurrentActivity());
        promise.resolve(ddShareApi.isDDSupportAPI());
    }

    @ReactMethod
    public void shareWebPage(String url, String thumbImage, String title, String content, Promise promise) {
        mPromise = promise;
        if (!checkSupport()) {
            return;
        }
        // 初始化一个DDWebpageMessage并填充网页链接地址
        DDWebpageMessage webPageObject = new DDWebpageMessage();
        webPageObject.mUrl = url;

        // 构造一个DDMediaMessage对象
        DDMediaMessage webMessage = new DDMediaMessage();
        webMessage.mMediaObject = webPageObject;

        // 填充网页分享必需参数,开发者需按照自己的数据进行填充
        webMessage.mTitle = title;
        webMessage.mContent = content;
        webMessage.mThumbUrl = thumbImage;
        // 构造一个Req
        SendMessageToDD.Req webReq = new SendMessageToDD.Req();
        webReq.mMediaMessage = webMessage;

        // 调用api接口发送消息到支付宝
        if (!getDdShareApi(getCurrentActivity()).sendReq(webReq)) {
            mPromise.reject(SHARE_FAILED_CODE, "分享失败");
        }
    }

    /**
     * 分享图片
     */
    @ReactMethod
    private void shareImage(String image, Promise promise) {
        mPromise = promise;
        if (!checkSupport()) {
            return;
        }
        // 初始化一个DDImageMessage
        DDImageMessage imageObject = new DDImageMessage();
        if (isLocalResource(image)) {
            imageObject.mImagePath = image;
        } else {
            imageObject.mImageUrl = image;
        }

        // 构造一个mMediaObject对象
        DDMediaMessage mediaMessage = new DDMediaMessage();
        mediaMessage.mMediaObject = imageObject;

        // 构造一个Req
        SendMessageToDD.Req req = new SendMessageToDD.Req();
        req.mMediaMessage = mediaMessage;

        // 调用api接口发送消息到支付宝
        if (!getDdShareApi(getCurrentActivity()).sendReq(req)) {
            mPromise.reject(SHARE_FAILED_CODE, "分享失败");
        }
    }

    @ReactMethod
    public void getAuthCode(Promise promise) {
        mPromise = promise;
        if (!checkSupport()) {
            return;
        }
        // WritableMap map = Arguments.createMap();
        // map.putInt("errCode", 1);
        // map.putString("msg", "ddd");
        // DDModule.promise.resolve(map);

        SendAuth.Req req = new SendAuth.Req();
        req.scope = SendAuth.Req.SNS_LOGIN;
        req.state = "CESHI";

        // 调用api接口发送消息到支付宝
//        if (!getDdShareApi(getCurrentActivity()).sendReq(req)) {
//            mPromise.reject(SHARE_FAILED_CODE, "分享失败");
//        }
        mDDShareApi.sendReq(req);
    }

    @Override
    public void onReq(BaseReq baseReq) {
        Log.d(TAG, "onReq");
    }

    // @Override
    // public void onResp(BaseResp baseResp) {
    // Log.d(TAG, baseResp.mErrStr);
    // int errCode = baseResp.mErrCode;
    // switch (errCode) {
    // case BaseResp.ErrCode.ERR_OK:
    // mPromise.resolve(true);
    // break;
    // default:
    // mPromise.reject(errCode + "", baseResp.mErrStr);
    // break;
    // }
    // }

    @Override
    public void onResp(BaseResp baseResp) {
        int errCode = baseResp.mErrCode;
        String errMsg = baseResp.mErrStr;

        Log.d("DingTalkShare", "errCode=============>" + errCode);
        Log.d("DingTalkShare", "errMsg=============>" + errMsg);

        switch (errCode) {
            case BaseResp.ErrCode.ERR_OK:
                SendAuth.Resp authResp = (SendAuth.Resp) baseResp;
                WritableMap mapSuccess = Arguments.createMap();
                mapSuccess.putString("code", authResp.code);
                mPromise.resolve(mapSuccess);

                break;
            default:
                mPromise.reject(String.valueOf((errCode)) + ": " + errMsg);
        }
    }

    /**
     * 获取钉钉 App ID
     *
     * @param context
     * @return
     */
    public static String getAppID(Context context) {
        ApplicationInfo appInfo = null;
        try {
            appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(),
                    PackageManager.GET_META_DATA);
            return appInfo.metaData.get("DT_APP_ID").toString();
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void handleIntent(Intent intent) {
        if (mInstance != null && mDDShareApi != null) {
            mDDShareApi.handleIntent(intent, mInstance);
        }
    }

    private boolean isLocalResource(String url) {
        Uri thumbUri = Uri.parse(url);
        // Verify scheme is set, so that relative uri (used by static resources) are not
        // handled.
        String scheme = thumbUri.getScheme();
        return (scheme == null || scheme.equals("file"));
    }

    private boolean checkSupport() {
        IDDShareApi ddShareApi = getDdShareApi(getCurrentActivity());
        if (!ddShareApi.isDDAppInstalled()) {
             mPromise.reject(NOT_INSTALLED_CODE, "请安装钉钉客户端");

            Toast toast=Toast.makeText(getReactApplicationContext(), "请安装钉钉客户端", Toast.LENGTH_SHORT);

            toast.show();
            return false;
        } else if (!ddShareApi.isDDSupportAPI()) {
            mPromise.reject(NOT_SUPPORTED_CODE, "请升级钉钉客户端");
            return false;
        }
        return true;
    }
}

DingTalkSharePackage.java

  package com.vyungapps.rn.vy.Native;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class DingTalkSharePackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(DingTalkShareModule.getInstance(reactContext));
        return modules;
    }

    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

mainapplication.java添加如下

 packages.add(new DingTalkSharePackage());

androidmainfest.xml文件添加下面代码

  <activity
            android:exported="true"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:launchMode="singleInstance"
            android:name=".ddshare.DDShareActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>
        </activity>

好了 OK了 API 自己去看 不想多说了 也不是写给新手的
同样 也适用于flutter 但是代码格式需要改改 方法和理论都相同

JS

//IOS 和 Android 调用方式不同 需要注意
//module 自己写吧 这个我就不贴出来了   也不做回复了
            if (iOS) {
                await DingTalk.getAuthCode().then((res) => {
                    alert(JSON.stringify(res))
                })
            } else if (Android) {
                let data = null
                data= await DingTalk.getAuthCode()
                if(data){
                    alert(JSON.stringify(data))
                }else{
                    alert('钉钉调用失败')
                }
                
            }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容