0 1 00:00:01,140 --> 00:00:08,430 Now, in the last lesson, we've written the code that's required to trigger a paymentRequest in the payment 1 2 00:00:08,430 --> 00:00:10,600 queue to the Apple App Store, 2 3 00:00:10,890 --> 00:00:17,700 and we specified the product that we want to purchase or the user wants to purchase. And we set up 3 4 00:00:17,760 --> 00:00:19,010 this paymentQueue 4 5 00:00:19,030 --> 00:00:27,150 updated transaction delegate method which observes for any changes in the paymentQueue and lets us know 5 6 00:00:27,420 --> 00:00:31,990 when a transaction is purchased and successful or when it's failed. 6 7 00:00:32,040 --> 00:00:38,250 So, now we are going to create a sandbox user in order to test this without having to pay every single 7 8 00:00:38,250 --> 00:00:39,660 time we test it. 8 9 00:00:39,690 --> 00:00:41,690 So let's go into, again, 9 10 00:00:41,730 --> 00:00:46,020 Apo Store Connect and we're going to go to Users and Roles here. 10 11 00:00:46,140 --> 00:00:49,290 So just click on this dropdown list to head over there. 11 12 00:00:49,560 --> 00:00:57,840 And if you head over to sandbox testers, then you can create some new testers by clicking on this plus 12 13 00:00:57,840 --> 00:01:01,260 button. Now, rather awkwardly, 13 14 00:01:01,260 --> 00:01:09,900 Apple actually enforces very strong data validation in the sandbox user creation and I really wish they 14 15 00:01:09,900 --> 00:01:10,280 didn't, 15 16 00:01:10,280 --> 00:01:16,170 because often, I'm forced to create 10 or 20 of these users. And for every single one of them, you have 16 17 00:01:16,170 --> 00:01:19,680 to fill out pretty much every single field. 17 18 00:01:19,680 --> 00:01:24,640 So it doesn't really matter what you give the first name or the last name. 18 19 00:01:24,660 --> 00:01:31,440 I usually just write something like Test Test. But the email has to be unique and it has to be a real 19 20 00:01:31,460 --> 00:01:36,000 email, which is quite difficult, if you're not a professional spammer. 20 21 00:01:36,150 --> 00:01:39,690 How would you have access to even 10 emails that you own? 21 22 00:01:39,690 --> 00:01:41,090 So here's a trick. 22 23 00:01:41,460 --> 00:01:47,630 If you have a Gmail address that is, say, Angela@gmail.com, 23 24 00:01:47,640 --> 00:01:54,160 this, unfortunately, is not my email because I wasn't there fast enough, need to be an earlier adopter. 24 25 00:01:54,390 --> 00:02:02,100 But if, say, this was your e-mail, then Gmail actually has a really neat thing called address alias, and 25 26 00:02:02,100 --> 00:02:06,590 what allows you to do is just before the at sign, 26 27 00:02:07,050 --> 00:02:12,570 you can add a plus and you can write some things like news letter, 27 28 00:02:12,670 --> 00:02:13,110 right? 28 29 00:02:13,380 --> 00:02:18,410 And you can use this e-mail for all of the news letters that you sign up to, 29 30 00:02:18,570 --> 00:02:22,230 and you can filter on this incoming e-mail address in your Gmail inbox. 30 31 00:02:22,230 --> 00:02:29,070 But even though it looks a little bit weird, it still goes to your e-mail address, your inbox. 31 32 00:02:29,070 --> 00:02:32,710 So Angela@gmail.com's inbox in this case. 32 33 00:02:32,730 --> 00:02:39,510 Now, what I often like to do is sometimes when I sign up to something I'm not really that sure about, 33 34 00:02:39,810 --> 00:02:48,480 you know, say, if I sign up to American Express, right? I will actually sign up with my e-mail, plus the 34 35 00:02:48,570 --> 00:02:51,310 address that I signed up to at gmail.com. 35 36 00:02:51,540 --> 00:02:58,510 And this is a really easy way to know which businesses are selling your e-mails for money and to just 36 37 00:02:58,510 --> 00:03:06,240 a protest. But this is a really neat trick. And this is helpful in our case because now you have an infinite 37 38 00:03:06,240 --> 00:03:13,860 variety of unique email addresses, so you can just keep creating new aliases for every single one of 38 39 00:03:13,860 --> 00:03:14,520 your testers. 39 40 00:03:14,520 --> 00:03:17,130 Now, there's just one caveat. 40 41 00:03:17,130 --> 00:03:24,180 The main e-mail for your e-mail alias cannot already belong to an Apple ID. 41 42 00:03:24,180 --> 00:03:30,030 So, say, if you sign up to your Apple ID with this e-mail address, you can't use an alias on it. 42 43 00:03:30,030 --> 00:03:31,380 It doesn't work. 43 44 00:03:31,380 --> 00:03:38,460 But if you haven't used this e-mail, this Gmail address of any Apple IDs, then you can do this quite easily. 44 45 00:03:38,460 --> 00:03:46,890 Now, another option, if you don't have many e-mails that you can use for your sandbox testers is use 45 46 00:03:46,980 --> 00:03:53,460 something like maildrop.cc, and this allows you to just generate a random mailbox, and it'll be able 46 47 00:03:53,460 --> 00:03:57,090 to receive messages, and you'll be able to verify the account. 47 48 00:03:57,090 --> 00:04:02,760 But you, obviously, don't monitor it and it doesn't have a painful creation process. 48 49 00:04:02,850 --> 00:04:07,970 But what it does mean though is that it is a public account. 49 50 00:04:08,070 --> 00:04:13,350 So if you go to some of the ones that somebody might have already used, say, John@maildrop.cc, 50 51 00:04:13,830 --> 00:04:18,950 then you can see that this has all of the stuff that they've previously signed up to, 51 52 00:04:18,950 --> 00:04:21,000 and there's a lot of spam in here, 52 53 00:04:21,030 --> 00:04:21,350 right? 53 54 00:04:21,480 --> 00:04:26,460 So if you use any of these account on maildrop.cc, remember that it's completely public. Do not 54 55 00:04:26,460 --> 00:04:31,110 sign up for anything that has your private details in it using the service. 55 56 00:04:31,110 --> 00:04:37,590 But if you're using it for just testing, then it doesn't really matter because there's nothing sensitive 56 57 00:04:37,590 --> 00:04:39,600 that's going to be sent to it. 57 58 00:04:39,600 --> 00:04:44,730 So in my case, I'm just going to generate a new e-mail address on our website domain 58 59 00:04:44,760 --> 00:04:52,200 that is called tester134@londonappbrewery.com. 59 60 00:04:52,260 --> 00:04:56,800 And the password, rather awkwardly, also has very strict security rules, 60 61 00:04:57,000 --> 00:05:05,490 so you need one capital letter and some numbers and it needs to be quite long, so come up with some sort 61 62 00:05:05,490 --> 00:05:06,830 of combination for that. 62 63 00:05:10,060 --> 00:05:14,220 And the secret question and secret answer, you can take it very seriously if you want to, 63 64 00:05:14,230 --> 00:05:15,660 but I tend to just write 64 65 00:05:15,650 --> 00:05:17,080 TesterA. 65 66 00:05:17,110 --> 00:05:18,100 TesterQ 66 67 00:05:18,280 --> 00:05:23,290 because it has to be more than six characters or something like that. And date of birth, of course, just 67 68 00:05:23,290 --> 00:05:25,860 some random numbers. And App Store territory, 68 69 00:05:25,870 --> 00:05:31,190 you should choose the App Store that you're testing device is currently signed into. 69 70 00:05:31,210 --> 00:05:37,630 So, for example, I live in the UK, so my App Store, my native App Store, that my testing device is normally 70 71 00:05:37,630 --> 00:05:43,610 set to is the UK territory, so I'll go and find United Kingdom and add that in there. 71 72 00:05:43,900 --> 00:05:50,170 If your device is normally signed into United States territory, then be sure to select that. And once 72 73 00:05:50,170 --> 00:05:57,790 you're done, go ahead and click save, and you'll have this brand-new sandbox user ready to go. 73 74 00:05:57,790 --> 00:06:05,590 So, now we are ready to run our app onto our physical device which is the phone, and we're going to make 74 75 00:06:05,590 --> 00:06:12,610 sure that the team is selected so that it will side load, and I'm going to plug in my phone through USB, 75 76 00:06:13,000 --> 00:06:20,260 and I'm going to select my device as the destination and run this app. 76 77 00:06:20,270 --> 00:06:25,700 So, now while the app is running, I'm going to click on the home button and I'm going to go into Settings. 77 78 00:06:26,540 --> 00:06:34,370 And inside Settings, I'm going to scroll down to iTunes and App Store, and I'm going to scroll all the 78 79 00:06:34,370 --> 00:06:37,340 way down to the bottom where it says sandbox account. 79 80 00:06:37,580 --> 00:06:43,460 And here I'm going to click on it and a sign out of any previous sandbox accounts you've got going on 80 81 00:06:43,850 --> 00:06:48,010 and I'm going to sign in with that new user that I just created. 81 82 00:06:48,170 --> 00:07:01,370 He was called tester134@londonappbrewery.com and I'm going to enter the password of that 82 83 00:07:01,370 --> 00:07:04,790 user that I set up just now, and click Sign In. 83 84 00:07:05,030 --> 00:07:11,400 So now my sandbox account is showing that my tester134 is now signed in, 84 85 00:07:11,630 --> 00:07:15,940 and I'm going to go ahead and relaunch that app InspoQuotes. 85 86 00:07:15,950 --> 00:07:19,380 Now, you can rerun it from Xcode as long as you haven't force quit the app. 86 87 00:07:19,400 --> 00:07:22,360 This is still a active session. 87 88 00:07:22,400 --> 00:07:28,700 So, now if I click on Get More Quotes, then you can see I get this pop-up "Enter your password 88 89 00:07:28,710 --> 00:07:33,540 to confirm your In-App Purchase of 1 Premium Quotes for 0.99p.. 89 90 00:07:33,620 --> 00:07:42,630 So I'm going to enter my password for my test user and I'm going to click Buy. And now, we wait for a 90 91 00:07:42,630 --> 00:07:50,000 little bit, and you can see that I get a pop-up that says, "You are all set. Your purchase was successful" in 91 92 00:07:50,120 --> 00:07:53,720 the app. And in the debug console, 92 93 00:07:53,810 --> 00:08:00,330 I get that print statement "Transaction successful" which means that if you look inside quoteTableViewController, 93 94 00:08:00,350 --> 00:08:07,880 the part where that transaction successful gets printed is inside this if statement, 94 95 00:08:08,150 --> 00:08:10,780 if transaction.transactionState == .purchased. 95 96 00:08:10,790 --> 00:08:13,640 So a successful transaction, then print this. 96 97 00:08:13,730 --> 00:08:19,730 So,now you can see that we can change the quote inside this block to give the user whatever it is that 97 98 00:08:19,730 --> 00:08:24,710 they paid for: extra coins, extra fish, extra quotes 98 99 00:08:24,890 --> 00:08:28,260 in this case. Then we can implement that right here. 99 100 00:08:28,400 --> 00:08:30,850 So way, it's actually working. 100 101 00:08:30,860 --> 00:08:37,160 Now, there's just one thing to remember that if you make a purchase that's been successful with a sandbox 101 102 00:08:37,160 --> 00:08:47,390 user, that user won't be able to make the same purchase again if your in-app purchase is a non-consumable product. 102 103 00:08:47,510 --> 00:08:53,990 So remember that when we created our in-app purchase Premium Quotes, we created it as a non-consumable 103 104 00:08:53,990 --> 00:08:58,370 product because the users shouldn't need to buy it multiple times. 104 105 00:08:58,370 --> 00:09:05,210 They should only pay once to get rid of the ads or pay wants to get the extra quotes and never again. 105 106 00:09:05,210 --> 00:09:10,650 And the way that Apple implements it is that your sandbox users can only purchase a non-consumable 106 107 00:09:10,650 --> 00:09:13,940 product once in their whole lifetime. 107 108 00:09:13,940 --> 00:09:19,610 They can restore purchases that they bought before, but they can't keep buying the same non-consumable 108 109 00:09:19,910 --> 00:09:20,780 product. 109 110 00:09:20,780 --> 00:09:27,680 So this is why you end up creating loads and loads of test users and sandbox accounts, 110 111 00:09:27,680 --> 00:09:32,260 and this is also why you need some alternative emails in order to do this. 111 112 00:09:32,270 --> 00:09:40,450 So, now we have written the code that implements the basic functionality of creating a new paymentRequest 112 113 00:09:40,460 --> 00:09:46,960 and adding it to the payment queue to ask the user for their password and to purchase that in-app purchase. 113 114 00:09:47,090 --> 00:09:52,540 And we've got this delegate method that listens for when that successful and when it's not. 114 115 00:09:52,580 --> 00:09:59,000 And we created a sandbox user that can allow us to test these payments without having to cover and 115 116 00:09:59,090 --> 00:10:06,030 we can activate blocks of our code when the transaction is successful or when the transaction has failed. 116 117 00:10:06,380 --> 00:10:13,170 Now, once the payments have been successful or they have failed, we need to end our transaction. 117 118 00:10:13,250 --> 00:10:16,250 So we're not still holding onto the same transaction. 118 119 00:10:16,490 --> 00:10:24,020 So inside the if statement when our transaction has completed, we're going to write SKPaymentQueue 119 120 00:10:24,170 --> 00:10:24,620 .default() 120 121 00:10:24,620 --> 00:10:34,100 .finishTransaction, and the transaction that we want to terminate is the current transaction 121 122 00:10:34,520 --> 00:10:42,080 that is in question. And we're going to copy that code over to here as well. 122 123 00:10:42,080 --> 00:10:48,800 And finally, even though we are checking to see if there was an error, we're not actually being very explicit 123 124 00:10:48,830 --> 00:10:50,650 with what the error was. 124 125 00:10:50,720 --> 00:10:57,050 And with SKPaymentQueue and StoreKit it, we can actually get a really accurate description of what the 125 126 00:10:57,050 --> 00:10:57,760 error was. 126 127 00:10:57,770 --> 00:11:01,510 So it can guide our debugging if we do get any problems. 127 128 00:11:01,640 --> 00:11:09,220 So let's use optional binding to say if let error = transaction.error. 128 129 00:11:09,470 --> 00:11:19,400 So if there was an error, if it's not nil, then let errorDescription = error.localizedDescription. 129 130 00:11:19,400 --> 00:11:25,220 So instead of just printing "Transaction failed!" I'm going to move that down here and we're going to print 130 131 00:11:25,580 --> 00:11:29,180 "Transaction failed due to error." 131 132 00:11:29,480 --> 00:11:33,610 And I'm going to insert that errorDescription into here. 132 133 00:11:33,680 --> 00:11:36,990 So, now that's a little bit more comprehensive. 133 134 00:11:37,100 --> 00:11:41,820 And that will be really useful when we do have some payment issues that we're testing. 134 135 00:11:41,900 --> 00:11:47,320 So that, in a nutshell, is how you implement in-app purchases. In the next lesson, 135 136 00:11:47,330 --> 00:11:54,320 we're going to enable the user to be able to access the rest of the premiumQuotes in addition to the 136 137 00:11:54,320 --> 00:11:58,940 free quotes after the purchase has been successful. 137 138 00:11:58,940 --> 00:12:02,230 So for all of that and more, I'll see you on the next lesson.