接入微信分享 SDK 并配置 Universal Link。

集成 WechatOpenSDK、www.zhifly.cn/suixinkan/ 通用链接与邀请页分享能力,附带 AASA 部署文件与单元测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-02 15:02:37 +08:00
parent 5d34cda730
commit a528d9b0d7
48 changed files with 5260 additions and 506 deletions

28
Podfile
View File

@ -8,20 +8,26 @@ target 'suixinkan' do
pod 'AMapSearch-NO-IDFA', '~> 9.7' pod 'AMapSearch-NO-IDFA', '~> 9.7'
pod 'AMapLocation-NO-IDFA', '~> 2.11' pod 'AMapLocation-NO-IDFA', '~> 2.11'
# 微信 Open SDK分享能力不调用支付 API
pod 'WechatOpenSDK-XCFramework', '~> 2.0.4'
target 'suixinkanTests' do target 'suixinkanTests' do
inherit! :search_paths inherit! :search_paths
end end
end end
# 模拟器可用的链接参数(不含高德 prebuilt framework # 模拟器可用的链接参数(不含高德 prebuilt framework,但保留微信 SDK
SIMULATOR_OTHER_LDFLAGS = <<~FLAGS.squish 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 "CoreGraphics" -framework "CoreLocation" -framework "CoreTelephony"
-framework "CoreText" -framework "ExternalAccessory" -framework "GLKit" -framework "CoreText" -framework "ExternalAccessory" -framework "GLKit"
-framework "OpenGLES" -framework "QuartzCore" -framework "Security" -framework "OpenGLES" -framework "QuartzCore" -framework "Security"
-framework "SystemConfiguration" -framework "SystemConfiguration" -framework "UIKit" -framework "WebKit"
-framework "WechatOpenSDK"
FLAGS FLAGS
SIMULATOR_FRAMEWORK_SEARCH_PATHS = '"${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"'
post_install do |installer| post_install do |installer|
# 1. 修正 aggregate xcconfig去掉 arm64 排除,模拟器单独链接(不链 AMap # 1. 修正 aggregate xcconfig去掉 arm64 排除,模拟器单独链接(不链 AMap
%w[Pods-suixinkan Pods-suixinkanTests].each do |target_name| %w[Pods-suixinkan Pods-suixinkanTests].each do |target_name|
@ -30,9 +36,23 @@ post_install do |installer|
content = File.read(path) content = File.read(path)
content.gsub!("EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64\n", '') 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*]') unless content.include?('OTHER_LDFLAGS[sdk=iphonesimulator*]')
content << "\nOTHER_LDFLAGS[sdk=iphonesimulator*] = #{SIMULATOR_OTHER_LDFLAGS}\n" 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 end
File.write(path, content) File.write(path, content)

View File

@ -6,11 +6,13 @@ PODS:
- AMapFoundation-NO-IDFA (>= 1.8.7) - AMapFoundation-NO-IDFA (>= 1.8.7)
- AMapSearch-NO-IDFA (9.7.5): - AMapSearch-NO-IDFA (9.7.5):
- AMapFoundation-NO-IDFA (>= 1.8.0) - AMapFoundation-NO-IDFA (>= 1.8.0)
- WechatOpenSDK-XCFramework (2.0.5)
DEPENDENCIES: DEPENDENCIES:
- AMap3DMap-NO-IDFA (~> 11.1) - AMap3DMap-NO-IDFA (~> 11.1)
- AMapLocation-NO-IDFA (~> 2.11) - AMapLocation-NO-IDFA (~> 2.11)
- AMapSearch-NO-IDFA (~> 9.7) - AMapSearch-NO-IDFA (~> 9.7)
- WechatOpenSDK-XCFramework (~> 2.0.4)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
@ -18,13 +20,15 @@ SPEC REPOS:
- AMapFoundation-NO-IDFA - AMapFoundation-NO-IDFA
- AMapLocation-NO-IDFA - AMapLocation-NO-IDFA
- AMapSearch-NO-IDFA - AMapSearch-NO-IDFA
- WechatOpenSDK-XCFramework
SPEC CHECKSUMS: SPEC CHECKSUMS:
AMap3DMap-NO-IDFA: 393a24abb0451fed2daa4316c8d3d356a395f2be AMap3DMap-NO-IDFA: 393a24abb0451fed2daa4316c8d3d356a395f2be
AMapFoundation-NO-IDFA: f48acbf6e74913dc6744581053f7d984f2432850 AMapFoundation-NO-IDFA: f48acbf6e74913dc6744581053f7d984f2432850
AMapLocation-NO-IDFA: 0fa6e7d5e42e10253f4437424d98966f53760862 AMapLocation-NO-IDFA: 0fa6e7d5e42e10253f4437424d98966f53760862
AMapSearch-NO-IDFA: 8e9d104032990a3b0cab66afb535299887c61047 AMapSearch-NO-IDFA: 8e9d104032990a3b0cab66afb535299887c61047
WechatOpenSDK-XCFramework: ff342ae616bb86df3d236aca38059dfd4bc4a949
PODFILE CHECKSUM: baa972253fcebc312545f7592c48cbba632f1907 PODFILE CHECKSUM: e8cba7a3776cf5c925cda135f2774d8f243899c4
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2

6
Pods/Manifest.lock generated
View File

@ -6,11 +6,13 @@ PODS:
- AMapFoundation-NO-IDFA (>= 1.8.7) - AMapFoundation-NO-IDFA (>= 1.8.7)
- AMapSearch-NO-IDFA (9.7.5): - AMapSearch-NO-IDFA (9.7.5):
- AMapFoundation-NO-IDFA (>= 1.8.0) - AMapFoundation-NO-IDFA (>= 1.8.0)
- WechatOpenSDK-XCFramework (2.0.5)
DEPENDENCIES: DEPENDENCIES:
- AMap3DMap-NO-IDFA (~> 11.1) - AMap3DMap-NO-IDFA (~> 11.1)
- AMapLocation-NO-IDFA (~> 2.11) - AMapLocation-NO-IDFA (~> 2.11)
- AMapSearch-NO-IDFA (~> 9.7) - AMapSearch-NO-IDFA (~> 9.7)
- WechatOpenSDK-XCFramework (~> 2.0.4)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
@ -18,13 +20,15 @@ SPEC REPOS:
- AMapFoundation-NO-IDFA - AMapFoundation-NO-IDFA
- AMapLocation-NO-IDFA - AMapLocation-NO-IDFA
- AMapSearch-NO-IDFA - AMapSearch-NO-IDFA
- WechatOpenSDK-XCFramework
SPEC CHECKSUMS: SPEC CHECKSUMS:
AMap3DMap-NO-IDFA: 393a24abb0451fed2daa4316c8d3d356a395f2be AMap3DMap-NO-IDFA: 393a24abb0451fed2daa4316c8d3d356a395f2be
AMapFoundation-NO-IDFA: f48acbf6e74913dc6744581053f7d984f2432850 AMapFoundation-NO-IDFA: f48acbf6e74913dc6744581053f7d984f2432850
AMapLocation-NO-IDFA: 0fa6e7d5e42e10253f4437424d98966f53760862 AMapLocation-NO-IDFA: 0fa6e7d5e42e10253f4437424d98966f53760862
AMapSearch-NO-IDFA: 8e9d104032990a3b0cab66afb535299887c61047 AMapSearch-NO-IDFA: 8e9d104032990a3b0cab66afb535299887c61047
WechatOpenSDK-XCFramework: ff342ae616bb86df3d236aca38059dfd4bc4a949
PODFILE CHECKSUM: baa972253fcebc312545f7592c48cbba632f1907 PODFILE CHECKSUM: e8cba7a3776cf5c925cda135f2774d8f243899c4
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2

File diff suppressed because it is too large Load Diff

View File

@ -20,4 +20,9 @@ Copyright © 2014 AutoNavi. All Rights Reserved.
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 Generated by CocoaPods - https://cocoapods.org

View File

@ -56,6 +56,17 @@
<key>Type</key> <key>Type</key>
<string>PSGroupSpecifier</string> <string>PSGroupSpecifier</string>
</dict> </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> <dict>
<key>FooterText</key> <key>FooterText</key>
<string>Generated by CocoaPods - https://cocoapods.org</string> <string>Generated by CocoaPods - https://cocoapods.org</string>

View File

@ -1,16 +1,18 @@
ARCHS = $(ARCHS_STANDARD) ARCHS = $(ARCHS_STANDARD)
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 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 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 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_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" 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_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 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" 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) FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"

View File

@ -1,16 +1,18 @@
ARCHS = $(ARCHS_STANDARD) ARCHS = $(ARCHS_STANDARD)
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 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 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 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_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" 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_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 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" 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) FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"

View File

@ -1,14 +1,16 @@
ARCHS = $(ARCHS_STANDARD) ARCHS = $(ARCHS_STANDARD)
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 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 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_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 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" 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) FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"

View File

@ -1,14 +1,16 @@
ARCHS = $(ARCHS_STANDARD) ARCHS = $(ARCHS_STANDARD)
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 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 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_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 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" 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) FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) "${PODS_ROOT}/WechatOpenSDK-XCFramework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework"

View File

@ -0,0 +1,2 @@
${PODS_ROOT}/Target Support Files/WechatOpenSDK-XCFramework/WechatOpenSDK-XCFramework-xcframeworks.sh
${PODS_ROOT}/WechatOpenSDK-XCFramework/WechatOpenSDK.xcframework

View File

@ -0,0 +1 @@
${PODS_XCFRAMEWORKS_BUILD_DIR}/WechatOpenSDK-XCFramework/WechatOpenSDK.framework

View 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"

View 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

View 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

View 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>

View 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>

View 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。

View File

@ -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

View File

@ -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

View File

@ -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>

View 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>

View File

@ -0,0 +1,5 @@
framework module WechatOpenSDK {
umbrella header "WechatOpenSDK.h"
export *
link "WechatOpenSDK"
}

View File

@ -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

View File

@ -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

View File

@ -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>

View 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>

View File

@ -0,0 +1,5 @@
framework module WechatOpenSDK {
umbrella header "WechatOpenSDK.h"
export *
link "WechatOpenSDK"
}

View File

@ -0,0 +1,13 @@
{
"applinks": {
"apps": [],
"details": [
{
"appID": "56GVN5RNVN.com.yuanzhixiang.suixinkan",
"paths": [
"/suixinkan/*"
]
}
]
}
}

View File

@ -0,0 +1,11 @@
{
"applinks": {
"apps": [],
"details": [
{
"appID": "56GVN5RNVN.com.yuanzhixiang.suixinkan",
"paths": ["/suixinkan/*"]
}
]
}
}

View File

@ -7,8 +7,38 @@
import UIKit import UIKit
/// AppDelegate APNs SwiftUI App adaptor /// AppDelegate APNs SDK SwiftUI App adaptor
final class AppDelegate: NSObject, UIApplicationDelegate { 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( func application(
_ application: UIApplication, _ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data

View 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
}
}

View File

@ -20,6 +20,12 @@ struct suixinkanApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
RootView() RootView()
.onOpenURL { url in
WeChatManager.shared.handleOpenURL(url)
}
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
_ = WeChatManager.shared.handleContinueUserActivity(userActivity)
}
} }
} }
} }

View File

@ -0,0 +1,59 @@
# WeChat 模块业务逻辑
## 模块职责
WeChat 模块封装微信 Open SDK 的注册、Universal Link 回跳与分享能力。当前仅接入分享(文本、网页、图片),不调用微信支付 API。
## 配置
- `WeChatConfig`AppID、Universal Link、AASA 部署参考信息
- `Info.plist`URL SchemeAppID`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 访问

View 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)
}
}
}

View 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
}

View 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)
}
}

View 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) {}
}

View 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))
}
}
}

View File

@ -12,6 +12,8 @@ Invite 模块负责首页 `registration_invitation`、`photographer_invite` 和
复制邀请链接时只由 View 层写入剪贴板ViewModel 不关心系统剪贴板状态。 复制邀请链接时只由 View 层写入剪贴板ViewModel 不关心系统剪贴板状态。
点击「分享」弹出 `WeChatShareSheet`,支持分享到微信好友、朋友圈;未安装微信时走系统分享兜底。分享网页使用 `WeChatShareService.shareWebPage`,缩略图优先使用邀请二维码。
## 邀请记录 ## 邀请记录
`InviteRecordViewModel` 提供“邀请记录 / 奖励记录”分段: `InviteRecordViewModel` 提供“邀请记录 / 奖励记录”分段:

View File

@ -13,6 +13,7 @@ struct PhotographerInviteView: View {
@EnvironmentObject private var toastCenter: ToastCenter @EnvironmentObject private var toastCenter: ToastCenter
@Environment(\.globalLoading) private var globalLoading @Environment(\.globalLoading) private var globalLoading
@StateObject private var viewModel = PhotographerInviteViewModel() @StateObject private var viewModel = PhotographerInviteViewModel()
@State private var isPresentingShareSheet = false
var body: some View { var body: some View {
ScrollView { ScrollView {
@ -37,6 +38,17 @@ struct PhotographerInviteView: View {
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.task { await reload(showLoading: true) } .task { await reload(showLoading: true) }
.refreshable { await reload(showLoading: false) } .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 { private var inviteCard: some View {
@ -77,8 +89,11 @@ struct PhotographerInviteView: View {
.frame(height: 44) .frame(height: 44)
} }
Button { Button {
viewModel.copyInviteUrl() guard !viewModel.inviteUrl.isEmpty else {
toastCenter.show("链接已复制,可粘贴分享") toastCenter.show("邀请链接加载中,请稍后重试")
return
}
isPresentingShareSheet = true
} label: { } label: {
Label("分享", systemImage: "square.and.arrow.up") Label("分享", systemImage: "square.and.arrow.up")
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)

View File

@ -20,6 +20,25 @@
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string> <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> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>

View File

@ -4,5 +4,9 @@
<dict> <dict>
<key>aps-environment</key> <key>aps-environment</key>
<string>development</string> <string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:www.zhifly.cn</string>
</array>
</dict> </dict>
</plist> </plist>

View 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)
}
}
}