很久没写了 我们来改个钉钉登录吧
网上文章很少
目前测试已经跑通了
服务端还没对接
大家自己看吧
iOS:
钉钉官网
https://open.dingtalk.com/document/orgapp/procedures-for-authorized-logon-to-ios-applications
其他的按照步骤走就行了
这东西一定要导入到工程 官方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
记得添加这个:
Android
安卓文档在这 自己去看,看不懂的话我也帮不了你
https://open.dingtalk.com/document/orgapp/android-platform-application-authorization-login-access
这些要做好
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('钉钉调用失败')
}
}