Hi everyone,
I'm experiencing an issue with APNs server notifications where I receive a 404 error when trying to validate the signedPayload from Apple's notification. Below is a sanitized version of my code:
class ServerNotificationAppleController extends Controller
{
// URL for StoreKit keys (Sandbox environment)
private $storeKitKeysUrl = 'https://api.storekit-sandbox.itunes.apple.com/inApps/v1/keys';
public function handleNotification(Request $request)
{
\Log::info($request);
$signedPayload = $request->input('signedPayload');
if (!$signedPayload) {
return response()->json(['error' => 'signedPayload not provided'], 400);
}
// Step 1: Create your JWT token (token creation logic can be in a separate service)
$jwtToken = $this->generateAppleJWT();
// Step 2: Send a request to the StoreKit keys endpoint
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $jwtToken,
])->get($this->storeKitKeysUrl);
Log::info('Apple Keys Status:', ['status' => $response->status()]);
Log::info('Apple Keys Body:', ['body' => $response->body()]);
if ($response->status() !== 200) {
return response()->json(['error' => "Apple public keys couldn't be retrieved"], 401);
}
$keysData = $response->json();
// Step 3: Validate the signedPayload
$validatedPayload = $this->validateSignedPayload($signedPayload, $keysData);
if (!$validatedPayload) {
return response()->json(['error' => 'Invalid signedPayload'], 400);
}
// Process the validated data as needed
Log::info("Apple Purchase Data:", (array)$validatedPayload);
return response()->json(['message' => 'Notification processed successfully'], 200);
}
private function generateAppleJWT()
{
// API key details (replace placeholders with actual values)
$keyId = config('services.apple.key_id'); // e.g., <YOUR_KEY_ID>
$issuerId = config('services.apple.issuer_id'); // e.g., <YOUR_ISSUER_ID>
$privateKey = file_get_contents(storage_path(config('services.apple.private_key')));
// Set current UTC time and expiration time (20 minutes later)
$nowUtc = Carbon::now('UTC');
$expirationUtc = $nowUtc->copy()->addMinutes(20);
// Create the payload with UTC timestamps
$payload = [
'iss' => $issuerId,
'iat' => $nowUtc->timestamp,
'exp' => $expirationUtc->timestamp,
'aud' => 'appstoreconnect-v1',
'bid' => 'com.example.app', // Replace with your Bundle ID if necessary
];
// Generate the JWT token
return JWT::encode($payload, $privateKey, 'ES256', $keyId);
}
private function validateSignedPayload($signedPayload, $keysData)
{
try {
$jwkKeys = JWK::parseKeySet($keysData);
return JWT::decode($signedPayload, $jwkKeys, ['RS256']);
} catch (\Exception $e) {
Log::error("Apple Purchase Validation Error: " . $e->getMessage());
return null;
}
}
}
I’m particularly puzzled by the fact that I receive a 404 error when trying to retrieve the public keys from the StoreKit keys endpoint. Has anyone encountered this issue or can provide insight into what might be causing the error?
Any help or suggestions would be greatly appreciated. Thanks!
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I am creating a project with Flutter, but in the Runner/Frameworks folder, all files such as Pods_Runner.framework etc. are red and the file is not located in the specified folder. The same situation exists in my old projects. I don't know where I'm doing wrong, it was normal until a few days ago, but now even if I create a new project, I get the same error.
Flutter Version: 3.13.9
Cocoapods Version: 1.15.2
XCode: 15.1
Hello,
We detected some fraudulent activity in one of my app. The user purchases the in-app product, makes use of the service, and then returns it immediately. And he repeats this process every day. We have done some actions to prevent this, but this process continues by using clone app creators. How is the return process going, is there no control in this regard? Normally, if a user buys the same product for the second time, I think that he should not return it anymore.