"The receipt could not be authenticated" - should it be checked again? - ios

Out of Apple's status codes for an in-app purchase (in Table 2-1 here), some should obviously be tried again, and some not and should be considered to say that the receipt in invalid.
But what about "21003 - The receipt could not be authenticated."? Is it similar to 21010 or to 21005? I.e. should this be sent again later or considered an invalid purchase?

From my experience, the "21003 - The receipt could not be authenticated." status is related to the App-Specific Shared Secret.
When you validate receipts with the AppStore, the App-Specific Shared Secret is used to set the value of the password field in the JSON request that you sent to the AppStore validation endpoint. (See Validating Receipts with the App Store documentation)
Keep in mind that according to Apple's documentation, this apps-specific shared secret is only necessary when validating receipt for apps that use auto-renewable subscriptions. However, in my experience, it might be worth setting it for any app receipt validation, just to avoid the 21003 error.

Related

Verify Receipt Apple Not Using the Password

I am attempting to validate a receipt in the sandbox environment (https://sandbox.itunes.apple.com/verifyReceipt). The response looks successful and it is showing me the LatestReceiptInfo and any InApp transactions.
The part that is confusing me is that I am able to do it with an invalid secret as well. I am even able to verify with a receipt that was generated from a very different app. It appears as if validation is ignoring the shared secret entirely.
I would expect a status code of 21003 for the valid receipt that wasn't created by my app. I would also expect a 21004 for the invalid secret. In both cases I get a status code of 0 and the receipt is available.
There is something that I am not understanding about how verification works. Is this expected behavior for the sandbox?
Below is the response body that i am sending to verify.
{
"receipt-data": "MyReceiptData",
"password": "FakePassword",
"exclude-old-transactions": true
}
If your purchase item isn't an subscription. then apple will ignore the password.
Only verify the password when it's an subscription.

google renewable subscriptions abuse

we have an application that utilizes auto renewable subscriptions in android.
The users are going subscribing through the app normally and the receipt is sent for our backend to be validated using the IAP Google API.
until this point everything is fine, but we recently discovred a loophole in our system, some users are subscribe and cancel their subscriptions and re-enable the auto subscription, this way google will issues a new receipt that is sent to our backend and we are giving them another year, this is easily solved by granting the only the duration given in the receipt
but then users started using the same google account with different accounts for our apps and they give everyone free subscriptions by the generated receipt
I read the API in here and I can't find any field that tells us that this receipt is only a re-activation not a new subscription
https://developers.google.com/android-publisher/api-ref/purchases/subscriptions
when we send a request for google api to get the info this is what we are getting:
status_from_google_play
{
"autoRenewing": true,
"cancelReason": null,
"countryCode": "SA",
"developerPayload": "",
"expiryTimeMillis": "1534073485784",
"kind": "androidpublisher#subscriptionPurchase",
"linkedPurchaseToken": "sometoken",
"orderId": "GPA.xxxx-xxxx-xxxx-xxxxx",
"paymentState": 1,
"priceAmountMicros": "290000",
"priceCurrencyCode": "SAR",
"purchaseType": 0,
"startTimeMillis": "1534071687580",
"userCancellationTimeMillis": null
}
There is no field that gives me this piece of information
am I missing something? is there another way to validate this?
Turns out the linkedPurchaseToken field can be used for this purpose
if the linked token is not empty it means it's a re-activation only or an upgrade/downgrade for the subscription.
It's not a direct usage as you can see but it's how you know.

Apple Receipt Validation

I am doing the application with Non renewable subscriptions. I am receiving the Status code 21007, while validating the Receipt , what should i do after receiving that status?
Thanks advance
21007
This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.
Check this page AppStore receipt validation

Stripe card authentication passed from iPhone, failed on server

The card was validated by Stripe's iPhone code, where I create a card, send to their server and receive a stripe token.
When I charge that token, the server receives an error from Stripe saying invalid CVC.
I checked Zip code & CVC verification required in my account settings.
Is there a way to authenticate the credit card prior to charging it?
You can pre-validate any or all of the card data beforehand—check out the Validation section of the documentation.
To deal with ZIP code mismatches or incorrect CVV data, you'll have to implement appropriate error handling on both your server and client.
If you haven't worked with other payment processors before, this is not specific to Stripe. CVV is generated with private encryption keys and can only be verified by trusted parties (i.e. the issuing banks). The payment card industry's not in the habit of enabling brute force attacks, so you must actually post a charge to determine whether card validation data is correct.
There is no way to know the data is correct until you attempt a charge—if that charge is rejected for reasons of incorrect data, that's how you know it's incorrect. It's how the payment network functions, and it's how your application must function.

Is there anyway to check if an Apple Inapp purchase product identifier is valid from the content server?

I am creating the backend for an iOSapp that has inapp purchase products in them.
The backend does the content serving stuff and validations of receipts and what not.
What bothers me is that there is no way to be sure that the product identifier entered in the backend is a valid one.
I know there is an API that can be called from the iOS to get a list of product identifiers for a specific app(was it company?), is there anyway to obtain this information from the backend so true validation of the entered identifier can be done?
Thanks in advance.
Once a user makes a valid purchase, you receive an encoded purchase receipt. To check if the purchase is valid, you need to send this receipt to Apple's validation servers. You'll receive a response indicating if the purchase was valid, and if it's valid - details about the purchase (purchase time, product ID, transaction ID, etc...).
I used the example code here and it was pretty easy and straight forward. Use the sandbox url as an endpoint while testing (including with TestFlight), and the production URL once the app is in the app store.
BTW, I would recommend generating a shared secret for your IAP (you can do it in iTunes Connect), and including it in your validation requests under a field called password:
private function encodeRequest() {
return json_encode(array(
'receipt-data' => $this->getReceipt(),
'password' => $sharedSecret));
}

Resources