很久沒寫了 我們來改個釘釘?shù)卿洶?br>
網(wǎng)上文章很少
目前測試已經(jīng)跑通了
服務端還沒對接
大家自己看吧
iOS:
釘釘官網(wǎng)
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"http://這個文件是自己的 我后面會貼出來
//在下面方法區(qū)添加
//釘釘?shù)卿浥渲?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//...
[DTOpenAPI registerApp:@"這里是你釘釘?shù)膋ey"];
//...
}
- (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 {
}
}
下面文件創(chuàng)建好后添加到你的項目
這個是和 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
/**
收到一個來自釘釘?shù)恼埱? 第三方APP處理完成后要調(diào)用 +[DTOpenAPI sendResp:] 將處理結(jié)果返回給釘釘.
@param req 來自釘釘具體的請求.
*/
- (void)onReq:(DTBaseReq *)req {
}
/**
第三方APP使用 +[DTOpenAPI sendReq:] 向釘釘發(fā)送消息后, 釘釘會處理完請求后會回調(diào)該接口.
@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)
首先在工程中創(chuàng)建 ddshare 的 package,然后在在該 package 下創(chuàng)建 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();
}
}
再創(chuàng)建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;
// 不能在構(gòu)造方法里初始化,因為構(gòu)造方法獲取不到需要的 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并填充網(wǎng)頁鏈接地址
DDWebpageMessage webPageObject = new DDWebpageMessage();
webPageObject.mUrl = url;
// 構(gòu)造一個DDMediaMessage對象
DDMediaMessage webMessage = new DDMediaMessage();
webMessage.mMediaObject = webPageObject;
// 填充網(wǎng)頁分享必需參數(shù),開發(fā)者需按照自己的數(shù)據(jù)進行填充
webMessage.mTitle = title;
webMessage.mContent = content;
webMessage.mThumbUrl = thumbImage;
// 構(gòu)造一個Req
SendMessageToDD.Req webReq = new SendMessageToDD.Req();
webReq.mMediaMessage = webMessage;
// 調(diào)用api接口發(fā)送消息到支付寶
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;
}
// 構(gòu)造一個mMediaObject對象
DDMediaMessage mediaMessage = new DDMediaMessage();
mediaMessage.mMediaObject = imageObject;
// 構(gòu)造一個Req
SendMessageToDD.Req req = new SendMessageToDD.Req();
req.mMediaMessage = mediaMessage;
// 調(diào)用api接口發(fā)送消息到支付寶
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";
// 調(diào)用api接口發(fā)送消息到支付寶
// 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 調(diào)用方式不同 需要注意
//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('釘釘調(diào)用失敗')
}
}