All right. 1
So, now that we've created the delegate method for our table view so that we can detect when the user 2
presses that last row that gets more quotes, 3
we can call a function called buyPremiumQuotes and it's in this function that we're going to trigger 4
the in-app purchase. 5
So first of all, we're going to create a new constant that is going to record our product ID and that 6
ID is the same as the ID that we put into App Store Connect under Features, In-App Purchases. 7
We've got that product called Premium Quotes and this is the product ID that we want. 8
So I'm just going to copy it over to our code here and I'm going to put it in just as a simple string. 9
Now, this is the ID that we're going to use to hit up the Apple App Store to tell it what we want to 10
buy, 11
and so that the user gets charged the right amount, namely, whatever it is that we've put in in here, and 12
that they can purchase and that the funds go towards ourselves as our developer account. 13
So, now that we've got what we want to purchase, how are we going to purchase that, 14
well, in order to implement in-app purchases, the framework that we're going to be using is something 15
called a StoreKit and StoreKit has all of the functionality that we'll need to implement in-app purchases 16
for virtual products. 17
So once we've added StoreKit, then we'll be able to tap into all of its functions and attributes. 18
So inside our buyPremiumQuotes function, the first thing we need to check is whether if the user can 19
actually make a purchase because if they're on a phone that has parental controls enabled, then we won't 20
be able to get them to make any sort of in-app purchases, 21
and this is the way that Apple tries to keep your kids from running up the credit card bill and buying 22
thousands of dollars worth of in-app purchases in Clash of Clans, for example. 23
So the way to check that is something called 24
SKPaymentQueue, and this is the queue of payment transactions to be processed by the App Store. 25
And it has a method called canMakePayments, and this method returns a Boolean, 26
so true or false, as to whether if the user is allowed to make payments, and that's exactly what we need 27
to know. 28
So if this returns true, then, in that case, the user can make payments. And if it returns false or rather 29
else, then can't make payments. 30
So it's a good idea while we're testing our app to just put in a print statement that says, 31
"User can't make payments." That we go. 32
But if they can make payments, then we can go ahead and trigger the next step of our in-app purchase request 33
which is to create a new request. 34
So we're going to use a let to create a constant called paymentRequest and this is going to be a new 35
object created from the class called SKMutablePayment which is a mutable request to the App Store 36
to process payment for additional functionality namely in in-app purchase. 37
So this is where we're creating a new in-app purchase request basically. 38
And we're going to specify that this paymentRequest is for the product with productIdentifier of whatever 39
it is that we had up here which is saved under this constant called productID. 40
So we're saying that we're making a request to purchase a new in-app purchase and the product that we 41
want is the one that has the productID that we've specified. 42
And finally, we tap into that SKPaymentQueue again and we grab the default queue and we add this 43
payment request to the queue. 44
So paymentRequest goes in there, and that's it. 45
That's all the code that we need in order to implement our in-app purchase. 46
Now, this is not the end of the tutorial, however, because we still need to figure out how we can detect 47
when a payment has been successful so that we know that we can give them access to the extra information, 48
or that when a payment is failed so that we don't accidentally give them access to all of our premium 49
features, even though they haven't paid for it. 50
So in order to do that, we need to read a little bit about this payment business. 51
So if you hold down alt and click on SKPaymentQueue, there's a quick talk of how this all works. 52
So the summary is that this is a queue of payment transactions to be processed by the App Store. 53
So, of course, you can add multiple paymentRequests to this queue, so you can purchase, you know, five in-app 54
purchases in the same go if you wanted to. 55
And the discussion part says that the payment queue communicate with the App Store and presents a user 56
or a user interface, so a pop up, so that they can enter the password and authorize the payment. 57
Now, to process a payment, first, and at least one observer object which is called SKOaymentTransactionObserver 58
to the queue, and then add a payment object which is what we've done here for the item that 59
the user wants to purchase. 60
And after the payment is fulfilled, the queue updates the transaction object, and then calls the observer 61
so that it tells us that the transaction has been updated and whether if it failed or succeeded. 62
So the next thing that we need to implement is this SKPaymentTransactionObserver 63
and this has a delegate method, 64
so we have to add the protocol of SKPaymentTransactionObserver which contains a set of methods that 65
processes transactions, unlocks purchase functionality, and continue promoted in-app purchases. 66
So that basically means that when we add this observer, then once the payment goes through and the user 67
types in their user name and password for the App Store and it was successful, then we'll get a message 68
back telling us that it was successful, or if it failed, then we'll get a message saying it failed or a 69
whole bunch of other things. 70
So as soon as I add this protocol, you can see we get an error. 71
And it says that in order to conform to this protocol, you have to add the delegate method. 72
So let's get it to add it automatically. 73
And the only delegate method that's required is this one which is paymentQueue updated transactions. 74
So this delegate method will inform us when the transactions have been updated in the paymentQueue. 75
So let's move this down a little bit to the parts where we've got our in-app purchase methods, and we're going 76
to put it over here, and I'm going to just delete this placeholder that says code. 77
Now, remember that whenever you add a new protocol and you want to use a delegate method, you have to 78
declare a class as the delegate. 79
So we want to declare this current class, the QuoteTabVviewController as the delegate who's going 80
to receive the messages from the SKPaymentTransactionObserver when the transaction status changes. 81
So inside viewDidLoad, 82
we're going to add ourselves as the delegate. And the code for this is simply 83
SKPaymentQueue.default which is the default queue that we're using to process our payment request 84
.add. And this adds an observer. 85
So notice that when I write .add, there's actually two methods that this object has. 86
One is add observer and the other one is add the payment to be processed. 87
Now, the only difference they have is the names of the parameters. And in Swift, 88
this is perfectly legal. 89
You can have the same method name, but as long as the parameter names for the methods are different, then 90
they are treated as completely separate methods. 91
So, if you're coming from other programming languages, for example, C or C++, this should be familiar to 92
you as well. 93
So the one that we want is to add an observer. 94
And this takes an object that is a SKPaymentTransactionObserver. And by declaring ourselves 95
as conforming to this protocol and implementing the required delegate method, then we are qualified to 96
set ourselves or this current class as the observer. 97
So now whenever any changes happens to the payment transaction, it's going to contact our 98
QuoteTableViewController and it's going to try and find this delegate method to trigger an update. 99
Now, if you Allt click on this paymentQueue function or search for it in Google or StackOverflow or 100
Apple Docs, you can see that we have a summary which tells an observer, which is this current class, that 101
one or more transactions have been updated. 102
So it gets triggered every single time the transaction status changes. 103
But not only that, the application should process each transaction by examining the transaction's 104
transactionState property. 105
So this is the transactions that we get back and it has a property, apparently, called transactionState. 106
And if we click on transactionState, it tells us the whole bunch of transaction States we can 107
get back. 108
Namely, one is purchasing, being purchased by the aApp Store. Purchased, so successfully process payment. 109
The money is going to hit your developer account and you are ready to release the premium product. 110
Failed, so the transaction failed and you can check the property to see what happened. 111
Or restored which is where, say, if a user buys a new phone and they download the apps all over again, 112
they want to be able to restore the previous in-app purchases that they've made. 113
So we're going to check for each of these cases in the transaction state inside this delegate method. 114
Now, remember, previously, I said the paymentQueue can contain any number of transactions. 115
So if you were to purchase three in-app purchases all in one go, then all the transactions will get piled 116
into this array of SKPaymentTransactions. 117
So in order to check each of these transactions, we're going to have to loop through it. 118
So we're going to say "for transaction in transactions," and that transactions comes from here. 119
This one is just the variable we're creating to loop through these transactions. 120
And for every transaction in all of the array of transactions, we're going to check if the current transaction 121
that we're looping through .transactionState is equal to .purchased, and that means that it was 122
a successful purchase. 123
So User 124
payment successful 125
Now, else if the transaction.transactionState was actually something like .failed, then in that 126
case, something bad happened and payment failed. 127
Now, this can also include if they click the cancel button and they didn't want to go ahead with the 128
payment anymore. 129
So now we have two if statements, one when it's successful and one when the transaction failed. 130
So let's go ahead and add a print statement to show in the console when we test our app which case it 131
is. 132
So print "Transaction successful!" Print "Transaction failed!" 133
So, now we're ready to test our in-app purchases, and remember what I said before that you have to test 134
it on a physical iPhone or iPad device. 135
It can't be in the simulator. 136
It doesn't work and it won't tell you that it's not working or give you any logical errors. 137
You just have to know that you have to use a physical device. 138
Now, the other problem is that I've set this is in-app purchase for my premium quotes to be .99 cents 139
and I don't really want to pay 99 cents every single time I want to test my app, 140
right? 141
So I don't want to use my normal Apple ID. 142
So what's the workaround? 143
Well, we can create a sandbox user that's just for testing these payments. 144
So in the next lesson, 145
that's exactly what we're going to be doing and we're going to be testing our app and seeing whether 146
if it work.