Token导航 LogoToken导航TokenDH.com
研究检索敏感数据github未标认证来源可访问clear审计通过

recur-webhooks重复网络钩子

Agent Skill

recur-webhooks 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

689

周安装

29

GitHub Stars

公开资料未说明

下载量

241
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:recur-webhooks(重复网络钩子)
来源仓库:https://github.com/recur-tw/skills
仓库路径:skills/recur-webhooks
安装命令:
npx skills add https://github.com/recur-tw/skills --skill recur-webhooks
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/recur-tw/skills --skill recur-webhooks

简介

recur-webhooks 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中快速定位候选结果。

  • 适用于需要根据关键词或任务场景进行信息定位的研究与检索任务。
  • 通过关键词、任务场景或来源线索输入,获取相关结果列表。
  • 安装命令:npx skills add https://github.com/recur-tw/skills --skill recur-webhooks。
  • 建议确认权限范围和维护状态,注意是否触发联网或文件操作。

SKILL.md

Recur Webhook Integration

You are helping implement Recur webhooks to receive real-time payment and subscription events.

Webhook Events

Core Events (Most Common)

EventWhen Fired
checkout.completedPayment successful, subscription/order created
subscription.activatedSubscription is now active
subscription.cancelledSubscription was cancelled
subscription.renewedRecurring payment successful
subscription.past_duePayment failed, subscription at risk
order.paidOne-time purchase completed
refund.createdRefund initiated

All Supported Events

type WebhookEventType =
  // Checkout
  | 'checkout.created'
  | 'checkout.completed'
  // Orders
  | 'order.paid'
  | 'order.payment_failed'
  // Subscription Lifecycle
  | 'subscription.created'
  | 'subscription.activated'
  | 'subscription.cancelled'
  | 'subscription.expired'
  | 'subscription.trial_ending'
  // Subscription Changes
  | 'subscription.upgraded'
  | 'subscription.downgraded'
  | 'subscription.renewed'
  | 'subscription.past_due'
  // Scheduled Changes
  | 'subscription.schedule_created'
  | 'subscription.schedule_executed'
  | 'subscription.schedule_cancelled'
  // Invoices
  | 'invoice.created'
  | 'invoice.paid'
  | 'invoice.payment_failed'
  // Customer
  | 'customer.created'
  | 'customer.updated'
  // Product
  | 'product.created'
  | 'product.updated'
  // Refunds
  | 'refund.created'
  | 'refund.succeeded'
  | 'refund.failed'

Webhook Handler Implementation

Next.js App Router

// app/api/webhooks/recur/route.ts
import { NextRequest, NextResponse } from 'next/server'
import crypto from 'crypto'

const WEBHOOK_SECRET = process.env.RECUR_WEBHOOK_SECRET!

function verifySignature(payload: string, signature: string): boolean {
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(payload)
    .digest('hex')
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  )
}

export async function POST(request: NextRequest) {
  const payload = await request.text()
  const signature = request.headers.get('x-recur-signature')

  // Verify signature
  if (!signature || !verifySignature(payload, signature)) {
    return NextResponse.json({ error: 'Invalid signature' }, { status: 401 })
  }

  const event = JSON.parse(payload)

  // Handle events
  switch (event.type) {
    case 'checkout.completed':
      await handleCheckoutCompleted(event.data)
      break

    case 'subscription.activated':
      await handleSubscriptionActivated(event.data)
      break

    case 'subscription.cancelled':
      await handleSubscriptionCancelled(event.data)
      break

    case 'subscription.renewed':
      await handleSubscriptionRenewed(event.data)
      break

    case 'subscription.past_due':
      await handleSubscriptionPastDue(event.data)
      break

    case 'refund.created':
      await handleRefundCreated(event.data)
      break

    default:
      console.log(`Unhandled event type: ${event.type}`)
  }

  return NextResponse.json({ received: true })
}

// Event handlers
async function handleCheckoutCompleted(data: any) {
  const { customerId, subscriptionId, orderId, productId, amount } = data

  // Update your database
  // Grant access to the user
  // Send confirmation email
}

async function handleSubscriptionActivated(data: any) {
  const { subscriptionId, customerId, productId, status } = data

  // Update user's subscription status in your database
  // Enable premium features
}

async function handleSubscriptionCancelled(data: any) {
  const { subscriptionId, customerId, cancelledAt, accessUntil } = data

  // Mark subscription as cancelled
  // User still has access until accessUntil date
  // Send cancellation confirmation email
}

async function handleSubscriptionRenewed(data: any) {
  const { subscriptionId, customerId, amount, nextBillingDate } = data

  // Update billing records
  // Extend access period
}

async function handleSubscriptionPastDue(data: any) {
  const { subscriptionId, customerId, failureReason } = data

  // Notify user of payment failure
  // Consider sending dunning emails
  // May want to restrict access after grace period
}

async function handleRefundCreated(data: any) {
  const { refundId, orderId, amount, reason } = data

  // Update order status
  // Adjust user credits/access
  // Send refund notification
}

Express.js

import express from 'express'
import crypto from 'crypto'

const app = express()

// Important: Use raw body for signature verification
app.post(
  '/api/webhooks/recur',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const payload = req.body.toString()
    const signature = req.headers['x-recur-signature'] as string

    // Verify signature
    const expected = crypto
      .createHmac('sha256', process.env.RECUR_WEBHOOK_SECRET!)
      .update(payload)
      .digest('hex')

    if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
      return res.status(401).json({ error: 'Invalid signature' })
    }

    const event = JSON.parse(payload)

    // Handle event...
    console.log('Received event:', event.type)

    res.json({ received: true })
  }
)

Event Payload Structure

interface WebhookEvent {
  id: string           // Event ID (for idempotency)
  type: string         // Event type
  timestamp: string    // ISO 8601 timestamp
  data: {
    // Varies by event type
    customerId?: string
    customerEmail?: string
    subscriptionId?: string
    orderId?: string
    productId?: string
    amount?: number
    currency?: string
    // ... more fields depending on event
  }
}

Webhook Configuration

  1. Go to Recur DashboardSettingsWebhooks
  2. Click Add Endpoint
  3. Enter your endpoint URL (e.g., https://yourapp.com/api/webhooks/recur)
  4. Select events to receive
  5. Copy the Webhook Secret to your environment variables

Testing Webhooks Locally

Using ngrok

# Start ngrok tunnel
ngrok http 3000

# Use the ngrok URL in Recur dashboard
# https://xxxx.ngrok.io/api/webhooks/recur

Using Recur CLI (if available)

# Forward webhooks to local server
recur webhooks forward --to localhost:3000/api/webhooks/recur

Best Practices

1. Always Verify Signatures

Never trust webhook payloads without verifying the signature.

2. Handle Idempotency

Webhooks may be delivered multiple times. Use the event id to deduplicate:

async function handleEvent(event: WebhookEvent) {
  // Check if already processed
  const existing = await db.webhookEvent.findUnique({
    where: { eventId: event.id }
  })

  if (existing) {
    console.log('Event already processed:', event.id)
    return
  }

  // Process event...

  // Mark as processed
  await db.webhookEvent.create({
    data: { eventId: event.id, processedAt: new Date() }
  })
}

3. Return 200 Quickly

Process events asynchronously to avoid timeouts:

export async function POST(request: NextRequest) {
  // Verify and parse...

  // Queue for async processing
  await queue.add('process-webhook', event)

  // Return immediately
  return NextResponse.json({ received: true })
}

4. Handle Retries Gracefully

Recur retries failed webhook deliveries. Ensure your handler is idempotent.

5. Log Everything

console.log('Webhook received:', {
  type: event.type,
  id: event.id,
  timestamp: event.timestamp,
})

Debugging Webhooks

Check Webhook Logs

In Recur Dashboard → Webhooks → Click endpoint → View delivery logs

Common Issues

401 Unauthorized

  • Check webhook secret is correct
  • Ensure using raw body for signature verification
  • Verify signature algorithm (HMAC SHA-256)

Timeout (no response)

  • Return 200 before processing
  • Use async processing for heavy operations

Missing events

  • Check event types are selected in dashboard
  • Verify endpoint URL is correct and accessible

Related Skills

  • /recur-quickstart - Initial SDK setup
  • /recur-checkout - Implement payment flows
  • /recur-entitlements - Check subscription access after webhook

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

28.88%
按下载量换算70

Antigravity

22.18%
按下载量换算53

Codex

17.93%
按下载量换算43

Gemini CLI

11.36%
按下载量换算27

OpenCode

6.58%
按下载量换算16

Cursor

3.14%
按下载量换算8

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills