- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我尝试在我的应用程序上进行应用程序内购买。但是当我尝试在设备中运行它时没有结果。
我的代码如下:
这是获取产品信息和购买产品所需的对象。
.h
#import <Foundation/Foundation.h>
#import "StoreKit/StoreKit.h"
#define kProductsLoadedNotification @"ProductsLoaded"
#define kProductPurchasedNotification @"ProductPurchased"
#define kProductPurchaseFailedNotification @"ProductPurchaseFailed"
@interface StoreManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver>
@property (strong, nonatomic) NSMutableSet * _purchasedProducts;
@property (strong, nonatomic) NSArray *products;
@property (strong, nonatomic) NSSet *_productIdentifiers;
@property (strong, nonatomic) SKProductsRequest *request;
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers;
- (void)requestProducts;
- (void)buyProduct:(SKProduct *)product;
- (void)completeTransaction:(SKPaymentTransaction *)transaction;
- (void)restoreTransaction:(SKPaymentTransaction *)transaction;
- (void)failedTransaction:(SKPaymentTransaction *)transaction;
- (void)provideContent:(NSString *)productIdentifier;
- (void)recordTransaction:(SKPaymentTransaction *)transaction;
@end
.m
#import "StoreManager.h"
@implementation StoreManager
@synthesize _purchasedProducts;
@synthesize products;
@synthesize _productIdentifiers;
@synthesize request;
// Initializes the request object with the set of product identifiers.
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers{
self = [super init];
if(self){
self._productIdentifiers = productIdentifiers;
NSMutableSet *purchased = [NSMutableSet set];
for(NSString * productId in self._productIdentifiers){
BOOL flag = [[NSUserDefaults standardUserDefaults] boolForKey:productId];
if(flag){
[purchased addObject:productId];
NSLog(@"Previously purchased: %@", productId);
}
NSLog(@"Not purchased: %@", productId);
}
self._purchasedProducts = purchased;
}
return self;
}
// Request info for the product.
- (void)requestProducts{
self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:self._productIdentifiers];
self.request.delegate = self;
[self.request start];
}
// Request fail.
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
NSLog(@"Fail request! Error: %@", error);
}
// Delegate method - did receive responce.
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
self.products = response.products;
self.request = nil;
[[NSNotificationCenter defaultCenter] postNotificationName:kProductsLoadedNotification object:self.products];
}
// Buy product.
- (void)buyProduct:(SKProduct *)product{
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
// Payment transactions
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
}
}
- (void)recordTransaction:(SKPaymentTransaction *)transaction {
// TODO: Record the transaction on the server side...
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
[self recordTransaction: transaction];
[self provideContent: transaction.payment.productIdentifier];
NSLog(@"completeTransaction...");
}
- (void)provideContent:(NSString *)productIdentifier {
NSLog(@"Toggling flag for: %@", productIdentifier);
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier];
[[NSUserDefaults standardUserDefaults] synchronize];
[self._purchasedProducts addObject:productIdentifier];
[[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"restoreTransaction...");
[self recordTransaction: transaction];
[self provideContent: transaction.originalTransaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if (transaction.error.code != SKErrorPaymentCancelled)
{
NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
}
[[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
@end
单例对象
.h
#import <Foundation/Foundation.h>
#import "StoreManager.h"
@interface StoreWrapper : StoreManager
+ (StoreWrapper *)sharedInstance;
@end
.m
#import "StoreWrapper.h"
@implementation StoreWrapper
static StoreWrapper *gInstance = NULL;
- (id)init{
NSSet *productId = [NSSet setWithObjects:@"com.company.sb.pack1", @"com.company.sb.pack5", nil];
self = [super initWithProductIdentifiers:productId];
if(self){
}
return self;
}
+ (StoreWrapper *)sharedInstance{
if(gInstance == NULL){
gInstance = [[self alloc] init];
}
return gInstance;
}
@end
在我的 View Controller 中我接下来调用:
- (void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productsLoaded:) name:kProductsLoadedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productPurchased:) name:kProductPurchasedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(productPurchaseFailed:) name:kProductPurchaseFailedNotification object: nil];
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [reach currentReachabilityStatus];
if (netStatus == NotReachable) {
NSLog(@"No internet connection!");
} else {
NSLog(@"Internet connection available!");
// Request product
[[StoreWrapper sharedInstance] requestProducts];
[activIndicator startAnimating];
}
[super viewWillAppear:animated];
}
为此,我发送请求以使用我的产品 ID 从服务器获取产品信息
下一步,如果产品已加载,我的类会收到有关此的通知(并调用以下方法)。
- (void)productsLoaded:(NSNotification *)notification{
[activIndicator stopAnimating];
[activIndicator setHidden:YES];
NSArray *arr = [notification object];
for(int i = 0; i < [arr count]; i++){
SKProduct *product = [[StoreWrapper sharedInstance].products objectAtIndex:i];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(0, i*55, 100, 50)];
[btn setTitle:product.localizedTitle forState:UIControlStateNormal];
[btn setTag:i];
[btn addTarget:self action:@selector(buyProduct:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
}
我为按钮添加选择器 buyProduct(如上所示)
- (void)buyProduct:(id)sender{
NSLog(@"sender tag %d", [sender tag]);
int tag = [sender tag];
SKProduct *product = [[StoreWrapper sharedInstance].products objectAtIndex:tag];
[[StoreWrapper sharedInstance] buyProduct:product];
}
对于 iPhone Simulator,这项工作很棒,但在设备上我没有任何按钮,因为没有下载 response.products。
调用了所有方法,但委托(delegate)方法*- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse )response 不返回response.products。
感谢您的宝贵时间,感谢您的回答!
最佳答案
为了解决这个问题,我重置了我的设备并重新运行了应用程序。
这对我有帮助。
关于ios - 应用内购买不适用于设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9193770/
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 6年前关闭。 Improve t
我们有一个专有的销售系统,我们已经使用了一段时间了。最近我们添加了“购买”方面,以便我们可以比较匹配产品的平均购买/销售价格以及查看库存状况。 在 MySQL 中,我有 2 个表:tblPurchas
在查看 Paypal 文档以寻找针对这种情况的解决方案后,我一头雾水。我想要的是一种让购物车订阅(定期付款)和购买商品的方法。有没有一种方法可以解决这个问题,或者我是否必须做一些自定义的事情(如果我使
我想知道是否可以使用youtube api获取可购买或可租借的电影列表。当我转到youtube网站并登录到Google帐户时,我可以看到要购买的电影及其价格。 我想在我的应用程序(http://www
我使用 JavaScript 购买 SDK 和 Node.js。 const fetch = require('node-fetch'); const shopify = require('shopi
我购买了三个不同期限的不同订阅。我已经配置了测试账户,我可以进行测试购买。对于这些购买,谷歌不向我收费,但它们看起来非常像真实的。购买成功后,应用内结算会向我发送一些有关我的购买的数据,例如 pack
我目前正在实现应用内购买,并且刚刚阅读了一些帖子,说需要恢复购买按钮,否则苹果将拒绝应用。 我不想在我的 UI 设计中添加第二个按钮。 所以我的问题是... 有没有办法检查用户之前是否进行过应用内购买
我的应用中有多个项目。我有两个设备。如果我在这些设备中的第一个上购买商品,然后尝试在另一个设备上购买相同的商品,我不能。(Google play intent 显示消息 - 商品已拥有!然后它崩溃了.
有没有办法检测何时通过应用商店为您的应用进行了购买? 检测应用内购买似乎很容易(即我们的服务器可以收到通知),但是对于直接购买有没有办法做到这一点? 如果没有,是否有一些用户的唯一标识符(例如购买时通
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我计划在用户使用该应用程序成功扫描二维码时为应用内购买提供折扣。我知道无法为现有商品提供折扣。我打算以折扣价添加另一件商品。有没有人以前有过使用这种方法的经验? 提前致谢 最佳答案 没有办法直接这样做
我很好奇其他商店在基础应用程序框架方面做了什么?我将应用程序框架视为能够提供额外或扩展的功能以提高基于它构建的应用程序的质量。 有各种开箱即用的框架,例如 Spring(或 Spring.NET)等。
我们正在开发一款使用非续订订阅 IAP 模型的应用。在沙盒中测试订阅购买流程时,我们看到弹出两 strip 有“购买”按钮的消息。 显示第一条消息和产品信息:“您想以 xx.xx 美元购买一个订阅吗?
我的老板购买了 Microsoft 365,它包含三种产品。他现在要求我设计一个管理系统,比如员工自助服务门户。我特此寻求有关从哪里开始或使用哪种产品的建议,因为我对此很陌生。 我尝试了一些研究,发现
我的老板购买了 Microsoft 365,它包含三种产品。他现在要求我设计一个管理系统,比如员工自助服务门户。我特此寻求有关从哪里开始或使用哪种产品的建议,因为我对此很陌生。 我尝试了一些研究,发现
我刚刚了解了IAP Cracker的存在,并试图找出在我的应用中验证IAP购买的最佳方法。 我无法确定的是IAP Cracker是否可以处理“消耗性”商品。如果没有,我没有什么可担心的。 这是维护/验
我正在编写一个允许应用内购买的简单应用。我已经使用 SKU 代码 android.test.purchased 进行了测试,一切正常。 我进入我的 google play 控制台,创建了一个应用程序,
我即将启动一个应用程序,该应用程序将包含多个“应用程序内购买”。 我想做的是有一种方法可以提供少量免费的“应用内购买”来选择评论家等人。 在 apple 框架内有没有办法做到这一点,如果没有,我可以采
所以我在这个网站上工作,用户可以在该网站上发布他们的商品,其他用户可以将一些商品添加到他们的购物车并在线购买。 我考虑的流程是这样的: 商家发布商品及其信用卡/ Paypal 信息。 买家将(来自不同
我对这个主题进行了广泛的研究,但我的知识仍然很模糊。我正在寻找一个简单站点的基本 DV,但我看到每个在线 SSL 都具有三个级别, Root->Intermidiate (充当 Root 的代理)和我
我是一名优秀的程序员,十分优秀!