Hi I'm trying to make an in-app store in my game for players to buy virtual currencies, which is consumables. But I am a bit unsure if my approach is correct or not. So I think it might be good to ask for help here.
After pressing the Buy Button, buyProductIdentifier is called
- (void)buyProductIdentifier:(NSString *)productIdentifier {
NSLog(#"Buying %#...", productIdentifier);
SKPayment *payment = [SKPayment paymentWithProductIdentifier: productIdentifier];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
and then followed up by paymentQueue
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
CCLOG(#"PAYMENT QUEUE CALLED!");
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;
}
}
}
I tried by commenting out the SKPaymentTransactionStateRestored case in order to make the player complete a purchase every time instead of popping up a message saying that "You've already purchased this but it hasn't been downloaded".
Is this approach correct? if not, can you guys give me some hints?
Many thanks.
I don't think it is a code problem.
Are you sure that you you have created the In-App Purchases in iTunes Connect as "Consumable" ?
If you have chosen "Non-Consumable" it is only possible to buy the item once.
Related
When I purchase a previously purchased "Auto-Renewable Subscriptions" in my app, it said
You're currently subscribed to this...
When I clicked the OK, in the delegate of the payment queue..
- (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]; // Why this is called?
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
}
}
The transaction.transactionState returned is SKPaymentTransactionStateFailed instead of SKPaymentTransactionStateRestored, is it normal?
So how do I handle this correctly?
I have the same issue and I don't think there's any way to distinguish this event from other errors (it returns error code SKErrorPaymentCancelled). I think the only way you can handle it is by having a "Restore Purchases" button, and call [[SKPaymentQueue defaultQueue] restoreCompletedTransactions] when the user presses it.
Actually, you can't determine if the user is already subscribed. You should have Subscribe button that new users use to subscribe, and Restore button for already subscribed users.
And when you get SKPaymentTransactionStateFailed you can show a message that suggests to use Restore button in case the user is already subscribed.
Hey guys I am trying to figure out this IAP tutorial I would like to just make one simple app with my content instead of flooding the app store with a lot of smaller apps.
http://www.raywenderlich.com/2797/introduction-to-in-app-purchases
I have been going through this tutorial, I just need someone to help me after the person clicks the check to purchase and the transaction goes through I want it to take them to a new view controller could anyone help me with this?
Thanks in advance :)
Based on your comment i believe once the content is purchased then you want to show a new view
So here is the code for that
1) This is The Main Code for the transaction
- (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];
break;
default:
break;
}
}
}
2) Since you are checking for successful payment : your case is SKPaymentTransactionStatePurchased:
The following method will be called
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
[self provideContent:transaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
3) In the Provide Content Method you have to show your view :
- (void)provideContent:(NSString *)productId
{
if ([productId isEqualToString:kInAppPurchaseProUpgradeProductId])//kInAppPurchaseProUpgradeProductId is your IAP id in iTunes Connect
{
//Your code goes here;
}
}
I am using in-app purchase to buy a set audiobooks.
I am using MKStoreKit wrapper for in-app purchase. my products are of non consumable type.therefore bought only once.
However whenever i press the buy button the message "Do you want to buy one {audiobook name} for {price}" .
how to change this message?
if any one has used MKStoreKit, how to know if the purchase is completed.(I need to change the title of button only if the purchase is complete).
I'm not really sure, but I think you can't customize this alert, it's specific to Apple.
And about how to know if the purchase is completed, I suggest you to take a look at this website, and specially at this method :
- (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];
break;
default:
break;
}
}
}
You also have to call this before ( again, take a look on the website above ) :
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
When the transaction.transactionState is SKPaymentTransactionStatePurchased, this means that the transaction is completed.
Hope it helps
I have just managed to integrate in app purchases into my ios application however i have know run into a problem that i can't really ask google about.
I have an app with 2 products to purchase but once payment is complete i need to differentiate between the 2 products purchased to then fire another method.
please see the paymentQueue method below:
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for(SKPaymentTransaction *transaction in transactions)
{
switch(transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
break;
case SKPaymentTransactionStatePurchased:
//do crediting here
NSLog(#"transactionid = %#",transaction);
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
if(transaction.error.code != SKErrorPaymentCancelled)
{
NSLog(#"Error Encountered");
}
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
}
}
When the SKPaymentStatePurchased is hit it needs to find the initial product that was purchased to then fire the method for the product to credit an account set up on a remote server.
I hope someone can help!
Thanks in advance :)
You can get that from the transaction itself
transaction.payment.productIdentifier
This will give you the product identifier that the user have purchased
I am trying to test my in app purchase (in sandbox) and have the following problem :
The app retrieves the available products successfully and displays them in a table.
The user clicks on "Buy"
The user is asked to enter user name and password (this is my test user).
A confirmation comes back saying on screen that the transcation was succesful.
The problem is that the content is then not downloaded and that the following method doesn't seem to be called :
- (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;
}
}
}
Can anyone help ?
Check whether you added transaction observer
[[SKPaymentQueue defaultQueue]addTransactionObserver:mObserverObject];
Where mObserverObject is the object of class where you have implemented updatedTransactions method.