Skip to content

Instantly share code, notes, and snippets.

@nicocavallo
Created October 30, 2017 10:11
Show Gist options
  • Save nicocavallo/753f896cda1ce2974778e1166e2dbb70 to your computer and use it in GitHub Desktop.
Save nicocavallo/753f896cda1ce2974778e1166e2dbb70 to your computer and use it in GitHub Desktop.
Example about manual checking Stripe signature in webhook calls in Scala
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import org.apache.commons.codec.binary.Hex
val sharedSecret = "whsec_A2EdfajGiGHx9jFmkP7ia6j25VXh9IWV"
val payload = "{\n \"id\": \"evt_YEEz4JGN6UwGkCjdqr7wfPqL\",\n \"object\": \"event\",\n \"api_version\": \"2017-06-05\",\n \"created\": 1509023721,\n \"data\": {\n \"object\": {\n \"id\": \"my-first-test-plan\",\n \"object\": \"plan\",\n \"amount\": 599,\n \"created\": 1509023721,\n \"currency\": \"gbp\",\n \"interval\": \"month\",\n \"interval_count\": 1,\n \"livemode\": false,\n \"metadata\": {\n },\n \"name\": \"My first test plan\",\n \"statement_descriptor\": \"My first test plan\",\n \"trial_period_days\": 31\n }\n },\n \"livemode\": false,\n \"pending_webhooks\": 1,\n \"request\": {\n \"id\": \"req_6UwGkCjdqr7wfPqLAq\",\n \"idempotency_key\": null\n },\n \"type\": \"plan.created\"\n}"
val header = "t=1509023726,v1=e786c1d46f2fa3bbd57cf974e89533ecb89ba2ea006c8ef672da3e7cb2c1101d,v0=6d9e8a0b0de1d3f363c85f02842950c056dbb453d70863d4d2900214396052ac"
class StripeWebHookSignatureValidator(sharedSecret: String) {
private val secret = new SecretKeySpec(sharedSecret.getBytes, "HmacSHA256")
def apply(stripeSignature: String, payload: String): Option[String] = {
val mac = Mac.getInstance("HmacSHA256")
mac.init(secret)
val headers = stripeSignature.split(",")
for {
timestamp <- headers.find(_.startsWith("t=")).map(_.drop(2))
signature <- headers.find(_.startsWith("v1=")).map(_.drop(3))
if signature == Hex.encodeHexString(mac.doFinal(s"$timestamp.$payload".getBytes))
} yield signature
}
}
object StripeWebHookSignatureValidator {
def apply(sharedSecret: String):(String, String) => Option[String] =
new StripeWebHookSignatureValidator(sharedSecret).apply
}
val validateSignature = StripeWebHookSignatureValidator(sharedSecret)
validateSignature(header, payload)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment