Ios 应用内购买正确的实现
我在移动应用程序中实现应用内购买时遇到问题 基本上,有时用户会收取两次费用。 此外,当用户在应用程序中被中断时,就像他们被重定向回itunes以完成付款,然后返回到应用程序,他们会看到错误“发生了错误…” 我是否正确实施了应用内购买 这是我的密码: 我做错了什么Ios 应用内购买正确的实现,ios,in-app-purchase,in-app,Ios,In App Purchase,In App,我在移动应用程序中实现应用内购买时遇到问题 基本上,有时用户会收取两次费用。 此外,当用户在应用程序中被中断时,就像他们被重定向回itunes以完成付款,然后返回到应用程序,他们会看到错误“发生了错误…” 我是否正确实施了应用内购买 这是我的密码: 我做错了什么 - (void) myLeftAction { [self performSegueWithIdentifier: @"login" sender: self]; } - (void)viewDidLoad { [su
- (void) myLeftAction {
[self performSegueWithIdentifier: @"login" sender: self];
}
- (void)viewDidLoad {
[super viewDidLoad];
UISwipeGestureRecognizer * recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(myLeftAction)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.view addGestureRecognizer:recognizer];
done = NO;
paymentProcessing = NO;
shownProducts = [NSArray arrayWithObjects: @"com.example.a", @"com.example.b", @"com.example.c", @"com.example.d", nil];
hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = @"Loading";
[self fetchAvailableProducts];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)fetchAvailableProducts {
if ([SKPaymentQueue canMakePayments])
{
NSSet *productIdentifiers = [NSSet setWithObjects: @"com.example.a", @"com.example.b", @"com.example.c", @"com.example.d",nil];
productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:
@"Purchases are disabled in your device. Please enable in-app purchases before continuing." message:nil delegate:
self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
[alertView show];
}
}
- (BOOL)canMakePurchases {
return [SKPaymentQueue canMakePayments];
}
- (void)purchaseMyProduct:(SKProduct*)product {
if ([self canMakePurchases]) {
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addTransactionObserver: self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
else{
paymentProcessing = NO;
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle: @"Purchases are disabled on your device. Please enable in-app purchases before continuing." message:nil delegate: self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
[alertView show];
}
}
-(IBAction)purchase:(id)sender
{
if(done && !paymentProcessing) {
paymentProcessing = YES;
chosenProduct = [validProducts objectAtIndex: [sender tag]];
[self purchaseMyProduct: chosenProduct];
}
}
#pragma mark StoreKit Delegate
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
[self occuringTransaction: transaction];
break;
case SKPaymentTransactionStatePurchased:
[self completeTransaction: transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction: transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction: transaction];
break;
default:
break;
}
}
}
- (void) occuringTransaction:(SKPaymentTransaction *)transaction
{
[hud show: YES];
NSLog(@"Purchasing");
}
- (void) processPurchase: (SKPaymentTransaction *)transaction
{
id<FBGraphUser> fb = [[Auth sharedInstance] user];
NSString * firstName = fb.first_name;
NSString * lastName = fb.last_name;
NSString * email = [fb objectForKey: @"email"];
NSString * facebook_id = fb.id;
PFObject * result = [PFObject objectWithClassName:@"payments"];
result[@"firstName"] = firstName;
result[@"lastName"] = lastName;
result[@"email"] = email;
result[@"facebookId"] = facebook_id;
result[@"package"] = transaction.payment.productIdentifier;
result[@"transactionId"] = transaction.transactionIdentifier;
result[@"transactionError"] = transaction.error.localizedDescription;
NSString *dateString = [NSDateFormatter localizedStringFromDate: transaction.transactionDate
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterFullStyle];
result[@"transactionDate"] = dateString;
result[@"transactionState"] = [NSString stringWithFormat: @"%ld", transaction.transactionState];
[result saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:
@"Purchase is completed successfully. You can now choose the hashtags you want shown in your review on lulu." message:nil delegate:
self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
[alertView show];
NSString * category = @"";
if(
[transaction.payment.productIdentifier isEqualToString: @"com.fakemylulu.player_1"] ||
[transaction.payment.productIdentifier isEqualToString: @"com.fakemylulu.player_3"]
) {
category = @"a";
}
else {
category = @"b";
}
paymentProcessing = NO;
[hud hide:YES];
//push view manually
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
fmHashtagsViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:@"hashtags"];
ivc.category = transaction.payment.productIdentifier;
[self.navigationController pushViewController:ivc animated:NO];
}];
}
-(void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"Completed transaction");
if([transaction.payment.productIdentifier isEqualToString: chosenProduct.productIdentifier]) {
[self processPurchase: transaction];
}
}
-(void)restoreTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"Restored transaction");
[self processPurchase: transaction];
}
-(void)failedTransaction:(SKPaymentTransaction *)transaction
{
[hud hide: YES];
paymentProcessing = NO;
if(transaction.error.code != SKErrorPaymentCancelled)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"An error occured! We could not process your payment. Please try again."
message:[transaction.error localizedDescription]
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:@"OK", nil];
[alert show];
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSInteger count = [response.products count];
if (count>0)
{
validProducts = response.products;
NSUInteger index = 0;
for (SKProduct * x in validProducts)
{
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale: x.priceLocale];
NSString *formattedPrice = [numberFormatter stringFromNumber: x.price];
if([x.productIdentifier isEqualToString: @"com.fakemylulu.romantic_1"]) {
[self.a setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
self.a.tag = index;
}
else if([x.productIdentifier isEqualToString: @"com.fakemylulu.romantic_3"])
{
[self.b setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
self.b.tag = index;
}
else if([x.productIdentifier isEqualToString: @"com.fakemylulu.player_1"])
{
[self.c setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
self.c.tag = index;
}
else if([x.productIdentifier isEqualToString: @"com.fakemylulu.player_3"])
{
[self.d setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
self.d.tag = index;
}
index += 1;
}
done = YES;
} else {
UIAlertView *tmp = [[UIAlertView alloc]
initWithTitle:@"Not Available"
message:@"No products available for purchase"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"Ok", nil];
[tmp show];
}
[hud hide:YES];
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
NSLog(@"Failed to load list of products. %@", error);
UIAlertView *tmp = [[UIAlertView alloc]
initWithTitle:@"Oops"
message:@"There was an error retrieving the list of products. Please try this app again later."
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"Ok", nil];
[tmp show];
}
- (void)dealloc {
if ([SKPaymentQueue canMakePayments]) {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
}
-(无效)我的引用{
[self-PerformsgueWithIdentifier:@“登录”发件人:self];
}
-(无效)viewDidLoad{
[超级视图下载];
UISweepGestureRecognizer*recognizer=[[UISweepGestureRecognizer alloc]initWithTarget:self action:@selector(myLeftAction)];
[识别器设置方向:(UISwipegestureRecognitizerDirectionRight)];
[self.view addgesturecognizer:recognizer];
完成=否;
paymentProcessing=否;
shownProducts=[NSArray数组,其对象为:@“com.example.a”@“com.example.b”@“com.example.c”@“com.example.d”,无];
hud=[MBProgressHUD ShowHUD AddedTo:self.view动画:是];
hud.labelText=@“加载”;
[自取可用产品];
}
-(无效)未收到记忆警告{
[超级记忆警告];
//处置所有可以重新创建的资源。
}
-(无效)获取可用产品{
如果([SKPaymentQueue canMakePayments])
{
NSSet*productIdentifiers=[NSSet setWithObjects:@“com.example.a”、@“com.example.b”、@“com.example.c”、@“com.example.d”、nil];
productsRequest=[[SKProductsRequest alloc]initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate=self;
[产品需求启动];
}
否则{
UIAlertView*alertView=[[UIAlertView alloc]initWithTitle:
@“在您的设备中已禁用购买。请在继续之前启用应用内购买。”消息:无委托:
自取消按钮提示:@“Ok”其他按钮提示:无];
[警报视图显示];
}
}
-(BOOL)可以进行购买{
return[SKPaymentQueue canMakePayments];
}
-(无效)purchaseMyProduct:(SKProduct*)产品{
如果([self-canMakePurchases]){
SKPayment*payment=[SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue]addTransactionObserver:self];
[[SKPaymentQueue defaultQueue]addPayment:payment];
}
否则{
paymentProcessing=否;
UIAlertView*alertView=[[UIAlertView alloc]initWithTitle:@“在您的设备上禁用购买。请在继续之前启用应用内购买。”消息:无委托:自取消按钮提示:@“确定”其他按钮提示:无];
[警报视图显示];
}
}
-(iAction)购买:(id)发件人
{
如果(完成&&!付款处理){
paymentProcessing=是;
chosenProduct=[validProducts objectAtIndex:[sender tag]];
[自购MyProduct:chosenProduct];
}
}
#pragma-mark-StoreKit委托
-(void)paymentQueue:(SKPaymentQueue*)队列更新事务:(NSArray*)事务
{
用于(SKPaymentTransaction*交易中的交易){
开关(transaction.transactionState){
案例SKPaymentTransactionStatePurchasing:
[自发生交易:交易];
打破
案例SKPaymentTransactionStatesPurchased:
[自完成交易:交易];
打破
案例SKPaymentTransactionStateRestored:
[自恢复交易:交易];
打破
案例SKPaymentTransactionState失败:
[自失效交易:交易];
打破
违约:
打破
}
}
}
-(作废)发生交易:(SKPaymentTransaction*)交易
{
[抬头显示器显示:是];
NSLog(“采购”);
}
-(作废)processPurchase:(SKPaymentTransaction*)交易
{
id fb=[[Auth sharedInstance]用户];
NSString*firstName=fb.first\u name;
NSString*lastName=fb.last_name;
NSString*email=[fb objectForKey:@“email”];
NSString*facebook_id=fb.id;
PFObject*result=[pfobjectobjectwithclassname:@“payments”];
结果[@“firstName”]=firstName;
结果[@“lastName”]=lastName;
结果[@“电子邮件”]=电子邮件;
结果[@“facebookId”]=facebook_id;
结果[@“package”]=transaction.payment.productIdentifier;
结果[@“transactionId”]=transaction.transactionIdentifier;
结果[@“transactionError”]=transaction.error.localizedDescription;
NSString*dateString=[NSDateFormatter localizedStringFromDate:transaction.transactionDate
dateStyle:NSDateFormatterShortStyle
时间样式:NSDateFormatterFullStyle];
结果[@“transactionDate”]=dateString;
结果[@“transactionState”]=[NSString stringWithFormat:@“%ld”,transaction.transactionState];
[结果saveInBackgroundWithBlock:^(布尔成功,N错误*错误)
{
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
UIAlertView*alertView=[[UIAlertView alloc]initWithTitle:
@“购买已成功完成。您现在可以选择要在您对lulu的评论中显示的标签。”消息:无代表:
自取消按钮提示:@“Ok”其他按钮提示:无];
[警报视图显示];
NSString*类别=@“”;
如果(
[transaction.payment.productIdentifier IsequalString:@“com.fakemylu.player_1”]||
[transaction.payment.productIdentifier IsequalString:@“com.fakemyluu.player_3”]
) {
类别=@“a”;
}
否则{
类别=@“b”;
}
paymentProcessing=否;
[抬头显示器隐藏:是];
//手动推送视图
UIStoryboard*情节提要=[UIStoryboard storyboard with name