Auto Renewing IAP: latest_receipt field - objective-c

When a user purchases a subscription, I store the receipt on completed transaction on the server alongside a key to identify the user the receipt belongs to. When the app needs to check if the subscription is still active, it queries the server, the server validates the receipt with Apple and returns info to my app wether the subscription is expired or not.
Now the question is:
When the response returns a latest_receipt/_info field, the server should take that receipt and replace the old receipt for future verifications. What happens if there is a gap in the subscription period (e.g. the user subscribed for 1 month, then cancelled, then subscribed again) or the user changed the subscription type (e.g. from 1 month to 3 moths)?
Will the original receipt still validate, and return a latest_receipt/_info field, or do I need to store a new receipt from the new transaction?
I'm really confused on this auto-renewal thing right now, so I'm not even sure if my validation process is right.

I'm not sure about all possibilities you have to verify receipts and maybe it works your way, but we did slightly different and by that don't face your problem.
We store all the receipts on device-side (note that auto-renews result in new receipts as well). Whenever verification is necessary we post the latest device-stored receipt to server where it is verified by calling iTunes. After that the server responds to device about user's rights.
I think that's the way Apple recommends it (or at least this is how I understood Apple's docs).

Related

Receipt does not get updated after purchasing an automatically renewable subscription in a macOS sandbox environment

I am trying to implement StoreKit's ability to have automatically renewable subscriptions in my macOS application.
After reading dozens of pages and checking examples, I understand how everything fits together but fail to get it to work correctly.
What I am trying to do:
As soon as the app starts, check if an active subscription is available by evaluating the local receipt. I'm specifically checking the unavailability of a cancellation date in any of the In-App Purchase field entries of the receipt and whether the subscription expiration date is in the future.
In case no (active) subscription is available, I'm purchasing the subscription using StoreKit's APIs.
Both scenarios are working fine as this flow works perfectly when the subscription is purchased for the first time. However, the receipt does not get updated automatically after the subscription expiration date ends. I'm expecting this receipt to be updated periodically as also shown on Auto-renewing subscription and app receipt. As a result the first step described above fails because the expiration date at some point is in the history and hence, is considered expired.
Two things I find strange:
My SKPaymentTransactionObserver instance only gets called after purchasing the subscription (after a user explicitly buying it). It never gets called when the subscription expires and should automatically renew (as shown in the above blog post);
Explicitly asking my receipt (containing the IAP's expiration date) to be updated using the SKReceiptRefreshRequest API fails by calling it's request:didFailWithError: delegate method. The error object is nil so I cannot see why it fails updating.
I can share code but I have a feeling this is not related to code but instead is some kind of project/environment setting and/or behaviour I do not fully get.
Do you have any suggestions what to try?
After a few days of experimenting I changed the mechanism to use the server-side validation documented on https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1. Obviously this requires a web service running somewhere and makes your environment more complicated but at least things work in a more stable (and secure) way.

Windows 8 IAP Receipt handling server side & consumables?

I am implementing a simple server-side verification for Windows 8 IAPs and I'm slightly baffled on how to handle this. Basically what I do know is I verify the receipt using the code that was included in the example
http://msdn.microsoft.com/en-ie/library/windows/apps/jj649137.aspx
In the example, there is a AppReceipt and ProductReceipt. If I understood it correctly, having a simple IAP to buy, for example, gold in the game, I am only interested in the ProductReceipt. However, I don't understand why "AppReceipt" is included here at all. Is the initial app purchase always included in the receipt or is it an optional field?
So an unified way of making sure the user cannot "cash in" the same receipt twice would simply to save the ProductReceipt ID in the back end database? And that this would be a valid approach for both durables and consumables, of which the latter is not yet implemented?
AppReceipt is just an example that you can ignore. In most cases game will send you receipt (ProductReceipt XML) and you will have to verify it on server side.
If you look at: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/8b3cf68d-897d-4a47-ace0-2c42355bf688/protecting-your-windows-store-app-from-unauthorized-use?forum=windowsstore
You will notice:
The ID of each receipt element is unique per user (and device) and you can validate it on your server to confirm that the transaction is legitimate for that user and not a fraudulent transaction. This is especially valuable when your app has its own authentication mechanism because it allows you to validate that each user that appears to have purchased your app is, in fact, a unique customer.
So if you want to, you can extract IDs from this XML.

Notification of cancellation of auto-renewal for an in-app purchase

I am working on an iPhone app and I want to implement the new model of auto-renewal for in-app purchases. I am able to successfully implement transactions and can even get subscribed to the app, but what if the user cancels the auto renewal subscription?
How will I be able to know that it has been cancelled, and so not continue to allow access (once expired)?
You can find the expiration date of a user's subscription by sending a receipt verification to Apple's servers. Check out figure 1-3 on the In-App Purchase Programming Guide.
Basically the steps are:
On the device, get a transaction receipt for an in-app-purchase. Either one you've saved during a transaction or by calling [SKPaymentQueue restoreCompletedTransactions].
Send that receipt to your server. (This is preferred over trying to do a receipt verification with Apple's servers directly from the app, since that would require you to store your shared secret on the device.)
Send the receipt to Apple's servers from your server, and in the response look for a key named expires_date (expressed in milli seconds since Jan 1, 1970 GMT).
I used this guide to help me on the server side: Verifying Apple App Store Receipts For In App Purchases With PHP and cURL.
There is no way to determine if the user has auto-renewal turned on or off. Apple doesn't give you access to this information. The only way is to wait until the expiration date passes without a renewal.
if the receipt status is 21006 and there is a key named cancellation_date, then it's a cancellation, you can find the new expiration date in that key but it's a formatted date, if you need a better value to parse check for receipt['latest_expired_receipt_info']['cancellation_date_ms'] same as expires_date

Is this processus to pay a user, reliable and safe?

I'm working on a project that require my application to pay the user to his paypal account when he asks it.
Here's how I did it so far:
The (logged) user goes to the Pay page that will list all his Payments (received or not)
He enters his Paypal email and his application (mine) password (for security)
The POST page get a list of all the Payments that have status="UNPAID" for that user and update the status to "WORKING" (to avoid the user to refresh the page before the whole process is done and resend the same amount of money)
We count the total amount to pay in that list (a simple for)
The amount is sent to Paypal via Paypal Adaptive Payment API (request: PAY)
The response is checked, if completed, the list status is set to "COMPLETED", if not, the list is reverted to "UNPAID" (the SQL update is made via a WHERE id IN(x, y, z) in case a second Payment request has been made during that time.
A message is then displayed to the user
But I need your help, I'm in front of one risky problem I'd like to avoid, and I would know how you would do:
If the user hit refresh on the process page, I don't want to send him twice (or more) the amount (The "WORKING" lock is here for that, but what happens if the user hit refresh before I set the lock ?)
Rare possible: what happens if the user hit f5 after the lock "WORKING" is made, but before the request to paypal, and a new payment is received. By following what I did, just one item (the new) would be get and set to WORKING, but all others previous payment would be losts
How would you do? What is the best way to make it to be 100% reliable?
Thanks for your help
Note:
The steps between 4 to 6 is made via a PlayFramework jobs, called with now() and awaiting() the result
you can:
prevent double post via JQuery
use the checkAuthenticity() method to validate the request
do a GET redirect after processing the POST (so they can't submit the same 2 times even by mistake)
do the payment processing asynchronous (see below)
For the payment, instead of calling the job, set the id's of payments in a queue (or table in the database) and a job that runs once per minute that processes that table if it has some data. When the user does the POST you redirect to a page that says that you are processing the payments and will notify if there is some issue. You can notify the user later via a UI warning using comet or via mail.
That way you don't link the request to the processing, and you won't have threading/racing issues, as well as being able to detect stale requests (payments already done) if you do a sequential processing.

How to solve the problem of not being informed of successful payments by the 3rd party system used by my website?

I have a subscription based website that interacts with a 3rd party system to handle the payments. The steps to process a new subscriber registration are as follow:
The subscriber enters his/her details in the subscription form and click on the submit button.
Assuming the details specified are valid, a new record is created in the database to store these details.
The subscriber is then redirected to the website of the 3rd party system (similar to paypal) to process the payment.
Once the payment is succesful, the 3rd party website then redirect the subscriber back to our website.
At this time, I know that the payment was succesful, so the record in the database is updated to indicate that payment has been made successfully.
A problem that I have found occurring quite often is that if a subscriber pays but does not complete the process correctly (e.g. uses the back browser, closes the window), his/her record in the database doesn't get updated about this. Accordingly, I don't know if s/he has paid by just looking the record and need to wait for the report from the 3rd party system to find this out.
How do you solve this problem?
PS. One of the main reasons to store their details into the database before the payment process is done is so they can come back to complete the payment without re-entering their details again. For example, when their credit cards were rejected by the 3rd party system and they need to sort this out with their financial institution which may take a while.
The third-party payment system should inform you of the successful transaction regardless of what the user does.
For example, in PayPal, an IPN (instant payment notification) is sent to your server as POST data to a URL that you specify. Your server then verifies with Paypal that the transaction is genuine, and if so, updates the database record to indicate the subscription is valid. At a point in the future, PayPal may or may not then redirect the user back to your website. (The "may not" can occur in cases such as the user closing their browser, hitting Back, or jumping to a new URL)
Note that this "conversation" between Paypal and your server is independent of the user's session - it is a "private conversation" between you and PayPal about that user's transaction.
Obviously there can be communications outages and server failures, so if Paypal does not get the validation request from your server immediately it will periodically send retries to your server to ensure that the transaction is eventually completed.
If your payment system doesn't have at least some basic mechanism for ensuring transaction reliability, then choose a different provider. Chances are that they do, but you will have to implement things correctly on your server to be sure that the system works properly.
P.S. It is quite normal to require a user to log in (and thus be registered in the database) before they initiate any financial transaction. You need to gather all the relevant information before they go to purchase, as after the purchase you have no way of guaranteeing that they will return to you to provide any further information.