Created
August 29, 2025 08:42
-
-
Save marvinkome/4bb156219051cbd5156d58fd68597e8b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import fs from "fs/promises"; | |
| import path from "path"; | |
| import { env } from "@/libs/env/server"; | |
| import { AppStoreServerAPIClient, Environment, SignedDataVerifier } from "@apple/app-store-server-library"; | |
| const loadRootCertificate = async () => { | |
| const certificatesDirectory = path.join(process.cwd(), "./apple-root-certificates"); | |
| return Promise.all([ | |
| fs.readFile(path.join(certificatesDirectory, "./cert-1.cer")), | |
| fs.readFile(path.join(certificatesDirectory, "./cert-2.cer")), | |
| fs.readFile(path.join(certificatesDirectory, "./cert-3.cer")), | |
| fs.readFile(path.join(certificatesDirectory, "./cert-4.cer")), | |
| ]); | |
| }; | |
| export const getClient = async () => { | |
| const environment = process.env.NODE_ENV === "production" ? Environment.PRODUCTION : Environment.SANDBOX; | |
| const apiKey = env.APP_STORE_PRIVATE_KEY.replace(/\\n/g, "\n"); | |
| const client = new AppStoreServerAPIClient(apiKey, env.APP_STORE_KEY_ID, env.APP_STORE_ISSUER_ID, env.APP_STORE_BUNDLE_ID, environment); | |
| const certificates = await loadRootCertificate(); | |
| const verifier = new SignedDataVerifier(certificates, true, environment, env.APP_STORE_BUNDLE_ID, env.APP_STORE_APP_ID); | |
| return { client, verifier }; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export async function POST(request: NextRequest) { | |
| const { signedPayload } = await request.json(); | |
| console.log("[apple-webhook] received signed notification from apple"); | |
| const { verifier } = await getClient(); | |
| try { | |
| const payload = await verifier.verifyAndDecodeNotification(signedPayload); | |
| console.log("[apple-webhook] decoded signed payload", { payload: _.omit(payload, ["data"]) }); | |
| await handleNotification(payload); | |
| return NextResponse.json({ message: "handled" }); | |
| } catch (error: any) { | |
| console.error("[apple-webhook] error decoding signed payload - %j", { | |
| name: error.name, | |
| message: error.message, | |
| stack: error.stack, | |
| }); | |
| return NextResponse.json({ error: "request failed" }, { status: 400 }); | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment