接入微信分享 SDK 并配置 Universal Link。
集成 WechatOpenSDK、www.zhifly.cn/suixinkan/ 通用链接与邀请页分享能力,附带 AASA 部署文件与单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
28
Podfile
28
Podfile
@ -8,20 +8,26 @@ target 'suixinkan' do
|
||||
pod 'AMapSearch-NO-IDFA', '~> 9.7'
|
||||
pod 'AMapLocation-NO-IDFA', '~> 2.11'
|
||||
|
||||
# 微信 Open SDK:分享能力(不调用支付 API)
|
||||
pod 'WechatOpenSDK-XCFramework', '~> 2.0.4'
|
||||
|
||||
target 'suixinkanTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
# 模拟器可用的链接参数(不含高德 prebuilt framework)
|
||||
# 模拟器可用的链接参数(不含高德 prebuilt framework,但保留微信 SDK)
|
||||
SIMULATOR_OTHER_LDFLAGS = <<~FLAGS.squish
|
||||
-ObjC -l"c++" -l"z"
|
||||
-ObjC -l"c++" -l"sqlite3.0" -l"z"
|
||||
-framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony"
|
||||
-framework "CoreText" -framework "ExternalAccessory" -framework "GLKit"
|
||||
-framework "OpenGLES" -framework "QuartzCore" -framework "Security"
|
||||
-framework "SystemConfiguration"
|
||||
-framework "SystemConfiguration" -framework "UIKit" -framework "WebKit"
|
||||
-framework "WechatOpenSDK"
|
||||
FLAGS
|
||||
|
||||
SIMULATOR_FRAMEWORK_SEARCH_PATHS = '"${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"'
|
||||
|
||||
post_install do |installer|
|
||||
# 1. 修正 aggregate xcconfig:去掉 arm64 排除,模拟器单独链接(不链 AMap)
|
||||
%w[Pods-suixinkan Pods-suixinkanTests].each do |target_name|
|
||||
@ -30,9 +36,23 @@ post_install do |installer|
|
||||
content = File.read(path)
|
||||
content.gsub!("EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64\n", '')
|
||||
|
||||
# 模拟器链接微信 SDK,同时剥离高德 framework
|
||||
content.gsub!(
|
||||
/OTHER_LDFLAGS\[sdk=iphonesimulator\*\] = .*\n/,
|
||||
"OTHER_LDFLAGS[sdk=iphonesimulator*] = #{SIMULATOR_OTHER_LDFLAGS}\n"
|
||||
)
|
||||
if content.include?('FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]')
|
||||
content.gsub!(
|
||||
/FRAMEWORK_SEARCH_PATHS\[sdk=iphonesimulator\*\] = .*\n/,
|
||||
"FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) #{SIMULATOR_FRAMEWORK_SEARCH_PATHS}\n"
|
||||
)
|
||||
else
|
||||
content << "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) #{SIMULATOR_FRAMEWORK_SEARCH_PATHS}\n"
|
||||
end
|
||||
|
||||
unless content.include?('OTHER_LDFLAGS[sdk=iphonesimulator*]')
|
||||
content << "\nOTHER_LDFLAGS[sdk=iphonesimulator*] = #{SIMULATOR_OTHER_LDFLAGS}\n"
|
||||
content << "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited)\n"
|
||||
content << "FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) #{SIMULATOR_FRAMEWORK_SEARCH_PATHS}\n"
|
||||
end
|
||||
|
||||
File.write(path, content)
|
||||
|
||||
@ -6,11 +6,13 @@ PODS:
|
||||
- AMapFoundation-NO-IDFA (>= 1.8.7)
|
||||
- AMapSearch-NO-IDFA (9.7.5):
|
||||
- AMapFoundation-NO-IDFA (>= 1.8.0)
|
||||
- WechatOpenSDK-XCFramework (2.0.5)
|
||||
|
||||
DEPENDENCIES:
|
||||
- AMap3DMap-NO-IDFA (~> 11.1)
|
||||
- AMapLocation-NO-IDFA (~> 2.11)
|
||||
- AMapSearch-NO-IDFA (~> 9.7)
|
||||
- WechatOpenSDK-XCFramework (~> 2.0.4)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
@ -18,13 +20,15 @@ SPEC REPOS:
|
||||
- AMapFoundation-NO-IDFA
|
||||
- AMapLocation-NO-IDFA
|
||||
- AMapSearch-NO-IDFA
|
||||
- WechatOpenSDK-XCFramework
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AMap3DMap-NO-IDFA: 393a24abb0451fed2daa4316c8d3d356a395f2be
|
||||
AMapFoundation-NO-IDFA: f48acbf6e74913dc6744581053f7d984f2432850
|
||||
AMapLocation-NO-IDFA: 0fa6e7d5e42e10253f4437424d98966f53760862
|
||||
AMapSearch-NO-IDFA: 8e9d104032990a3b0cab66afb535299887c61047
|
||||
WechatOpenSDK-XCFramework: ff342ae616bb86df3d236aca38059dfd4bc4a949
|
||||
|
||||
PODFILE CHECKSUM: baa972253fcebc312545f7592c48cbba632f1907
|
||||
PODFILE CHECKSUM: e8cba7a3776cf5c925cda135f2774d8f243899c4
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
6
Pods/Manifest.lock
generated
6
Pods/Manifest.lock
generated
@ -6,11 +6,13 @@ PODS:
|
||||
- AMapFoundation-NO-IDFA (>= 1.8.7)
|
||||
- AMapSearch-NO-IDFA (9.7.5):
|
||||
- AMapFoundation-NO-IDFA (>= 1.8.0)
|
||||
- WechatOpenSDK-XCFramework (2.0.5)
|
||||
|
||||
DEPENDENCIES:
|
||||
- AMap3DMap-NO-IDFA (~> 11.1)
|
||||
- AMapLocation-NO-IDFA (~> 2.11)
|
||||
- AMapSearch-NO-IDFA (~> 9.7)
|
||||
- WechatOpenSDK-XCFramework (~> 2.0.4)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
@ -18,13 +20,15 @@ SPEC REPOS:
|
||||
- AMapFoundation-NO-IDFA
|
||||
- AMapLocation-NO-IDFA
|
||||
- AMapSearch-NO-IDFA
|
||||
- WechatOpenSDK-XCFramework
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AMap3DMap-NO-IDFA: 393a24abb0451fed2daa4316c8d3d356a395f2be
|
||||
AMapFoundation-NO-IDFA: f48acbf6e74913dc6744581053f7d984f2432850
|
||||
AMapLocation-NO-IDFA: 0fa6e7d5e42e10253f4437424d98966f53760862
|
||||
AMapSearch-NO-IDFA: 8e9d104032990a3b0cab66afb535299887c61047
|
||||
WechatOpenSDK-XCFramework: ff342ae616bb86df3d236aca38059dfd4bc4a949
|
||||
|
||||
PODFILE CHECKSUM: baa972253fcebc312545f7592c48cbba632f1907
|
||||
PODFILE CHECKSUM: e8cba7a3776cf5c925cda135f2774d8f243899c4
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
1083
Pods/Pods.xcodeproj/project.pbxproj
generated
1083
Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
@ -20,4 +20,9 @@ Copyright © 2014 AutoNavi. All Rights Reserved.
|
||||
|
||||
Copyright © 2014 AutoNavi. All Rights Reserved.
|
||||
|
||||
|
||||
## WechatOpenSDK-XCFramework
|
||||
|
||||
Copyright 2020 tencent.com. All rights reserved.
|
||||
|
||||
Generated by CocoaPods - https://cocoapods.org
|
||||
|
||||
@ -56,6 +56,17 @@
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright 2020 tencent.com. All rights reserved.
|
||||
</string>
|
||||
<key>License</key>
|
||||
<string>Copyright</string>
|
||||
<key>Title</key>
|
||||
<string>WechatOpenSDK-XCFramework</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Generated by CocoaPods - https://cocoapods.org</string>
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
ARCHS = $(ARCHS_STANDARD)
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "AMapFoundationKit" -framework "AMapLocationKit" -framework "AMapSearchKit" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "MAMapKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch-NO-IDFA"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3.0" -l"z" -framework "AMapFoundationKit" -framework "AMapLocationKit" -framework "AMapSearchKit" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "MAMapKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit" -framework "WechatOpenSDK"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
VALID_ARCHS = arm64 x86_64
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited)
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit" -framework "WechatOpenSDK"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
ARCHS = $(ARCHS_STANDARD)
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "AMapFoundationKit" -framework "AMapLocationKit" -framework "AMapSearchKit" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "MAMapKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch-NO-IDFA"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3.0" -l"z" -framework "AMapFoundationKit" -framework "AMapLocationKit" -framework "AMapSearchKit" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "MAMapKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit" -framework "WechatOpenSDK"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AMap3DMap-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapFoundation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapLocation-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/AMapSearch-NO-IDFA" "-F${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
VALID_ARCHS = arm64 x86_64
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited)
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit" -framework "WechatOpenSDK"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
ARCHS = $(ARCHS_STANDARD)
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
VALID_ARCHS = arm64 x86_64
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited)
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit" -framework "WechatOpenSDK"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
ARCHS = $(ARCHS_STANDARD)
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AMap3DMap-NO-IDFA" "${PODS_ROOT}/AMapFoundation-NO-IDFA" "${PODS_ROOT}/AMapLocation-NO-IDFA" "${PODS_ROOT}/AMapSearch-NO-IDFA" "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
VALID_ARCHS = arm64 x86_64
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited)
|
||||
OTHER_LDFLAGS[sdk=iphonesimulator*] = -ObjC -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit" -framework "WechatOpenSDK"
|
||||
FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
${PODS_ROOT}/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework-xcframeworks.sh
|
||||
${PODS_ROOT}/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework
|
||||
@ -0,0 +1 @@
|
||||
${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework/WechatOpenSDK.framework
|
||||
121
Pods/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework-xcframeworks.sh
generated
Executable file
121
Pods/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework-xcframeworks.sh
generated
Executable file
@ -0,0 +1,121 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
function on_error {
|
||||
echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
|
||||
}
|
||||
trap 'on_error $LINENO' ERR
|
||||
|
||||
|
||||
# This protects against multiple targets copying the same framework dependency at the same time. The solution
|
||||
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
|
||||
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
|
||||
|
||||
|
||||
variant_for_slice()
|
||||
{
|
||||
case "$1" in
|
||||
"WechatOpenSDK.xcframework/ios-arm64")
|
||||
echo ""
|
||||
;;
|
||||
"WechatOpenSDK.xcframework/ios-arm64_x86_64-simulator")
|
||||
echo "simulator"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
archs_for_slice()
|
||||
{
|
||||
case "$1" in
|
||||
"WechatOpenSDK.xcframework/ios-arm64")
|
||||
echo "arm64"
|
||||
;;
|
||||
"WechatOpenSDK.xcframework/ios-arm64_x86_64-simulator")
|
||||
echo "arm64 x86_64"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
copy_dir()
|
||||
{
|
||||
local source="$1"
|
||||
local destination="$2"
|
||||
|
||||
# Use filter instead of exclude so missing patterns don't throw errors.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" \"${source}*\" \"${destination}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}"/* "${destination}"
|
||||
}
|
||||
|
||||
SELECT_SLICE_RETVAL=""
|
||||
|
||||
select_slice() {
|
||||
local xcframework_name="$1"
|
||||
xcframework_name="${xcframework_name##*/}"
|
||||
local paths=("${@:2}")
|
||||
# Locate the correct slice of the .xcframework for the current architectures
|
||||
local target_path=""
|
||||
|
||||
# Split archs on space so we can find a slice that has all the needed archs
|
||||
local target_archs=$(echo $ARCHS | tr " " "\n")
|
||||
|
||||
local target_variant=""
|
||||
if [[ "$PLATFORM_NAME" == *"simulator" ]]; then
|
||||
target_variant="simulator"
|
||||
fi
|
||||
if [[ ! -z ${EFFECTIVE_PLATFORM_NAME+x} && "$EFFECTIVE_PLATFORM_NAME" == *"maccatalyst" ]]; then
|
||||
target_variant="maccatalyst"
|
||||
fi
|
||||
for i in ${!paths[@]}; do
|
||||
local matched_all_archs="1"
|
||||
local slice_archs="$(archs_for_slice "${xcframework_name}/${paths[$i]}")"
|
||||
local slice_variant="$(variant_for_slice "${xcframework_name}/${paths[$i]}")"
|
||||
for target_arch in $target_archs; do
|
||||
if ! [[ "${slice_variant}" == "$target_variant" ]]; then
|
||||
matched_all_archs="0"
|
||||
break
|
||||
fi
|
||||
|
||||
if ! echo "${slice_archs}" | tr " " "\n" | grep -F -q -x "$target_arch"; then
|
||||
matched_all_archs="0"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$matched_all_archs" == "1" ]]; then
|
||||
# Found a matching slice
|
||||
echo "Selected xcframework slice ${paths[$i]}"
|
||||
SELECT_SLICE_RETVAL=${paths[$i]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
install_xcframework() {
|
||||
local basepath="$1"
|
||||
local name="$2"
|
||||
local package_type="$3"
|
||||
local paths=("${@:4}")
|
||||
|
||||
# Locate the correct slice of the .xcframework for the current architectures
|
||||
select_slice "${basepath}" "${paths[@]}"
|
||||
local target_path="$SELECT_SLICE_RETVAL"
|
||||
if [[ -z "$target_path" ]]; then
|
||||
echo "warning: [CP] $(basename ${basepath}): Unable to find matching slice in '${paths[@]}' for the current build architectures ($ARCHS) and platform (${EFFECTIVE_PLATFORM_NAME-${PLATFORM_NAME}})."
|
||||
return
|
||||
fi
|
||||
local source="$basepath/$target_path"
|
||||
|
||||
local destination="${PODS_XCFRAMEWORKS_BUILD_DIR}/${name}"
|
||||
|
||||
if [ ! -d "$destination" ]; then
|
||||
mkdir -p "$destination"
|
||||
fi
|
||||
|
||||
copy_dir "$source/" "$destination"
|
||||
echo "Copied $source to $destination"
|
||||
}
|
||||
|
||||
install_xcframework "${PODS_ROOT}/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework" "WechatOpenSDK-XCFramework" "framework" "ios-arm64" "ios-arm64_x86_64-simulator"
|
||||
|
||||
15
Pods/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework.debug.xcconfig
generated
Normal file
15
Pods/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework.debug.xcconfig
generated
Normal file
@ -0,0 +1,15 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "Security" -framework "UIKit" -framework "WebKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/WechatOpenSDK-XCFramework
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
VALID_ARCHS = arm64 x86_64
|
||||
15
Pods/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework.release.xcconfig
generated
Normal file
15
Pods/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework.release.xcconfig
generated
Normal file
@ -0,0 +1,15 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/WechatOpenSDK-XCFramework
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3.0" -l"z" -framework "CoreGraphics" -framework "Security" -framework "UIKit" -framework "WebKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/WechatOpenSDK-XCFramework
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
VALID_ARCHS = arm64 x86_64
|
||||
44
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/Info.plist
generated
Normal file
44
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/Info.plist
generated
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AvailableLibraries</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>WechatOpenSDK.framework/WechatOpenSDK</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64_x86_64-simulator</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>WechatOpenSDK.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>x86_64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
<key>SupportedPlatformVariant</key>
|
||||
<string>simulator</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>WechatOpenSDK.framework/WechatOpenSDK</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>WechatOpenSDK.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XFWK</string>
|
||||
<key>XCFrameworkFormatVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
17
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/PrivacyInfo.xcprivacy
generated
Normal file
17
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/PrivacyInfo.xcprivacy
generated
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
167
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/README.txt
generated
Normal file
167
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/README.txt
generated
Normal file
@ -0,0 +1,167 @@
|
||||
重要!
|
||||
SDK2.0.5
|
||||
1. 支持模块化集成:XCFramework 头文件引用改为标准化格式 #import <WechatOpenSDK/WXApi.h>,解决路径冲突并支持 Swift/ObjC 混合开发
|
||||
2. 修复openWXApp偶现失败的问题
|
||||
|
||||
SDK2.0.4
|
||||
1.增加privacy manifest文件
|
||||
2.修复跳微信时可能卡顿的问题
|
||||
|
||||
SDK2.0.2
|
||||
1. 优化XCFramework打包方式
|
||||
|
||||
SDK2.0.1
|
||||
1. SDK支持XCFramework
|
||||
|
||||
SDK2.0.0
|
||||
1. 分享能力支持内容防篡改校验
|
||||
|
||||
SDK1.9.9
|
||||
1. 授权登录支持关闭自动授权
|
||||
2. 分享支持添加签名,防止篡改
|
||||
|
||||
SDK1.9.7
|
||||
1. 适配CocoaPods
|
||||
|
||||
SDK1.9.6
|
||||
1. 适配iOS 16,减少读写剪切板
|
||||
|
||||
SDK1.9.4
|
||||
1. 修复授权登录取消/拒绝时state字段没有带回
|
||||
|
||||
SDK1.9.3
|
||||
1. 新增发起二维码支付能力
|
||||
|
||||
SDK1.9.2
|
||||
1. 新增发起企微客服会话能力
|
||||
|
||||
SDK1.9.1
|
||||
1. 音乐视频分享类型增加运营H5字段
|
||||
|
||||
SDK1.8.9
|
||||
1. 增加音乐视频分享类型
|
||||
|
||||
SDK1.8.8
|
||||
1. 增加游戏直播消息类型
|
||||
|
||||
SDK1.8.7.1
|
||||
1. 修复Xcode11以下编译不通过
|
||||
|
||||
SDK1.8.7
|
||||
1. 修复iPadOS,未安装微信的情况下,因为UA问题无法授权登录
|
||||
2. 修复未安装微信的情况下, 适配了UIScene的App因为UIAlertView Crash
|
||||
3. 增加Universal Link检测函数
|
||||
|
||||
SDK1.8.6.2
|
||||
1. 修改包含"UIWebView"字符的类名
|
||||
|
||||
SDK1.8.6.1
|
||||
1.短信授权登录使用的UIWebview切换成WKWebview
|
||||
|
||||
SDK1.8.6
|
||||
1. 支持Universal Link拉起微信以及返回App
|
||||
2. SDK移除MTA库
|
||||
|
||||
SDK1.8.5
|
||||
1. 更换MTA库:取消对剪切板的访问, 防止和其他SDK竞争导致crash
|
||||
2. NSMutableArray的MTA分类方法改名,减少命名冲突
|
||||
3. 不含支付功能版本移除非税支付和医保支付接口
|
||||
4. 分享音乐支持填写歌词和高清封面图
|
||||
|
||||
SDK1.8.4
|
||||
1. 调整分享图片大小限制
|
||||
2. 新增openBusinessView接口
|
||||
|
||||
SDK1.8.3
|
||||
1. SDK增加调起微信刷卡支付接口
|
||||
2. SDK增加小程序订阅消息接口
|
||||
3. 修复小程序订阅消息接口没有resp的问题
|
||||
|
||||
SDK1.8.2
|
||||
1. SDK增加开发票授权 WXInvoiceAuthInsert
|
||||
2. SDK增加非税接口 WXNontaxPay
|
||||
3. SDK增加医保接口 WXPayInsurance
|
||||
4. 更换MTA库
|
||||
|
||||
SDK1.8.1
|
||||
1. SDK打开小程序支持指定版本(体验,开发,正式版)
|
||||
2. SDK分享小程序支持指定版本(体验,开发,正式版)
|
||||
3. SDK支持输出log日志
|
||||
|
||||
SDK1.8.0
|
||||
1. SDK支持打开小程序
|
||||
2. SDK分享小程序支持shareTicket
|
||||
|
||||
SDK1.7.9
|
||||
1. SDK订阅一次性消息
|
||||
|
||||
SDK1.7.8
|
||||
1 SDK分享小程序支持大图
|
||||
|
||||
SDK1.7.7
|
||||
1 增加SDK分享小程序
|
||||
2 增加选择发票接口
|
||||
|
||||
SDK1.7.6
|
||||
1. 提高稳定性
|
||||
1 修复mta崩溃
|
||||
2 新增接口支持开发者关闭mta数据统计上报
|
||||
|
||||
SDK1.7.5
|
||||
1. 提高稳定性
|
||||
2. 加快registerApp接口启动速度
|
||||
|
||||
SDK1.7.4
|
||||
1. 更新支持iOS启用 ATS(App Transport Security)
|
||||
2. 需要在工程中链接CFNetwork.framework
|
||||
3. 在工程配置中的”Other Linker Flags”中加入”-Objc -all_load”
|
||||
|
||||
SDK1.7.3
|
||||
1. 增强稳定性,适配iOS10
|
||||
2. 修复小于32K的jpg格式缩略图设置失败的问题
|
||||
|
||||
SDK1.7.2
|
||||
1. 修复因CTTeleponyNetworkInfo引起的崩溃问题
|
||||
|
||||
SDK1.7.1
|
||||
1. 支持兼容ipv6(提升稳定性)
|
||||
2. xCode Version 7.3.1 (7D1014) 编译
|
||||
|
||||
SDK1.7
|
||||
1. 支持兼容ipv6
|
||||
2. 修复若干问题增强稳定性
|
||||
|
||||
SDK1.6.3
|
||||
1. xCode7.2 构建的sdk包。
|
||||
2. 请使用xCode7.2进行编译。
|
||||
3. 需要在Build Phases中Link Security.framework
|
||||
4. 修复若干小问题。
|
||||
|
||||
SDK1.6.2
|
||||
1、xCode7.1 构建的sdk包
|
||||
2、请使用xCode7.1进行编译
|
||||
|
||||
SDK1.6.1
|
||||
1、修复armv7s下,bitcode可能编译不过
|
||||
2、解决warning
|
||||
|
||||
SDK1.6
|
||||
1、iOS 9系统策略更新,限制了http协议的访问,此外应用需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。
|
||||
受此影响,当你的应用在iOS 9中需要使用微信SDK的相关能力(分享、收藏、支付、登录等)时,需要在“Info.plist”里增加如下代码:
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>weixin</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
2、开发者需要在工程中链接上 CoreTelephony.framework
|
||||
3、解决bitcode编译不过问题
|
||||
|
||||
SDK1.5
|
||||
1、废弃safeSendReq:接口,使用sendReq:即可。
|
||||
2、新增+(BOOL) sendAuthReq:(SendAuthReq*) req viewController : (UIViewController*) viewController delegate:(id<WXApiDelegate>) delegate;
|
||||
支持未安装微信情况下Auth,具体见WXApi.h接口描述
|
||||
3、微信开放平台新增了微信模块用户统计功能,便于开发者统计微信功能模块的用户使用和活跃情况。开发者需要在工程中链接上:SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib。
|
||||
@ -0,0 +1,231 @@
|
||||
//
|
||||
// WXApi.h
|
||||
// 所有Api接口
|
||||
//
|
||||
// Created by Wechat on 12-2-28.
|
||||
// Copyright (c) 2012年 Tencent. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "WXApiObject.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
typedef BOOL(^WXGrantReadPasteBoardPermissionCompletion)(void);
|
||||
|
||||
|
||||
#pragma mark - WXApiDelegate
|
||||
/*! @brief 接收并处理来自微信终端程序的事件消息
|
||||
*
|
||||
* 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。
|
||||
* WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。
|
||||
*/
|
||||
@protocol WXApiDelegate <NSObject>
|
||||
@optional
|
||||
|
||||
/*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果
|
||||
*
|
||||
* 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。
|
||||
* 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
|
||||
* @param req 具体请求内容,是自动释放的
|
||||
*/
|
||||
- (void)onReq:(BaseReq*)req;
|
||||
|
||||
|
||||
|
||||
/*! @brief 发送一个sendReq后,收到微信的回应
|
||||
*
|
||||
* 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
|
||||
* 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
|
||||
* @param resp具体的回应内容,是自动释放的
|
||||
*/
|
||||
- (void)onResp:(BaseResp*)resp;
|
||||
|
||||
/* ! @brief 用于在iOS16以及以上系统上,控制OpenSDK是否读取剪切板中微信传递的数据以及读取的时机
|
||||
* 在iOS16以及以上系统,在SDK需要读取剪切板中微信写入的数据时,会回调该方法。没有实现默认会直接读取微信通过剪切板传递过来的数据
|
||||
* 注意:
|
||||
* 1. 只在iOS16以及以上的系统版本上回调;
|
||||
* 2. 不实现时,OpenSDK会直接调用读取剪切板接口,读取微信传递过来的数据;
|
||||
* 3. 若实现该方法:开发者需要通过调用completion(), 支持异步,通知SDK允许读取剪切板中微信传递的数据,
|
||||
* 不调用completion()则代表不授权OpenSDK读取剪切板,会导致收不到onReq:, onResp:回调,无法后续业务流程。请谨慎使用
|
||||
* 4. 不要长时间持有completion不释放,可能会导致内存泄漏。
|
||||
*/
|
||||
- (void)onNeedGrantReadPasteBoardPermissionWithURL:(nonnull NSURL *)openURL completion:(nonnull WXGrantReadPasteBoardPermissionCompletion)completion;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - WXApiLogDelegate
|
||||
|
||||
@protocol WXApiLogDelegate <NSObject>
|
||||
|
||||
- (void)onLog:(NSString*)log logLevel:(WXLogLevel)level;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - WXApi
|
||||
|
||||
/*! @brief 微信Api接口函数类
|
||||
*
|
||||
* 该类封装了微信终端SDK的所有接口
|
||||
*/
|
||||
@interface WXApi : NSObject
|
||||
|
||||
/*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。
|
||||
*
|
||||
* 需要在每次启动第三方应用程序时调用。
|
||||
* @attention 请保证在主线程中调用此函数
|
||||
* @param appid 微信开发者ID
|
||||
* @param universalLink 微信开发者Universal Link
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)registerApp:(NSString *)appid universalLink:(NSString *)universalLink;
|
||||
|
||||
|
||||
/*! @brief 处理旧版微信通过URL启动App时传递的数据
|
||||
*
|
||||
* 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
|
||||
* @param url 微信启动第三方应用时传递过来的URL
|
||||
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id<WXApiDelegate>)delegate;
|
||||
|
||||
|
||||
/*! @brief 处理微信通过Universal Link启动App时传递的数据
|
||||
*
|
||||
* 需要在 application:continueUserActivity:restorationHandler:中调用。
|
||||
* @param userActivity 微信启动第三方应用时系统API传递过来的userActivity
|
||||
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity delegate:(nullable id<WXApiDelegate>)delegate;
|
||||
|
||||
|
||||
/*! @brief 检查微信是否已被用户安装
|
||||
*
|
||||
* @return 微信已安装返回YES,未安装返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppInstalled;
|
||||
|
||||
|
||||
|
||||
/*! @brief 判断当前微信的版本是否支持OpenApi
|
||||
*
|
||||
* @return 支持返回YES,不支持返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppSupportApi;
|
||||
|
||||
|
||||
/*! @brief 判断当前微信的版本是否支持分享微信状态功能
|
||||
*
|
||||
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinStateAPI
|
||||
* @return 支持返回YES,不支持返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppSupportStateAPI;
|
||||
|
||||
|
||||
#ifndef BUILD_WITHOUT_PAY
|
||||
/*! @brief 判断当前微信的版本是否支持二维码拉起微信支付
|
||||
*
|
||||
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinQRCodePayAPI
|
||||
* @return 支持返回YES,不支持返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppSupportQRCodePayAPI;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*! @brief 获取微信的itunes安装地址
|
||||
*
|
||||
* @return 微信的安装地址字符串。
|
||||
*/
|
||||
+ (NSString *)getWXAppInstallUrl;
|
||||
|
||||
|
||||
|
||||
/*! @brief 获取当前微信SDK的版本号
|
||||
*
|
||||
* @return 返回当前微信SDK的版本号
|
||||
*/
|
||||
+ (NSString *)getApiVersion;
|
||||
|
||||
|
||||
|
||||
/*! @brief 打开微信
|
||||
*
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)openWXApp;
|
||||
|
||||
|
||||
|
||||
/*! @brief 发送请求到微信,等待微信返回onResp
|
||||
*
|
||||
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型
|
||||
* SendAuthReq、SendMessageToWXReq、PayReq等。
|
||||
* @param req 具体的发送请求。
|
||||
* @param completion 调用结果回调block
|
||||
*/
|
||||
+ (void)sendReq:(BaseReq *)req completion:(void (^ __nullable)(BOOL success))completion;
|
||||
|
||||
/*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面
|
||||
*
|
||||
* 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有
|
||||
* GetMessageFromWXResp、ShowMessageFromWXResp等。
|
||||
* @param resp 具体的应答内容
|
||||
* @param completion 调用结果回调block
|
||||
*/
|
||||
+ (void)sendResp:(BaseResp*)resp completion:(void (^ __nullable)(BOOL success))completion;
|
||||
|
||||
|
||||
/*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp
|
||||
*
|
||||
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。
|
||||
* @param req 具体的发送请求。
|
||||
* @param viewController 当前界面对象。
|
||||
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
|
||||
* @param completion 调用结果回调block
|
||||
*/
|
||||
+ (void)sendAuthReq:(SendAuthReq *)req viewController:(UIViewController*)viewController delegate:(nullable id<WXApiDelegate>)delegate completion:(void (^ __nullable)(BOOL success))completion;
|
||||
|
||||
|
||||
/*! @brief 测试函数,用于排查当前App通过Universal Link方式分享到微信的流程
|
||||
注意1: 调用自检函数之前必须要先调用registerApp:universalLink接口, 并确认调用成功
|
||||
注意2: 自检过程中会有Log产生,可以先调用startLogByLevel函数,根据Log排查问题
|
||||
注意3: 会多次回调block
|
||||
注意4: 仅用于新接入SDK时调试使用,请勿在正式环境的调用
|
||||
*
|
||||
* 当completion回调的step为WXULCheckStepFinal时,表示检测通过,Universal Link接入成功
|
||||
* @param completion 回调Block
|
||||
*/
|
||||
+ (void)checkUniversalLinkReady:(nonnull WXCheckULCompletion)completion;
|
||||
|
||||
|
||||
/*! @brief WXApi的成员函数,接受微信的log信息。byBlock
|
||||
注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏
|
||||
注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock
|
||||
*
|
||||
* @param level 打印log的级别
|
||||
* @param logBlock 打印log的回调block
|
||||
*/
|
||||
|
||||
+ (void)startLogByLevel:(WXLogLevel)level logBlock:(WXLogBolock)logBlock;
|
||||
|
||||
/*! @brief WXApi的成员函数,接受微信的log信息。byDelegate
|
||||
注意1:sdk会弱引用这个delegate,这里可加任意对象为代理,不需要与WXApiDelegate同一个对象
|
||||
注意2:调用过一次startLog by delegate之后,再调用一次任意方式的startLoad,不会再回调上一个logDelegate对象
|
||||
* @param level 打印log的级别
|
||||
* @param logDelegate 打印log的回调代理,
|
||||
*/
|
||||
+ (void)startLogByLevel:(WXLogLevel)level logDelegate:(id<WXApiLogDelegate>)logDelegate;
|
||||
|
||||
/*! @brief 停止打印log,会清理block或者delegate为空,释放block
|
||||
* @param
|
||||
*/
|
||||
+ (void)stopLog;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,68 @@
|
||||
//
|
||||
// WechatAuthSDK.h
|
||||
// WechatAuthSDK
|
||||
//
|
||||
// Created by 李凯 on 13-11-29.
|
||||
// Copyright (c) 2013年 Tencent. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
enum AuthErrCode {
|
||||
WechatAuth_Err_Ok = 0, //Auth成功
|
||||
WechatAuth_Err_NormalErr = -1, //普通错误
|
||||
WechatAuth_Err_NetworkErr = -2, //网络错误
|
||||
WechatAuth_Err_GetQrcodeFailed = -3, //获取二维码失败
|
||||
WechatAuth_Err_Cancel = -4, //用户取消授权
|
||||
WechatAuth_Err_Timeout = -5, //超时
|
||||
};
|
||||
|
||||
@protocol WechatAuthAPIDelegate<NSObject>
|
||||
@optional
|
||||
|
||||
- (void)onAuthGotQrcode:(UIImage *)image; //得到二维码
|
||||
- (void)onQrcodeScanned; //二维码被扫描
|
||||
- (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode; //成功登录
|
||||
|
||||
@end
|
||||
|
||||
@interface WechatAuthSDK : NSObject{
|
||||
NSString *_sdkVersion;
|
||||
__weak id<WechatAuthAPIDelegate> _delegate;
|
||||
}
|
||||
|
||||
@property(nonatomic, weak, nullable) id<WechatAuthAPIDelegate> delegate;
|
||||
@property(nonatomic, readonly) NSString *sdkVersion; //authSDK版本号
|
||||
|
||||
/*! @brief 发送登录请求,等待WechatAuthAPIDelegate回调
|
||||
*
|
||||
* @param appId 微信开发者ID
|
||||
* @param nonceStr 一个随机的尽量不重复的字符串,用来使得每次的signature不同
|
||||
* @param timeStamp 时间戳
|
||||
* @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔
|
||||
* @param signature 签名
|
||||
* @param schemeData 会在扫码后拼在scheme后
|
||||
* @return 成功返回YES,失败返回NO
|
||||
注:该实现只保证同时只有一个Auth在运行,Auth未完成或未Stop再次调用Auth接口时会返回NO。
|
||||
*/
|
||||
|
||||
- (BOOL)Auth:(NSString *)appId
|
||||
nonceStr:(NSString *)nonceStr
|
||||
timeStamp:(NSString *)timeStamp
|
||||
scope:(NSString *)scope
|
||||
signature:(NSString *)signature
|
||||
schemeData:(nullable NSString *)schemeData;
|
||||
|
||||
|
||||
/*! @brief 暂停登录请求
|
||||
*
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
- (BOOL)StopAuth;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,9 @@
|
||||
// WechatOpenSDK.h
|
||||
//
|
||||
// Created by Wechat.
|
||||
// Copyright (c) 2012年 Tencent. All rights reserved.
|
||||
//
|
||||
#import <WechatOpenSDK/WXApi.h>
|
||||
#import <WechatOpenSDK/WXApiObject.h>
|
||||
#import <WechatOpenSDK/WechatAuthSDK.h>
|
||||
|
||||
15
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/ios-arm64/WechatOpenSDK.framework/Info.plist
generated
Executable file
15
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/ios-arm64/WechatOpenSDK.framework/Info.plist
generated
Executable file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.tencent.WechatOpenSDK</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>WechatOpenSDK</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,5 @@
|
||||
framework module WechatOpenSDK {
|
||||
umbrella header "WechatOpenSDK.h"
|
||||
export *
|
||||
link "WechatOpenSDK"
|
||||
}
|
||||
BIN
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/ios-arm64/WechatOpenSDK.framework/WechatOpenSDK
generated
Normal file
BIN
Pods/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework/ios-arm64/WechatOpenSDK.framework/WechatOpenSDK
generated
Normal file
Binary file not shown.
@ -0,0 +1,231 @@
|
||||
//
|
||||
// WXApi.h
|
||||
// 所有Api接口
|
||||
//
|
||||
// Created by Wechat on 12-2-28.
|
||||
// Copyright (c) 2012年 Tencent. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "WXApiObject.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
typedef BOOL(^WXGrantReadPasteBoardPermissionCompletion)(void);
|
||||
|
||||
|
||||
#pragma mark - WXApiDelegate
|
||||
/*! @brief 接收并处理来自微信终端程序的事件消息
|
||||
*
|
||||
* 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。
|
||||
* WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。
|
||||
*/
|
||||
@protocol WXApiDelegate <NSObject>
|
||||
@optional
|
||||
|
||||
/*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果
|
||||
*
|
||||
* 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。
|
||||
* 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
|
||||
* @param req 具体请求内容,是自动释放的
|
||||
*/
|
||||
- (void)onReq:(BaseReq*)req;
|
||||
|
||||
|
||||
|
||||
/*! @brief 发送一个sendReq后,收到微信的回应
|
||||
*
|
||||
* 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
|
||||
* 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
|
||||
* @param resp具体的回应内容,是自动释放的
|
||||
*/
|
||||
- (void)onResp:(BaseResp*)resp;
|
||||
|
||||
/* ! @brief 用于在iOS16以及以上系统上,控制OpenSDK是否读取剪切板中微信传递的数据以及读取的时机
|
||||
* 在iOS16以及以上系统,在SDK需要读取剪切板中微信写入的数据时,会回调该方法。没有实现默认会直接读取微信通过剪切板传递过来的数据
|
||||
* 注意:
|
||||
* 1. 只在iOS16以及以上的系统版本上回调;
|
||||
* 2. 不实现时,OpenSDK会直接调用读取剪切板接口,读取微信传递过来的数据;
|
||||
* 3. 若实现该方法:开发者需要通过调用completion(), 支持异步,通知SDK允许读取剪切板中微信传递的数据,
|
||||
* 不调用completion()则代表不授权OpenSDK读取剪切板,会导致收不到onReq:, onResp:回调,无法后续业务流程。请谨慎使用
|
||||
* 4. 不要长时间持有completion不释放,可能会导致内存泄漏。
|
||||
*/
|
||||
- (void)onNeedGrantReadPasteBoardPermissionWithURL:(nonnull NSURL *)openURL completion:(nonnull WXGrantReadPasteBoardPermissionCompletion)completion;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - WXApiLogDelegate
|
||||
|
||||
@protocol WXApiLogDelegate <NSObject>
|
||||
|
||||
- (void)onLog:(NSString*)log logLevel:(WXLogLevel)level;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - WXApi
|
||||
|
||||
/*! @brief 微信Api接口函数类
|
||||
*
|
||||
* 该类封装了微信终端SDK的所有接口
|
||||
*/
|
||||
@interface WXApi : NSObject
|
||||
|
||||
/*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。
|
||||
*
|
||||
* 需要在每次启动第三方应用程序时调用。
|
||||
* @attention 请保证在主线程中调用此函数
|
||||
* @param appid 微信开发者ID
|
||||
* @param universalLink 微信开发者Universal Link
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)registerApp:(NSString *)appid universalLink:(NSString *)universalLink;
|
||||
|
||||
|
||||
/*! @brief 处理旧版微信通过URL启动App时传递的数据
|
||||
*
|
||||
* 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
|
||||
* @param url 微信启动第三方应用时传递过来的URL
|
||||
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id<WXApiDelegate>)delegate;
|
||||
|
||||
|
||||
/*! @brief 处理微信通过Universal Link启动App时传递的数据
|
||||
*
|
||||
* 需要在 application:continueUserActivity:restorationHandler:中调用。
|
||||
* @param userActivity 微信启动第三方应用时系统API传递过来的userActivity
|
||||
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity delegate:(nullable id<WXApiDelegate>)delegate;
|
||||
|
||||
|
||||
/*! @brief 检查微信是否已被用户安装
|
||||
*
|
||||
* @return 微信已安装返回YES,未安装返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppInstalled;
|
||||
|
||||
|
||||
|
||||
/*! @brief 判断当前微信的版本是否支持OpenApi
|
||||
*
|
||||
* @return 支持返回YES,不支持返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppSupportApi;
|
||||
|
||||
|
||||
/*! @brief 判断当前微信的版本是否支持分享微信状态功能
|
||||
*
|
||||
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinStateAPI
|
||||
* @return 支持返回YES,不支持返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppSupportStateAPI;
|
||||
|
||||
|
||||
#ifndef BUILD_WITHOUT_PAY
|
||||
/*! @brief 判断当前微信的版本是否支持二维码拉起微信支付
|
||||
*
|
||||
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinQRCodePayAPI
|
||||
* @return 支持返回YES,不支持返回NO。
|
||||
*/
|
||||
+ (BOOL)isWXAppSupportQRCodePayAPI;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*! @brief 获取微信的itunes安装地址
|
||||
*
|
||||
* @return 微信的安装地址字符串。
|
||||
*/
|
||||
+ (NSString *)getWXAppInstallUrl;
|
||||
|
||||
|
||||
|
||||
/*! @brief 获取当前微信SDK的版本号
|
||||
*
|
||||
* @return 返回当前微信SDK的版本号
|
||||
*/
|
||||
+ (NSString *)getApiVersion;
|
||||
|
||||
|
||||
|
||||
/*! @brief 打开微信
|
||||
*
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
+ (BOOL)openWXApp;
|
||||
|
||||
|
||||
|
||||
/*! @brief 发送请求到微信,等待微信返回onResp
|
||||
*
|
||||
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型
|
||||
* SendAuthReq、SendMessageToWXReq、PayReq等。
|
||||
* @param req 具体的发送请求。
|
||||
* @param completion 调用结果回调block
|
||||
*/
|
||||
+ (void)sendReq:(BaseReq *)req completion:(void (^ __nullable)(BOOL success))completion;
|
||||
|
||||
/*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面
|
||||
*
|
||||
* 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有
|
||||
* GetMessageFromWXResp、ShowMessageFromWXResp等。
|
||||
* @param resp 具体的应答内容
|
||||
* @param completion 调用结果回调block
|
||||
*/
|
||||
+ (void)sendResp:(BaseResp*)resp completion:(void (^ __nullable)(BOOL success))completion;
|
||||
|
||||
|
||||
/*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp
|
||||
*
|
||||
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。
|
||||
* @param req 具体的发送请求。
|
||||
* @param viewController 当前界面对象。
|
||||
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
|
||||
* @param completion 调用结果回调block
|
||||
*/
|
||||
+ (void)sendAuthReq:(SendAuthReq *)req viewController:(UIViewController*)viewController delegate:(nullable id<WXApiDelegate>)delegate completion:(void (^ __nullable)(BOOL success))completion;
|
||||
|
||||
|
||||
/*! @brief 测试函数,用于排查当前App通过Universal Link方式分享到微信的流程
|
||||
注意1: 调用自检函数之前必须要先调用registerApp:universalLink接口, 并确认调用成功
|
||||
注意2: 自检过程中会有Log产生,可以先调用startLogByLevel函数,根据Log排查问题
|
||||
注意3: 会多次回调block
|
||||
注意4: 仅用于新接入SDK时调试使用,请勿在正式环境的调用
|
||||
*
|
||||
* 当completion回调的step为WXULCheckStepFinal时,表示检测通过,Universal Link接入成功
|
||||
* @param completion 回调Block
|
||||
*/
|
||||
+ (void)checkUniversalLinkReady:(nonnull WXCheckULCompletion)completion;
|
||||
|
||||
|
||||
/*! @brief WXApi的成员函数,接受微信的log信息。byBlock
|
||||
注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏
|
||||
注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock
|
||||
*
|
||||
* @param level 打印log的级别
|
||||
* @param logBlock 打印log的回调block
|
||||
*/
|
||||
|
||||
+ (void)startLogByLevel:(WXLogLevel)level logBlock:(WXLogBolock)logBlock;
|
||||
|
||||
/*! @brief WXApi的成员函数,接受微信的log信息。byDelegate
|
||||
注意1:sdk会弱引用这个delegate,这里可加任意对象为代理,不需要与WXApiDelegate同一个对象
|
||||
注意2:调用过一次startLog by delegate之后,再调用一次任意方式的startLoad,不会再回调上一个logDelegate对象
|
||||
* @param level 打印log的级别
|
||||
* @param logDelegate 打印log的回调代理,
|
||||
*/
|
||||
+ (void)startLogByLevel:(WXLogLevel)level logDelegate:(id<WXApiLogDelegate>)logDelegate;
|
||||
|
||||
/*! @brief 停止打印log,会清理block或者delegate为空,释放block
|
||||
* @param
|
||||
*/
|
||||
+ (void)stopLog;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,68 @@
|
||||
//
|
||||
// WechatAuthSDK.h
|
||||
// WechatAuthSDK
|
||||
//
|
||||
// Created by 李凯 on 13-11-29.
|
||||
// Copyright (c) 2013年 Tencent. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
enum AuthErrCode {
|
||||
WechatAuth_Err_Ok = 0, //Auth成功
|
||||
WechatAuth_Err_NormalErr = -1, //普通错误
|
||||
WechatAuth_Err_NetworkErr = -2, //网络错误
|
||||
WechatAuth_Err_GetQrcodeFailed = -3, //获取二维码失败
|
||||
WechatAuth_Err_Cancel = -4, //用户取消授权
|
||||
WechatAuth_Err_Timeout = -5, //超时
|
||||
};
|
||||
|
||||
@protocol WechatAuthAPIDelegate<NSObject>
|
||||
@optional
|
||||
|
||||
- (void)onAuthGotQrcode:(UIImage *)image; //得到二维码
|
||||
- (void)onQrcodeScanned; //二维码被扫描
|
||||
- (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode; //成功登录
|
||||
|
||||
@end
|
||||
|
||||
@interface WechatAuthSDK : NSObject{
|
||||
NSString *_sdkVersion;
|
||||
__weak id<WechatAuthAPIDelegate> _delegate;
|
||||
}
|
||||
|
||||
@property(nonatomic, weak, nullable) id<WechatAuthAPIDelegate> delegate;
|
||||
@property(nonatomic, readonly) NSString *sdkVersion; //authSDK版本号
|
||||
|
||||
/*! @brief 发送登录请求,等待WechatAuthAPIDelegate回调
|
||||
*
|
||||
* @param appId 微信开发者ID
|
||||
* @param nonceStr 一个随机的尽量不重复的字符串,用来使得每次的signature不同
|
||||
* @param timeStamp 时间戳
|
||||
* @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔
|
||||
* @param signature 签名
|
||||
* @param schemeData 会在扫码后拼在scheme后
|
||||
* @return 成功返回YES,失败返回NO
|
||||
注:该实现只保证同时只有一个Auth在运行,Auth未完成或未Stop再次调用Auth接口时会返回NO。
|
||||
*/
|
||||
|
||||
- (BOOL)Auth:(NSString *)appId
|
||||
nonceStr:(NSString *)nonceStr
|
||||
timeStamp:(NSString *)timeStamp
|
||||
scope:(NSString *)scope
|
||||
signature:(NSString *)signature
|
||||
schemeData:(nullable NSString *)schemeData;
|
||||
|
||||
|
||||
/*! @brief 暂停登录请求
|
||||
*
|
||||
* @return 成功返回YES,失败返回NO。
|
||||
*/
|
||||
- (BOOL)StopAuth;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -0,0 +1,9 @@
|
||||
// WechatOpenSDK.h
|
||||
//
|
||||
// Created by Wechat.
|
||||
// Copyright (c) 2012年 Tencent. All rights reserved.
|
||||
//
|
||||
#import <WechatOpenSDK/WXApi.h>
|
||||
#import <WechatOpenSDK/WXApiObject.h>
|
||||
#import <WechatOpenSDK/WechatAuthSDK.h>
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.tencent.WechatOpenSDK</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>WechatOpenSDK</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -0,0 +1,5 @@
|
||||
framework module WechatOpenSDK {
|
||||
umbrella header "WechatOpenSDK.h"
|
||||
export *
|
||||
link "WechatOpenSDK"
|
||||
}
|
||||
Binary file not shown.
13
docs/apple-app-site-association
Normal file
13
docs/apple-app-site-association
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"applinks": {
|
||||
"apps": [],
|
||||
"details": [
|
||||
{
|
||||
"appID": "56GVN5RNVN.com.yuanzhixiang.suixinkan",
|
||||
"paths": [
|
||||
"/suixinkan/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
11
docs/apple-app-site-association.example.json
Normal file
11
docs/apple-app-site-association.example.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"applinks": {
|
||||
"apps": [],
|
||||
"details": [
|
||||
{
|
||||
"appID": "56GVN5RNVN.com.yuanzhixiang.suixinkan",
|
||||
"paths": ["/suixinkan/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -7,8 +7,38 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
/// AppDelegate 承接 APNs 系统回调,SwiftUI App 入口通过 adaptor 注入。
|
||||
/// AppDelegate 承接 APNs 与微信 SDK 系统回调,SwiftUI App 入口通过 adaptor 注入。
|
||||
final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
||||
) -> Bool {
|
||||
Task { @MainActor in
|
||||
WeChatManager.shared.registerIfNeeded()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func application(
|
||||
_ app: UIApplication,
|
||||
open url: URL,
|
||||
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
|
||||
) -> Bool {
|
||||
MainActor.assumeIsolated {
|
||||
WeChatManager.shared.handleOpenURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
continue userActivity: NSUserActivity,
|
||||
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
|
||||
) -> Bool {
|
||||
MainActor.assumeIsolated {
|
||||
WeChatManager.shared.handleContinueUserActivity(userActivity)
|
||||
}
|
||||
}
|
||||
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
||||
|
||||
36
suixinkan/App/WeChatConfig.swift
Normal file
36
suixinkan/App/WeChatConfig.swift
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// WeChatConfig.swift
|
||||
// suixinkan
|
||||
//
|
||||
// 微信 Open SDK 配置。上线前请替换为开放平台真实 AppID,并同步 Info.plist URL Scheme。
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// 微信开放平台接入配置,集中管理 AppID 与 Universal Link。
|
||||
enum WeChatConfig {
|
||||
/// 占位 AppID,上线前替换为微信开放平台移动应用 AppID。
|
||||
static let appID = "wxdd80ec12c4fee322"
|
||||
|
||||
/// Universal Link,必须以 `/` 结尾,且与开放平台填写完全一致。
|
||||
static let universalLink = "https://www.zhifly.cn/suixinkan/"
|
||||
|
||||
/// Associated Domains 域名(不含 `applinks:` 前缀)。
|
||||
static let associatedDomain = "www.zhifly.cn"
|
||||
|
||||
/// AASA 文件 paths 通配规则,需与运维部署的 apple-app-site-association 一致。
|
||||
static let aasaPathPattern = "/suixinkan/*"
|
||||
|
||||
/// Apple Team ID + Bundle ID,供运维部署 AASA 使用。
|
||||
static let aasaAppID = "56GVN5RNVN.com.yuanzhixiang.suixinkan"
|
||||
|
||||
/// 校验 Universal Link 格式是否符合微信要求。
|
||||
static func validateUniversalLink(_ link: String) -> Bool {
|
||||
guard let url = URL(string: link),
|
||||
url.scheme?.lowercased() == "https",
|
||||
link.hasSuffix("/") else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,12 @@ struct suixinkanApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
RootView()
|
||||
.onOpenURL { url in
|
||||
WeChatManager.shared.handleOpenURL(url)
|
||||
}
|
||||
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
|
||||
_ = WeChatManager.shared.handleContinueUserActivity(userActivity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
59
suixinkan/Core/WeChat/WeChat.md
Normal file
59
suixinkan/Core/WeChat/WeChat.md
Normal file
@ -0,0 +1,59 @@
|
||||
# WeChat 模块业务逻辑
|
||||
|
||||
## 模块职责
|
||||
|
||||
WeChat 模块封装微信 Open SDK 的注册、Universal Link 回跳与分享能力。当前仅接入分享(文本、网页、图片),不调用微信支付 API。
|
||||
|
||||
## 配置
|
||||
|
||||
- `WeChatConfig`:AppID、Universal Link、AASA 部署参考信息
|
||||
- `Info.plist`:URL Scheme(AppID)、`LSApplicationQueriesSchemes`
|
||||
- `suixinkan.entitlements`:`applinks:www.zhifly.cn`
|
||||
|
||||
### Universal Link
|
||||
|
||||
- 地址:`https://www.zhifly.cn/suixinkan/`(必须以 `/` 结尾)
|
||||
- 运维需在 `https://www.zhifly.cn/.well-known/apple-app-site-association` 部署 AASA 文件
|
||||
- 示例见 [`docs/apple-app-site-association.example.json`](../../docs/apple-app-site-association.example.json)
|
||||
|
||||
### 微信开放平台
|
||||
|
||||
移动应用开发信息需填写:
|
||||
|
||||
| 字段 | 值 |
|
||||
|------|-----|
|
||||
| iOS Bundle ID | `com.yuanzhixiang.suixinkan` |
|
||||
| Universal Links | `https://www.zhifly.cn/suixinkan/` |
|
||||
|
||||
## 核心类型
|
||||
|
||||
| 类型 | 职责 |
|
||||
|------|------|
|
||||
| `WeChatManager` | SDK 注册、URL/UL 回调、`WXApiDelegate` 分享结果 |
|
||||
| `WeChatShareService` | 对外分享 API:`shareText` / `shareWebPage` / `shareImage` |
|
||||
| `WeChatShareSheet` | SwiftUI 分享面板(好友/朋友圈/系统兜底) |
|
||||
| `WeChatThumbImageProcessor` | 缩略图压缩至 32KB 以内 |
|
||||
|
||||
## 回调链路
|
||||
|
||||
1. 启动:`AppDelegate.didFinishLaunching` → `WeChatManager.registerIfNeeded()`
|
||||
2. URL Scheme:`AppDelegate.openURL` + `suixinkanApp.onOpenURL`
|
||||
3. Universal Link:`AppDelegate.continueUserActivity` + `suixinkanApp.onContinueUserActivity`
|
||||
|
||||
## 业务接入
|
||||
|
||||
邀请页 `PhotographerInviteView` 通过 `WeChatShareSheet` 分享邀请链接。
|
||||
|
||||
后续举报、排队二维码等入口可复用 `WeChatShareService`。
|
||||
|
||||
## 真机验收
|
||||
|
||||
1. Safari 访问 `https://www.zhifly.cn/suixinkan/test`,下拉应出现打开 App 入口
|
||||
2. 邀请页点击「分享」→ 微信好友/朋友圈,首次可能出现「正在连接」属正常
|
||||
3. 未安装微信时走系统分享兜底
|
||||
|
||||
## 上线前
|
||||
|
||||
- 替换 `WeChatConfig.appID` 与 Info.plist URL Scheme
|
||||
- 确认开放平台 Universal Link 与代码一致
|
||||
- 确认 AASA 文件可公网 HTTPS 访问
|
||||
119
suixinkan/Core/WeChat/WeChatManager.swift
Normal file
119
suixinkan/Core/WeChat/WeChatManager.swift
Normal file
@ -0,0 +1,119 @@
|
||||
//
|
||||
// WeChatManager.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import WechatOpenSDK
|
||||
|
||||
/// 微信 SDK 生命周期与回调管理,负责注册、URL/Universal Link 回跳及分享结果分发。
|
||||
@MainActor
|
||||
final class WeChatManager: NSObject {
|
||||
static let shared = WeChatManager()
|
||||
|
||||
/// 最近一次分享结果,供 UI 监听。
|
||||
private(set) var lastShareResult: WeChatShareResult?
|
||||
|
||||
private var shareCompletion: ((WeChatShareResult) -> Void)?
|
||||
private var isRegistered = false
|
||||
|
||||
private override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// 向微信注册 AppID 与 Universal Link,应用启动时调用。
|
||||
func registerIfNeeded() {
|
||||
guard !isRegistered else { return }
|
||||
guard WeChatConfig.validateUniversalLink(WeChatConfig.universalLink) else {
|
||||
assertionFailure("WeChat Universal Link 必须以 https 开头并以 / 结尾")
|
||||
return
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
WXApi.startLog(by: WXLogLevel.detail) { log in
|
||||
print("WeChatSDK: \(log)")
|
||||
}
|
||||
#endif
|
||||
|
||||
let success = WXApi.registerApp(WeChatConfig.appID, universalLink: WeChatConfig.universalLink)
|
||||
isRegistered = success
|
||||
|
||||
#if DEBUG
|
||||
if success {
|
||||
checkUniversalLinkReady()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// 处理 URL Scheme 回调。
|
||||
@discardableResult
|
||||
func handleOpenURL(_ url: URL) -> Bool {
|
||||
WXApi.handleOpen(url, delegate: self)
|
||||
}
|
||||
|
||||
/// 处理 Universal Link 回调。
|
||||
@discardableResult
|
||||
func handleContinueUserActivity(_ userActivity: NSUserActivity) -> Bool {
|
||||
WXApi.handleOpenUniversalLink(userActivity, delegate: self)
|
||||
}
|
||||
|
||||
/// 注册单次分享完成回调。
|
||||
func setShareCompletion(_ completion: ((WeChatShareResult) -> Void)?) {
|
||||
shareCompletion = completion
|
||||
}
|
||||
|
||||
/// 发送分享请求到微信。
|
||||
func sendShareRequest(_ request: SendMessageToWXReq, completion: ((WeChatShareResult) -> Void)? = nil) {
|
||||
guard WXApi.isWXAppInstalled() else {
|
||||
let result = WeChatShareResult.notInstalled
|
||||
completion?(result)
|
||||
return
|
||||
}
|
||||
guard WXApi.isWXAppSupport() else {
|
||||
let result = WeChatShareResult.unsupported
|
||||
completion?(result)
|
||||
return
|
||||
}
|
||||
|
||||
if let completion {
|
||||
shareCompletion = completion
|
||||
}
|
||||
|
||||
WXApi.send(request) { success in
|
||||
if !success {
|
||||
Task { @MainActor in
|
||||
self.finishShare(with: .sendFailed(-1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// 调试 Universal Link 配置,仅 DEBUG 环境调用。
|
||||
private func checkUniversalLinkReady() {
|
||||
WXApi.checkUniversalLinkReady { step, result in
|
||||
print("WeChat UL check step=\(step.rawValue) success=\(result.success) info=\(result.errorInfo ?? "") suggestion=\(result.suggestion ?? "")")
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private func finishShare(with result: WeChatShareResult) {
|
||||
lastShareResult = result
|
||||
shareCompletion?(result)
|
||||
shareCompletion = nil
|
||||
}
|
||||
}
|
||||
|
||||
extension WeChatManager: WXApiDelegate {
|
||||
nonisolated func onReq(_ req: BaseReq) {
|
||||
// 分享模块暂不处理来自微信的主动请求。
|
||||
}
|
||||
|
||||
nonisolated func onResp(_ resp: BaseResp) {
|
||||
guard let shareResp = resp as? SendMessageToWXResp else { return }
|
||||
let result = WeChatShareResult.fromWXErrorCode(shareResp.errCode)
|
||||
Task { @MainActor in
|
||||
self.finishShare(with: result)
|
||||
}
|
||||
}
|
||||
}
|
||||
70
suixinkan/Core/WeChat/WeChatShareModels.swift
Normal file
70
suixinkan/Core/WeChat/WeChatShareModels.swift
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// WeChatShareModels.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// 微信分享目标场景。
|
||||
enum WeChatShareScene: Int, CaseIterable, Sendable {
|
||||
/// 微信好友会话。
|
||||
case session = 0
|
||||
/// 朋友圈。
|
||||
case timeline = 1
|
||||
/// 微信收藏。
|
||||
case favorite = 2
|
||||
|
||||
/// 展示用标题。
|
||||
var title: String {
|
||||
switch self {
|
||||
case .session: "微信好友"
|
||||
case .timeline: "朋友圈"
|
||||
case .favorite: "收藏"
|
||||
}
|
||||
}
|
||||
|
||||
/// 映射到微信 SDK 的 scene 常量。
|
||||
var wxSceneValue: Int32 {
|
||||
Int32(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
/// 微信分享请求结果。
|
||||
enum WeChatShareResult: Equatable, Sendable {
|
||||
case success
|
||||
case cancelled
|
||||
case notInstalled
|
||||
case unsupported
|
||||
case invalidPayload(String)
|
||||
case sendFailed(Int)
|
||||
case unknown(Int)
|
||||
|
||||
/// 根据微信 SDK 错误码解析分享结果。
|
||||
static func fromWXErrorCode(_ code: Int32) -> WeChatShareResult {
|
||||
switch code {
|
||||
case 0:
|
||||
.success
|
||||
case -2:
|
||||
.cancelled
|
||||
default:
|
||||
.unknown(Int(code))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 网页分享载荷,供业务层与分享服务之间传递。
|
||||
struct WeChatWebPageSharePayload: Equatable, Sendable {
|
||||
let title: String
|
||||
let description: String
|
||||
let url: String
|
||||
}
|
||||
|
||||
/// 文本分享载荷。
|
||||
struct WeChatTextSharePayload: Equatable, Sendable {
|
||||
let text: String
|
||||
}
|
||||
|
||||
/// 图片分享载荷。
|
||||
struct WeChatImageSharePayload: Equatable, Sendable {
|
||||
let imageData: Data
|
||||
}
|
||||
115
suixinkan/Core/WeChat/WeChatShareService.swift
Normal file
115
suixinkan/Core/WeChat/WeChatShareService.swift
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// WeChatShareService.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import WechatOpenSDK
|
||||
|
||||
/// 微信分享服务,封装文本、网页、图片分享能力(不含支付)。
|
||||
enum WeChatShareService {
|
||||
/// 是否已安装微信且支持 Open SDK。
|
||||
static var isWeChatAvailable: Bool {
|
||||
WXApi.isWXAppInstalled() && WXApi.isWXAppSupport()
|
||||
}
|
||||
|
||||
/// 分享纯文本到微信。
|
||||
@MainActor
|
||||
static func shareText(
|
||||
_ payload: WeChatTextSharePayload,
|
||||
scene: WeChatShareScene,
|
||||
completion: ((WeChatShareResult) -> Void)? = nil
|
||||
) {
|
||||
let trimmed = payload.text.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !trimmed.isEmpty else {
|
||||
completion?(.invalidPayload("分享文本不能为空"))
|
||||
return
|
||||
}
|
||||
|
||||
let request = SendMessageToWXReq()
|
||||
request.bText = true
|
||||
request.text = trimmed
|
||||
request.scene = scene.wxSceneValue
|
||||
WeChatManager.shared.sendShareRequest(request, completion: completion)
|
||||
}
|
||||
|
||||
/// 分享网页链接到微信。
|
||||
@MainActor
|
||||
static func shareWebPage(
|
||||
_ payload: WeChatWebPageSharePayload,
|
||||
scene: WeChatShareScene,
|
||||
thumbImage: UIImage? = nil,
|
||||
completion: ((WeChatShareResult) -> Void)? = nil
|
||||
) {
|
||||
let title = payload.title.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let url = payload.url.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !title.isEmpty else {
|
||||
completion?(.invalidPayload("分享标题不能为空"))
|
||||
return
|
||||
}
|
||||
guard !url.isEmpty else {
|
||||
completion?(.invalidPayload("分享链接不能为空"))
|
||||
return
|
||||
}
|
||||
|
||||
let webpageObject = WXWebpageObject()
|
||||
webpageObject.webpageUrl = url
|
||||
|
||||
let message = WXMediaMessage()
|
||||
message.title = title
|
||||
message.description = payload.description
|
||||
message.mediaObject = webpageObject
|
||||
if let thumbImage, let thumbData = WeChatThumbImageProcessor.makeThumbData(from: thumbImage) {
|
||||
message.thumbData = thumbData
|
||||
}
|
||||
|
||||
let request = SendMessageToWXReq()
|
||||
request.bText = false
|
||||
request.message = message
|
||||
request.scene = scene.wxSceneValue
|
||||
WeChatManager.shared.sendShareRequest(request, completion: completion)
|
||||
}
|
||||
|
||||
/// 分享图片到微信。
|
||||
@MainActor
|
||||
static func shareImage(
|
||||
_ payload: WeChatImageSharePayload,
|
||||
scene: WeChatShareScene,
|
||||
thumbImage: UIImage? = nil,
|
||||
completion: ((WeChatShareResult) -> Void)? = nil
|
||||
) {
|
||||
guard !payload.imageData.isEmpty else {
|
||||
completion?(.invalidPayload("分享图片不能为空"))
|
||||
return
|
||||
}
|
||||
|
||||
let imageObject = WXImageObject()
|
||||
imageObject.imageData = payload.imageData
|
||||
|
||||
let message = WXMediaMessage()
|
||||
message.mediaObject = imageObject
|
||||
if let thumbImage, let thumbData = WeChatThumbImageProcessor.makeThumbData(from: thumbImage) {
|
||||
message.thumbData = thumbData
|
||||
} else if let image = UIImage(data: payload.imageData),
|
||||
let thumbData = WeChatThumbImageProcessor.makeThumbData(from: image) {
|
||||
message.thumbData = thumbData
|
||||
}
|
||||
|
||||
let request = SendMessageToWXReq()
|
||||
request.bText = false
|
||||
request.message = message
|
||||
request.scene = scene.wxSceneValue
|
||||
WeChatManager.shared.sendShareRequest(request, completion: completion)
|
||||
}
|
||||
|
||||
/// 获取 App 图标,用作分享缩略图兜底。
|
||||
static func defaultThumbImage() -> UIImage? {
|
||||
guard let icons = Bundle.main.infoDictionary?["CFBundleIcons"] as? [String: Any],
|
||||
let primary = icons["CFBundlePrimaryIcon"] as? [String: Any],
|
||||
let iconFiles = primary["CFBundleIconFiles"] as? [String],
|
||||
let iconName = iconFiles.last else {
|
||||
return nil
|
||||
}
|
||||
return UIImage(named: iconName)
|
||||
}
|
||||
}
|
||||
105
suixinkan/Core/WeChat/WeChatShareSheet.swift
Normal file
105
suixinkan/Core/WeChat/WeChatShareSheet.swift
Normal file
@ -0,0 +1,105 @@
|
||||
//
|
||||
// WeChatShareSheet.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
/// 微信分享选项面板,支持好友/朋友圈及系统分享兜底。
|
||||
struct WeChatShareSheet: View {
|
||||
let title: String
|
||||
let description: String
|
||||
let url: String
|
||||
let thumbImage: UIImage?
|
||||
let onResult: (String) -> Void
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var isPresentingSystemShare = false
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
if WeChatShareService.isWeChatAvailable {
|
||||
shareButton("微信好友", systemImage: "message.fill") {
|
||||
share(scene: .session)
|
||||
}
|
||||
shareButton("朋友圈", systemImage: "person.2.fill") {
|
||||
share(scene: .timeline)
|
||||
}
|
||||
}
|
||||
shareButton("更多分享", systemImage: "square.and.arrow.up") {
|
||||
isPresentingSystemShare = true
|
||||
}
|
||||
}
|
||||
.navigationTitle("分享")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("取消") { dismiss() }
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $isPresentingSystemShare) {
|
||||
let text = shareText
|
||||
ActivityShareView(activityItems: [text]) {
|
||||
onResult("已打开系统分享")
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var shareText: String {
|
||||
let trimmedURL = url.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !trimmedURL.isEmpty else { return title }
|
||||
return "\(title)\n\(trimmedURL)"
|
||||
}
|
||||
|
||||
private func shareButton(_ label: String, systemImage: String, action: @escaping () -> Void) -> some View {
|
||||
Button(action: action) {
|
||||
Label(label, systemImage: systemImage)
|
||||
}
|
||||
}
|
||||
|
||||
private func share(scene: WeChatShareScene) {
|
||||
let payload = WeChatWebPageSharePayload(
|
||||
title: title,
|
||||
description: description,
|
||||
url: url
|
||||
)
|
||||
let thumb = thumbImage ?? WeChatShareService.defaultThumbImage()
|
||||
WeChatShareService.shareWebPage(payload, scene: scene, thumbImage: thumb) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
onResult("已分享到\(scene.title)")
|
||||
case .cancelled:
|
||||
onResult("已取消分享")
|
||||
case .notInstalled:
|
||||
isPresentingSystemShare = true
|
||||
case .unsupported:
|
||||
onResult("当前微信版本不支持分享")
|
||||
case .invalidPayload(let message):
|
||||
onResult(message)
|
||||
case .sendFailed, .unknown:
|
||||
onResult("分享失败,请稍后重试")
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 系统分享面板封装。
|
||||
private struct ActivityShareView: UIViewControllerRepresentable {
|
||||
let activityItems: [Any]
|
||||
let onComplete: () -> Void
|
||||
|
||||
func makeUIViewController(context: Context) -> UIActivityViewController {
|
||||
let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
||||
controller.completionWithItemsHandler = { _, _, _, _ in
|
||||
onComplete()
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
|
||||
}
|
||||
47
suixinkan/Core/WeChat/WeChatThumbImageProcessor.swift
Normal file
47
suixinkan/Core/WeChat/WeChatThumbImageProcessor.swift
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// WeChatThumbImageProcessor.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 微信分享缩略图处理器,将图片压缩到微信限制(32KB)以内。
|
||||
enum WeChatThumbImageProcessor {
|
||||
/// 微信缩略图最大字节数。
|
||||
static let maxThumbBytes = 32 * 1024
|
||||
|
||||
/// 将图片压缩为符合微信要求的缩略图数据。
|
||||
static func makeThumbData(from image: UIImage, maxBytes: Int = maxThumbBytes) -> Data? {
|
||||
guard maxBytes > 0 else { return nil }
|
||||
|
||||
let resized = resize(image, maxPixel: 120)
|
||||
var quality: CGFloat = 0.8
|
||||
var data = resized.jpegData(compressionQuality: quality)
|
||||
|
||||
while let current = data, current.count > maxBytes, quality > 0.1 {
|
||||
quality -= 0.1
|
||||
data = resized.jpegData(compressionQuality: quality)
|
||||
}
|
||||
|
||||
guard let result = data, result.count <= maxBytes else { return nil }
|
||||
return result
|
||||
}
|
||||
|
||||
/// 等比缩放图片,使最长边不超过指定像素。
|
||||
static func resize(_ image: UIImage, maxPixel: CGFloat) -> UIImage {
|
||||
let size = image.size
|
||||
guard size.width > 0, size.height > 0 else { return image }
|
||||
|
||||
let maxSide = max(size.width, size.height)
|
||||
guard maxSide > maxPixel else { return image }
|
||||
|
||||
let scale = maxPixel / maxSide
|
||||
let targetSize = CGSize(width: size.width * scale, height: size.height * scale)
|
||||
let format = UIGraphicsImageRendererFormat.default()
|
||||
format.scale = 1
|
||||
let renderer = UIGraphicsImageRenderer(size: targetSize, format: format)
|
||||
return renderer.image { _ in
|
||||
image.draw(in: CGRect(origin: .zero, size: targetSize))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,8 @@ Invite 模块负责首页 `registration_invitation`、`photographer_invite` 和
|
||||
|
||||
复制邀请链接时只由 View 层写入剪贴板,ViewModel 不关心系统剪贴板状态。
|
||||
|
||||
点击「分享」弹出 `WeChatShareSheet`,支持分享到微信好友、朋友圈;未安装微信时走系统分享兜底。分享网页使用 `WeChatShareService.shareWebPage`,缩略图优先使用邀请二维码。
|
||||
|
||||
## 邀请记录
|
||||
|
||||
`InviteRecordViewModel` 提供“邀请记录 / 奖励记录”分段:
|
||||
|
||||
@ -13,6 +13,7 @@ struct PhotographerInviteView: View {
|
||||
@EnvironmentObject private var toastCenter: ToastCenter
|
||||
@Environment(\.globalLoading) private var globalLoading
|
||||
@StateObject private var viewModel = PhotographerInviteViewModel()
|
||||
@State private var isPresentingShareSheet = false
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
@ -37,6 +38,17 @@ struct PhotographerInviteView: View {
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.task { await reload(showLoading: true) }
|
||||
.refreshable { await reload(showLoading: false) }
|
||||
.sheet(isPresented: $isPresentingShareSheet) {
|
||||
WeChatShareSheet(
|
||||
title: "邀请你加入随心瞰商家版",
|
||||
description: viewModel.inviteCode.isEmpty ? "摄影师邀请" : "邀请码:\(viewModel.inviteCode)",
|
||||
url: viewModel.inviteUrl,
|
||||
thumbImage: viewModel.qrImage
|
||||
) { message in
|
||||
toastCenter.show(message)
|
||||
}
|
||||
.presentationDetents([.medium])
|
||||
}
|
||||
}
|
||||
|
||||
private var inviteCard: some View {
|
||||
@ -77,8 +89,11 @@ struct PhotographerInviteView: View {
|
||||
.frame(height: 44)
|
||||
}
|
||||
Button {
|
||||
viewModel.copyInviteUrl()
|
||||
toastCenter.show("链接已复制,可粘贴分享")
|
||||
guard !viewModel.inviteUrl.isEmpty else {
|
||||
toastCenter.show("邀请链接加载中,请稍后重试")
|
||||
return
|
||||
}
|
||||
isPresentingShareSheet = true
|
||||
} label: {
|
||||
Label("分享", systemImage: "square.and.arrow.up")
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
@ -20,6 +20,25 @@
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>weixin</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>wxdd80ec12c4fee322</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>weixin</string>
|
||||
<string>weixinULAPI</string>
|
||||
<string>weixinURLParamsAPI</string>
|
||||
</array>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
|
||||
@ -4,5 +4,9 @@
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:www.zhifly.cn</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
68
suixinkanTests/WeChatShareServiceTests.swift
Normal file
68
suixinkanTests/WeChatShareServiceTests.swift
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// WeChatShareServiceTests.swift
|
||||
// suixinkanTests
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import XCTest
|
||||
@testable import suixinkan
|
||||
|
||||
final class WeChatShareServiceTests: XCTestCase {
|
||||
func testUniversalLinkMustEndWithSlash() {
|
||||
XCTAssertTrue(WeChatConfig.validateUniversalLink(WeChatConfig.universalLink))
|
||||
XCTAssertFalse(WeChatConfig.validateUniversalLink("https://www.zhifly.cn/suixinkan"))
|
||||
XCTAssertFalse(WeChatConfig.validateUniversalLink("http://www.zhifly.cn/suixinkan/"))
|
||||
}
|
||||
|
||||
func testShareSceneMapsToWXValues() {
|
||||
XCTAssertEqual(WeChatShareScene.session.wxSceneValue, 0)
|
||||
XCTAssertEqual(WeChatShareScene.timeline.wxSceneValue, 1)
|
||||
XCTAssertEqual(WeChatShareScene.favorite.wxSceneValue, 2)
|
||||
}
|
||||
|
||||
func testShareResultFromWXErrorCode() {
|
||||
XCTAssertEqual(WeChatShareResult.fromWXErrorCode(0), .success)
|
||||
XCTAssertEqual(WeChatShareResult.fromWXErrorCode(-2), .cancelled)
|
||||
XCTAssertEqual(WeChatShareResult.fromWXErrorCode(99), .unknown(99))
|
||||
}
|
||||
|
||||
func testThumbImageCompressionStaysWithinLimit() throws {
|
||||
let size = CGSize(width: 512, height: 512)
|
||||
let format = UIGraphicsImageRendererFormat.default()
|
||||
format.scale = 1
|
||||
let renderer = UIGraphicsImageRenderer(size: size, format: format)
|
||||
let image = renderer.image { context in
|
||||
UIColor.systemBlue.setFill()
|
||||
context.fill(CGRect(origin: .zero, size: size))
|
||||
}
|
||||
|
||||
let thumbData = try XCTUnwrap(WeChatThumbImageProcessor.makeThumbData(from: image))
|
||||
XCTAssertLessThanOrEqual(thumbData.count, WeChatThumbImageProcessor.maxThumbBytes)
|
||||
}
|
||||
|
||||
func testThumbImageResizeReducesLargeImage() {
|
||||
let size = CGSize(width: 800, height: 600)
|
||||
let format = UIGraphicsImageRendererFormat.default()
|
||||
format.scale = 1
|
||||
let renderer = UIGraphicsImageRenderer(size: size, format: format)
|
||||
let image = renderer.image { _ in }
|
||||
|
||||
let resized = WeChatThumbImageProcessor.resize(image, maxPixel: 120)
|
||||
XCTAssertLessThanOrEqual(max(resized.size.width, resized.size.height), 120)
|
||||
}
|
||||
|
||||
func testWebPagePayloadValidationRequiresNonEmptyFields() async {
|
||||
await MainActor.run {
|
||||
let expectation = expectation(description: "invalid title")
|
||||
WeChatShareService.shareWebPage(
|
||||
WeChatWebPageSharePayload(title: " ", description: "desc", url: "https://example.com"),
|
||||
scene: .session
|
||||
) { result in
|
||||
if case .invalidPayload = result {
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
wait(for: [expectation], timeout: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user