Webhooks.verifyAndParse checks TikTok’s signature against the raw request body, then parses the body into a WebhookEvent you narrow with when. See webhooks for how TikTok signs and delivers them.
import com.isaackogan.tiktok.shop.WebhookEventimport com.isaackogan.tiktok.shop.WebhookSignatureExceptionimport com.isaackogan.tiktok.shop.Webhooks
class WebhookExample { /** Call with the body bytes exactly as received, and the Authorization header. */ fun handle(rawBody: ByteArray, authorizationHeader: String?) { val event = try { Webhooks.verifyAndParse("YOUR_APP_KEY", "YOUR_APP_SECRET", rawBody, authorizationHeader) } catch (e: WebhookSignatureException) { return // respond 401 }
when (event) { is WebhookEvent.OrderStatusChange -> println(event.payload.data?.orderId) is WebhookEvent.Unknown -> println("a webhook type this SDK does not know: ${event.type}") else -> {} } }}verifyAndParse, verify and parse take the body as a ByteArray or a String.
- Verify the raw body. Never re-serialize the body before verifying: changed bytes make the signature fail.
- Parsing is strict.
parsethrowsIllegalArgumentExceptionwhen:- the body is not a JSON object;
typeis missing or is not an integer;- a known type is missing a required property, or the property is null. A known type missing a required field is always a parse error.
- Unknown types are kept. An integer
typethis SDK does not know becomesWebhookEvent.Unknown(type, raw). Unknown fields are ignored. - A sealed class.
WebhookEventhas one subclass per webhook type (each holds the generated payload model inpayload) plusUnknown. The subclasses are rendered from the spec, so they stay in sync. They live in the generated folder but in the packagecom.isaackogan.tiktok.shop, because a sealed class’s subclasses must share its package. - Type names.
Webhooks.EVENT_TYPESmaps a type number to its name;1isORDER_STATUS_CHANGE.
Exceptions
Section titled “Exceptions”A bad signature throws WebhookSignatureException. A body that cannot be read as a webhook throws IllegalArgumentException. Answer the first with 401 and the second with 400, so neither is mistaken for success. The README example catches only WebhookSignatureException; add a second catch for IllegalArgumentException in a real handler.