commit 94d30a78549d7e77485bd1a776ee81b910f820cd Author: Jerry Yan <792602257@qq.com> Date: Tue Feb 25 22:39:44 2020 +0800 Init diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..a6107ad --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +/android/build diff --git a/README.md b/README.md new file mode 100644 index 0000000..03e96d1 --- /dev/null +++ b/README.md @@ -0,0 +1,172 @@ +# react-native-qq + +React Native的QQ登录插件, react-native版本需要0.33.0及以上 + +## 如何安装 + +### 首先安装npm包 + +```bash +npm install react-native-qq --save +``` +### 安装iOS工程 +将`node_modules/react-native-qq/ios/RCTQQAPI.xcodeproj`加入到工程中 + +在工程target的`Build Phases->Link Binary with Libraries`中加入`libRCTQQAPI.a、libiconv.tbd、libsqlite3.tbd、libz.tbd、libc++.tbd` + +在 `Build Settings->Search Paths->Framework Search Paths` 中加入路径 `$(SRCROOT)/../node_modules/react-native-qq/ios/RCTQQAPI` + +在 `Build Settings->Link->Other Linker Flags` 中加入 `-framework "TencentOpenAPI"` + +在 `Apple LLVM 7.0 - Custom Compiler Flags->Link->Other C Flags`中加入 `-isystem "$(SRCROOT)/../node_modules/react-native-qq/ios/RCTQQAPI"` + +在工程plist文件中加入qq白名单:(ios9以上必须) +如果plist中没有 `LSApplicationQueriesSchemes`项,请先添加该项,Type设置为Array。接着,在`LSApplicationQueriesSchemes`中添加子项:`mqqapi、mqq、mqqOpensdkSSoLogin、mqqconnect、mqqopensdkdataline、mqqopensdkgrouptribeshare、mqqopensdkfriend、mqqopensdkapi、mqqopensdkapiV2、mqqopensdkapiV3、mqzoneopensdk、wtloginmqq、wtloginmqq2、mqqwpa、mqzone、mqzonev2、mqzoneshare、wtloginqzone、mqzonewx、 +mqzoneopensdkapiV2、mqzoneopensdkapi19、mqzoneopensdkapi、mqzoneopensdk、` + +在`Info->URL Types` 中增加QQ的scheme: `Identifier` 设置为`qq`, `URL Schemes` 设置为你注册的QQ开发者账号中的APPID,需要加前缀`tencent`,例如`tencent1104903684` + +在你工程的`AppDelegate.m`文件中添加如下代码: + +``` +#import "../Libraries/LinkingIOS/RCTLinkingManager.h" + + +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { + return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; +} + +``` + +### 安装Android工程 + +在`android/settings.gradle`里添加如下代码: + +``` +include ':react-native-qq' +project(':react-native-qq').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-qq/android') +``` + +在`app/build.gradle`里添加如下代码: + +``` +compile project(':react-native-qq') +``` + +在`android/app/build.gradle`里的`dependencies`结构中添加如下代码: + +``` +dependencies{ + ... // 原本的代码 + compile project(':react-native-qq') +} +``` + + +在`android/app/build.gradle`里,defaultConfig栏目下添加如下代码: + +``` + manifestPlaceholders = [ + QQ_APPID: "<平台申请的APPID>" + ] +``` + +以后如果需要修改APPID,只需要修改此一处。 + +`android/app/src/main/java/<你的包名>/MainApplication.java`中添加如下两行: + +```java +... +import cn.reactnative.modules.qq.QQPackage; // 在public class MainApplication之前import + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { + @Override + protected boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + return Arrays.asList( +          new QQPackage(), // 然后添加这一行 + new MainReactPackage() + ); + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } +} +``` + +另外,确保你的MainActivity.java中有`onActivityResult`的实现: + +```java + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data){ + super.onActivityResult(requestCode, resultCode, data); + mReactInstanceManager.onActivityResult(requestCode, resultCode, data); + } +``` + +## 如何使用 + +### 引入包 + +``` +import * as QQAPI from 'react-native-qq'; +``` + +### API + +#### QQAPI.login([scopes]) + +- scopes: 登录所申请的权限,默认为get_simple_userinfo。 需要多个权限时,以逗号分隔。 + +调用QQ登录,可能会跳转到QQ应用或者打开一个网页浏览器以供用户登录。在本次login返回前,所有接下来的login调用都会直接失败。 + +返回一个`Promise`对象。成功时的回调为一个类似这样的对象: + +```javascript +{ + "access_token": "CAF0085A2AB8FDE7903C97F4792ECBC3", + "openid": "0E00BA738F6BB55731A5BBC59746E88D" + "expires_in": "1458208143094.6" + "oauth_consumer_key": "12345" +} +``` + +#### QQAPI.shareToQQ(data) + +分享到QQ好友,参数同QQAPI.shareToQzone,返回一个`Promise`对象 + +#### QQAPI.shareToQzone(data) + +分享到QZone,参数为一个object,可以有如下的形式: + +```javascript +// 分享图文消息 +{ + type: 'news', + title: 分享标题, + description: 描述, + webpageUrl: 网页地址, + imageUrl: 远程图片地址, +} + +// 其余格式尚未实现。 +``` + +## 常见问题 + +#### Android: 调用QQAPI.login()没有反应 + +通常出现这个原因是因为Manifest没有配置好,检查Manifest中有关Activity的配置。 + +#### Android: 已经成功激活QQ登录,但回调没有被执行 + +通常出现这个原因是因为MainActivity.java中缺少onActivityResult的调用。 diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..0bf4c38 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,33 @@ +apply plugin: 'com.android.library' + +def safeExtGet(prop, fallback) { + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback +} + +android { + compileSdkVersion safeExtGet("compileSdkVersion", 28) + + defaultConfig { + minSdkVersion safeExtGet('minSdkVersion', 16) + targetSdkVersion safeExtGet('targetSdkVersion', 28) + versionCode 1 + versionName "1.0" + ndk { + abiFilters "armeabi-v7a", "x86" + } + } +} + +repositories { + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url "$rootDir/../node_modules/react-native/android" + } +} + +dependencies { + implementation 'com.facebook.react:react-native:+' + implementation files('libs/mta-sdk-1.6.2.jar') + implementation files('libs/open_sdk_r2973327_lite.jar') +} + diff --git a/android/libs/mta-sdk-1.6.2.jar b/android/libs/mta-sdk-1.6.2.jar new file mode 100755 index 0000000..49b7787 Binary files /dev/null and b/android/libs/mta-sdk-1.6.2.jar differ diff --git a/android/libs/open_sdk_r2973327_lite.jar b/android/libs/open_sdk_r2973327_lite.jar new file mode 100644 index 0000000..0fc336f Binary files /dev/null and b/android/libs/open_sdk_r2973327_lite.jar differ diff --git a/android/libs/open_sdk_r5756.jar b/android/libs/open_sdk_r5756.jar new file mode 100755 index 0000000..72daab6 Binary files /dev/null and b/android/libs/open_sdk_r5756.jar differ diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2a30d77 --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + diff --git a/android/src/main/java/cn/reactnative/modules/qq/QQModule.java b/android/src/main/java/cn/reactnative/modules/qq/QQModule.java new file mode 100644 index 0000000..8e4cb31 --- /dev/null +++ b/android/src/main/java/cn/reactnative/modules/qq/QQModule.java @@ -0,0 +1,260 @@ +package cn.reactnative.modules.qq; + +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.Log; +import android.app.Activity; + +import com.facebook.react.bridge.ActivityEventListener; +import com.facebook.react.bridge.Arguments; +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.ReadableMap; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.modules.core.RCTNativeAppEventEmitter; +import com.tencent.connect.common.Constants; +import com.tencent.connect.share.QQShare; +import com.tencent.tauth.IUiListener; +import com.tencent.tauth.Tencent; +import com.tencent.tauth.UiError; + +import org.json.JSONObject; + +import java.util.Date; + +/** + * Created by tdzl2_000 on 2015-10-10. + * + * Modified by Renguang Dong on 2016-05-25. + */ +public class QQModule extends ReactContextBaseJavaModule implements IUiListener, ActivityEventListener { + private String appId; + private Tencent api; + private final static String INVOKE_FAILED = "QQ API invoke returns false."; + private boolean isLogin; + + private static final String RCTQQShareTypeNews = "news"; + private static final String RCTQQShareTypeImage = "image"; + private static final String RCTQQShareTypeText = "text"; + private static final String RCTQQShareTypeVideo = "video"; + private static final String RCTQQShareTypeAudio = "audio"; + + private static final String RCTQQShareType = "type"; + private static final String RCTQQShareText = "text"; + private static final String RCTQQShareTitle = "title"; + private static final String RCTQQShareDescription = "description"; + private static final String RCTQQShareWebpageUrl = "webpageUrl"; + private static final String RCTQQShareImageUrl = "imageUrl"; + + private static final int SHARE_RESULT_CODE_SUCCESSFUL = 0; + private static final int SHARE_RESULT_CODE_FAILED = 1; + private static final int SHARE_RESULT_CODE_CANCEL = 2; + + public QQModule(ReactApplicationContext context) { + super(context); + ApplicationInfo appInfo = null; + try { + appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); + } catch (PackageManager.NameNotFoundException e) { + throw new Error(e); + } + if (!appInfo.metaData.containsKey("QQ_APPID")){ + throw new Error("meta-data QQ_APPID not found in AndroidManifest.xml"); + } + this.appId = appInfo.metaData.get("QQ_APPID").toString(); + } + + @Override + public void initialize() { + super.initialize(); + + if (api == null) { + api = Tencent.createInstance(appId, getReactApplicationContext().getApplicationContext()); + } + getReactApplicationContext().addActivityEventListener(this); + } + + @Override + public void onCatalystInstanceDestroy() { + + if (api != null){ + api = null; + } + getReactApplicationContext().removeActivityEventListener(this); + + super.onCatalystInstanceDestroy(); + } + + @Override + public String getName() { + return "RCTQQAPI"; + } + + @ReactMethod + public void isQQInstalled(Promise promise) { + if (api.isSupportSSOLogin(getCurrentActivity())) { + promise.resolve(true); + } + else { + promise.reject("not installed"); + } + } + + @ReactMethod + public void isQQSupportApi(Promise promise) { + if (api.isSupportSSOLogin(getCurrentActivity())) { + promise.resolve(true); + } + else { + promise.reject("not support"); + } + } + + @ReactMethod + public void login(String scopes, Promise promise){ + this.isLogin = true; + if (!api.isSessionValid()){ + api.login(getCurrentActivity(), scopes == null ? "get_simple_userinfo" : scopes, this); + promise.resolve(null); + } else { + promise.reject(INVOKE_FAILED); + } + } + + @ReactMethod + public void shareToQQ(ReadableMap data, Promise promise){ + this._shareToQQ(data, 0); + promise.resolve(null); + } + + @ReactMethod + public void shareToQzone(ReadableMap data, Promise promise){ + this._shareToQQ(data, 1); + promise.resolve(null); + } + + private void _shareToQQ(ReadableMap data, int scene) { + this.isLogin = false; + Bundle bundle = new Bundle(); + if (data.hasKey(RCTQQShareTitle)){ + bundle.putString(QQShare.SHARE_TO_QQ_TITLE, data.getString(RCTQQShareTitle)); + } + if (data.hasKey(RCTQQShareDescription)){ + bundle.putString(QQShare.SHARE_TO_QQ_SUMMARY, data.getString(RCTQQShareDescription)); + } + if (data.hasKey(RCTQQShareWebpageUrl)){ + bundle.putString(QQShare.SHARE_TO_QQ_TARGET_URL, data.getString(RCTQQShareWebpageUrl)); + } + if (data.hasKey(RCTQQShareImageUrl)){ + bundle.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, data.getString(RCTQQShareImageUrl)); + } + if (data.hasKey("appName")){ + bundle.putString(QQShare.SHARE_TO_QQ_APP_NAME, data.getString("appName")); + } + + String type = RCTQQShareTypeNews; + if (data.hasKey(RCTQQShareType)) { + type = data.getString(RCTQQShareType); + } + + if (type.equals(RCTQQShareTypeNews)){ + bundle.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT); + } else if (type.equals(RCTQQShareTypeImage)){ + bundle.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE); + bundle.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, data.getString(RCTQQShareImageUrl)); + } else if (type.equals(RCTQQShareTypeAudio)) { + bundle.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_AUDIO); + if (data.hasKey("flashUrl")){ + bundle.putString(QQShare.SHARE_TO_QQ_AUDIO_URL, data.getString("flashUrl")); + } + } else if (type.equals("app")){ + bundle.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_APP); + } + + Log.e("QQShare", bundle.toString()); + + if (scene == 0 ) { + // Share to QQ. + bundle.putInt(QQShare.SHARE_TO_QQ_EXT_INT, QQShare.SHARE_TO_QQ_FLAG_QZONE_ITEM_HIDE); + api.shareToQQ(getCurrentActivity(), bundle, this); + } + else if (scene == 1) { + // Share to Qzone. + bundle.putInt(QQShare.SHARE_TO_QQ_EXT_INT, QQShare.SHARE_TO_QQ_FLAG_QZONE_AUTO_OPEN); + api.shareToQQ(getCurrentActivity(), bundle, this); + } + } + + private String _getType() { + return (this.isLogin?"QQAuthorizeResponse":"QQShareResponse"); + } + + public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { + Tencent.onActivityResultData(requestCode, resultCode, data, this); + } + + public void onNewIntent(Intent intent){ + + } + + @Override + public void onComplete(Object o) { + + WritableMap resultMap = Arguments.createMap(); + + if (isLogin) { + resultMap.putString("type", "QQAuthorizeResponse"); + try { + JSONObject obj = (JSONObject) (o); + resultMap.putInt("errCode", 0); + resultMap.putString("openid", obj.getString(Constants.PARAM_OPEN_ID)); + resultMap.putString("access_token", obj.getString(Constants.PARAM_ACCESS_TOKEN)); + resultMap.putString("oauth_consumer_key", this.appId); + resultMap.putDouble("expires_in", (new Date().getTime() + obj.getLong(Constants.PARAM_EXPIRES_IN))); + } catch (Exception e){ + WritableMap map = Arguments.createMap(); + map.putInt("errCode", Constants.ERROR_UNKNOWN); + map.putString("errMsg", e.getLocalizedMessage()); + + getReactApplicationContext() + .getJSModule(RCTNativeAppEventEmitter.class) + .emit("QQ_Resp", map); + } + } else { + resultMap.putString("type", "QQShareResponse"); + resultMap.putInt("errCode", SHARE_RESULT_CODE_SUCCESSFUL); + resultMap.putString("message", "Share successfully."); + } + + this.resolvePromise(resultMap); + } + + @Override + public void onError(UiError uiError) { + WritableMap resultMap = Arguments.createMap(); + resultMap.putInt("errCode", SHARE_RESULT_CODE_FAILED); + resultMap.putString("message", "Share failed." + uiError.errorDetail); + + this.resolvePromise(resultMap); + } + + @Override + public void onCancel() { + WritableMap resultMap = Arguments.createMap(); + resultMap.putInt("errCode", SHARE_RESULT_CODE_CANCEL); + resultMap.putString("message", "Share canceled."); + + this.resolvePromise(resultMap); + } + + private void resolvePromise(ReadableMap resultMap) { + getReactApplicationContext() + .getJSModule(RCTNativeAppEventEmitter.class) + .emit("QQ_Resp", resultMap); + + } +} diff --git a/android/src/main/java/cn/reactnative/modules/qq/QQPackage.java b/android/src/main/java/cn/reactnative/modules/qq/QQPackage.java new file mode 100644 index 0000000..340d709 --- /dev/null +++ b/android/src/main/java/cn/reactnative/modules/qq/QQPackage.java @@ -0,0 +1,33 @@ +package cn.reactnative.modules.qq; + +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.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Created by tdzl2_000 on 2015-10-10. + */ +public class QQPackage implements ReactPackage { + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Arrays.asList(new NativeModule[]{ + // Modules from third-party + new QQModule(reactContext), + }); + } + + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..b5c226f --- /dev/null +++ b/index.js @@ -0,0 +1,77 @@ +/** + * Created by Yun on 2015-12-12. + */ +import {NativeModules, NativeAppEventEmitter} from 'react-native'; + +const {QQAPI} = NativeModules; + +function translateError(err, result) { + if (!err) { + return this.resolve(result); + } + if (typeof err === 'object') { + if (err instanceof Error) { + return this.reject(ret); + } + return this.reject(Object.assign(new Error(err.message), { errCode: err.errCode })); + } else if (typeof err === 'string') { + return this.reject(new Error(err)); + } + this.reject(Object.assign(new Error(), { origin: err })); +} + +export const isQQInstalled = QQAPI.isQQInstalled; +export const isQQSupportApi = QQAPI.isQQSupportApi; + +// Save callback and wait for future event. +let savedCallback = undefined; +function waitForResponse(type) { + return new Promise((resolve, reject) => { + if (savedCallback) { + savedCallback('User canceled.'); + } + savedCallback = result => { + if (result.type !== type) { + return; + } + savedCallback = undefined; + if (result.errCode !== 0) { + const err = new Error(result.errMsg); + err.errCode = result.errCode; + reject(err); + } else { + const {type, ...r} = result + resolve(r); + } + }; + }); +} + +NativeAppEventEmitter.addListener('QQ_Resp', resp => { + const callback = savedCallback; + savedCallback = undefined; + callback && callback(resp); +}); + +export function login(scopes) { + return QQAPI.login(scopes) + .then(() => waitForResponse("QQAuthorizeResponse")); +} + +export function shareToQQ(data={}) { + return QQAPI.shareToQQ(data) + .then(() => waitForResponse("QQShareResponse")); +} + +export function shareToQzone(data={}) { + return QQAPI.shareToQzone(data) + .then(() => waitForResponse("QQShareResponse")); +} + +export function logout(){ + QQAPI.logout() +} + + + + diff --git a/ios/RCTQQAPI.debug.xcconfig b/ios/RCTQQAPI.debug.xcconfig new file mode 100644 index 0000000..a50ebc5 --- /dev/null +++ b/ios/RCTQQAPI.debug.xcconfig @@ -0,0 +1,15 @@ +// +// RCTQQAPI.debug.xcconfig +// RCTQQAPI +// +// Created by LvBingru on 12/18/15. +// Copyright © 2015 erica. All rights reserved. +// + +FRAMEWORK_SEARCH_PATHS = $(inherited) "${QQAPI_ROOT}/RCTQQAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) +HEADER_SEARCH_PATHS = $(inherited) "${QQAPI_ROOT}/RCTQQAPI" +LIBRARY_SEARCH_PATHS = $(inherited) +OTHER_CFLAGS = $(inherited) -isystem "${QQAPI_ROOT}/RCTQQAPI/" +OTHER_LDFLAGS = $(inherited) -ObjC -weak_library /usr/lib/libz.dylib -l"c++" -l"c++abi" -l"iconv" -l"sqlite3" -l"stdc++" -l"z" -framework "CoreGraphics" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "Security" -framework "SystemConfiguration" -framework "TencentOpenAPI" +QQAPI_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/ios/RCTQQAPI.release.xcconfig b/ios/RCTQQAPI.release.xcconfig new file mode 100644 index 0000000..effdbfb --- /dev/null +++ b/ios/RCTQQAPI.release.xcconfig @@ -0,0 +1,15 @@ +// +// RCTQQAPI.release.xcconfig +// RCTQQAPI +// +// Created by LvBingru on 12/18/15. +// Copyright © 2015 erica. All rights reserved. +// + +FRAMEWORK_SEARCH_PATHS = $(inherited) "${QQAPI_ROOT}/RCTQQAPI" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) +HEADER_SEARCH_PATHS = $(inherited) "${QQAPI_ROOT}/RCTQQAPI" +LIBRARY_SEARCH_PATHS = $(inherited) +OTHER_CFLAGS = $(inherited) -isystem "${QQAPI_ROOT}/RCTQQAPI/" +OTHER_LDFLAGS = $(inherited) -ObjC -weak_library /usr/lib/libz.dylib -l"c++" -l"c++abi" -l"iconv" -l"sqlite3" -l"stdc++" -l"z" -framework "CoreGraphics" -framework "CoreTelephony" -framework "CoreText" -framework "CoreVideo" -framework "Foundation" -framework "Security" -framework "SystemConfiguration" -framework "TencentOpenAPI" +QQAPI_ROOT = ${SRCROOT} \ No newline at end of file diff --git a/ios/RCTQQAPI.xcodeproj/project.pbxproj b/ios/RCTQQAPI.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e7ae159 --- /dev/null +++ b/ios/RCTQQAPI.xcodeproj/project.pbxproj @@ -0,0 +1,286 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 913932201C232D310085E3BA /* RCTQQAPI.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9139321F1C232D310085E3BA /* RCTQQAPI.h */; }; + 913932221C232D310085E3BA /* RCTQQAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 913932211C232D310085E3BA /* RCTQQAPI.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9139321A1C232D310085E3BA /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + 913932201C232D310085E3BA /* RCTQQAPI.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 9139321C1C232D310085E3BA /* libRCTQQAPI.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTQQAPI.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 9139321F1C232D310085E3BA /* RCTQQAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTQQAPI.h; sourceTree = ""; }; + 913932211C232D310085E3BA /* RCTQQAPI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTQQAPI.m; sourceTree = ""; }; + 913932401C232ED60085E3BA /* TencentOpenAPI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = TencentOpenAPI.framework; sourceTree = ""; }; + 9139325C1C233E370085E3BA /* RCTQQAPI.debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RCTQQAPI.debug.xcconfig; sourceTree = ""; }; + 9139325D1C233E480085E3BA /* RCTQQAPI.release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RCTQQAPI.release.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 913932191C232D310085E3BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 913932131C232D310085E3BA = { + isa = PBXGroup; + children = ( + 9139325C1C233E370085E3BA /* RCTQQAPI.debug.xcconfig */, + 9139325D1C233E480085E3BA /* RCTQQAPI.release.xcconfig */, + 9139321E1C232D310085E3BA /* RCTQQAPI */, + 9139321D1C232D310085E3BA /* Products */, + ); + sourceTree = ""; + }; + 9139321D1C232D310085E3BA /* Products */ = { + isa = PBXGroup; + children = ( + 9139321C1C232D310085E3BA /* libRCTQQAPI.a */, + ); + name = Products; + sourceTree = ""; + }; + 9139321E1C232D310085E3BA /* RCTQQAPI */ = { + isa = PBXGroup; + children = ( + 913932401C232ED60085E3BA /* TencentOpenAPI.framework */, + 9139321F1C232D310085E3BA /* RCTQQAPI.h */, + 913932211C232D310085E3BA /* RCTQQAPI.m */, + ); + path = RCTQQAPI; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9139321B1C232D310085E3BA /* RCTQQAPI */ = { + isa = PBXNativeTarget; + buildConfigurationList = 913932251C232D310085E3BA /* Build configuration list for PBXNativeTarget "RCTQQAPI" */; + buildPhases = ( + 913932181C232D310085E3BA /* Sources */, + 913932191C232D310085E3BA /* Frameworks */, + 9139321A1C232D310085E3BA /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RCTQQAPI; + productName = RCTQQAPI; + productReference = 9139321C1C232D310085E3BA /* libRCTQQAPI.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 913932141C232D310085E3BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + ORGANIZATIONNAME = erica; + TargetAttributes = { + 9139321B1C232D310085E3BA = { + CreatedOnToolsVersion = 7.1.1; + }; + }; + }; + buildConfigurationList = 913932171C232D310085E3BA /* Build configuration list for PBXProject "RCTQQAPI" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 913932131C232D310085E3BA; + productRefGroup = 9139321D1C232D310085E3BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9139321B1C232D310085E3BA /* RCTQQAPI */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 913932181C232D310085E3BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 913932221C232D310085E3BA /* RCTQQAPI.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 913932231C232D310085E3BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 913932241C232D310085E3BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 913932261C232D310085E3BA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9139325C1C233E370085E3BA /* RCTQQAPI.debug.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/RCTQQAPI", + ); + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../react-native/React/**", + "$(SRCROOT)/../../react-native/Libraries/**", + "$(SRCROOT)/RCTQQAPI/**", + "$(BUILT_PRODUCTS_DIR)/include", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 913932271C232D310085E3BA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9139325D1C233E480085E3BA /* RCTQQAPI.release.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/RCTQQAPI", + ); + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../react-native/React/**", + "$(SRCROOT)/../../react-native/Libraries/**", + "$(SRCROOT)/RCTQQAPI/**", + "$(BUILT_PRODUCTS_DIR)/include", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 913932171C232D310085E3BA /* Build configuration list for PBXProject "RCTQQAPI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 913932231C232D310085E3BA /* Debug */, + 913932241C232D310085E3BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 913932251C232D310085E3BA /* Build configuration list for PBXNativeTarget "RCTQQAPI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 913932261C232D310085E3BA /* Debug */, + 913932271C232D310085E3BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 913932141C232D310085E3BA /* Project object */; +} diff --git a/ios/RCTQQAPI.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/RCTQQAPI.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/RCTQQAPI.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/RCTQQAPI.xcodeproj/project.xcworkspace/xcuserdata/tdzl2003.xcuserdatad/UserInterfaceState.xcuserstate b/ios/RCTQQAPI.xcodeproj/project.xcworkspace/xcuserdata/tdzl2003.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..fb283af Binary files /dev/null and b/ios/RCTQQAPI.xcodeproj/project.xcworkspace/xcuserdata/tdzl2003.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ios/RCTQQAPI.xcodeproj/xcuserdata/lvbingru.xcuserdatad/xcschemes/RCTQQAPI.xcscheme b/ios/RCTQQAPI.xcodeproj/xcuserdata/lvbingru.xcuserdatad/xcschemes/RCTQQAPI.xcscheme new file mode 100644 index 0000000..e27fed5 --- /dev/null +++ b/ios/RCTQQAPI.xcodeproj/xcuserdata/lvbingru.xcuserdatad/xcschemes/RCTQQAPI.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/RCTQQAPI.xcodeproj/xcuserdata/lvbingru.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/RCTQQAPI.xcodeproj/xcuserdata/lvbingru.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..b55cc06 --- /dev/null +++ b/ios/RCTQQAPI.xcodeproj/xcuserdata/lvbingru.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + RCTQQAPI.xcscheme + + orderHint + 13 + + + SuppressBuildableAutocreation + + 9139321B1C232D310085E3BA + + primary + + + + + diff --git a/ios/RCTQQAPI.xcodeproj/xcuserdata/tdzl2003.xcuserdatad/xcschemes/RCTQQAPI.xcscheme b/ios/RCTQQAPI.xcodeproj/xcuserdata/tdzl2003.xcuserdatad/xcschemes/RCTQQAPI.xcscheme new file mode 100644 index 0000000..f6993b0 --- /dev/null +++ b/ios/RCTQQAPI.xcodeproj/xcuserdata/tdzl2003.xcuserdatad/xcschemes/RCTQQAPI.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/RCTQQAPI.xcodeproj/xcuserdata/tdzl2003.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/RCTQQAPI.xcodeproj/xcuserdata/tdzl2003.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..6ace871 --- /dev/null +++ b/ios/RCTQQAPI.xcodeproj/xcuserdata/tdzl2003.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + RCTQQAPI.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 9139321B1C232D310085E3BA + + primary + + + + + diff --git a/ios/RCTQQAPI/RCTQQAPI.h b/ios/RCTQQAPI/RCTQQAPI.h new file mode 100644 index 0000000..e00640e --- /dev/null +++ b/ios/RCTQQAPI/RCTQQAPI.h @@ -0,0 +1,29 @@ +// +// RCTQQAPI.h +// RNThirdShareMangager +// +// Created by LvBingru on 10/10/15. +// Copyright © 2015 erica. All rights reserved. +// + +#if __has_include() +#import +#else +#import "RCTBridgeModule.h" +#endif + +#define RCTQQShareTypeNews @"news" +#define RCTQQShareTypeImage @"image" +#define RCTQQShareTypeText @"text" +#define RCTQQShareTypeVideo @"video" +#define RCTQQShareTypeAudio @"audio" + +#define RCTQQShareType @"type" +#define RCTQQShareTitle @"title" +#define RCTQQShareDescription @"description" +#define RCTQQShareWebpageUrl @"webpageUrl" +#define RCTQQShareImageUrl @"imageUrl" + +@interface RCTQQAPI : NSObject + +@end diff --git a/ios/RCTQQAPI/RCTQQAPI.m b/ios/RCTQQAPI/RCTQQAPI.m new file mode 100644 index 0000000..8abe0da --- /dev/null +++ b/ios/RCTQQAPI/RCTQQAPI.m @@ -0,0 +1,301 @@ +// +// QQAPI.m +// RNThirdShareMangager +// +// Created by LvBingru on 10/10/15. +// Copyright © 2015 erica. All rights reserved. +// + +#import "RCTQQAPI.h" +#import +#import +#import +#import + +#if __has_include() +#import +#import +#import +#import +#else +#import "RCTLog.h" +#import "RCTEventDispatcher.h" +#import "RCTBridge.h" +#import "RCTImageLoader.h" +#endif + +//#define NOT_REGISTERED (@"registerApp required.") +#define INVOKE_FAILED (@"QQ API invoke returns false.") + +@interface RCTQQAPI() { + TencentOAuth* _qqapi; +} + +@end + + +@implementation RCTQQAPI + +@synthesize bridge = _bridge; + +RCT_EXPORT_MODULE(); + +- (dispatch_queue_t)methodQueue +{ + return dispatch_get_main_queue(); +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURL:) name:@"RCTOpenURLNotification" object:nil]; + [self _autoRegisterAPI]; + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)handleOpenURL:(NSNotification *)note +{ + NSDictionary *userInfo = note.userInfo; + NSString *url = userInfo[@"url"]; + if ([TencentOAuth HandleOpenURL:[NSURL URLWithString:url]]) { + } + else { + [QQApiInterface handleOpenURL:[NSURL URLWithString:url] delegate:self]; + } +} + +RCT_EXPORT_METHOD(isQQInstalled:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + if ([QQApiInterface isQQInstalled]) { + resolve(@[[NSNull null]]); + } + else { + reject(@"-1",INVOKE_FAILED,nil); + } +} + +RCT_EXPORT_METHOD(isQQSupportApi:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + if ([QQApiInterface isQQSupportApi]) { + resolve(@[[NSNull null]]); + } + else { + reject(@"-1",INVOKE_FAILED,nil); + } +} + +RCT_EXPORT_METHOD(login:(NSString *)scopes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + NSArray *scopeArray = nil; + if (scopes && scopes.length) { + scopeArray = [scopes componentsSeparatedByString:@","]; + } + if (scopeArray == nil) { + scopeArray = @[@"get_user_info", @"get_simple_userinfo"]; + } + BOOL success = [_qqapi authorize:scopeArray]; + if (success) { + resolve(@[[NSNull null]]); + } + else { + reject(@"-1",INVOKE_FAILED,nil); + } +} + +RCT_EXPORT_METHOD(shareToQQ:(NSDictionary *)data resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + [self _shareToQQWithData:data scene:0 resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(shareToQzone:(NSDictionary *)data resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) +{ + [self _shareToQQWithData:data scene:1 resolve:resolve reject:reject]; +} + +RCT_EXPORT_METHOD(logout) +{ + [_qqapi logout:nil]; +} + +- (void)_shareToQQWithData:(NSDictionary *)aData scene:(int)aScene resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject{ + NSString *imageUrl = aData[RCTQQShareImageUrl]; + if (imageUrl.length && _bridge.imageLoader) { + CGSize size = CGSizeZero; + if (![aData[RCTQQShareType] isEqualToString:RCTQQShareTypeImage]) { + CGFloat thumbImageSize = 80; + size = CGSizeMake(thumbImageSize,thumbImageSize); + } + [_bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:imageUrl] callback:^(NSError *error, UIImage *image) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self _shareToQQWithData:aData image:image scene:aScene resolve:resolve reject:reject]; + }); + }]; + } + else { + [self _shareToQQWithData:aData image:nil scene:aScene resolve:resolve reject:reject]; + } +} + + +- (void)_shareToQQWithData:(NSDictionary *)aData image:(UIImage*) image scene:(int)aScene resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject { + NSString *type = aData[RCTQQShareType]; + + NSString *title = aData[RCTQQShareTitle]; + + NSString *description= aData[RCTQQShareDescription]; + NSString *imgPath = aData[RCTQQShareImageUrl]; + NSString *webpageUrl = aData[RCTQQShareWebpageUrl]? :@""; + NSString *flashUrl = aData[@"flashUrl"]; + + QQApiObject *message = nil; + + if (type.length <=0 || [type isEqualToString: RCTQQShareTypeNews]) { + message = [QQApiNewsObject + objectWithURL:[NSURL URLWithString:webpageUrl] + title:title + description:description + previewImageURL:[NSURL URLWithString:imgPath]]; + } + else if ([type isEqualToString: RCTQQShareTypeText]) { + message = [QQApiTextObject objectWithText:description]; + } + else if ([type isEqualToString: RCTQQShareTypeImage]) { + NSData *imgData = UIImageJPEGRepresentation(image, 1); + message = [QQApiImageObject objectWithData:imgData + previewImageData:imgData + title:title + description:description]; + } + else if ([type isEqualToString: RCTQQShareTypeAudio]) { + QQApiAudioObject *audioObj = [QQApiAudioObject objectWithURL:[NSURL URLWithString:webpageUrl] + title:title + description:description + previewImageURL:[NSURL URLWithString:imgPath]]; + if (flashUrl) { + [audioObj setFlashURL:[NSURL URLWithString:flashUrl]]; + } + message = audioObj; + } + else if ([type isEqualToString: RCTQQShareTypeVideo]) { + QQApiVideoObject *videoObj = [QQApiVideoObject objectWithURL:[NSURL URLWithString:webpageUrl] + title:title + description:description + previewImageURL:[NSURL URLWithString:imgPath]]; + if (flashUrl) { + [videoObj setFlashURL:[NSURL URLWithString:flashUrl]]; + } + message = videoObj; + } + + QQApiSendResultCode sent = EQQAPISENDFAILD; + + if (message != nil) { + SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:message]; + if (aScene == 0) { + sent = [QQApiInterface sendReq:req]; + } + else { + sent = [QQApiInterface SendReqToQZone:req]; + } + } + + if (sent == EQQAPISENDSUCESS) { + resolve(@[[NSNull null]]); + } + else if (sent == EQQAPIAPPSHAREASYNC) { + resolve(@[[NSNull null]]); + } + else { + reject(@"-1",INVOKE_FAILED,nil); + } +} + + +- (void)_autoRegisterAPI +{ + NSString *appId = nil; + NSArray *list = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleURLTypes"]; + for (NSDictionary *item in list) { + NSString *name = item[@"CFBundleURLName"]; + if ([name isEqualToString:@"qq"]) { + NSArray *schemes = item[@"CFBundleURLSchemes"]; + if (schemes.count > 0) + { + appId = [schemes[0] substringFromIndex:@"tencent".length]; + break; + } + } + } + _qqapi = [[TencentOAuth alloc] initWithAppId:appId andDelegate:self]; + +} + +#pragma mark - qq delegate +- (void)onReq:(QQBaseReq *)req +{ + +} + +- (void)onResp:(QQBaseResp *)resp +{ + if ([resp isKindOfClass:[SendMessageToQQResp class]]) { + + } + NSMutableDictionary *body = @{@"type":@"QQShareResponse"}.mutableCopy; + body[@"errMsg"] = resp.errorDescription; + if (resp.errorDescription) { + body[@"errCode"] = @(-1); + } + else { + body[@"errCode"] = @(0); + } + body[@"result"] =resp.result; + body[@"extendInfo"] =resp.extendInfo; + + [self.bridge.eventDispatcher sendAppEventWithName:@"QQ_Resp" body:body]; +} + +- (void)isOnlineResponse:(NSDictionary *)response +{ + +} + +#pragma mark - oauth delegate +- (void)tencentDidLogin +{ + NSMutableDictionary *body = @{@"type":@"QQAuthorizeResponse"}.mutableCopy; + body[@"errCode"] = @(0); + body[@"openid"] = _qqapi.openId; + body[@"access_token"] = _qqapi.accessToken; + body[@"expires_in"] = @([_qqapi.expirationDate timeIntervalSince1970]*1000); + body[@"oauth_consumer_key"] =_qqapi.appId; + + [self.bridge.eventDispatcher sendAppEventWithName:@"QQ_Resp" body:body]; +} + +- (void)tencentDidNotLogin:(BOOL)cancelled +{ + NSMutableDictionary *body = @{@"type":@"QQAuthorizeResponse"}.mutableCopy; + body[@"errCode"] = @(-1); + if (cancelled) { + body[@"errMsg"] = @"login canceled"; + } + else { + body[@"errMsg"] = @"login failed"; + } + [self.bridge.eventDispatcher sendAppEventWithName:@"QQ_Resp" body:body]; + +} + +- (void)tencentDidNotNetWork +{ +} + +@end diff --git a/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/QQApiInterface.h b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/QQApiInterface.h new file mode 100644 index 0000000..c52a1ee --- /dev/null +++ b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/QQApiInterface.h @@ -0,0 +1,158 @@ +/// +/// \file QQApiInterface.h +/// \brief QQApi接口简化封装 +/// +/// Created by Tencent on 12-5-15. +/// Copyright (c) 2012年 Tencent. All rights reserved. +/// + +#import +#import "QQApiInterfaceObject.h" + +typedef void (^sendResultBlock)(NSDictionary *result); + +/** + \brief 处理来至QQ的请求及响应的回调协议 + */ +@protocol QQApiInterfaceDelegate + +/** + 处理来至QQ的请求 + */ +- (void)onReq:(QQBaseReq *)req; + +/** + 处理来至QQ的响应 + */ +- (void)onResp:(QQBaseResp *)resp; + +/** + 处理QQ在线状态的回调 + */ +- (void)isOnlineResponse:(NSDictionary *)response; + +@end + +/** + \brief 对QQApi的简单封装类 + */ +@interface QQApiInterface : NSObject + +/** + 处理由手Q唤起的普通跳转请求 + \param url 待处理的url跳转请求 + \param delegate 第三方应用用于处理来至QQ请求及响应的委托对象 + \return 跳转请求处理结果,YES表示成功处理,NO表示不支持的请求协议或处理失败 + */ ++ (BOOL)handleOpenURL:(NSURL *)url delegate:(id)delegate; + +/** + 处理由手Q唤起的universallink跳转请求 + \param universallink 待处理的universallink跳转请求 + \param delegate 第三方应用用于处理来至QQ请求及响应的委托对象 + \return 跳转请求处理结果,YES表示成功处理,NO表示不支持的请求协议或处理失败 + */ ++ (BOOL)handleOpenUniversallink:(NSURL*)universallink delegate:(id)delegate; + +/** + 向手Q发起分享请求 + \param req 分享内容的请求 + \return 请求发送结果码 + */ ++ (QQApiSendResultCode)sendReq:(QQBaseReq *)req; + + +/** + 向手Q QZone结合版发起分享请求 + \note H5分享只支持单张网络图片的传递 + \param req 分享内容的请求 + \return 请求发送结果码 + */ ++ (QQApiSendResultCode)SendReqToQZone:(QQBaseReq *)req; + +/** + 向手Q发起设置QQ头像 + \param req 分享内容的请求 + \return 请求发送结果码 + */ ++ (QQApiSendResultCode)sendMessageToQQAvatarWithReq:(QQBaseReq*)req; + +/** + 向手Q发起组图分享到表情收藏 + \param req 分享内容的请求 + \return 请求发送结果码 + */ ++ (QQApiSendResultCode)sendMessageToFaceCollectionWithReq:(QQBaseReq*)req; + +/** + 检测是否已安装QQ + \return 如果QQ已安装则返回YES,否则返回NO + + \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 + 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 + 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 + */ ++ (BOOL)isQQInstalled; + +/** + 检测是否已安装TIM + \return 如果TIM已安装则返回YES,否则返回NO + + \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 + 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 + 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 + */ ++ (BOOL)isTIMInstalled; + +/** + 检测QQ是否支持API调用 + \return 如果当前安装QQ版本支持API调用则返回YES,否则返回NO + */ ++ (BOOL)isQQSupportApi; + +/** + 检测TIM是否支持API调用 + \return 如果当前安装TIM版本支持API调用则返回YES,否则返回NO + */ ++ (BOOL)isTIMSupportApi __attribute__((deprecated("已过期, 建议删除调用,调用地方用YES替代。"))); + +/** + 检测是否支持分享 + \return 如果当前已安装QQ且QQ版本支持API调用 或者 当前已安装TIM且TIM版本支持API调用则返回YES,否则返回NO + */ ++ (BOOL)isSupportShareToQQ; + +/** + 检测是否支持分享到QQ结合版QZone + \return 如果当前已安装QQ且QQ版本支持API调用则返回YES,否则返回NO + */ ++ (BOOL)isSupportPushToQZone; + +/** + 启动QQ + \return 成功返回YES,否则返回NO + */ ++ (BOOL)openQQ; + +/** + 启动TIM + \return 成功返回YES,否则返回NO + */ ++ (BOOL)openTIM; + +/** + 获取QQ下载地址 + + 如果App通过QQApiInterface#isQQInstalledQQApiInterface#isQQSupportApi检测发现QQ没安装或当前版本QQ不支持API调用,可引导用户通过打开此链接下载最新版QQ。 + \return iPhoneQQ下载地址 + */ ++ (NSString *)getQQInstallUrl; + +/** + 获取TIM下载地址 + + 如果App通过QQApiInterface#isTIMInstalled检测发现TIM没安装或当前版本TIM不支持API调用,可引导用户通过打开此链接下载最新版TIM。 + \return iPhoneTIM下载地址 + */ ++ (NSString *)getTIMInstallUrl; +@end diff --git a/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/QQApiInterfaceObject.h b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/QQApiInterfaceObject.h new file mode 100644 index 0000000..3a73da4 --- /dev/null +++ b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/QQApiInterfaceObject.h @@ -0,0 +1,645 @@ +/// +/// \file QQApiInterfaceObject.h +/// \brief QQApiInterface所依赖的请求及应答消息对象封装帮助类 +/// +/// Created by Tencent on 12-5-15. +/// Copyright (c) 2012年 Tencent. All rights reserved. +/// + +#ifndef QQApiInterface_QQAPIOBJECT_h +#define QQApiInterface_QQAPIOBJECT_h + +#import + +typedef NS_ENUM(NSInteger,QQApiSendResultCode) { + EQQAPISENDSUCESS = 0, + EQQAPIQQNOTINSTALLED = 1, //QQ未安装 + EQQAPIQQNOTSUPPORTAPI = 2, // QQ api不支持 + EQQAPIMESSAGETYPEINVALID = 3, + EQQAPIMESSAGECONTENTNULL = 4, + EQQAPIMESSAGECONTENTINVALID = 5, + EQQAPIAPPNOTREGISTED = 6, + EQQAPIAPPSHAREASYNC = 7, + EQQAPIQQNOTSUPPORTAPI_WITH_ERRORSHOW = 8, //QQ api不支持 && SDK显示error提示(已废弃) + EQQAPIMESSAGEARKCONTENTNULL = 9, //ark内容为空 + EQQAPIMESSAGE_MINI_CONTENTNULL = 10, //小程序参数为空 + EQQAPISENDFAILD = -1, //发送失败 + EQQAPISHAREDESTUNKNOWN = -2, //未指定分享到QQ或TIM + EQQAPITIMSENDFAILD = -3, //发送失败 + EQQAPITIMNOTINSTALLED = 11, //TIM未安装 + EQQAPITIMNOTSUPPORTAPI = 12, // TIM api不支持 + EQQAPI_INCOMING_PARAM_ERROR = 13, // 外部传参错误 + EQQAPI_THIRD_APP_GROUP_ERROR_APP_NOT_AUTHORIZIED = 14, // APP未获得授权 + EQQAPI_THIRD_APP_GROUP_ERROR_CGI_FAILED = 15, // CGI请求失败 + EQQAPI_THIRD_APP_GROUP_ERROR_HAS_BINDED = 16, // 该组织已经绑定群聊 + EQQAPI_THIRD_APP_GROUP_ERROR_NOT_BINDED = 17, // 该组织尚未绑定群聊 + EQQAPIQZONENOTSUPPORTTEXT = 10000, //qzone分享不支持text类型分享 + EQQAPIQZONENOTSUPPORTIMAGE = 10001, //qzone分享不支持image类型分享 + EQQAPIVERSIONNEEDUPDATE = 10002, //当前QQ版本太低,需要更新至新版本才可以支持 + ETIMAPIVERSIONNEEDUPDATE = 10004, //当前TIM版本太低,需要更新至新版本才可以支持 +}; + +#pragma mark - QQApiObject(分享对象类型) + +// QQApiObject control flags +typedef NS_ENUM(NSUInteger,kQQAPICtrlFlag) { + kQQAPICtrlFlagQZoneShareOnStart = 0x01, + kQQAPICtrlFlagQZoneShareForbid = 0x02, + kQQAPICtrlFlagQQShare = 0x04, + kQQAPICtrlFlagQQShareFavorites = 0x08, //收藏 + kQQAPICtrlFlagQQShareDataline = 0x10, //数据线 + kQQAPICtrlFlagQQShareEnableArk = 0x20, //支持ARK + kQQAPICtrlFlagQQShareEnableMiniProgram = 0x40, //支持小程序 +}; + +// 分享到QQ或TIM +typedef NS_ENUM(NSUInteger, ShareDestType) { + ShareDestTypeQQ = 0, + ShareDestTypeTIM, +}; + +//小程序的类型 +typedef NS_ENUM(NSUInteger, MiniProgramType) { + MiniProgramType_Develop=0, // 开发版 + MiniProgramType_Test=1, // 测试版 + MiniProgramType_Online=3, // 正式版,默认 + MiniProgramType_Preview=4, // 预览版 +}; + +// QQApiObject +/** \brief 所有在QQ及插件间发送的数据对象的根类。 + */ +__attribute__((visibility("default"))) @interface QQApiObject : NSObject +@property(nonatomic, retain) NSString* title; ///< 标题,最长128个字符 +@property(nonatomic, retain) NSString* description; ///<简要描述,最长512个字符 +@property(nonatomic, retain) NSString* universalLink; ///(>=3.3.7)支持第三方传入在互联开放平台注册的universallink +@property(nonatomic, assign) uint64_t cflag; +/* + * 分享到QQ/TIM + * SDK根据是否安装对应客户端进行判断,判断顺序:QQ > TIM + * 默认分享到QQ,如果QQ未安装检测TIM是否安装 + */ +@property (nonatomic, assign) ShareDestType shareDestType; +@end + +// ArkObject +/** \brief 支持Ark的根类。 + */ +__attribute__((visibility("default"))) @interface ArkObject : NSObject +@property(nonatomic,retain) NSString* arkData; ///< 显示Ark所需的数据,json串,长度暂不限制 +@property(nonatomic,assign) QQApiObject* qqApiObject; ///<原有老版本的QQApiObject + +- (id)initWithData:(NSString *)arkData qqApiObject:(QQApiObject*)qqApiObject; ++ (id)objectWithData:(NSString *)arkData qqApiObject:(QQApiObject*)qqApiObject; +@end + +#pragma mark QQ小程序 +//分享小程序消息 - QQ 8.0.8 +__attribute__((visibility("default"))) @interface QQApiMiniProgramObject : NSObject +@property(nonatomic,retain) QQApiObject* qqApiObject; //原有老版本的QQApiObject +@property(nonatomic,retain) NSString* miniAppID; //必填,小程序的AppId(注:必须在QQ互联平台中,将该小程序与分享的App绑定) +@property(nonatomic,retain) NSString* miniPath; //必填,小程序的展示路径 +@property(nonatomic,retain) NSString* webpageUrl; //必填,兼容低版本的网页链接 +@property(nonatomic,assign) MiniProgramType miniprogramType; //非必填,小程序的类型,默认正式版(3),可选测试版(1)、预览版(4) +@end + +//唤起小程序 - QQ 8.1.8 +__attribute__((visibility("default"))) @interface QQApiLaunchMiniProgramObject : QQApiObject +@property(nonatomic,retain) NSString* miniAppID; //必填,小程序的AppId(注:必须在QQ互联平台中,将该小程序与分享的App绑定) +@property(nonatomic,retain) NSString* miniPath; //必填,小程序的展示路径 +@property(nonatomic,assign) MiniProgramType miniprogramType; //非必填,小程序的类型,默认正式版(3),可选测试版(1)、开发版(0) +@end +// QQApiResultObject +/** \brief 用于请求回应的数据类型。 +

可能错误码及描述如下:

+ + + + + + + + +
errorerrorDescription注释
0nil成功
-1param error参数错误
-2group code is invalid该群不在自己的群列表里面
-3upload photo failed上传图片失败
-4user give up the current operation用户放弃当前操作
-5client internal error客户端内部处理错误
+ */ +__attribute__((visibility("default"))) @interface QQApiResultObject : QQApiObject +@property(nonatomic,retain) NSString* error; ///<错误 +@property(nonatomic,retain) NSString* errorDescription; ///<错误描述 +@property(nonatomic,retain) NSString* extendInfo; ///<扩展信息 +@end + +// QQApiTextObject +/** \brief 文本对象 + */ +@interface QQApiTextObject : QQApiObject +@property(nonatomic,retain)NSString* text; ///<文本内容,必填,最长1536个字符 + +-(id)initWithText:(NSString*)text; ///<初始化方法 ++(id)objectWithText:(NSString*)text;///<工厂方法,获取一个QQApiTextObject对象. +@end + +// QQApiURLObject +typedef NS_ENUM(NSUInteger, QQApiURLTargetType) { + QQApiURLTargetTypeNotSpecified = 0x00, + QQApiURLTargetTypeAudio = 0x01, + QQApiURLTargetTypeVideo = 0x02, + QQApiURLTargetTypeNews = 0x03 +}; + +/** @brief URL对象类型。 + + 包括URL地址,URL地址所指向的目标类型及预览图像。 + */ +__attribute__((visibility("default"))) @interface QQApiURLObject : QQApiObject +/** + URL地址所指向的目标类型. + @note 参见QQApi.h 中的 QQApiURLTargetType 定义. + */ +@property(nonatomic)QQApiURLTargetType targetContentType; + +@property(nonatomic,retain)NSURL* url; ///QQApiExtendObject对象 + @param data 数据内容 + @param previewImageData 用于预览的图片 + @param title 标题 + @param description 此对象,分享的描述 + @return + 一个自动释放的QQApiExtendObject实例 + */ ++ (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description; + +/** + helper方法获取一个autorelease的QQApiExtendObject对象 + @param data 数据内容 + @param previewImageData 用于预览的图片 + @param title 标题 + @param description 此对象,分享的描述 + @param imageDataArray 发送的多张图片队列 + @return + 一个自动释放的QQApiExtendObject实例 + */ ++ (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description imageDataArray:(NSArray*)imageDataArray; + +@end + +// QQApiImageObject +/** @brief 图片对象 + 用于分享图片内容的对象,是一个指定为图片类型的QQApiExtendObject + */ +@interface QQApiImageObject : QQApiExtendObject +@end + +// QQApiImageForQQAvatarObject +/** @brief 图片对象 + 用于设置QQ头像内容的对象,是一个指定为图片类型的QQApiExtendObject + */ +@interface QQApiImageForQQAvatarObject : QQApiExtendObject +@end +/** + * @brief 视频对象 + * 用于设置动态头像 + * assetURL可传ALAsset的ALAssetPropertyAssetURL,或者PHAsset的localIdentifier + 从手Q返回的错误码: + //第三方设置动态头像结果 + @"ret=0"//设置成功 + @"ret=-10&error_des=user cancel"//用户取消设置 + @"ret=-11&error_des=pasteboard have no video data"//剪切板没有数据 + @"ret=-12&error_des=export data failed"//从剪切板导出数据到本地失败 + @"ret=-13&error_des=url param invalid"//sdk传递过来的数据有误 + @"ret=-14&error_des=video param invalid"//视频的参数不符合要求(检测第三方视频源方案:1、分辨率跟480*480保持一致;2、视频长度0.5s~8s) + @"ret=-15&error_des=app authorised failed"//应用鉴权失败 + @"ret=-16&error_des=upload video failed"//设置头像,上传到后台失败 + @"ret=-17&error_des=account diff"//账号不一致 + */ +@interface QQApiVideoForQQAvatarObject : QQApiExtendObject +@property(nonatomic, retain) NSString *assetURL; +@end + +// QQApiImageArrayForFaceCollectionObject +/** @brief 图片数组对象 + 用于分享图片组到表情收藏,是一个指定为图片类型的QQApiObject + */ +@interface QQApiImageArrayForFaceCollectionObject : QQApiObject + +@property(nonatomic,retain) NSArray* imageDataArray;///图片数组 + +/** + 初始化方法 + @param imageDataArray 图片数组 + */ +- (id)initWithImageArrayData:(NSArray*)imageDataArray; +/** + helper方法获取一个autorelease的QQApiObject对象 + @param imageDataArray 发送的多张图片队列 + @return + 一个自动释放的QQApiObject实例 + */ ++ (id)objectWithimageDataArray:(NSArray *)imageDataArray; + +@end + +// QQApiImageArrayForQZoneObject +/** @brief 图片对象 + 用于分享图片到空间,走写说说路径,是一个指定为图片类型的,当图片数组为空时,默认走文本写说说QQApiObject + */ +@interface QQApiImageArrayForQZoneObject : QQApiObject + +@property(nonatomic,retain) NSArray* imageDataArray;///图片数组 +@property(nonatomic,retain) NSDictionary* extMap; // 扩展字段 + +/** + 初始化方法 + @param imageDataArray 图片数组 + @param title 写说说的内容,可以为空 + @param extMap 扩展字段 + */ +- (id)initWithImageArrayData:(NSArray*)imageDataArray title:(NSString*)title extMap:(NSDictionary *)extMap; + +/** + helper方法获取一个autorelease的QQApiExtendObject对象 + @param title 写说说的内容,可以为空 + @param imageDataArray 发送的多张图片队列 + @param extMap 扩展字段 + @return + 一个自动释放的QQApiExtendObject实例 + */ ++ (id)objectWithimageDataArray:(NSArray*)imageDataArray title:(NSString*)title extMap:(NSDictionary *)extMap; + +@end + +// QQApiVideoForQZoneObject +/** @brief 视频对象 + 用于分享视频到空间,走写说说路径QQApiObject,assetURL和videoData两个参数必须设置至少一个参数,如果assetURL设置了忽略videoData参数 + @param assetURL可传ALAsset的ALAssetPropertyAssetURL,或者PHAsset的localIdentifier + @param extMap 扩展字段 + @param videoData 视频数据,大小不超过50M + */ +@interface QQApiVideoForQZoneObject : QQApiObject + +@property(nonatomic, retain) NSString *assetURL; +@property(nonatomic,retain) NSDictionary* extMap; // 扩展字段 +@property(nonatomic,retain) NSData* videoData; + +- (id)initWithAssetURL:(NSString*)assetURL title:(NSString*)title extMap:(NSDictionary *)extMap; + ++ (id)objectWithAssetURL:(NSString*)assetURL title:(NSString*)title extMap:(NSDictionary *)extMap; + +- (id)initWithVideoData:(NSData*)videoData title:(NSString*)title extMap:(NSDictionary *)extMap; + ++ (id)objectWithVideoData:(NSData*)videoData title:(NSString*)title extMap:(NSDictionary *)extMap; + +@end + +// QQApiWebImageObject +/** @brief 图片对象 + 用于分享网络图片内容的对象,是一个指定网络图片url的: 该类型只在2.9.0的h5分享中才支持, + 原有的手q分享是不支持该类型的。 + */ +@interface QQApiWebImageObject : QQApiObject + +@property(nonatomic, retain) NSURL *previewImageURL; ///<预览图像URL + +/** + 初始化方法 + @param previewImageURL 用于预览的图片 + @param title 标题 + @param description 此对象,分享的描述 + */ +- (id)initWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; + +/** + helper方法获取一个autorelease的QQApiWebImageObject对象 + @param previewImageURL 用于预览的图片 + @param title 标题 + @param description 此对象,分享的描述 + */ ++ (id)objectWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; + +@end + + +//QQApiFileObject +/** @brief 本地文件对象(暂只支持分享到手机QQ数据线功能) + 用于分享文件内容的对象,是一个指定为文件类型的QQApiExtendObject + */ +@interface QQApiFileObject : QQApiExtendObject +{ + NSString* _fileName; +} +@property(nonatomic, retain)NSString* fileName; +@end + +// QQApiAudioObject +/** @brief 音频URL对象 + 用于分享目标内容为音频的URL的对象 + */ +@interface QQApiAudioObject : QQApiURLObject + +@property (nonatomic, retain) NSURL *flashURL; ///<音频URL地址,最长512个字符 + +/** + 获取一个autorelease的QQApiAudioObject + @param url 音频内容的目标URL + @param title 分享内容的标题 + @param description 分享内容的描述 + @param data 分享内容的预览图像 + @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE + */ ++(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; + +/** + 获取一个autorelease的QQApiAudioObject + @param url 音频内容的目标URL + @param title 分享内容的标题 + @param description 分享内容的描述 + @param previewURL 分享内容的预览图像URL + @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE + */ ++(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; + +@end + +// QQApiVideoObject +/** @brief 视频URL对象 + 用于分享目标内容为视频的URL的对象 + + QQApiVideoObject类型的分享,目前在Android和PC QQ上接收消息时,展现有待完善,待手机QQ版本以后更新支持 + 目前如果要分享视频,推荐使用 QQApiNewsObject 类型 + */ +@interface QQApiVideoObject : QQApiURLObject + +@property (nonatomic, retain) NSURL *flashURL; ///<视频URL地址,最长512个字符 + +/** + 获取一个autorelease的QQApiVideoObject + @param url 视频内容的目标URL + @param title 分享内容的标题 + @param description 分享内容的描述 + @param data 分享内容的预览图像 + @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE + */ ++(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; + +/** + 获取一个autorelease的QQApiVideoObject + @param url 视频内容的目标URL + @param title 分享内容的标题 + @param description 分享内容的描述 + @param previewURL 分享内容的预览图像URL + @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE + */ ++(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; + +@end + +// QQApiNewsObject +/** @brief 新闻URL对象 + 用于分享目标内容为新闻的URL的对象 + */ +@interface QQApiNewsObject : QQApiURLObject +/** + 获取一个autorelease的QQApiNewsObject + @param url 视频内容的目标URL + @param title 分享内容的标题 + @param description 分享内容的描述 + @param data 分享内容的预览图像 + @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE + */ ++(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; + +/** + 获取一个autorelease的QQApiNewsObject + @param url 视频内容的目标URL + @param title 分享内容的标题 + @param description 分享内容的描述 + @param previewURL 分享内容的预览图像URL + @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE + */ ++(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; + +@end + +// QQApiCommonContentObject; +/** @brief 通用模板类型对象 + 用于分享一个固定显示模板的图文混排对象 + @note 图片列表和文本列表不能同时为空 + */ +@interface QQApiCommonContentObject : QQApiObject +/** + 预定义的界面布局类型 + */ +@property(nonatomic,assign) unsigned int layoutType; +@property(nonatomic,assign) NSData* previewImageData;///<预览图 +@property(nonatomic,retain) NSArray* textArray;///<文本列表 +@property(nonatomic,retain) NSArray* pictureDataArray;///<图片列表 ++(id)objectWithLayoutType:(int)layoutType textArray:(NSArray*)textArray pictureArray:(NSArray*)pictureArray previewImageData:(NSData*)data; +/** + 将一个NSDictionary对象转化为QQApiCommomContentObject,如果无法转换,则返回空 + */ ++(id)objectWithDictionary:(NSDictionary*)dic; +-(NSDictionary*)toDictionary; +@end + +// QQApiExtraServiceObject; +/** + @brief OpenSDK扩展支持的服务,通用接口,后续会扩充能力 + @param serviceID [必选] 扩展支持的服务类型ID,参考官方文档说明 + @param openID [必选] 授权登录后对该用户的唯一标识 + @param toUin [可选] 对方的QQ号码 + @param extraInfo [可选] 扩展字段 + @note 该接口的使用须先登录 + */ +@interface QQApiExtraServiceObject : QQApiObject +@property (nonatomic,retain) NSString* serviceID; +@property (nonatomic,retain) NSString* openID; +@property (nonatomic,retain) NSString* toUin; +@property (nonatomic,retain) NSDictionary* extraInfo; + +- (id)initWithOpenID:(NSString *)openID serviceID:(NSString *)serviceID; ++ (id)objecWithOpenID:(NSString *)openID serviceID:(NSString *)serviceID; +@end + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Ad item object definition +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @brief 广告数据对象 + */ +@interface QQApiAdItem : NSObject +@property(nonatomic,retain) NSString* title; ///<名称 +@property(nonatomic,retain) NSString* description;///<描述 +@property(nonatomic,retain) NSData* imageData;///<广告图片 +@property(nonatomic,retain) NSURL* target;///<广告目标链接 +@end + + +#pragma mark - QQApi请求消息类型 + +/** + QQApi请求消息类型 + */ +typedef NS_ENUM(NSUInteger, QQApiInterfaceReqType) { + EGETMESSAGEFROMQQREQTYPE = 0, ///< 手Q -> 第三方应用,请求第三方应用向手Q发送消息 + ESENDMESSAGETOQQREQTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用向手Q分享消息 + ESHOWMESSAGEFROMQQREQTYPE = 2, ///< 手Q -> 第三方应用,请求第三方应用展现消息中的数据 + ESENDMESSAGEARKTOQQREQTYPE = 3, ///< 第三方应用 -> 手Q,第三方应用向手Q分享Ark消息 + ESENDMESSAGE_MINI_TOQQREQTYPE = 4 ///< 第三方应用 -> 手Q,第三方应用向手Q分享小程序消息 +}; + +/** + QQApi应答消息类型 + */ +typedef NS_ENUM(NSUInteger, QQApiInterfaceRespType) { + ESHOWMESSAGEFROMQQRESPTYPE = 0, ///< 第三方应用 -> 手Q,第三方应用应答消息展现结果 + EGETMESSAGEFROMQQRESPTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用回应发往手Q的消息 + ESENDMESSAGETOQQRESPTYPE = 2 ///< 手Q -> 第三方应用,手Q应答处理分享消息的结果 +}; + +/** + QQApi请求消息基类 + */ +@interface QQBaseReq : NSObject + +/** 请求消息类型,参见\ref QQApiInterfaceReqType */ +@property (nonatomic, assign) int type; + +@end + +/** + QQApi应答消息基类 + */ +@interface QQBaseResp : NSObject + +/** 请求处理结果 */ +@property (nonatomic, copy) NSString* result; + +/** 具体错误描述信息 */ +@property (nonatomic, copy) NSString* errorDescription; + +/** 应答消息类型,参见\ref QQApiInterfaceRespType */ +@property (nonatomic, assign) int type; + +/** 扩展信息 */ +@property (nonatomic, assign) NSString* extendInfo; + +@end + +/** + GetMessageFromQQReq请求帮助类 + */ +@interface GetMessageFromQQReq : QQBaseReq + +/** + 创建一个GetMessageFromQQReq请求实例 + */ ++ (GetMessageFromQQReq *)req; + +@end + +@interface SendMessageToQQReq : QQBaseReq + +/** + 创建一个SendMessageToQQReq请求实例 + \param message 具体分享消息实例 + \return 新创建的SendMessageToQQReq请求实例 + */ ++ (SendMessageToQQReq *)reqWithContent:(QQApiObject *)message; + +/** + 创建一个支持Ark的SendMessageToQQReq请求实例 + \param message 具体分享消息实例 + \return 新创建的SendMessageToQQReq请求实例 + */ ++ (SendMessageToQQReq *)reqWithArkContent:(ArkObject *)message; +/** + * 创建一个支持小程序的消息请求实例 + * @param miniMessage 小程序实例对象 + * @return 消息请求实例 + */ ++(SendMessageToQQReq*) reqWithMiniContent:(QQApiMiniProgramObject *)miniMessage; +/** 具体分享消息 */ +@property (nonatomic, retain) QQApiObject *message; + +/** 支持Ark的具体分享消息 */ +@property (nonatomic, retain) ArkObject *arkMessage; +/** 支持小程序的具体分享消息 */ +@property (nonatomic, retain) QQApiMiniProgramObject *miniMessage; +@end + +/** + SendMessageToQQResp应答帮助类 + */ +@interface SendMessageToQQResp : QQBaseResp + +/** + 创建一个SendMessageToQQResp应答实例 + \param result 请求处理结果 + \param errDesp 具体错误描述信息 + \param extendInfo 扩展信息 + \return 新创建的SendMessageToQQResp应答实例 + */ ++ (SendMessageToQQResp *)respWithResult:(NSString *)result errorDescription:(NSString *)errDesp extendInfo:(NSString*)extendInfo; + +@end + +/** + ShowMessageFromQQReq请求帮助类 + */ +@interface ShowMessageFromQQReq : QQBaseReq + +/** + 创建一个ShowMessageFromQQReq请求实例 + \param message 具体待展现消息实例 + \return 新创建的ShowMessageFromQQReq请求实例 + */ ++ (ShowMessageFromQQReq *)reqWithContent:(QQApiObject *)message; + +/** 具体待展现消息 */ +@property (nonatomic, retain) QQApiObject *message; + +@end + + +#endif diff --git a/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/TencentOAuth.h b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/TencentOAuth.h new file mode 100644 index 0000000..1bb4189 --- /dev/null +++ b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/TencentOAuth.h @@ -0,0 +1,494 @@ +/// +/// \file TencentOAuth.h +/// \brief QQ互联开放平台授权登录及相关开放接口实现类 +/// +/// Created by Tencent on 12-12-21. +/// Copyright (c) 2012年 Tencent. All rights reserved. +/// + +#import +#import "sdkdef.h" + +@protocol TencentSessionDelegate; +@protocol TencentLoginDelegate; +@protocol TencentApiInterfaceDelegate; +@protocol TencentWebViewDelegate; + +@class TencentApiReq; +@class TencentApiResp; + +typedef NS_ENUM(NSUInteger, TencentAuthorizeState) { + kTencentNotAuthorizeState, + kTencentSSOAuthorizeState, + kTencentWebviewAuthorzieState, +}; + +typedef NS_ENUM(NSUInteger, TencentAuthMode) { + kAuthModeClientSideToken, + kAuthModeServerSideCode, +}; + +#pragma mark - TencentOAuth(授权登录及相关开放接口调用) + +/** + * \brief TencentOpenAPI授权登录及相关开放接口调用 + * + * TencentOAuth实现授权登录逻辑以及相关开放接口的请求调用 + */ +@interface TencentOAuth : NSObject +{ + NSMutableDictionary* _apiRequests; + NSString* _accessToken; + NSDate* _expirationDate; + id _sessionDelegate; + NSString* _localAppId; + NSString* _openId; + NSString* _redirectURI; + NSArray* _permissions; +} + +/** Access Token凭证,用于后续访问各开放接口 */ +@property(nonatomic, copy) NSString* accessToken; + +/** Access Token的失效期 */ +@property(nonatomic, copy) NSDate* expirationDate; + +/** 已实现的开放接口的回调委托对象 */ +@property(nonatomic, assign) id sessionDelegate; + +/** 第三方应用在开发过程中设置的URLSchema,用于浏览器登录后后跳到第三方应用 */ +@property(nonatomic, copy) NSString* localAppId; + +/** 用户授权登录后对该用户的唯一标识 */ +@property(nonatomic, copy) NSString* openId; + +/** 用户登录成功过后的跳转页面地址 */ +@property(nonatomic, copy) NSString* redirectURI; + +/** 第三方应用在互联开放平台申请的appID */ +@property(nonatomic, retain) NSString* appId; + +/** 第三方应用在互联开放平台注册的UniversalLink */ +@property(nonatomic, retain) NSString* universalLink; + +/** 主要是互娱的游戏设置uin */ +@property(nonatomic, retain) NSString* uin; + +/** 主要是互娱的游戏设置鉴定票据 */ +@property(nonatomic, retain) NSString* skey; + +/** 登陆透传的数据 */ +@property(nonatomic, copy) NSDictionary* passData; + +/** 授权方式(Client Side Token或者Server Side Code) */ +@property(nonatomic, assign) TencentAuthMode authMode; + +/** union id */ +@property(nonatomic, retain) NSString* unionid; + +/** 第三方在授权登录/分享 时选择 QQ,还是TIM 。在授权前一定要指定其中一个类型*/ +@property(nonatomic, assign) TencentAuthShareType authShareType; + +/** + * 获取上次登录得到的token + * + **/ +- (NSString *)getCachedToken; + +/** + * 获取上次登录得到的openid + * + **/ +- (NSString *)getCachedOpenID; + +/** + * 获取上次登录的token过期日期 + * + **/ +- (NSDate *)getCachedExpirationDate; + +/** + * 上次登录的token是否过期(本地判断) + **/ +- (BOOL)isCachedTokenValid; + +/** + * 删除上次登录登录的token信息 + * + **/ +- (BOOL)deleteCachedToken; + +/** + * 用来获得当前sdk的版本号 + * \return 返回sdk版本号 + **/ + ++ (NSString*)sdkVersion; + +/** + * 用来获得当前sdk的小版本号 + * \return 返回sdk小版本号 + **/ + ++ (NSString*)sdkSubVersion; + +/** + * 用来获得当前sdk的是否精简版 + * \return 返回YES表示精简版 + **/ + ++ (BOOL)isLiteSDK; + +/** + * 主要是用来帮助判断是否有登陆被发起,但是还没有过返回结果 + * \return + * kTencentNotAuthorizeState:无授权 + * kTencentSSOAuthorizeState:有人发起了sso授权但无返回 + * kTencentWebviewAuthorzieState:有人发起了webview授权还未返回 + **/ + ++ (TencentAuthorizeState *)authorizeState; + +/** + * 用来获得当前手机qq的版本号 + * \return 返回手机qq版本号 + **/ ++ (int)iphoneQQVersion __attribute__((deprecated("已过期, 建议删除调用"))); + + +/** + * 用来获得当前手机TIM的版本号 + * \return 返回手机qq版本号 + **/ ++ (int)iphoneTIMVersion __attribute__((deprecated("已过期, 建议删除调用"))); + +/** + * 初始化TencentOAuth对象 + * \param appId 第三方应用在互联开放平台申请的唯一标识 + * \param delegate 第三方应用用于接收请求返回结果的委托对象 + * \return 初始化后的授权登录对象 + */ +- (id)initWithAppId:(NSString *)appId + andDelegate:(id)delegate; + +/** +* 初始化TencentOAuth对象(>=3.3.7) +* \param appId 第三方应用在互联开放平台申请的唯一标识 +* \param universalLink 第三方应用在互联开放平台注册的universallink,和bundleID一一对应 +* \param delegate 第三方应用用于接收请求返回结果的委托对象 +* \return 初始化后的授权登录对象 +*/ +- (id)initWithAppId:(NSString *)appId + andUniversalLink:(NSString *)universalLink + andDelegate:(id)delegate; + +/** + * 判断用户手机上是否安装手机QQ + * \return YES:安装 NO:没安装 + * + * \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 + * 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 + * 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 + */ ++ (BOOL)iphoneQQInstalled; + +/** + * 判断用户手机上是否安装手机TIM + * \return YES:安装 NO:没安装 + * + * \note SDK目前已经支持QQ、TIM授权登录及分享功能, 会按照QQ>TIM的顺序进行调用。 + * 只要用户安装了QQ、TIM中任意一个应用,都可为第三方应用进行授权登录、分享功能。 + * 第三方应用在接入SDK时不需要判断是否安装QQ、TIM。若有判断安装QQ、TIM的逻辑建议移除。 + */ ++ (BOOL)iphoneTIMInstalled; + +/** + * 判断用户手机上的手机QQ是否支持SSO登录 + * \return YES:支持 NO:不支持 + */ ++ (BOOL)iphoneQQSupportSSOLogin __attribute__((deprecated("QQ版本均支持SSO登录。该接口已过期, 建议删除调用"))); + +/** + * 判断用户手机上的手机TIM是否支持SSO登录 + * \return YES:支持 NO:不支持 + */ ++ (BOOL)iphoneTIMSupportSSOLogin __attribute__((deprecated("TIM版本均支持SSO登录。该接口已过期, 建议删除调用"))); + +/** + * 登录授权 + * + * \param permissions 授权信息列 + */ +- (BOOL)authorize:(NSArray *)permissions; + +/** + * 登录授权 + * \param permissions 授权信息列表 + * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 + */ +- (BOOL)authorize:(NSArray *)permissions + inSafari:(BOOL)bInSafari; + +/** + * 登录授权 + * \param permissions 授权信息列表 + * \param localAppId 应用APPID + * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 + */ +- (BOOL)authorize:(NSArray *)permissions + localAppId:(NSString *)localAppId + inSafari:(BOOL)bInSafari; + +/** + * 登录授权 + * + * \param permissions 授权信息列 + */ +- (BOOL)authorizeWithQRlogin:(NSArray *)permissions; + +/** + * 增量授权,因用户没有授予相应接口调用的权限,需要用户确认是否授权 + * \param permissions 需增量授权的信息列表 + * \return 增量授权调用是否成功 + */ +- (BOOL)incrAuthWithPermissions:(NSArray *)permissions; + +/** + * 重新授权,因token废除或失效导致接口调用失败,需用户重新授权 + * \param permissions 授权信息列表,同登录授权 + * \return 授权调用是否成功 + */ +- (BOOL)reauthorizeWithPermissions:(NSArray *)permissions; + +/** + * 获取UnindID,可以根据UnindID的比较来确定OpenID是否属于同一个用户 + * \return NO未登录,信息不足;YES条件满足,发送请求成功,请等待回调 + */ +- (BOOL)RequestUnionId; + +/** + * (静态方法)处理应用拉起协议 + * \param url 处理被其他应用呼起时的逻辑 + * \return 处理结果,YES表示成功,NO表示失败 + */ ++ (BOOL)HandleOpenURL:(NSURL *)url; + +/** + * (静态方法)sdk是否可以处理应用拉起协议 + * \param url 处理被其他应用呼起时的逻辑 + * \return 处理结果,YES表示可以 NO表示不行 + */ ++ (BOOL)CanHandleOpenURL:(NSURL *)url; + +/** + * (静态方法)处理应用的UniversalLink拉起协议 + * \param url 处理被其他应用呼起时的逻辑 + * \return 处理结果,YES表示成功,NO表示失败 + */ ++ (BOOL)HandleUniversalLink:(NSURL *)url; + +/** + * (静态方法)sdk是否可以处理应用的Universallink拉起协议 + * \param url 处理被其他应用呼起时的逻辑(应用的Universallink链接须满足官网注册时的格式要求) + * \return 处理结果,YES表示可以 NO表示不行 + * 注:在调用其他Universallink相关处理接口之前,均需进行此项判断 + */ ++ (BOOL)CanHandleUniversalLink:(NSURL *)url; + +/** + * (静态方法)获取TencentOAuth调用的上一次错误信息 + */ ++ (NSString *)getLastErrorMsg; + +/** + * 以Server Side Code模式授权登录时,通过此接口获取返回的code值; + * 以Client Side Token模式授权登录时,忽略此接口。 + */ +- (NSString *)getServerSideCode; + +/** + * 退出登录(退出登录后,TecentOAuth失效,需要重新初始化) + * \param delegate 第三方应用用于接收请求返回结果的委托对象 + */ +- (void)logout:(id)delegate; + +/** + * 判断登录态是否有效 + * \return 处理结果,YES表示有效,NO表示无效,请用户重新登录授权 + */ +- (BOOL)isSessionValid; + +/** + * 获取用户个人信息 + * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 + */ +- (BOOL)getUserInfo; + +/** + * 退出指定API调用 + * \param userData 用户调用某条API的时候传入的保留参数 + * \return 处理结果,YES表示成功 NO表示失败 + */ +- (BOOL)cancel:(id)userData; + +/** + * CGI类任务创建接口 + * \param apiURL CGI请求的URL地址 + * \param method CGI请求方式:"GET","POST" + * \param params CGI请求参数字典 + * \param callback CGI请求结果的回调接口对象 + * \return CGI请求任务实例,用于取消任务,返回nil代表任务创建失败 + */ +- (TCAPIRequest *)cgiRequestWithURL:(NSURL *)apiURL method:(NSString *)method params:(NSDictionary *)params callback:(id)callback; + +/** + * TencentOpenApi发送任务统一接口 + * \param request 请求发送的任务 + * \param callback 任务发送后的回调地址 + */ +- (BOOL)sendAPIRequest:(TCAPIRequest *)request callback:(id)callback; + +- (NSString *)getUserOpenID; + +@end + +#pragma mark - TencentLoginDelegate(授权登录回调协议) + +/** + * \brief TencentLoginDelegate iOS Open SDK 1.3 API回调协议 + * + * 第三方应用实现登录的回调协议 + */ +@protocol TencentLoginDelegate + +@required + +/** + * 登录成功后的回调 + */ +- (void)tencentDidLogin; + +/** + * 登录失败后的回调 + * \param cancelled 代表用户是否主动退出登录 + */ +- (void)tencentDidNotLogin:(BOOL)cancelled; + +/** + * 登录时网络有问题的回调 + */ +- (void)tencentDidNotNetWork; + +@optional +/** + * 登录时权限信息的获得 + */ +- (NSArray *)getAuthorizedPermissions:(NSArray *)permissions withExtraParams:(NSDictionary *)extraParams; + +/** + * unionID获得 + */ +- (void)didGetUnionID; + +/** + * 强制网页登录,包括账号密码登录和二维码登录 + * return YES时,就算本地有手Q也会打开web界面 + */ +- (BOOL)forceWebLogin; +@end + +#pragma mark - TencentSessionDelegate(开放接口回调协议) + +/** + * \brief TencentSessionDelegate iOS Open SDK 1.3 API回调协议 + * + * 第三方应用需要实现每条需要调用的API的回调协议 + */ +@protocol TencentSessionDelegate + +@optional + +/** + * 退出登录的回调 + */ +- (void)tencentDidLogout; + +/** + * 因用户未授予相应权限而需要执行增量授权。在用户调用某个api接口时,如果服务器返回操作未被授权,则触发该回调协议接口,由第三方决定是否跳转到增量授权页面,让用户重新授权。 + * \param tencentOAuth 登录授权对象。 + * \param permissions 需增量授权的权限列表。 + * \return 是否仍然回调返回原始的api请求结果。 + * \note 不实现该协议接口则默认为不开启增量授权流程。若需要增量授权请调用\ref TencentOAuth#incrAuthWithPermissions: \n注意:增量授权时用户可能会修改登录的帐号 + */ +- (BOOL)tencentNeedPerformIncrAuth:(TencentOAuth *)tencentOAuth withPermissions:(NSArray *)permissions; + +/** + * [该逻辑未实现]因token失效而需要执行重新登录授权。在用户调用某个api接口时,如果服务器返回token失效,则触发该回调协议接口,由第三方决定是否跳转到登录授权页面,让用户重新授权。 + * \param tencentOAuth 登录授权对象。 + * \return 是否仍然回调返回原始的api请求结果。 + * \note 不实现该协议接口则默认为不开启重新登录授权流程。若需要重新登录授权请调用\ref TencentOAuth#reauthorizeWithPermissions: \n注意:重新登录授权时用户可能会修改登录的帐号 + */ +- (BOOL)tencentNeedPerformReAuth:(TencentOAuth *)tencentOAuth; + +/** + * 用户通过增量授权流程重新授权登录,token及有效期限等信息已被更新。 + * \param tencentOAuth token及有效期限等信息更新后的授权实例对象 + * \note 第三方应用需更新已保存的token及有效期限等信息。 + */ +- (void)tencentDidUpdate:(TencentOAuth *)tencentOAuth; + +/** + * 用户增量授权过程中因取消或网络问题导致授权失败 + * \param reason 授权失败原因,具体失败原因参见sdkdef.h文件中\ref UpdateFailType + */ +- (void)tencentFailedUpdate:(UpdateFailType)reason; + +/** + * 获取用户个人信息回调 + * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse + * \remarks 正确返回示例: \snippet example/getUserInfoResponse.exp success + * 错误返回示例: \snippet example/getUserInfoResponse.exp fail + */ +- (void)getUserInfoResponse:(APIResponse*) response; + +/** + * 社交API统一回调接口 + * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse + * \param message 响应的消息,目前支持‘SendStory’,‘AppInvitation’,‘AppChallenge’,‘AppGiftRequest’ + */ +- (void)responseDidReceived:(APIResponse*)response forMessage:(NSString *)message; + +/** + * post请求的上传进度 + * \param tencentOAuth 返回回调的tencentOAuth对象 + * \param bytesWritten 本次回调上传的数据字节数 + * \param totalBytesWritten 总共已经上传的字节数 + * \param totalBytesExpectedToWrite 总共需要上传的字节数 + * \param userData 用户自定义数据 + */ +- (void)tencentOAuth:(TencentOAuth *)tencentOAuth didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite userData:(id)userData; + + +/** + * 通知第三方界面需要被关闭 + * \param tencentOAuth 返回回调的tencentOAuth对象 + * \param viewController 需要关闭的viewController + */ +- (void)tencentOAuth:(TencentOAuth *)tencentOAuth doCloseViewController:(UIViewController *)viewController; + +@end + +#pragma mark - TencentWebViewDelegate(H5登录webview旋转方向回调) + +/** + * \brief TencentWebViewDelegate: H5登录webview旋转方向回调协议 + * + * 第三方应用可以根据自己APP的旋转方向限制,通过此协议设置 + */ +@protocol TencentWebViewDelegate +@optional +- (BOOL) tencentWebViewShouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation; +- (NSUInteger) tencentWebViewSupportedInterfaceOrientationsWithWebkit; +- (BOOL) tencentWebViewShouldAutorotateWithWebkit; +@end diff --git a/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/TencentOAuthObject.h b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/TencentOAuthObject.h new file mode 100644 index 0000000..2fc3a65 --- /dev/null +++ b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/TencentOAuthObject.h @@ -0,0 +1,452 @@ +/// +/// \file TencentOAuthObject.h +/// 对开放接口的调用提供参数字典封装的辅助类 +/// +/// Created by Tencent on 12-12-28. +/// Copyright (c) 2012年 Tencent. All rights reserved. +/// + +#import +#import +#import "sdkdef.h" + + +#pragma mark - +#pragma mark TCAddTopicDic + +/** + * \brief 发表说说的参数字典定义 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCAddTopicDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCAddTopicDic *) dictionary; + +/** + * 发布心情时引用的信息的类型。 + * \note 1表示图片; 2表示网页; 3表示视频 + */ +@property (nonatomic, retain) TCOptionalStr paramRichtype; + +/** + * 发布心情时引用的信息的值。有richtype时必须有richval + * + * \note + * -# 当richtype为图片(即richtype为1,应用场景为发布心情时引用某张图片)时,\n + * richval需要传入该图片的相关参数。引用的图片来源分为两种:一种为网站图片,\n + * 一种为QQ空间相册中的某张图片。 + * - 当引用的图片来自网站,richval包含下列参数的值:\n + * | 参数名称 | 是否必须 | 类型 | 描述 | + * | ------ | ------- | ------ | ----------------- | + * | url | 必须 | string | 网站图片的URL | + * | height | 必须 | string | 图片高度,单位: px | + * | width | 必须 | string | 图片宽度,单位: px | + * \n + * 输入时每个值中间用“&”分隔,如下所示:\n + * “url=http://qq.com/logo.png&width=25&height=21” + * + * - 当引用的图片来自QQ空间相册,richval包含下列参数的值。\n + * 这些值都需要通过调用相册OpenAPI来获得。参数意义如下:\n + * | 参数名称 | 是否必须 | 类型 | 描述 | + * | --------- | ------ | ------ | ---------------------------------- | + * | albumid | 必须 | string | 图片所属空间相册的ID | + * | pictureid | 必须 | string | 图片ID | + * | sloc | 必须 | string | 小图ID | + * | pictype | | string | 图片类型(JPG = 1;GIF = 2;PNG = 3) | + * | picheight | | string | 图片高度,单位: px | + * | picwidth | | string | 图片宽度,单位: px | + * 输入时每个值中间用逗号分隔,如下所示 :\n + * “albumid,pictureid,sloc,pictype,picheight,picwidth” + * -# 当richtype为网页(即richtype为2,应用场景为针对某网页发表评论)时,\n + * richval需要传入该网页的URL,发表为feeds时,后台会自动将该URL转换为短URL。 + * -# 当richtype为视频(即richtype为3,应用场景为针对某视频发表评论)时,\n + * richval需要传入该视频的URL,发表为feeds时,后台会对该URL进行解析,\n + * 在feeds上显示播放器,视频源及缩略图。 + */ +@property (nonatomic, retain) TCOptionalStr paramRichval; + +/** + * 发布的心情的内容。 + */ +@property (nonatomic, retain) TCRequiredStr paramCon; + +/** + * 地址文。例如:广东省深圳市南山区高新科技园腾讯大厦。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 + */ +@property (nonatomic, retain) TCOptionalStr paramLbs_nm; + +/** + * 经度。-180.0到+180.0,+表示东经。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 + */ +@property (nonatomic, retain) TCOptionalStr paramLbs_x; + +/** + * 纬度。-90.0到+90.0,+表示北纬。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 + */ +@property (nonatomic, retain) TCOptionalStr paramLbs_y; + +/** + * 第三方应用的平台类型。 + * \note 1表示QQ空间; 2表示腾讯朋友; 3表示腾讯微博平台; 4表示腾讯Q+平台。 + */ +@property (nonatomic, retain) TCOptionalStr paramThirdSource; +@end + + +#pragma mark - +#pragma mark TCAddOneBlogDic +/** + * \brief 发表日志的参数字典定义 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCAddOneBlogDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCAddOneBlogDic *) dictionary; + +/** + * 日志标题(纯文本,最大长度128个字节,utf-8编码)。 + */ +@property (nonatomic, retain) TCRequiredStr paramTitle; + +/** + * content 文章内容(html数据,最大长度100*1024个字节,utf-8编码) + */ +@property (nonatomic, retain) TCRequiredStr paramContent; +@end + +#pragma mark - +#pragma mark TCAddAlbumDic +/** + * \brief 创建空间相册的参数字典定义 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCAddAlbumDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCAddAlbumDic *) dictionary; + +/** + * albumname 必须 string 相册名 不能超过30个字符。 + */ +@property (nonatomic, retain) TCRequiredStr paramAlbumname; + + +/** + * albumdesc string 相册描述,不能超过200个字符。 + */ +@property (nonatomic, retain) TCOptionalStr paramAlbumdesc; + +/** + * priv string 相册权限 + * + * \note 其取值含义为: 1=公开;3=只主人可见; 4=QQ好友可见; 5=问答加密。\n + * 不传则相册默认为公开权限。\n + * 如果priv取值为5,即相册是问答加密的,则必须包含问题和答案两个参数:\n + * - question: 问题,不能超过30个字符。 + * - answer: 答案,不能超过30个字符。 + */ +@property (nonatomic, retain) TCOptionalStr paramPriv; + +/** + * question 问题,不能超过30个字符。 + * \note 如果priv取值为5,必须包含这个参数: + **/ +@property (nonatomic, retain) TCOptionalStr paramQuestion; + +/** + * answer 答案,不能超过30个字符。 + * \note 如果priv取值为5,必须包含这个参数: + **/ +@property (nonatomic, retain) TCOptionalStr paramAnswer; + +@end + +#pragma mark - +#pragma mark TCUploadPicDic +/** + * \brief 上传一张照片到QQ空间相册的参数字典定义 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCUploadPicDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCUploadPicDic *) dictionary; + +/** + * photodesc string 照片描述,注意照片描述不能超过200个字符。 + */ +@property (nonatomic, retain) TCOptionalStr paramPhotodesc; +/** + * string 照片的命名,必须以.jpg, .gif, .png, .jpeg, .bmp此类后缀结尾。 + */ +@property (nonatomic, retain) TCOptionalStr paramTitle; + +/** + * string 相册id。可不填,不填时则根据“mobile”标识选择默认上传的相册。 + */ +@property (nonatomic, retain) TCOptionalStr paramAlbumid; + +/** + * 标志位 + * + * \note 0表示PC,1表示手机。用于当不传相册id时(即albumid为空时)控制是否传到手机相册。\n + * -# 如果传1,则当albumid为空时,图片会上传到手机相册; + * -# 如果不传或传0,则当albumid为空时,图片会上传到贴图相册; + */ +@property (nonatomic, assign) TCOptionalStr paramMobile; + +/** + * x string 照片拍摄时的地理位置的经度。请使用原始数据(纯经纬度,0-360)。 + */ +@property (nonatomic, retain) TCOptionalStr paramX; + +/** + * y string 照片拍摄时的地理位置的纬度。请使用原始数据(纯经纬度,0-360)。 + */ +@property (nonatomic, retain) TCOptionalStr paramY; + +/** + * picture 必须 string 上传照片的文件名以及图片的内容(在发送请求时,图片内容以二进制数据流的形式发送,见下面的请求示例),注意照片名称不能超过30个字符。 + */ +@property (nonatomic, retain) TCRequiredImage paramPicture; + +/** + * needfeed int 标识上传照片时是否要发feed + * \note(0:不发feed; 1:发feed)。如果不填则默认为发feed。 + */ +@property (nonatomic, assign)TCOptionalStr paramNeedfeed; + +/** + * successnum int 批量上传照片时,已成功上传的张数,指明上传完成情况。 + * \note 单张上传时可以不填,不填则默认为0。 + */ +@property (nonatomic, assign)TCOptionalStr paramSuccessnum; + +/** + * picnum int 批量上传照片的总张数,如果不填则默认为1。 + * \note + * - 如果picnum=1,为单张上传,发送单张上传feed; + * - 如果picnum>1,为批量上传,发送批量上传feed。 + * 批量上传方式:picnum为一次上传照片的张数,successnum初始值为0,每调用一次照片上传接口后递增其值。 + * 信息中心中的feed表现形式:批量上传时最新的7张在feed中展示。其中最新上传的一张图片展示为大图,剩下的 + * 六张按从新到旧的顺序展示为小图,其他图片不在feed中展示。 + */ +@property (nonatomic, assign)TCOptionalStr paramPicnum; + +@end + +#pragma mark - +#pragma mark TCAddShareDic +/** + * \brief 同步分享到QQ空间,腾讯微博的参数字典定义 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCAddShareDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCAddShareDic *) dictionary; + +/** + * title 必须 string feeds的标题 最长36个中文字,超出部分会被截断。 + */ +@property (nonatomic, retain) TCRequiredStr paramTitle; + + +/** + * url 必须 string 分享所在网页资源的链接,点击后跳转至第三方网页,对应上文接口说明中2的超链接。请以http://开头。 + */ +@property (nonatomic, retain) TCRequiredStr paramUrl; + + +/** + * comment string 用户评论内容,也叫发表分享时的分享理由 禁止使用系统生产的语句进行代替。 + * 最长40个中文字,超出部分会被截断。 + */ +@property (nonatomic, retain) TCOptionalStr paramComment; + + +/** + * summary string 所分享的网页资源的摘要内容,或者是网页的概要描述 最长80个中文字,超出部分会被截断。 + */ +@property (nonatomic, retain) TCOptionalStr paramSummary; + +/** + * images string 所分享的网页资源的代表性图片链接",请以http://开头,长度限制255字符。多张图片以竖线(|)分隔,目前只有第一张图片有效,图片规格100*100为佳。 + */ +@property (nonatomic, retain) TCOptionalStr paramImages; + +/** + * type string 分享内容的类型。 + * + * \note 4表示网页;5表示视频(type=5时,必须传入playurl) + */ +@property (nonatomic, retain) TCOptionalStr paramType; + +/** + * playurl string 长度限制为256字节。仅在type=5的时候有效,表示视频的swf播放地址。 + */ +@property (nonatomic, retain) TCOptionalStr paramPlayurl; + +/** + * site 必须 string 分享的来源网站名称,请填写网站申请接入时注册的网站名称 + */ +@property (nonatomic, retain) TCRequiredStr paramSite; + +/** + * fromurl 必须 string 分享的来源网站对应的网站地址url 请以http://开头。 + */ +@property (nonatomic, retain) TCRequiredStr paramFromurl; + +/** + * nswb string 值为1时,表示分享不默认同步到微博,其他值或者不传此参数表示默认同步到微博。 + */ +@property (nonatomic, retain) TCOptionalStr paramNswb; + +@end + +#pragma mark - +#pragma mark TCCheckPageFansDic +/** + * \brief 验证是否认证空间粉丝tttyttyyyu的参数字典定义 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCCheckPageFansDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCCheckPageFansDic *) dictionary; + +/** + * 表示认证空间的QQ号码 + */ +@property (nonatomic, retain) TCRequiredStr paramPage_id; +@end + +#pragma mark - +#pragma mark TCSetUserHeadpic +/** + * \brief 设置用户头像 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCSetUserHeadpic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCSetUserHeadpic *) dictionary; + +/** + * 设置用户头像的图片 + */ +@property (nonatomic, retain) TCRequiredImage paramImage; + +/** + * 图片的文件名 + */ +@property (nonatomic, retain) TCOptionalStr paramFileName; +@end + +#pragma mark - +#pragma mark TCListPhotoDic + +/** + * \brief 获取用户QQ空间相册中的照片列表 + * + * 可以直接填写相应参数后将对象当作参数传入API中 + */ +@interface TCListPhotoDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCListPhotoDic *) dictionary; + +/** + * 表示要获取的照片列表所在的相册ID + */ +@property (nonatomic, retain) TCRequiredStr paramAlbumid; + +@end + +#pragma mark - +#pragma mark TCSendStoryDic +/** + * \brief QQ空间定向分享的参数字典定义 + * + * 该分享支持@到指定好友,最多支持10个好友。 + * 其中第三方应用可预传最多5个指定好友的openid,其余好友由用户自行选择。 + * 该分享形式仅提供跳QZone分享和本地Html5分享两种形式。 + * sendStroy不支持userData参数 + */ +@interface TCSendStoryDic : TCAPIRequest + +/** + * 返回一个对象用来进行API参数的填充 + * + * \note 不用释放,返回的对象是自动释放的 + */ ++ (TCSendStoryDic *) dictionary; + +/** + * 分享的标题 + */ +@property (nonatomic, retain) TCRequiredStr paramTitle; + +/** + * 故事摘要,最多不超过50个汉字,可以为空 + */ +@property (nonatomic, retain) TCOptionalStr paramSummary; + +/** + * 默认展示在输入框里的分享理由,最多120个汉字,可以为空 + */ +@property (nonatomic, retain) TCOptionalStr paramDescription; + +/** + * 图片url + */ +@property (nonatomic, retain) TCOptionalStr paramPics; + +/** + * 如果不填,则默认为"进入应用" + */ +@property (nonatomic, retain) TCRequiredStr paramAct; + +/** + * 点击分享的Url + */ +@property (nonatomic, retain) TCOptionalStr paramShareUrl; + +@end diff --git a/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/sdkdef.h b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/sdkdef.h new file mode 100644 index 0000000..fc112a7 --- /dev/null +++ b/ios/RCTQQAPI/TencentOpenAPI.framework/Headers/sdkdef.h @@ -0,0 +1,414 @@ +/// +/// \file sdkdef.h +/// \brief SDK中相关常量定义 +/// +/// Created by Tencent on 12-12-25. +/// Copyright (c) 2012年 Tencent. All rights reserved. +/// + +#import +#import + +/** + * \brief 设置sdk的log等级 + */ +typedef enum { + TCOLogLevel_Disabled = -1, // 关闭所有log + TCOLogLevel_Error = 0, + TCOLogLevel_Warning, + TCOLogLevel_Info, + TCOLogLevel_Debug, +} TCOLogLevel; + +/** + * \breif 授权/分享 方式 + */ +typedef enum TencentAuthShareType { + AuthShareType_QQ, + AuthShareType_TIM, +}TencentAuthShareType; + +/** + * \brief APIResponse.retCode可能的枚举常量 + */ +typedef enum +{ + URLREQUEST_SUCCEED = 0, /**< 网络请求成功发送至服务器,并且服务器返回数据格式正确 + * \note 这里包括所请求业务操作失败的情况,例如没有授权等原因导致 + */ + + URLREQUEST_FAILED = 1, /**< 网络异常,或服务器返回的数据格式不正确导致无法解析 */ +} REPONSE_RESULT; + +/** + * \brief 增量授权失败原因 + * + * \note 增量授权失败不影响原token的有效性(原token已失效的情况除外) + */ +typedef enum +{ + kUpdateFailUnknown = 1, ///< 未知原因 + kUpdateFailUserCancel, ///< 用户取消 + kUpdateFailNetwork, ///< 网络问题 +} UpdateFailType; + +/** + * \brief 封装服务器返回的结果 + * + * APIResponse用于封装所有请求的返回结果,包括错误码、错误信息、原始返回数据以及返回数据的json格式字典 + */ +@interface APIResponse : NSObject { + int _detailRetCode; + int _retCode; + int _seq; + NSString *_errorMsg; + NSDictionary *_jsonResponse; + NSString *_message; + id _userData; +} + +/** + * 新增的详细错误码\n + * detailRetCode主要用于区分不同的错误情况,参见\ref OpenSDKError + */ +@property (nonatomic, assign) int detailRetCode; + +/** + * 网络请求是否成功送达服务器,以及服务器返回的数据格式是否正确\n + * retCode具体取值可参考\ref REPONSE_RESULT + */ +@property (nonatomic, assign) int retCode; + +/** + * 网络请求对应的递增序列号,方便内部管理 + */ +@property (nonatomic, assign) int seq; + +/** + * 错误提示语 + */ +@property (nonatomic, retain) NSString *errorMsg; + +/** + * 服务器返回数据的json格式字典\n + * 字典内具体参数的命名和含义请参考\ref api_spec + */ +@property (nonatomic, retain) NSDictionary *jsonResponse; + +/** + * 服务器返回的原始数据字符串 + */ +@property (nonatomic, retain) NSString *message; + +/** + * 用户保留数据 + */ +@property (nonatomic, retain) id userData; + +@end + + +/** + * 用户自定义的保留字段 + */ +FOUNDATION_EXTERN NSString * const PARAM_USER_DATA; + +/** + * \name 应用邀请参数字段定义 + */ +///@{ + +/** 应用邀请展示图片url的key */ +FOUNDATION_EXTERN NSString * const PARAM_APP_ICON; + +/** 应用邀请描述文本的key */ +FOUNDATION_EXTERN NSString * const PARAM_APP_DESC; + +/** 应用邀请好友列表的key */ +FOUNDATION_EXTERN NSString * const PARAM_APP_INVITED_OPENIDS; + +///@} + +/** + * \name sendStory新分享参数字段定义 + */ +///@{ + +/** 预填入接受人列表的key */ +FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_RECEIVER; + +/** 分享feeds标题的key */ +FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_TITLE; + +/** 分享feeds评论内容的key */ +FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_COMMENT; + +/** 分享feeds摘要的key */ +FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_SUMMARY; + +/** 分享feeds展示图片url的key */ +FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_IMAGE; + +/** 分享feeds跳转链接url的key */ +FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_URL; + +/** 分享feeds点击操作默认行为的key */ +FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_ACT; + +///@} + +/** + * \name 设置头像参数字段定义 + */ +///@{ + +/** 头像图片数据的key */ +FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_PIC; + +/** 头像图片文件名的key */ +FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_FILENAME; + +///@} + +/** + * \name 服务器返回数据的参数字段定义 + */ +///@{ + +/** 服务器返回码的key */ +FOUNDATION_EXTERN NSString * const PARAM_RETCODE; + +/** 服务器返回错误信息的key */ +FOUNDATION_EXTERN NSString * const PARAM_MESSAGE; + +/** 服务器返回额外数据的key */ +FOUNDATION_EXTERN NSString * const PARAM_DATA; + +///@} + +/** + * \name 错误信息相关常量定义 + */ +///@{ + +/** 详细错误信息字典中额外信息的key */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyExtraInfo; + +/** 详细错误信息字典中返回码的key */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyRetCode; + +/** 详细错误信息字典中错误语句的key */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyMsg; + +/** 不支持的接口 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnsupportedAPI; + +/** 操作成功 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSuccess; + +/** 未知错误 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnknown; + +/** 用户取消 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserCancel; + +/** 请重新登录 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgReLogin; + +/** 应用没有操作权限 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgOperationDeny; + +/** 网络异常或没有网络 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgNetwork; + +/** URL格式或协议错误 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgURL; + +/** 解析数据出错 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgDataParse; + +/** 传入参数有误 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgParam; + +/** 连接超时 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgTimeout; + +/** 安全问题 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSecurity; + +/** 文件读写错误 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgIO; + +/** 服务器端错误 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgServer; + +/** 页面错误 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgWebPage; + +/** 设置头像图片过大 */ +FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserHeadPicLarge; + +///@} + +/** + * \brief SDK新增详细错误常量 + */ +typedef enum +{ + kOpenSDKInvalid = -1, ///< 无效的错误码 + kOpenSDKErrorUnsupportedAPI = -2, ///< 不支持的接口 + + /** + * \name CommonErrorCode + * 公共错误码 + */ + ///@{ + kOpenSDKErrorSuccess = 0, ///< 成功 + kOpenSDKErrorUnknown, ///< 未知错误 + kOpenSDKErrorUserCancel, ///< 用户取消 + kOpenSDKErrorReLogin, ///< token无效或用户未授权相应权限需要重新登录 + kOpenSDKErrorOperationDeny, ///< 第三方应用没有该api操作的权限 + ///@} + + /** + * \name NetworkRelatedErrorCode + * 网络相关错误码 + */ + ///@{ + kOpenSDKErrorNetwork, ///< 网络错误,网络不通或连接不到服务器 + kOpenSDKErrorURL, ///< URL格式或协议错误 + kOpenSDKErrorDataParse, ///< 数据解析错误,服务器返回的数据解析出错 + kOpenSDKErrorParam, ///< 传入参数错误 + kOpenSDKErrorConnTimeout, ///< http连接超时 + kOpenSDKErrorSecurity, ///< 安全问题 + kOpenSDKErrorIO, ///< 下载和文件IO错误 + kOpenSDKErrorServer, ///< 服务器端错误 + ///@} + + /** + * \name WebViewRelatedError + * webview特有错误 + */ + ///@{ + kOpenSDKErrorWebPage, ///< 页面错误 + ///@} + + /** + * \name SetUserHeadRelatedErrorCode + * 设置头像自定义错误码段 + */ + ///@{ + kOpenSDKErrorUserHeadPicLarge = 0x010000, ///< 图片过大 设置头像自定义错误码 + ///@} +} OpenSDKError; + +/** + * \name SDK版本(v1.3)支持的授权列表常量 + */ +///@{ + +/** 发表一条说说到QQ空间(需要申请权限) */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_TOPIC; + +/** 创建一个QQ空间相册(需要申请权限) */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_ALBUM; + +/** 上传一张照片到QQ空间相册(需要申请权限) */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_UPLOAD_PIC; + +/** 获取用户QQ空间相册列表(需要申请权限) */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_LIST_ALBUM; + +/** 验证是否认证空间粉丝 */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_CHECK_PAGE_FANS; + +/** 获取登录用户自己的详细信息 */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_INFO; + +/** 获取其他用户的详细信息 */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_OTHER_INFO; + +/** 获取会员用户基本信息 */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_INFO; + +/** 获取会员用户详细信息 */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_RICH_INFO; + +/** 获取用户信息 */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_USER_INFO; + +/** 移动端获取用户信息 */ +FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_SIMPLE_USER_INFO; +///@} + + +/** + * \name CGI接口相关参数类型定义 + */ + +/** 必填的字符串类型参数 */ +typedef NSString *TCRequiredStr; + +/** 必填的UIImage类型参数 */ +typedef UIImage *TCRequiredImage; + +/** 必填的整型参数 */ +typedef NSInteger TCRequiredInt; + +/** 必填的数字类型 */ +typedef NSNumber *TCRequiredNumber; + +/** 必填的NSData参数 */ +typedef NSData *TCRequiredData; + +/** 可选的字符串类型参数 */ +typedef NSString *TCOptionalStr; + +/** 可选的UIImage类型参数 */ +typedef UIImage *TCOptionalImage; + +/** 可选的整型参数 */ +typedef NSInteger TCOptionalInt; + +/** 可选的数字类型 */ +typedef NSNumber *TCOptionalNumber; + +/** 可选的不定类型参数 */ +typedef id TCRequiredId; +///@} + + +/** + * \brief CGI请求的参数字典封装辅助基类 + * + * 将相应属性的值以key-value的形式保存到参数字典中 + */ +@interface TCAPIRequest : NSMutableDictionary + +/** CGI请求的URL地址 */ +@property (nonatomic, readonly) NSURL *apiURL; + +/** CGI请求方式:"GET","POST" */ +@property (nonatomic, readonly) NSString *method; + +/** + * API参数中的保留字段,可以塞入任意字典支持的类型,再调用完成后会带回给调用方 + */ +@property (nonatomic, retain) TCRequiredId paramUserData; + +/** + * APIResponse,API的返回结果 + */ +@property (nonatomic, readonly) APIResponse *response; + +/** 取消相应的CGI请求任务 */ +- (void)cancel; + +@end + +@protocol TCAPIRequestDelegate +@optional +- (void)cgiRequest:(TCAPIRequest *)request didResponse:(APIResponse *)response; + +@end + diff --git a/ios/RCTQQAPI/TencentOpenAPI.framework/Resources/ios_open_sdk_3.1.0.1_iphone b/ios/RCTQQAPI/TencentOpenAPI.framework/Resources/ios_open_sdk_3.1.0.1_iphone new file mode 100644 index 0000000..e69de29 diff --git a/ios/RCTQQAPI/TencentOpenAPI.framework/TencentOpenAPI b/ios/RCTQQAPI/TencentOpenAPI.framework/TencentOpenAPI new file mode 100644 index 0000000..d25edee Binary files /dev/null and b/ios/RCTQQAPI/TencentOpenAPI.framework/TencentOpenAPI differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..b2f58eb --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "react-native-qq", + "version": "2.0.5", + "description": "QQ Login&Share support in React Native.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/reactnativecn/react-native-qq.git" + }, + "keywords": [ + "react-native", + "ios", + "android" + ], + "author": "tdzl2003", + "license": "ISC", + "bugs": { + "url": "https://github.com/reactnativecn/react-native-qq/issues" + }, + "homepage": "https://github.com/reactnativecn/react-native-qq#readme" +}