- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何将应用内购买添加到 iOS 应用?所有细节是什么,是否有任何示例代码?
这是关于如何向 iOS 应用程序添加应用程序内购买的各种知识
最佳答案
Swift 用户
Swift 用户可以查看 My Swift Answer for this question .或者,查看 Yedidya Reiss's Answer ,将这段 Objective-C 代码转换为 Swift。
Objective-C 用户
这个答案的其余部分是用 Objective-C 编写的
应用商店连接
My Apps
然后单击您想要添加购买的应用程序到 Features
标题,然后选择 In-App Purchases
左边+
中间的图标 non-consumable
.如果您要向用户发送实物,或者给他们一些他们可以多次购买的东西,您可以选择 consumable
. tld.websitename.appname.referencename
这将最有效,例如,您可以使用 com.jojodmo.blix.removeads
cleared for sale
然后选择价格等级为 1 (99¢)。第 2 层为 1.99 美元,第 3 层为 2.99 美元。如果您单击 view pricing matrix
,可以查看完整列表。我建议您使用第 1 层,因为这通常是任何人为删除广告而支付的最高费用。 add language
按钮,然后输入信息。这将全部显示给客户,所以不要放任何你不想让他们看到的东西 hosting content with Apple
选择 否 screenshot for review
现在,我们跳过的所有内容都会回来。 App Store Connect
中注册,所以要有耐心。
linked frameworks and libraries
单击小加号并添加框架
StoreKit.framework
如果您不这样做,应用内购买将不起作用!
.h
(头)文件通过转到 File
> New
> File...
(命令 ⌘ + N)。在本教程的其余部分,此文件将被称为“您的 .h
文件”.h
文件名为 Bridge.h
在主项目文件夹中,然后转到应用程序管理器(蓝色页面状图标),然后在 Targets
中选择您的应用程序部分,然后单击 Build Settings
.找到显示 的选项Swift 编译器 - 代码生成 ,然后设置 Objective-C 桥接头 选项 Bridge.h
#import "MyObjectiveCHeaderFile.h"
,其中 MyObjectiveCHeaderFile
是您在第一步中创建的头文件的名称。因此,例如,如果您将头文件命名为 InAppPurchase.h ,您将添加行 #import "InAppPurchase.h"
到您的网桥头文件。.m
创建一个新的 Objective-C 方法 ( File
) 文件> New
> File...
(命令 ⌘ + N)。将其命名为您在第 1 步中创建的头文件。例如,如果您在第 1 步中调用该文件 InAppPurchase.h,您将调用此新文件 InAppPurchase.m。在本教程的其余部分,此文件将被称为“您的 .m
文件”。.h
中文件:
BOOL areAdsRemoved;
- (IBAction)restore;
- (IBAction)tapsRemoveAds;
接下来,您需要导入
StoreKit
框架加入您的
.m
文件,以及添加
SKProductsRequestDelegate
和
SKPaymentTransactionObserver
在您的
@interface
之后宣言:
#import <StoreKit/StoreKit.h>
//put the name of your view controller in place of MyViewController
@interface MyViewController() <SKProductsRequestDelegate, SKPaymentTransactionObserver>
@end
@implementation MyViewController //the name of your view controller (same as above)
//the code below will be added here
@end
现在将以下内容添加到您的
.m
中文件,这部分比较复杂,建议大家阅读代码中的注释:
//If you have more than one in-app purchase, you can define both of
//of them here. So, for example, you could define both kRemoveAdsProductIdentifier
//and kBuyCurrencyProductIdentifier with their respective product ids
//
//for this example, we will only use one product
#define kRemoveAdsProductIdentifier @"put your product id (the one that we just made in App Store Connect) in here"
- (IBAction)tapsRemoveAds{
NSLog(@"User requests to remove ads");
if([SKPaymentQueue canMakePayments]){
NSLog(@"User can make payments");
//If you have more than one in-app purchase, and would like
//to have the user purchase a different product, simply define
//another function and replace kRemoveAdsProductIdentifier with
//the identifier for the other product
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:kRemoveAdsProductIdentifier]];
productsRequest.delegate = self;
[productsRequest start];
}
else{
NSLog(@"User cannot make payments due to parental controls");
//this is called the user cannot make payments, most likely due to parental controls
}
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
SKProduct *validProduct = nil;
int count = [response.products count];
if(count > 0){
validProduct = [response.products objectAtIndex:0];
NSLog(@"Products Available!");
[self purchase:validProduct];
}
else if(!validProduct){
NSLog(@"No products available");
//this is called if your product id is not valid, this shouldn't be called unless that happens.
}
}
- (void)purchase:(SKProduct *)product{
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (IBAction) restore{
//this is called when the user restores purchases, you should hook this up to a button
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
NSLog(@"received restored transactions: %i", queue.transactions.count);
for(SKPaymentTransaction *transaction in queue.transactions){
if(transaction.transactionState == SKPaymentTransactionStateRestored){
//called when the user successfully restores a purchase
NSLog(@"Transaction state -> Restored");
//if you have more than one in-app purchase product,
//you restore the correct product for the identifier.
//For example, you could use
//if(productID == kRemoveAdsProductIdentifier)
//to get the product identifier for the
//restored purchases, you can use
//
//NSString *productID = transaction.payment.productIdentifier;
[self doRemoveAds];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for(SKPaymentTransaction *transaction in transactions){
//if you have multiple in app purchases in your app,
//you can get the product identifier of this transaction
//by using transaction.payment.productIdentifier
//
//then, check the identifier against the product IDs
//that you have defined to check which product the user
//just purchased
switch(transaction.transactionState){
case SKPaymentTransactionStatePurchasing: NSLog(@"Transaction state -> Purchasing");
//called when the user is in the process of purchasing, do not add any of your own code here.
break;
case SKPaymentTransactionStatePurchased:
//this is called when the user has successfully purchased the package (Cha-Ching!)
[self doRemoveAds]; //you can add your code for what you want to happen when the user buys the purchase here, for this tutorial we use removing ads
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSLog(@"Transaction state -> Purchased");
break;
case SKPaymentTransactionStateRestored:
NSLog(@"Transaction state -> Restored");
//add the same code as you did from SKPaymentTransactionStatePurchased here
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
//called when the transaction does not finish
if(transaction.error.code == SKErrorPaymentCancelled){
NSLog(@"Transaction state -> Cancelled");
//the user cancelled the payment ;(
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
现在你想添加你的代码来处理当用户完成交易时会发生什么,在本教程中,我们使用删除添加,你必须为横幅 View 加载时发生的情况添加自己的代码。
- (void)doRemoveAds{
ADBannerView *banner;
[banner setAlpha:0];
areAdsRemoved = YES;
removeAdsButton.hidden = YES;
removeAdsButton.enabled = NO;
[[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"];
//use NSUserDefaults so that you can load whether or not they bought it
//it would be better to use KeyChain access, or something more secure
//to store the user data, because NSUserDefaults can be changed.
//You're average downloader won't be able to change it very easily, but
//it's still best to use something more secure than NSUserDefaults.
//For the purpose of this tutorial, though, we're going to use NSUserDefaults
[[NSUserDefaults standardUserDefaults] synchronize];
}
如果您的应用程序中没有广告,您可以使用任何其他您想要的东西。例如,我们可以将背景的颜色设为蓝色。为此,我们需要使用:
- (void)doRemoveAds{
[self.view setBackgroundColor:[UIColor blueColor]];
areAdsRemoved = YES
//set the bool for whether or not they purchased it to YES, you could use your own boolean here, but you would have to declare it in your .h file
[[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"];
//use NSUserDefaults so that you can load wether or not they bought it
[[NSUserDefaults standardUserDefaults] synchronize];
}
现在,在您的
viewDidLoad
中的某个地方方法,您将要添加以下代码:
areAdsRemoved = [[NSUserDefaults standardUserDefaults] boolForKey:@"areAdsRemoved"];
[[NSUserDefaults standardUserDefaults] synchronize];
//this will load wether or not they bought the in-app purchase
if(areAdsRemoved){
[self.view setBackgroundColor:[UIColor blueColor]];
//if they did buy it, set the background to blue, if your using the code above to set the background to blue, if your removing ads, your going to have to make your own code here
}
现在你已经添加了所有的代码,进入你的
.xib
或
storyboard
文件,并添加两个按钮,一个是购买,另一个是恢复。挂机
tapsRemoveAds
IBAction
到您刚刚制作的购买按钮,以及
restore
IBAction
到恢复按钮。
restore
action 将检查用户之前是否购买了应用内购买,如果他们还没有购买,则免费为他们提供应用内购买。
Users and Access
然后点击
Sandbox Testers
header ,然后单击
+
左边的符号是
Testers
.您可以随意输入名字和姓氏的内容,并且电子邮件不必是真实的——您只需要能够记住它。输入密码(您必须记住)并填写其余信息。我建议您制作
Date of Birth
使用户年满 18 岁的日期。
App Store Territory
有 在正确的国家。接下来,注销您现有的 iTunes 帐户(您可以在本教程之后重新登录)。
screenshot for review
在 App Store Connect 上。现在取消付款。
My Apps
>
the app you have the In-app purchase on
>
In-App Purchases
.然后点击您的应用内购买,然后点击应用内购买详情下的编辑。完成后,将您刚在 iPhone 上拍摄的照片导入计算机,并将其作为屏幕截图上传以供审核,然后在审核笔记中输入您的
测试用户 电子邮件和密码。这将有助于苹果在审查过程中。
doRemoveAds
就会出错。方法。同样,我建议使用将背景更改为蓝色来测试应用内购买,但这不应该是您实际的应用内购买。如果一切正常,你就可以开始了!当您将其上传到 App Store Connect 时,请确保将应用内购买包含在您的新二进制文件中!
No Products Available
这可能意味着四件事:
kRemoveAdsProductIdentifier
关于ios - 如何将应用内购买添加到 iOS 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19556336/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!