Created
October 30, 2017 10:11
-
-
Save nicocavallo/753f896cda1ce2974778e1166e2dbb70 to your computer and use it in GitHub Desktop.
Example about manual checking Stripe signature in webhook calls in Scala
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 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