1 首先 自动集成 搭建环境 网址搭建环境 点击
URL Schemes :wx537cf8aac45b25df
- 在 info .plist文件中 添加
LSApplicationQueriesSchemes | array类型(添加一个元素 string类型 Value: weixin) |
---|---|
请求网络数据 | YES |
3 导入第三方框架
WeChatSDK1.8.3_NoPay |
---|
JSONKit |
MBProgressHUD |
4 AppDelegate.m中代码
//
// AppDelegate.m
// 练习
//
// Created by 与 on 2018/10/15.
// Copyright © 2018 嗯. All rights reserved.
//
#import "AppDelegate.h"
#import "WeChatSDK1.8.3_NoPay/WXApi.h"
#define WXAppID @"wx537cf8aac45b25df"
#define WXAppsecretID @"879024ead533e25662a7fa7ca1dcc940"
@interface AppDelegate ()<WXApiDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//向微信注册
[WXApi registerApp:WXAppID];
return YES;
}
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
return [WXApi handleOpenURL:url delegate:self];
}
//通过code 值获取accesstoken
-(void)getAccessTokenwithCode:(NSString *)code{
NSString *urlStr=[NSString stringWithFormat:@"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%@&secret=%@&code=%@&grant_type=authorization_code",WXAppID,WXAppsecretID,code];
//开启子线程
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//把字符串封装为网址对象
NSURL *url =[NSURL URLWithString:urlStr];
//从网址中获取网络数据并封装为字符串
NSString *coneStr=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
//将conessStr转为二进制数据
NSData *urlData=[coneStr dataUsingEncoding:NSUTF8StringEncoding];
if (!urlData) {
NSLog(@"获取accessToken失败");
return ;
}
//json解析
id jsonData =[NSJSONSerialization JSONObjectWithData:urlData options:NSJSONReadingAllowFragments error:nil];
NSString *access_token = jsonData[@"access_token"];
NSString *openid = jsonData[@"openid"];
[self getWXUserInfoWithAccessToken:access_token poenID:openid];
});
}
// 根据accessToken和openid获取微信用户信息
-(void)getWXUserInfoWithAccessToken:(NSString *)token poenID:(NSString *)openID{
NSString *urlStr =[NSString stringWithFormat:@"https://api.weixin.qq.com/sns/userinfo?access_token=%@&openID=%@",token,openID];
NSURL *url =[NSURL URLWithString:urlStr];
//从网址中获取网络数据并封装为字符串
NSString *coneStr=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
//将conessStr转为二进制数据
NSData *urlData=[coneStr dataUsingEncoding:NSUTF8StringEncoding];
if (!urlData) {
NSLog(@"获取accessToken失败");
return ;
}
id jsonData =[NSJSONSerialization JSONObjectWithData:urlData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"微信用户信息%@",jsonData);
//调用后台接口 将微信信息保存
[[httpserrece getinstance] WXAuthorLoninWithWXUserinfo:jsonData registration_id:@"" device_id:@"123456789" parent_id:@"1" completion:^(id _Nonnull data, BOOL ok) {
if (!ok) {
return ;
}
NSLog(@"微信授权登陆成功:%@",data);
NSString *sacreKey=data[@"data"][@"secret_key"];
SaveUserToken(sacreKey);
NSString *secret_key = data[@"a9ce71c313108ebedaa1ce694e296e40" ];
SaveUserToken(secret_key);
//回主线程发通知
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"LongIn" object:nil];
});
}];
}
//如果微信对app 授权登陆 或分享触发的回掉
-(void)onResp:(BaseResp *)resp{
//如果是 授权登陆 h如果是分享
if ([resp isKindOfClass:[SendAuthResp class]]) {
//授权失败
if (resp.errCode!=0) {
return ;
}
//授权成功获得 code值
SendAuthResp *authresp =(SendAuthResp *)resp;
NSLog(@"%@",resp);
NSString *code=authresp.code;
//获取access接口
[self getAccessTokenwithCode:code];
}
else if ([resp isKindOfClass:[SendMessageToWXResp class]]){
}
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
return [WXApi handleOpenURL:url delegate:self];
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
5 ViewController.m中 代码
脱线 头像 网名 按钮(2个连)
//
// ViewController.m
// 练习
//
// Created by 与 on 2018/10/15.
// Copyright © 2018 嗯. All rights reserved.
//
#import "ViewController.h"
#import "loginViewController.h"
#import "httpserrece.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imgv;
@property (weak, nonatomic) IBOutlet UILabel *lab; //网名
@property (weak, nonatomic) IBOutlet UIButton *btn; //登陆按钮
- (IBAction)pppp:(id)sender;
@end
@implementation ViewController
- (IBAction)btn:(id)sender {
}
- (void)viewDidLoad {
[super viewDidLoad];
//头像照片 圆角
self.imgv.clipsToBounds=YES;
self.imgv.layer.cornerRadius = CGRectGetWidth(self.imgv.frame)/2;
self.imgv.layer.masksToBounds=YES;
self.imgv.layer.borderColor=[UIColor orangeColor].CGColor;
self.imgv.layer.borderWidth=1.0;
//找一张默认图片
self.imgv.image=[UIImage imageNamed:@"03"];
//点击手势
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(headimageDidPress:)];
//开启图片与用户交互
self.imgv.userInteractionEnabled =YES;
[self.imgv addGestureRecognizer:tap];
//将推出登陆 按钮隐藏
self.btn.hidden=YES;
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if (Had_Login) {
//显示退出按钮
self.btn.hidden=NO;
//请求网络数据
[[httpserrece getinstance] getUserHomePageCompletion:^(id _Nonnull data, BOOL ok) {
if (!ok) {
return ;
}
NSLog(@"控制器中的Data=%@",data);
}];
}else{
self.btn.hidden=YES;
self.lab.text=@"立即登陆";
self.imgv.image=[UIImage imageNamed:@"03"];
}
}
-(void)headimageDidPress:(id)sender{
if (!Had_Login) {
loginViewController *log=[loginViewController new];
[self presentViewController:log animated:YES completion:nil];
}
}
- (IBAction)pppp:(id)sender {
}
@end
6 创建类 httpserrece 继承自 NSobjc
7 httpserrece.h 代码
//
// httpserrece.h
// 练习
//
// Created by 与 on 2018/10/16.
// Copyright © 2018 嗯. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef void(^URLDataPass) (id,BOOL);
@interface httpserrece : NSObject
//遍历构造器 便于外部使用方法实例化一个对象
+(instancetype)getinstance;
//获取个人信息
-(void)getUserHomePageCompletion:(URLDataPass)done;
//退出登陆接口
-(void)LogoutCompletion:(URLDataPass)done;
//微信授权登陆接口
-(void)WXAuthorLoninWithWXUserinfo:(NSDictionary *)userinfo
registration_id:(NSString *)jpushID
device_id:(NSString *)device
parent_id:(NSString *)parentid
completion:(URLDataPass)done;
@end
NS_ASSUME_NONNULL_END
8 httpserrece.m 代码
在这里插入代//
// httpserrece.m
// 练习
//
// Created by 与 on 2018/10/16.
// Copyright © 2018 嗯. All rights reserved.
//
#import "httpserrece.h"
@implementation httpserrece
#pragma mark -----------------私有方法------------
-(void)showMBhudwithmassgae:(NSString *)msg{
//创建提示框
MBProgressHUD *hud=[[MBProgressHUD alloc]initWithWindow:g_wind];
[g_wind addSubview:hud];
hud.removeFromSuperViewOnHide=YES;
//设置为文本样式提示框
hud.mode=MBProgressHUDModeText;
//报错信息
hud.labelText=msg;
[hud show:YES];
//显示后两秒后隐藏
[hud hide:YES afterDelay:2.0];
}
//POST请求方法
-(void)POSTwithParemString:(NSString *)Str
completion:(URLDataPass)completion{
// 1 将网址封装
NSURL *url=[NSURL URLWithString:@"http://buluokes.huimor.com/api"];
// 2 请求对象
NSMutableURLRequest *req =[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
// 3 设置post请求方式
[req setHTTPMethod:@"POST"];
// 4 将所有的f参数拼成字符串
NSString *paramStr =Str;
// 5 将参数字符串 转换为二进制数据
NSData *parnmsdata =[paramStr dataUsingEncoding:NSUTF8StringEncoding];
// 6 将参数放入设置为请求体
[req setHTTPBody:parnmsdata];
// 7 回话对象
NSURLSession *sesstion =[NSURLSession sharedSession];
//请求网络数据
NSURLSessionDataTask *task = [sesstion dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 如果服务器发生错误 链接不上或服务器宕机 请求超时
if (error !=nil) {
dispatch_async(dispatch_get_main_queue(), ^{
[self showMBhudwithmassgae:@"服务器错误"];
});
completion(error,NO); //olock函数调用
return ;
}
NSError *jsonerror =nil;
//json 解析
id jsonData =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonerror];
//如果jsonerror不等于nil
if (jsonerror !=nil) {
dispatch_async(dispatch_get_main_queue(), ^{
[self showMBhudwithmassgae:@"网络数据错误"];
});
completion(jsonerror,NO); //olock函数调用
return ;
}
completion(jsonData,YES); //olock函数调用
}];
//开启异步请求网络数据
[task resume];
}
#pragma mark ----------------开放方法------------
+(instancetype)getinstance{
httpserrece *httplins =[[httpserrece alloc] init];
return httplins;
}
-(void)WXAuthorLoninWithWXUserinfo:(NSDictionary *)userinfo
registration_id:(NSString *)jpushID
device_id:(NSString *)deviceID
parent_id:(NSString *)parentid
completion:(URLDataPass)done{
NSString *userinfoStr=[userinfo JSONString];
NSString *params =[NSString stringWithFormat:@"method=%@&wx_info=%@&device=%@&device_id=%@&parent_id=%@®istration_id=%@&user_token=%@",
@"app.passport.wxauthorizelogin",
userinfoStr,
@"ios",
deviceID,
parentid,
jpushID,
User_Token];
[self POSTwithParemString:params completion:^(id _Nonnull data, BOOL ok) {
if (!ok) {
done(data,NO);
return ;
}
done(data,YES);
}];
}
//退出登陆
-(void)LogoutCompletion:(URLDataPass)done{
NSString *params =[NSString stringWithFormat:@"method=%@&user_token=%@",@"app.passport.signout",User_Token];
[self POSTwithParemString:params completion:^(id _Nonnull jsonData, BOOL ok) {
if (!ok) {
return ;
}
NSLog(@"%@",jsonData);
}];
}
//个人信息
-(void)getUserHomePageCompletion:(URLDataPass)done{
//1
NSString *params=[NSString stringWithFormat:@"method=%@&user_token=%@",@"app.user.homepage",User_Token];
//2 函数定义
[self POSTwithParemString:params completion:^(id _Nonnull jsonData, BOOL success) {
if (!success) {
done(jsonData,NO);
return ;
}
done(jsonData,YES);
NSLog(@"%@",jsonData);
}];
}
@end
码片
9 创建 loginViewController.h类 (勾选 试图 对勾)
loginViewController.h.m 托出界面 包含 退出按钮 登陆按钮
//
// loginViewController.m
// 练习
//
// Created by 与 on 2018/10/15.
// Copyright © 2018 嗯. All rights reserved.
//
#import "loginViewController.h"
#import "WeChatSDK1.8.3_NoPay/WXApi.h"
@interface loginViewController ()
- (IBAction)weChatlogin:(id)sender;
- (IBAction)BackPress:(UIButton *)sender;
@end
@implementation loginViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(weChatlogin:) name:@"LongIn" object:nil];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (IBAction)weChatlogin:(id)sender {
//构造SendAuthReq结构体
SendAuthReq* req =[[SendAuthReq alloc]init];
req.scope = @"snsapi_userinfo";
req.state = @"123";
//第三方向微信终端发送一个SendAuthReq消息结构
[WXApi sendReq:req];
}
- (IBAction)BackPress:(UIButton *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
10 创建 全局PCH 文件 demo.pch 代码
//
// demo.pch
// 练习
//
// Created by 与 on 2018/10/15.
// Copyright © 2018 嗯. All rights reserved.
//
#ifndef demo_pch
#define demo_pch
// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.
//判断有无s登陆大宏
#define Had_Login ([[NSUserDefaults standardUserDefaults]objectForKey:@"accessToken"] == nil ? NO : YES)
// 获取持久化的token
#define User_Token Had_Login ? [[NSUserDefaults standardUserDefaults]objectForKey:@"accessToken"]:@""
// 将获取到的user_token进行持久化
#define SaveUserToken(token) [[NSUserDefaults standardUserDefaults]setObject:token forKey:@"accessToken"]; \
[[NSUserDefaults standardUserDefaults]synchronize];
// 退出登录
#define LogoutRemoveToken [[NSUserDefaults standardUserDefaults]removeObjectForKey:@"accessToken"];\
[[NSUserDefaults standardUserDefaults]synchronize];
#import "MBProgressHUD/MBProgressHUD.h"
#import "JSONKit/JSONKit.h"
#import "httpserrece.h"
#define g_wind [UIApplication sharedApplication].delegate.window
#endif /* demo_pch */
如果还不行 参考 第三方 文档 配置 搭建环境
!!!!! 真机测试 (使用)
!
prefix $(SRCROOT)/你的工程名/PCH文件名.pch (参照图片)