前提:
Xcode12.5+下载真机调试dmg
微信SDK(WechatOpenSDK)1.8.7.1
QQ互联SDK(TencentOpenApi(Lite)_3.5.3.62)
生成app应用时需要勾选Associated Domains ,不然在后面编译的时候会报错的。(我记得xcode10是在本地就可以勾选的,但是xcode12没有这个开发)
part1 -->微信朋友列表和朋友圈<--
1)网站上上传apple-app-site-association文件,为了兼容版本,可以在根目录和子目录”.well-know”都传一份,格式大概是这样的
假设开发组id=“AB12345678”;产品的bundle id=“com.xxx.app” 网站=https://123test.com
为了简单起见,一个站点只一个APP,所以paths直接填*,如果多个app需要慎重填写。
{
"applinks": {
"apps": [
],
"details": [
{
"appID": "AB12345678.com.xxx.app",
"paths": [
"*"
]
}
]
}
}
2)申请微信移动应用APPID
填写bundle id(com.xxx.app)和网站Universal Link(Free tests that take you further! | 123test.com),还有App Store id,这个需要在appstoreconnect.apple.com先创建一个产品(实际上填写了一些产品信息),然后保存就可以得到一个id,申请下来一个微信的appid(wx12345678)。
下载WechatOpenSDK,然后是配置info.list
LSApplicationQueriesSchemes 添加两个值
weixin
weixinULAPI
这些值主要为了跳转调用使用
Signing&Capabilities 中Associatied Domains
添加applinks:123test.com (这个对微信分享没影响,但是对qq分享有影响的)
最后就是代码:
启动完成后就是注册这个(微信支付公用这行代码的)
[WXApi registerApp:@“wx12345678” universalLink:@"https://123test.com"]
发起分享
WXMediaMessage *message = [WXMediaMessage message];
message.title = @“标题”;
message.description = @“描述”;
//图片记得压缩一下64k以内(安卓好像是32k)
if (image) {
[message setThumbImage:image];//分享图片,使用SDK的setThumbImage方法可压缩图片大小
}
// 多媒体消息中包含的网页数据对象
WXWebpageObject *webpageObject = [WXWebpageObject object];
// 网页的url地址
webpageObject.webpageUrl = link; //链接
message.mediaObject = webpageObject;
SendMessageToWXReq *sendReq = [[SendMessageToWXReq alloc] init];
sendReq.bText = NO;
sendReq.message = message;
sendReq.scene = flag; //0=好友列表 1=朋友圈 2=收藏夹 3=。。。看记录
[WXApi sendReq:sendReq completion:^(BOOL success) {
//OK
}];
回调(返回app)在AppDelegate.m里面处理:
//设置Universal Links系统回调
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler{
//NSLog(@"userActivity.webpageURL=%@",userActivity.webpageURL);
//NSLog(@"restorationHandler=%@",restorationHandler);
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb])
{
NSURL *webpageURL = userActivity.webpageURL; //https://123test.com/wx12345678/
if (webpageURL) {
if ([webpageURL.absoluteString rangeOfString:@“wx12345678”].length)
{ // 微信
BOOL flag=[WXApi handleOpenUniversalLink:userActivity delegate:(id)self];
[WXApi handleOpenURL:url delegate:self]; //旧版兼容,可以忽略
return flag;
}
}
}
return YES;
}
上面是微信分享部分代码,下面提一下微信支付几个坑。
微信支付的前提是上面的微信分享已经调通。
客户端上能做不多,第一步发起订单请求,然后服务器根据订单向微信发起支付请求,返回一串类似这样的json字符串
{"return_code":"SUCCESS","return_msg":"OK","result_code":"SUCCESS","mch_id”:”…,”appid”:”…”,”nonce_str”:”…”,”sign”:”..”.,”prepay_id”:”…”,”trade_type":"APP"}
然后就是通过SDK向微信APP传递信息,打开微信。在分享成功的基础上,微信支付几乎水到渠成的。但是还有2个坑。
1.“商户传入的appid参数不正确,请联系商户处理”:第一步在微信开发应用账户上申请支付功能,和商家id关联;第二步就是服务器上签名要用到移动应用的appid,所以安卓和iOS需要区分处理。有人说订单2小时失效也是这样提示,貌似不对,我用新版微信测试过,上面明明白白提示“订单超时失效”之类的。
2.“签名验证失败”:我们第一次是因为使用了移动应用的appid和AppSecret,行不通(就算改了sign也一样失败,确定是不能用这个AppSecret),后来和安卓等使用统一的AppSecret,还有就是将回传的sign值改为其他值(就是不能与回传的那个字符串相同),然后就成功支付。。。
part2 -->QQ和QQ空间分享<—-
QQ互联上申请APPID,假设拿到URL Schema=“QQ12345678xx” Universal Link=“https://123test.com/qq_conn/1234567899/” 实际上APPID=“1234567899” 实际上在info的URL Types里面只需要填写“tencent+appid”(tencent1234567899)就可以了,那个“QQ12345678xx”根本没用上,保险起见也加上吧。
修改网站apple-app-site-association文件
{
"applinks": {
"apps": [
],
"details": [
{
"appID": "AB12345678.com.xxx.app",
"paths": [
"*"
]
},
{
"appID": “AB12345678.com.xxx.app",
"paths": [
"*",
"/qq_conn/1234567899/*”
]
}
]
}
}
修改info.list:
LSApplicationQueriesSchemes 添加值
mqq
mqqapi
mqqwpa
mqqbrowser
mqqOpensdkSSoLogin
mqqopensdkapiV2
mqqopensdkapiV3
mqqopensdkapiV4
mqqopensdknopasteboard
wtloginmqq2
mqzone
mqzoneopensdk
mqzoneopensdkapi
mqzoneopensdkapi19
mqzoneopensdkapiV2
mqqapiwallet
mqqopensdkfriend
mqqopensdkdataline
mqqgamebindinggroup
mqqopensdkgrouptribeshare
tencentapi.qq.reqContent
tencentapi.qzone.reqContent
(新版实际调试中,我只发现用到mqqapi和mqqopensdknopasteboard,其他的都是网上抄过来的)
QQ互联一定要用到: (Xcode12.5)Signing&Capabilities->Associated Domains添加一项“applinks:123test.com”,这里一般要按照申请qq互联时候填写的Universal Link去掉https头。注意applinks:后面不要自作主张加//。这里出错了,可能会提示“设备未授权(错误码25105)”,就算其他的都对了,怎么找也找不到问题的时候,看看这段话。出现错误码25105需要怀疑的地方有4个:1.网站上的apple-app-site-association;2.applinks的填写;3.info.list里面LSApplicationQueriesSchemes的设置;4.info.list的URL Types(前面提到,授权应该和这个没多大关系吧,和那个相应关系更大)
代码也是三段式的。
1. 注册授权
[[TencentOAuth alloc] initWithAppId:QQAPPID andUniversalLink:QQULink andDelegate:(id)delegate]; //这个返回值需要保存下来的,可以考虑做一个全局变量
2. 分享
QQApiNewsObject *newsObj = [QQApiNewsObject
objectWithURL:[NSURL URLWithString:link]
title:title
description:desc
previewImageURL:thumb_url];
SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:newsObj];
if (mode == 0)
{
QQApiSendResultCode code = [QQApiInterface sendReq:req];
//NSLog(@"QQ好友列表分享 - %d",code);
if (code==EQQAPISENDSUCESS) {
}
}
else if (mode == 1)
{
QQApiSendResultCode code = [QQApiInterface SendReqToQZone:req];
//NSLog(@"QQ空间分享 - %d",code);
if (code==EQQAPISENDSUCESS) {
}
}
3.处理回应
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler;
{
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb])
{
NSURL *webpageURL = userActivity.webpageURL;
NSLog(@"webpageURL=%@",webpageURL);
if (webpageURL) {
if([webpageURL.scheme isEqualToString:[NSString stringWithFormat:@"tencent%@",QQAPPID]]) //这个没跑进来,我随便写的
{
return [TencentOAuth HandleUniversalLink:webpageURL];
}
else if([TencentOAuth CanHandleUniversalLink:webpageURL]) //这个判断好像不行,我随便写的
{
return [TencentOAuth HandleUniversalLink:webpageURL];
}
}
}
return NO;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
//SDK3.5.1点返回app后是跳到这里的url格式是 “tencent{appid}://response_from_qq?xxxxxx”
if ([url.scheme isEqualToString:[NSString stringWithFormat:@"tencent%@",QQAPPID]])
{
return [QQApiInterface handleOpenURL:url delegate:(id)self];
}
}
- (void)onReq:(id)req
{
//else if([[req class] isSubclassOfClass:[QQBaseReq class]])
//{
// //处理来自QQ的请求
//}
}
- (void)onResp:(id)resp
{
//if([[resp class] isSubclassOfClass:[QQBaseReq class]])
//{
// // 处理来至QQ的响应
//}
}
QZone分享后直接自动返回;QQ分享需要选择点击返回或留在QQ上。
如果想知道放弃分享,通过
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
能提取到的:
tencent{qq-appid}://response_from_qq?error_description=dGhlIHVzZXIgZ2l2ZSB1cCB0aGUgY3VycmVudCBvcGVyYXRpb24=&appsign_bundlenull=2&source=qq&source_scheme=mqqapi&error=-4&version=1
将描述base64解一下,得到“the user give up the current operation”。
分享成功大概是这样的:
tencent{qq-appid}://response_from_qq?appsign_bundlenull=2&source=qq&source_scheme=mqqapi&error=0&version=1
如果只是分享,不管结果,理论上是不用处理
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler; //QQ互联 SDK3.5.1没有跑这里来
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options; //QQ互联 SDK3.5.1跑这里来
- (void)onReq:(id)req ;
- (void)onResp:(id)resp;
总结有点混乱,表达有点欠缺。。。