whop_sdk 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.fernignore +30 -17
- data/lib/whop_sdk/helpers/verify_webhook.rb +83 -0
- data/lib/whop_sdk/internal/http/raw_client.rb +1 -1
- data/lib/whop_sdk/version.rb +1 -1
- data/lib/whop_sdk.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9fc15ef6d359b6cf4784e9b9b4a43a677cd03a56bebe3b559dbf7ee65a611f21
|
|
4
|
+
data.tar.gz: 771adb6fcaf1b7564ee7383eead94c7a909a24522ddb0709f0c7e0f8cdfd35e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 62de0ee7e2ea242700d78b8e87bbc6f60257328bb7834cc9c8e66eee3338b1ac7f2510c2ea1ca6847e516fe154490ee97f6f23b0e9b2137ab71a872d3e8c324c
|
|
7
|
+
data.tar.gz: a587e338a0c270925b9de6b890cf4112a924c4906c5003b90d53f9b29ed172a11f18519db16261e186157e4d6f4493350f46acb3670a0a9777bcebab944ae13a
|
data/.fernignore
CHANGED
|
@@ -20,25 +20,37 @@
|
|
|
20
20
|
# one, so without this entry that history would disappear from the tree on the first
|
|
21
21
|
# generated PR.
|
|
22
22
|
#
|
|
23
|
-
# lib/whop_sdk/helpers holds
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
23
|
+
# lib/whop_sdk/helpers holds the hand-written helpers in this SDK. Each depends only on the
|
|
24
|
+
# standard library and one third-party gem, never on generated client code, so each survives
|
|
25
|
+
# the client being replaced:
|
|
26
|
+
#
|
|
27
|
+
# - verify_user_token — the x-whop-user-token verifier, on the jwt gem.
|
|
28
|
+
# - verify_webhook — the Standard Webhooks signature verifier, on the standardwebhooks gem.
|
|
29
|
+
# It restores the verification half of `client.webhooks.unwrap`, which the Stainless gem
|
|
30
|
+
# shipped through 0.0.41 and Fern cannot generate: Fern generates from OpenAPI paths and
|
|
31
|
+
# `unwrap` was never a path.
|
|
32
|
+
#
|
|
33
|
+
# This entry only keeps the files. Two things each helper needs are in Fern-owned files and
|
|
34
|
+
# are restored from the generator config in whop-monorepo's sdks/fern/generators.yml, not
|
|
35
|
+
# from here.
|
|
36
|
+
#
|
|
37
|
+
# - lib/whop_sdk.rb is regenerated, so the require_relative that loads a helper is lost.
|
|
38
|
+
# `requirePaths: [helpers/verify_user_token, helpers/verify_webhook]` re-emits them as
|
|
39
|
+
# File.exist?-guarded require_relatives at the bottom of the generated lib/whop_sdk.rb.
|
|
40
|
+
# - whop_sdk.gemspec is regenerated, so `add_dependency "jwt"` and
|
|
41
|
+
# `add_dependency "standardwebhooks"` are lost, the same way whopsdk-python's
|
|
42
|
+
# [user-tokens] extra does not survive. `extraDependencies: {jwt: ..., standardwebhooks: ...}`
|
|
43
|
+
# re-declares them.
|
|
44
|
+
#
|
|
45
|
+
# The two travel together, per helper. Each helper requires its gem at load, so re-emitting
|
|
46
|
+
# the require without the dependency turns a silently missing helper into a LoadError on
|
|
47
|
+
# `require "whop_sdk"` — the gem stops loading for everyone, not just that helper's callers.
|
|
48
|
+
# ci.yml asserts all of it every run so a regeneration that drops any of it fails there
|
|
40
49
|
# instead of on a caller's machine.
|
|
41
50
|
#
|
|
51
|
+
# test/unit/helpers holds those helpers' tests. Fern owns test/, so without this entry a
|
|
52
|
+
# regeneration would prune them and the helpers would go untested rather than fail loudly.
|
|
53
|
+
#
|
|
42
54
|
# lib/whop_sdk/internal/iterators/cursor_page_iterator.rb is a patched copy of a generated
|
|
43
55
|
# file. The generated clients all pass cursor_field: :end_cursor, but the response models
|
|
44
56
|
# declare end_cursor on page_info rather than at the root and Internal::Types::Model has no
|
|
@@ -60,3 +72,4 @@ CHANGELOG.md
|
|
|
60
72
|
lib/whop_sdk/helpers
|
|
61
73
|
lib/whop_sdk/internal/iterators/cursor_page_iterator.rb
|
|
62
74
|
lib/whop_sdk/internal/types/utils.rb
|
|
75
|
+
test/unit/helpers
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "json"
|
|
5
|
+
require "standardwebhooks"
|
|
6
|
+
|
|
7
|
+
module WhopSDK
|
|
8
|
+
module Helpers
|
|
9
|
+
# Verifies the Standard Webhooks signature Whop sends on every webhook
|
|
10
|
+
# delivery, then parses the body.
|
|
11
|
+
#
|
|
12
|
+
# This is the verification half of the `client.webhooks.unwrap` the
|
|
13
|
+
# Stainless-generated gem shipped through 0.0.41. Fern generates from
|
|
14
|
+
# OpenAPI paths and `unwrap` was never a path, so the generated client has
|
|
15
|
+
# no equivalent. It is a standalone module rather than a method on the
|
|
16
|
+
# client so that nothing generated has to be patched: it depends only on
|
|
17
|
+
# the standardwebhooks gem and the standard library, never on generated
|
|
18
|
+
# client code, so it survives the client being replaced.
|
|
19
|
+
#
|
|
20
|
+
# What it does NOT do, and the Stainless version did: coerce the parsed
|
|
21
|
+
# body into one of 42 typed event models. Fern generates no webhook event
|
|
22
|
+
# models — `Whop_sdk::Types::WebhookEvent` is the enum of event *names* a
|
|
23
|
+
# webhook subscribes to, not a payload type — so there is nothing to coerce
|
|
24
|
+
# into. The parsed Hash is returned as-is.
|
|
25
|
+
module VerifyWebhook
|
|
26
|
+
MISSING_KEY_MESSAGE =
|
|
27
|
+
"Cannot verify a webhook without a key. Pass the endpoint's signing secret as `key:`."
|
|
28
|
+
|
|
29
|
+
# Verifies `payload` against the signature headers and returns the parsed body.
|
|
30
|
+
#
|
|
31
|
+
# @param payload [String] The raw, unmodified request body. Verifying a
|
|
32
|
+
# re-serialized body fails: the signature covers the exact bytes sent.
|
|
33
|
+
# @param headers [Hash] The request headers. Only `webhook-id`,
|
|
34
|
+
# `webhook-timestamp` and `webhook-signature` are read, and the lookup
|
|
35
|
+
# is case-insensitive.
|
|
36
|
+
# @param key [String] The endpoint's signing secret, exactly as Whop
|
|
37
|
+
# shows it — a `ws_`-prefixed string. Pass it verbatim; do not strip the
|
|
38
|
+
# prefix and do not pre-encode it.
|
|
39
|
+
# @return [Hash] The parsed body, with symbol keys.
|
|
40
|
+
# @raise [ArgumentError] when `key` is missing or empty.
|
|
41
|
+
# @raise [StandardWebhooks::WebhookVerificationError] when a signature
|
|
42
|
+
# header is missing, the timestamp is outside the tolerance window, or
|
|
43
|
+
# no signature matches.
|
|
44
|
+
def self.unwrap(payload, headers:, key:)
|
|
45
|
+
raise ArgumentError, MISSING_KEY_MESSAGE if key.nil? || key.to_s.empty?
|
|
46
|
+
|
|
47
|
+
::StandardWebhooks::Webhook.new(hmac_key(key)).verify(payload, downcased_headers(headers))
|
|
48
|
+
JSON.parse(payload, symbolize_names: true)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Whop's backend HMACs with the *literal bytes* of the secret it issued
|
|
52
|
+
# (`WebhooksManager::SignWebhook` passes `webhook.webhook_secret` straight
|
|
53
|
+
# to `OpenSSL::HMAC`). `StandardWebhooks::Webhook` instead base64-decodes
|
|
54
|
+
# whatever it is handed to derive its key, so handing it the secret raw
|
|
55
|
+
# derives the wrong key and every genuine delivery fails to verify.
|
|
56
|
+
# Encoding here cancels that decode out, leaving exactly the bytes the
|
|
57
|
+
# backend signed with.
|
|
58
|
+
#
|
|
59
|
+
# The whole secret is encoded, prefix included, because the backend never
|
|
60
|
+
# strips a prefix either. That also disarms the library's own `whsec_`
|
|
61
|
+
# stripping: base64 output cannot begin with `whsec_`, since `_` is not in
|
|
62
|
+
# the base64 alphabet.
|
|
63
|
+
#
|
|
64
|
+
# @api private
|
|
65
|
+
def self.hmac_key(key)
|
|
66
|
+
Base64.strict_encode64(key.to_s)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# StandardWebhooks::Webhook#verify looks its three headers up by exact
|
|
70
|
+
# lowercase key, but HTTP header names are case-insensitive and a plain
|
|
71
|
+
# Rack/Sinatra headers Hash arrives capitalized.
|
|
72
|
+
#
|
|
73
|
+
# @api private
|
|
74
|
+
def self.downcased_headers(headers)
|
|
75
|
+
raise ArgumentError, "headers must be a Hash-like object of header names to values" unless headers.respond_to?(:each_pair)
|
|
76
|
+
|
|
77
|
+
headers.each_pair.with_object({}) do |(name, value), downcased|
|
|
78
|
+
downcased[name.to_s.downcase] = value
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -35,7 +35,7 @@ module Whop_sdk
|
|
|
35
35
|
@default_headers = {
|
|
36
36
|
"X-Fern-Language": "Ruby",
|
|
37
37
|
"X-Fern-SDK-Name": "whop_sdk",
|
|
38
|
-
"X-Fern-SDK-Version": "1.0.
|
|
38
|
+
"X-Fern-SDK-Version": "1.0.13"
|
|
39
39
|
}.merge(headers)
|
|
40
40
|
@overridable_headers = overridable_headers.to_set { |name| name.to_s.downcase }
|
|
41
41
|
end
|
data/lib/whop_sdk/version.rb
CHANGED
data/lib/whop_sdk.rb
CHANGED
|
@@ -3002,7 +3002,7 @@ require_relative "whop_sdk/environment"
|
|
|
3002
3002
|
|
|
3003
3003
|
# Load user-defined files if present (e.g., for Sentry integration)
|
|
3004
3004
|
# Files are loaded from lib/whop_sdk/ if they exist
|
|
3005
|
-
["whop_sdk/helpers/verify_user_token"].each do |relative_path|
|
|
3005
|
+
["whop_sdk/helpers/verify_user_token", "whop_sdk/helpers/verify_webhook"].each do |relative_path|
|
|
3006
3006
|
absolute_path = File.join(__dir__, "#{relative_path}.rb")
|
|
3007
3007
|
require_relative relative_path if File.exist?(absolute_path)
|
|
3008
3008
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: whop_sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Whop_sdk
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jwt
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '2.7'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: standardwebhooks
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.0'
|
|
27
41
|
description: The Whop_sdk Ruby library provides convenient access to the Whop_sdk
|
|
28
42
|
API from Ruby.
|
|
29
43
|
email:
|
|
@@ -886,6 +900,7 @@ files:
|
|
|
886
900
|
- lib/whop_sdk/forums/types/update_forums_request.rb
|
|
887
901
|
- lib/whop_sdk/forums/types/update_forums_request_banner_image.rb
|
|
888
902
|
- lib/whop_sdk/helpers/verify_user_token.rb
|
|
903
|
+
- lib/whop_sdk/helpers/verify_webhook.rb
|
|
889
904
|
- lib/whop_sdk/identity_profiles/client.rb
|
|
890
905
|
- lib/whop_sdk/identity_profiles/types/list_identity_profile_request.rb
|
|
891
906
|
- lib/whop_sdk/identity_profiles/types/list_identity_profile_response.rb
|