corona接入ios登录和支付
登录文件
SignInWithAppleView.h
#import <AuthenticationServices/AuthenticationServices.h>
NS_ASSUME_NONNULL_BEGIN
@interface SignInWithAppleView : UIViewController <ASAuthorizationControllerDelegate,ASAuthorizationControllerPresentationContextProviding>
{
}
+(SignInWithAppleView *) getInstance; //用来获取实例的方法
-(void)showAppleButton;
-(void)hideAppleButton;
-(void)signInWithApple;
@end
NS_ASSUME_NONNULL_END
SignInWithAppleView.mm
#import "SignInWithAppleView.h"
#import "YCSDKModule.h"
static SignInWithAppleView *instance; //这里声明一下静态实例,方便javascript层调用
@implementation SignInWithAppleView
//获取实例的方法,方便javascript层调用
+(SignInWithAppleView *) getInstance{
return instance;
}
- (void)viewDidLoad {
instance = self;
if (@available(iOS 13.0, *)) {
ASAuthorizationAppleIDButton *appleBtn = [[ASAuthorizationAppleIDButton alloc] initWithAuthorizationButtonType:ASAuthorizationAppleIDButtonTypeSignIn authorizationButtonStyle:ASAuthorizationAppleIDButtonStyleWhiteOutline];
appleBtn.frame = CGRectMake(0, 0, 132, 44);
appleBtn.center = CGPointMake(self.view.center.x, self.view.center.y+250);
appleBtn.cornerRadius = 15;
[appleBtn addTarget:self action:@selector(signInWithApple) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:appleBtn];
}
[self.view setHidden:YES];
}
-(void)showAppleButton API_AVAILABLE(ios(13.0)){
[self.view setHidden:NO];
}
-(void)hideAppleButton API_AVAILABLE(ios(13.0)){
[self.view setHidden:YES];
}
-(void)signInWithApple API_AVAILABLE(ios(13.0)){
if (@available(iOS 13.0, *)) {
ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
ASAuthorizationController *vc = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
vc.delegate = self;
vc.presentationContextProvider = self;
[vc performRequests];
}
}
// ASAuthorizationControllerDelegate 授权回调
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0))
{
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
ASAuthorizationAppleIDCredential *credential = authorization.credential;
NSString *state = credential.state;
NSString *userID = credential.user;
NSPersonNameComponents *fullName = credential.fullName;
NSString *nickname = @"";
if (fullName.nickname != nullptr) {
nickname = fullName.nickname;
}
NSString *email = credential.email;
NSString *authorizationCode = [[NSString alloc] initWithData:credential.authorizationCode encoding:NSUTF8StringEncoding]; // refresh token
NSString *identityToken = [[NSString alloc] initWithData:credential.identityToken encoding:NSUTF8StringEncoding]; // access token
ASUserDetectionStatus realUserStatus = credential.realUserStatus;
NSLog(@"state: %@", state);
NSLog(@"userID: %@", userID);
NSLog(@"fullName: %@", fullName);
NSLog(@"email: %@", email);
NSLog(@"authorizationCode: %@", authorizationCode);
NSLog(@"identityToken: %@", identityToken);
NSLog(@"realUserStatus: %@", @(realUserStatus));
YCSDKModule::onAppleLoginSuccess(userID,nickname,identityToken);
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0))
{
NSString *errorMsg = nil;
switch (error.code) {
case ASAuthorizationErrorCanceled:
errorMsg = @"用户取消了授权请求";
break;
case ASAuthorizationErrorFailed:
errorMsg = @"授权请求失败";
break;
case ASAuthorizationErrorInvalidResponse:
errorMsg = @"授权请求响应无效";
break;
case ASAuthorizationErrorNotHandled:
errorMsg = @"未能处理授权请求";
break;
case ASAuthorizationErrorUnknown:
errorMsg = @"授权请求失败未知原因";
break;
}
NSLog(@"%@", errorMsg);
}
@end
充值文件
RechargeVC.h
#import <StoreKit/StoreKit.h> //注意这个头文件要加入,是内购必须
//#import <conchRuntime.h> //想要oc调用ts的方法,就要加入这个.h
@interface RechargeVC : UIViewController <SKPaymentTransactionObserver,SKProductsRequestDelegate >
{
int buyTypeInt;//定义一个整型变量,.m文件用
}
- (void)viewDidLoad;
- (void) requestProUpgradeProductData;
- (void)RequestProductData:(NSString*)pId;
- (void)doPay:(NSString*)pId;
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
- (void) PurchasedTransaction: (SKPaymentTransaction *)transaction;
- (void) completeTransaction: (SKPaymentTransaction *)transaction;
- (void) failedTransaction: (SKPaymentTransaction *)transaction;
- (void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction;
- (void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error;
- (void) restoreTransaction: (SKPaymentTransaction *)transaction;
- (void)provideContent:(NSString *)product;
- (void)recordTransaction:(NSString *)product;
@end
RechargeVC.mm
#import "RechargeVC.h"
#import "YCSDKModule.h"
@interface RechargeVC ()
@end
@implementation RechargeVC
- (void)viewDidLoad //百度这个oc函数的作用,这里可以理解为整个类的初始化。
{
NSLog(@"---------RechargeVC.viewDidLoad------------");
//内购支付监听,不可或缺,没有这个ios不会给你回调↓↓↓↓
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
-(void) LogBox:(NSString*) msgStr
{
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示" message:msgStr
delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
[alerView show];
}
- (void)doPay:(NSString*)pId
{ //ts调用oc的接口,在游戏ts逻辑代码里需要调用这个oc的函数,怎样调用则在下篇讲解
buyTypeInt = [pId intValue];//要转为int类型,因为之后的函数使用的是这个id的整数值而不是字符串
buyTypeStr = pId ; //记录下来这个id字符串
NSLog(@"---------请求doPay的产品信息------------%@",pId);
if ([SKPaymentQueue canMakePayments]) {
[self RequestProductData:pId];
} else {
[self LogBox:@"不允许程序内付费购买"];
}
}
//请求产品信息
- (void)RequestProductData:(NSString*)pId
//苹果内购IPA函数,向苹果请求你的产品信息,这个函数你只需要根据实际去改switch和case的内容。
{
NSLog(@"---------请求对应的产品信息------------%@",pId);
//[self LogBox:@"---------请求对应的产品信息------------"];
NSArray *product = [[NSArray alloc] initWithObjects:pId,nil];
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
request.delegate=self;//代理 (这一步很重要,可以百度查SKProductsRequest 相关知识).
[request start];
}
//收到的产品信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
//苹果内购IPA函数,苹果返回你的产品信息,这个函数你也只需要根据实际去改switch和case的内容。
NSArray *myProduct = response.products;
NSLog(@"产品Product ID:%@",response.invalidProductIdentifiers);
NSLog(@"产品付费数量: %d", (int)[myProduct count]);
// populate UI
for(SKProduct *product in myProduct){
NSLog(@"product info");
NSLog(@"SKProduct 描述信息%@", [product description]);
NSLog(@"产品标题 %@" , product.localizedTitle);
NSLog(@"产品描述信息: %@" , product.localizedDescription);
NSLog(@"价格: %@" , product.price);
NSLog(@"Product id: %@" , product.productIdentifier);
SKPayment *payment = [SKPayment paymentWithProductIdentifier:product.productIdentifier];
[[SKPaymentQueue defaultQueue] addPayment:payment];
break;
}
}
- (void)requestProUpgradeProductData
{
//苹果的内购IPA函数,这是请求升级的函数
NSLog(@"------请求升级数据---------");
NSSet *productIdentifiers = [NSSet setWithObject:@"com.productid"];
SKProductsRequest* productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
}
//弹出错误信息
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
//[self LogBox:@"-----------弹出错误信息--------------"];//苹果的内购IPA函数,请求商品信息有错误就会调用
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Alert",NULL) message:[error localizedDescription]
delegate:nil cancelButtonTitle:NSLocalizedString(@"Close",nil) otherButtonTitles:nil];
[alerView show];
}
- (void) requestDidFinish:(SKRequest *)request
{
NSLog(@"----------反馈信息结束--------------");
}
- (void) PurchasedTransaction: (SKPaymentTransaction *)transaction
{
NSLog(@"-----PurchasedTransaction----");
NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
[self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易结果
{
//苹果的内购IPA函数、这是支付操作的返回。支付结果成功与失败都在这里做处理
NSLog(@"-----paymentQueue--------");
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
{
NSData *receipt = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]]; // Sent to the server by the device
NSString* encodeString = [receipt base64EncodedStringWithOptions:0];
NSLog(@"encodeString:%@",encodeString);
//交易完成
[self completeTransaction:transaction];
NSLog(@"-----交易完成 --------");
NSLog(@"productIdentifier:%@",transaction.payment.productIdentifier);
NSLog(@"transactionIdentifier:%@",transaction.transactionIdentifier);
YCSDKModule::onAppleRecharge(@"100",encodeString,transaction.transactionIdentifier);
//客户端验证
NSError *error;
NSDictionary *requestContents = @{
@"receipt-data": encodeString
};
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
options:0
error:&error];
if (!requestData) { // 交易凭证为空验证失败
NSLog(@"-----交易凭证为空验证失败 --------");
return;
}
NSLog(@"requestData:%@",requestData);
// NSString *serverString = @"https://sandbox.itunes.apple.com/verifyReceipt";
// NSURL *storeURL = [NSURL URLWithString:serverString];
// NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
// [storeRequest setHTTPMethod:@"POST"];
// [storeRequest setHTTPBody:requestData];
// [storeRequest setTimeoutInterval:30];
// NSURLSession *session = [NSURLSession sharedSession];
// NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:storeRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// //服务器返回的responseObject是gbk编码的字符串,通过gbk编码转码就行了,转码方法如下:
// NSString*gbkStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
// //转码之后再转utf8解析
// NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:[gbkStr dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
// if (jsonDict.allKeys.count > 0) {
// if ([[jsonDict objectForKey:@"code"]intValue] == 0) {
// NSLog(@"-----服务器验签成功 --------");
// NSDictionary * dataDict = jsonDict[@"data"];
// }else if ([[jsonDict objectForKey:@"code"]intValue] == 1){
// NSLog(@"-----服务器验签失败 --------");
// }
// }
// }];
//
// [dataTask resume];
}
break;
case SKPaymentTransactionStateFailed://交易失败
{
[self failedTransaction:transaction];
NSLog(@"-----交易失败 --------");
UIAlertView *alerView2 = [[UIAlertView alloc] initWithTitle:@"提示"
message:@"购买失败,请重新尝试购买" delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
[alerView2 show];
// YCSDKModule::onAppleRecharge(@"102",nil,nil);
// [self callbackToJs:false];//注意看这个函数,oc如何调用js代码的技巧
}
break;
case SKPaymentTransactionStateRestored://已经购买过该商品
{
[self restoreTransaction:transaction];
NSLog(@"-----已经购买过该商品 --------");
// [self callbackToJs:false];
}
break;
case SKPaymentTransactionStatePurchasing: //商品添加进列表
NSLog(@"-----商品添加进列表 --------");
break;
default:
break;
}
}
}
- (void) completeTransaction: (SKPaymentTransaction *)transaction
{
//苹果的内购IPA函数,交易完成会进来这里,这个不用改
NSLog(@"-----completeTransaction--------");
//[self LogBox:@"-----------completeTransaction--------------"];
// Your application should implement these two methods.
NSString *product = transaction.payment.productIdentifier;
if ([product length] > 0) {
NSLog(@"product = %@",product);
NSArray *tt = [product componentsSeparatedByString:@"."];
NSString *bookid = [tt lastObject];
if ([bookid length] > 0) {
[self recordTransaction:bookid];
[self provideContent:bookid];
}
}
// Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
//↓↓↓↓下面的函数都是苹果的内购IPA函数,只需理解就好,不用添加我们自己的代码了↓↓↓↓
//记录交易
- (void)recordTransaction:(NSString *)product
{
NSLog(@"-----记录交易--------%@",product);
}
//处理下载内容
- (void)provideContent:(NSString *)product
{
NSLog(@"-----下载--------%@",product);
}
- (void) failedTransaction: (SKPaymentTransaction *)transaction{
NSLog(@"失败");
//[self LogBox:@"-----------失败--------------"];
if (transaction.error.code != SKErrorPaymentCancelled)
{
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void) paymentQueueRestoreCompletedTransactionsFinished: (SKPaymentTransaction *)transaction
{
}
- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
NSLog(@" 交易恢复处理");
}
- (void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{
NSLog(@"-------paymentQueue----");
//[self LogBox:@"-----------paymentQueue--------------"];
}
#pragma mark connection delegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
switch([(NSHTTPURLResponse *)response statusCode])
{
case 200:
case 206:
break;
case 304:
break;
case 400:
break;
case 404:
break;
case 416:
break;
case 403:
break;
case 401:
case 500:
break;
default:
break;
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"test");
}
- (void)dealloc
{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];//解除监听
}
@end
lua调用OC文件
YCSDKModule.h
#ifndef YCSDKModule_h
#define YCSDKModule_h
#include "CoronaLua.h"
class YCSDKModule
{
public:
static const char * Name();
static int Open( lua_State *L);
static int Finalizer( lua_State *L);
static NSString * convertToJsonData(NSDictionary * dict);
static NSDictionary * dictionaryWithJsonString(NSString * jsonString);
static void onAppleLoginSuccess(NSString * userID,NSString * nickName,NSString * identityToken);
static void onAppleRecharge(NSString * code,NSString * transactionReceipt,NSString * transactionIdentifier);
};
//CORONA_EXPORT int luaopen_plugin_library( lua_State *L );
#endif /* YCSDKModule_h */
YCSDKModule.mm
#import <Foundation/Foundation.h>
#import "YCSDKModule.h"
#import "CoronaRuntime.h"
#import "SignInWithAppleView.h"
#import "RechargeVC.h"
//--------functions----------
//SDK登录(must call)
static int doSDKLogin(lua_State *L )
{
return 0;
}
const char* YCSDKModule::Name()
{
static const char sName[] = "YCSDKModule";
return sName;
}
static SignInWithAppleView * _signInWithAppleView;
static int showAppleButton(lua_State *L )
{
if (_signInWithAppleView) {
[_signInWithAppleView showAppleButton];
}
return 0;
}
static int hideAppleButton(lua_State *L )
{
if (_signInWithAppleView) {
[_signInWithAppleView hideAppleButton];
}
return 0;
}
static int signInWithApple(lua_State *L )
{
if (_signInWithAppleView) {
[_signInWithAppleView signInWithApple];
}
return 0;
}
static RechargeVC * _rechargeVC;
static int pay(lua_State *L )
{
const char *jsonstring = lua_tostring(L, 1);
NSString * _jsonstring = [NSString stringWithUTF8String:jsonstring];
// NSData *jsonData = [_jsonstring dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary * dic = YCSDKModule::dictionaryWithJsonString(_jsonstring);
if (_rechargeVC) {
[_rechargeVC doPay : [dic valueForKey:@"productId"]];
}
return 0;
}
static lua_State * mL = NULL;
int YCSDKModule::Open(lua_State * L)
{
id<CoronaRuntime> runtime = (id<CoronaRuntime>)CoronaLuaGetContext( L );
_signInWithAppleView = [[SignInWithAppleView alloc] init];
[runtime.appViewController.view addSubview:_signInWithAppleView.view];
_rechargeVC = [[RechargeVC alloc] init];
[runtime.appViewController.view addSubview:_rechargeVC.view];
mL = L;
NSLog(@"----YCSDKModule::Open-----");
const luaL_Reg kVTable[] =
{
// {"showAppleButton",showAppleButton},
// {"hideAppleButton",hideAppleButton},
{"signInWithApple",signInWithApple},
{"pay",pay},
{NULL, NULL}
};
luaL_openlib(L, Name(), kVTable, 1);//leave "YCSDK" on top of stack
return 1;
}
NSDictionary * YCSDKModule::dictionaryWithJsonString(NSString * jsonString)
{
if (jsonString == nil) {
return nil;
}
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *parseError = nil;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&parseError];
if(parseError)
{
NSLog(@"json解析失败:%@",parseError);
return nil;
}
return dic;
}
NSString * YCSDKModule::convertToJsonData(NSDictionary * dict) {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:NSJSONWritingSortedKeys
error:&error];
NSString *jsonString= [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
return jsonString;
}
void YCSDKModule::onAppleLoginSuccess(NSString * userID,NSString * nickName,NSString * identityToken)
{
lua_State *L = mL;
const char kvalueKey[] = "appstoreDelegate";
const char kNameKey[] = "name";
const char kNameKey2[] = "message";
NSDictionary *dict2 = @{@"userID" : userID, @"nickName" : nickName, @"identityToken" : identityToken};
NSDictionary *dict = @{@"code" : @"100", @"eventName" : @"login", @"eventData" : dict2};
NSString *jsonString = YCSDKModule::convertToJsonData(dict);
char* str = (char*) [jsonString UTF8String];
NSLog(@"str: %@",jsonString);
lua_newtable( L );
lua_pushstring(L, kvalueKey );
lua_setfield( L, -2, kNameKey );
lua_pushstring(L, str );
lua_setfield( L, -2, kNameKey2 );
CoronaLuaDispatchRuntimeEvent( L, -1 );
}
void YCSDKModule::onAppleRecharge(NSString * code,NSString * transactionReceipt,NSString * transactionIdentifier)
{
lua_State *L = mL;
const char kvalueKey[] = "appstoreDelegate";
const char kNameKey[] = "name";
const char kNameKey2[] = "message";
NSDictionary *dict = @{@"code" : code, @"eventName" : @"pay",@"transactionReceipt" : transactionReceipt,@"transactionIdentifier" : transactionIdentifier};
NSString *jsonString = YCSDKModule::convertToJsonData(dict);
char* str = (char*) [jsonString UTF8String];
// NSLog(@"str: %@",jsonString);
lua_newtable( L );
lua_pushstring(L, kvalueKey );
lua_setfield( L, -2, kNameKey );
lua_pushstring(L, str );
lua_setfield( L, -2, kNameKey2 );
CoronaLuaDispatchRuntimeEvent( L, -1 );
}
corona接入ios登录和支付相关推荐
- Unity接入iOS微信支付
最近因为公司项目需求,需要做iOS的位置支付,所谓初生牛犊不怕虎,博主直接二话不说就像二愣子一样的直接上手做了,虽然之前知道iOS使用OC(object-c)做的开发,到了真正接触了才发现,o my ...
- (unity)新手接入Facebook登录,分享以及google登录,Android,IOS,OC接入篇
最近接Android,IOS的Facebook登录,分享 以及Google登录,分享流程以及遇到的问题整理. 一. Android接入 google登录 第一步,前往 [ firebase] http ...
- 微信开发 - 第三方网站接入微信登录、微信支付时,本地 redirect_uri 参数错误导致无法调试的解决方案(微信开放平台)完美解决每次都需要部署到线上测试,在本地使用本地 ip 就能轻松调试
问题描述 网上的教程都非常乱且无效,本文将站在新手的角度,超级详细的讲解. 本文提供 在微信开放平台,接入微信登录和微信支付时,本文无法调试 redirect_uri 回调错误 的解决方案, 仅需几个 ...
- php支付宝手机网站支付功能,手机网站支付如何接入支付宝简易版支付功能PHP版...
接入支付宝准备工作:(关于账号可以是个体商户也可以是企业账号但必须有营业执照) 1.登录蚂蚁金服开放平台 2.创建应用,应用分类网页应用和移动应用.应用提交审核审核通过后得到appid才能调用相应的 ...
- iOS端移动支付的一些坑
已经很久没有写博客了,最近刚好工作比较轻松,希望能重新捡起来. 那么来简单说一下在iOS上做支付的一些东西 ( ̄▽ ̄*) 这里主要说支付宝和微信这样的第三方支付,像iOS本身的支付不做探究,话说,这个 ...
- Unity接入iOS内购
1.内购种类 consumable:可消费的,如游戏中的金币,用完还可以再购买. non-consumable:不可销毁的,一次购买,永久生效.比如去广告,解锁游戏关卡,这种商品只能购买一次. sub ...
- ios 登录 java 后台,IOS苹果登录sign in with apple后端校验
IOS苹果登录sign in with apple后端校验 最近新开发的app在IOS平台app store connent提审的时候,被拒了,原因是app上如果有接第三方登陆(比如微信,微博,fac ...
- 网易云信集成视频教程(四):如何快速实现iOS登录登出?
上期我们介绍了如何通过SDK实现自定义消息,第四期视频教程我们将教大家如何快速实现iOS系统下IM登录登出. 第四期 如何快速实现iOS登录登出? 8分钟视频手把手教你接入 文档详解 前期准备 1. ...
- Unity:Firebase接入Apple登录
Unity:Firebase接入Apple登录 开启Firebase的登录方式 设置Apple的后台信息 从Assets Store下载 Singn In With Apple Xcode设置 添加A ...
最新文章
- Python获取屏幕分辨率大小
- 如何在C ++中使用数组?
- Python之父,现在成为微软打工人
- 《从零开始学Swift》学习笔记(Day 10)——运算符是“ +、-、*、/ ”吗?
- 用最简单的方式训练史上最强ResNet-50,性能超过魔改结构的ResNeSt
- 03 HttpServletRequest_HttpServletResponse
- 在Spring中嵌入HSQLDB服务器实例
- 希尔排序是一种稳定的排序算法_十大经典排序算法——希尔排序
- 构建小型Linux跟文件系统镜像(Ext2 或 Ext3)
- 数学建模系列--灰色关联分析
- 5分钟学会五笔 (不用背口诀)
- Android通过webservice连接SQLServer 详细教程(数据库+服务器+客户端)
- 一步步教你破解WIFI无线WEP网络密钥
- CAD制图中该怎么查找文字呢?
- 真 彻底 Navicat导入Excel文件表时无法打开的四种解决办法
- LeetCode——110,判断平衡二叉树
- 挖一挖C#中那些我们不常用的东西之系列
- 一文带你怼明白进程和线程通信原理
- 应该担心什么不应该关心什么(做正确的事,把事情做对)
- 项目管理过程组–五大过程组
热门文章
- windows的Listbox控件支持UTF-8字符串
- mysql初始化报错
- 播放器制作初体验:FFMPEG + QT,只播放视频(持续更新,功能逐渐添加)(1)
- signature=d522a0024e7d20dbfee94b566a5dfed5,Severely Fading MIMO Channels
- 男人应该怎样对待女人的十条
- 性格分类--从唐僧四师徒看性格
- caffe2 01 caffe2 win10 vs2017编译(默认CPU版本)
- pytorch转caffe2 之 onnx转caffe2报错的解决方法 ValueError: Don't know how to translate op Unsqueeze
- LeetCode 1049. 最后一块石头的重量 II 做题小结
- 链表基本操作(详解)