npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sohu-bpd/wechat

v0.1.1

Published

WeChat JS-SDK utility library

Readme

@sohu-bpd/wechat

WeChat JS-SDK utility library with initialization helpers and SPA support.

Features

  • 🔄 SPA Support - Auto re-initialization on URL changes for single-page apps
  • 📱 iOS Compatible - Handles iOS WeChat signature URL quirks automatically
  • 🎯 High-level APIs - Simple config() and share() APIs for common tasks
  • 🛡️ Non-WeChat Safe - All APIs silently return in non-WeChat environments without errors
  • 📦 TypeScript - Full type definitions included
  • 🌐 Multiple Formats - ESM, CommonJS, and IIFE bundles

Installation

npm install @sohu-bpd/wechat
# or
pnpm add @sohu-bpd/wechat
# or
yarn add @sohu-bpd/wechat

Quick Start

1. Load WeChat JS-SDK

First, include the WeChat JS-SDK script in your HTML:

<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>

2. Configure (Optional on Sohu Domains)

Option A: Zero Configuration (Sohu Domains Only)

If you're on https://act.go.sohu.com or https://test.r.ads.sohu.com, you can skip configuration entirely:

import { share } from '@sohu-bpd/wechat'

// No config needed! Just use it directly
await share({
  title: 'My Page Title',
  desc: 'Share description',
  imgUrl: 'https://example.com/image.jpg',
})

Option B: Custom Configuration (Sohu Domains)

Or customize settings on supported domains:

import { config } from '@sohu-bpd/wechat'

// No need to provide getSignature on supported domains
config({
  debug: false,
  spa: true, // Enable SPA mode (default)
})

Option C: Custom Signature Function (Other Domains)

For other domains or custom backends:

import { config } from '@sohu-bpd/wechat'

config({
  getSignature: async (url) => {
    // Fetch signature from your backend
    const response = await fetch(`/api/wechat/signature?url=${encodeURIComponent(url)}`)
    return response.json()
  },
  debug: false,
  spa: true, // Enable SPA mode (default)
})

3. Use Anywhere

import { share } from '@sohu-bpd/wechat'

// Set share content
await share({
  title: 'My Page Title',
  desc: 'Share description',
  imgUrl: 'https://example.com/image.jpg',
  link: 'https://example.com/page', // optional, defaults to current URL
})

Usage

ESM / CommonJS

import { config, share } from '@sohu-bpd/wechat'

// or
const { config, share } = require('@sohu-bpd/wechat')

Browser (IIFE)

<!-- Load WeChat JS-SDK first -->
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<!-- Then load this library -->
<script src="https://unpkg.com/@sohu-bpd/wechat/dist/index.global.js"></script>
<script>
  const { config, share } = SohuWechat

  config({
    getSignature: async (url) => {
      const res = await fetch('/api/wechat/signature?url=' + encodeURIComponent(url))
      return res.json()
    }
  })

  share({
    title: 'My Page',
    desc: 'Description',
    imgUrl: 'https://example.com/image.jpg'
  })
</script>

API Reference

High-level APIs

config(options)

Set global configuration for WeChat JS-SDK.

Note:

  • You must load the WeChat JS-SDK script in your HTML before using this library
  • On https://act.go.sohu.com or https://test.r.ads.sohu.com, calling config() is optional - the library will auto-configure with defaults when you use features like share()
interface GlobalConfig {
  /**
   * Function to fetch signature, receives current URL
   * - Optional on https://act.go.sohu.com or https://test.r.ads.sohu.com
   * - Will auto-use built-in signature (requests /wechat/ticket) if not provided
   * - Required on other domains
   */
  getSignature?: (url: string) => Promise<SignatureResult>
  /** Enable debug mode, default false */
  debug?: boolean
  /** Enable SPA mode (auto re-init on URL change), default true */
  spa?: boolean
}

function config(options?: GlobalConfig): void

Example - No configuration needed (Sohu domains):

import { share } from '@sohu-bpd/wechat'

// Just use it directly!
await share({
  title: 'My Page',
  desc: 'Description',
  imgUrl: 'https://example.com/image.jpg',
})

Example - Custom signature function:

config({
  getSignature: async (url) => {
    const res = await fetch(`/api/wechat/signature?url=${encodeURIComponent(url)}`)
    return res.json()
  },
  debug: process.env.NODE_ENV === 'development',
  spa: true,
})

Example - Custom settings with built-in signature (Sohu domains):

// On https://act.go.sohu.com or https://test.r.ads.sohu.com
config({
  debug: true,
  spa: true,
})

share(options)

Set WeChat share content for both friends and moments.

interface ShareOptions {
  /** Share title */
  title: string
  /** Share description (for friends) */
  desc?: string
  /** Share link, defaults to current URL */
  link?: string
  /** Share image URL */
  imgUrl: string
}

function share(options: ShareOptions): Promise<void>

Example:

await share({
  title: 'Amazing Product',
  desc: 'Check out this amazing product!',
  imgUrl: 'https://example.com/product.jpg',
  link: 'https://example.com/product/123',
})

getConfig()

Get current global configuration (throws if not configured).

function getConfig(): GlobalConfig

isConfigured()

Check if global configuration has been set.

function isConfigured(): boolean

Low-level APIs

For advanced use cases, you can use the low-level APIs:

isWechat()

Check if the current environment is WeChat browser.

function isWechat(): boolean

Example:

import { isWechat, share } from '@sohu-bpd/wechat'

// Conditionally show share UI only in WeChat
if (isWechat()) {
  showShareButton()
}

// Or just call share() - it will silently do nothing outside WeChat
await share({
  title: 'My Page',
  imgUrl: 'https://example.com/image.jpg',
})

initSDK(jsApiList)

Initialize WeChat SDK with specified APIs (automatically called by high-level APIs).

Note: Requires WeChat JS-SDK to be loaded globally first. Silently returns in non-WeChat environments.

function initSDK(jsApiList: string[]): Promise<void>

getWx()

Get the global wx object after SDK is loaded. Returns null in non-WeChat environments or if wx is not available.

function getWx(): WxSDK | null

resetSDK()

Reset SDK state (useful for testing or manual re-initialization).

function resetSDK(): void

Original init Function

For use cases that don't need global configuration.

Note: Requires WeChat JS-SDK to be loaded globally first.

interface InitConfig {
  /** Public account appId */
  appId: string
  /** Signature timestamp */
  timestamp: number | string
  /** Signature nonce string */
  nonceStr: string
  /** Signature */
  signature: string
  /** JS API list to use */
  jsApiList: string[]
  /** Enable debug mode */
  debug?: boolean
}

function init(config: InitConfig): Promise<void>

SPA Mode

By default, spa: true is enabled, which means:

  • On the first API call (e.g., share()), the SDK is initialized with the current URL
  • On subsequent API calls, if the URL has changed, the SDK is automatically re-initialized
  • This is essential for single-page applications where the URL changes without page reloads

To disable SPA mode:

config({
  // ...
  spa: false, // Only initialize once
})

Built-in Signature Support

On specific Sohu domains, the library provides built-in signature functionality:

Supported Domains

  • https://act.go.sohu.com
  • https://test.r.ads.sohu.com

How It Works

When you call config() without providing getSignature on a supported domain:

  1. The library automatically detects the current domain
  2. Uses the built-in signature function that requests /wechat/ticket
  3. Converts the API response to the standard SignatureResult format

API Request Format

The built-in signature function sends a GET request to:

/wechat/ticket?url={encoded_current_url}

Parameters:

  • url (query parameter): The current page URL (URL-encoded)

Example Request:

GET /wechat/ticket?url=https%3A%2F%2Fact.go.sohu.com%2Fpage%3Fid%3D123

API Response Format

The built-in signature endpoint /wechat/ticket should return:

{
  code: number          // 0 for success
  data: {
    app_id: string      // Converted to appId
    timestamp: number   // Kept as timestamp
    nonce_str: string   // Converted to nonceStr
    signature: string   // Kept as signature
  }
  message: string       // Error message if code !== 0
}

Notes:

  • Uses fetch API if available (modern browsers)
  • Automatically falls back to XMLHttpRequest in older environments
  • Response format is automatically converted to match SignatureResult interface

Usage

Zero Configuration (Recommended):

import { share } from '@sohu-bpd/wechat'

// No config() needed on supported domains!
await share({
  title: 'My Page',
  desc: 'Description',
  imgUrl: 'https://example.com/image.jpg',
})

With Custom Settings:

import { config, share } from '@sohu-bpd/wechat'

// Optional: customize settings
config({
  debug: true,
  spa: true,
})

// Then use normally
await share({
  title: 'My Page',
  desc: 'Description',
  imgUrl: 'https://example.com/image.jpg',
})

Fallback to Custom Function

Even on supported domains, you can provide your own getSignature function:

config({
  getSignature: async (url) => {
    // Your custom implementation
    return await fetchSignatureFromCustomAPI(url)
  },
})

Custom Domain Configuration

For domains not in the built-in list, or to customize built-in domains, use the domainConfigs option:

Basic Usage

import { config } from '@sohu-bpd/wechat'

config({
  domainConfigs: {
    'https://your-domain.com': {
      endpoint: '/api/wechat/signature',
      urlParamKey: 'url',
    }
  }
})

Advanced: Custom Response Format

If your backend returns a different response format:

config({
  domainConfigs: {
    'https://your-domain.com': {
      endpoint: '/api/sign',
      urlParamKey: 'pageUrl',
      transformResponse: (response) => {
        // Convert your custom format to standard SignatureResult
        return {
          appId: response.appid,      // Map from your field names
          timestamp: response.ts,
          nonceStr: response.nonce,
          signature: response.sign
        }
      }
    }
  }
})

Configuration Priority

The library uses the following priority order (highest to lowest):

  1. Custom getSignature function - Complete override
  2. domainConfigs for current domain - Per-domain customization
  3. Built-in default configuration - For Sohu domains

Example - Priority demonstration:

// Priority 1: getSignature always takes precedence
config({
  getSignature: async (url) => {
    // This will be used, domainConfigs ignored
    return await fetchFromCustomAPI(url)
  },
  domainConfigs: {
    'https://act.go.sohu.com': {
      endpoint: '/ignored'  // This won't be used
    }
  }
})

// Priority 2: domainConfigs overrides built-in defaults
config({
  domainConfigs: {
    'https://act.go.sohu.com': {
      endpoint: '/custom/ticket',  // Overrides default /wechat/ticket
      urlParamKey: 'targetUrl'     // Overrides default 'url'
    }
  }
})

// Priority 3: Built-in defaults (no config needed)
// On https://act.go.sohu.com or https://test.r.ads.sohu.com
await share({
  title: 'My Page',
  imgUrl: 'https://example.com/image.jpg'
})

Configuration Options

| Option | Type | Required | Default | Description | |--------|------|:--------:|---------|-------------| | endpoint | string | No | '/wechat/ticket' | Signature API endpoint path | | urlParamKey | string | No | 'url' | Query parameter name for URL | | transformResponse | function | No | Built-in transform | Response format converter |

Backend API Requirements

Your signature endpoint should:

  1. Accept the page URL as a query parameter (default key: url)
  2. Return signature data in one of these formats:

Option A: Use built-in format (no transformResponse needed):

{
  "code": 0,
  "data": {
    "app_id": "wx123456",
    "timestamp": 1234567890,
    "nonce_str": "abc123",
    "signature": "sha1signature"
  },
  "message": "success"
}

Option B: Use custom format with transformResponse:

{
  "appid": "wx123456",
  "ts": 1234567890,
  "nonce": "abc123",
  "sign": "sha1signature"
}

With config:

transformResponse: (res) => ({
  appId: res.appid,
  timestamp: res.ts,
  nonceStr: res.nonce,
  signature: res.sign
})

Non-WeChat Environment Safety

All APIs are safe to call in non-WeChat environments (desktop browsers, other mobile browsers, SSR, etc.). They will silently return without throwing errors, so your application works normally:

import { share, init, initSDK, isWechat } from '@sohu-bpd/wechat'

// These all work safely in any environment:

// share() resolves immediately in non-WeChat
await share({
  title: 'My Page',
  imgUrl: 'https://example.com/image.jpg',
})

// init() resolves immediately in non-WeChat
await init({
  appId: 'wx123',
  timestamp: 123,
  nonceStr: 'abc',
  signature: 'sig',
  jsApiList: [],
})

// initSDK() resolves immediately in non-WeChat
await initSDK(['updateAppMessageShareData'])

// Use isWechat() to conditionally show WeChat-specific UI
if (isWechat()) {
  showWeChatShareButton()
}

This design allows you to integrate WeChat sharing without wrapping every call in environment checks.

iOS WeChat Quirk

On iOS WeChat, the signature URL should be the first entry URL of the app, not the current URL. This library handles this automatically:

  • On iOS, it remembers the first URL and always uses it for signatures
  • On Android, it uses the current URL for each signature request

You don't need to do anything special - it just works.

Backend Signature Endpoint

Your backend should provide an endpoint that generates WeChat JS-SDK signatures. Here's an example implementation:

// Node.js + Express example
app.get('/api/wechat/signature', async (req, res) => {
  const url = req.query.url as string

  // Generate signature using WeChat's algorithm
  const signature = await generateWeChatSignature(url)

  res.json({
    appId: 'your-app-id',
    timestamp: signature.timestamp,
    nonceStr: signature.nonceStr,
    signature: signature.signature,
  })
})

Refer to WeChat JS-SDK Documentation for signature generation details.

TypeScript Support

Full TypeScript definitions are included:

import type {
  GlobalConfig,
  SignatureResult,
  ShareOptions
} from '@sohu-bpd/wechat'

const config: GlobalConfig = {
  sdkUrl: '...',
  getSignature: async (url: string): Promise<SignatureResult> => {
    // ...
  }
}

Bundle Formats

  • ESM (.mjs) - Modern JavaScript modules
  • CommonJS (.js) - Node.js and bundlers
  • IIFE (.global.js) - Browser <script> tag with global SohuWechat

Changelog

0.0.6 (TBD)

  • Non-WeChat Safe: All APIs now silently return in non-WeChat environments without throwing errors
  • New API: Added isWechat() function to check if running in WeChat browser
  • Breaking Change: getWx() now returns WxSDK | null instead of throwing errors
  • share(), init(), and initSDK() resolve immediately in non-WeChat environments
  • This allows seamless integration without environment checks around every API call

0.0.5

  • New Feature: Built-in signature support for Sohu domains
  • Zero Configuration Mode: On https://act.go.sohu.com and https://test.r.ads.sohu.com, you can now use the library without calling config() at all
  • getSignature is now optional on supported domains
  • Automatic signature fetching from /wechat/ticket?url={current_url} endpoint on supported domains
  • Built-in request uses fetch API with automatic fallback to XMLHttpRequest for older browsers
  • Added comprehensive tests for built-in signature functionality, xhr fallback, and auto-initialization

0.0.3 (2026-01-29)

  • Breaking Change: Removed automatic SDK loading functionality
  • Users must now manually include the WeChat JS-SDK script in their HTML
  • Removed sdkUrl configuration option from GlobalConfig
  • Removed loadSDK() export from public API
  • Updated documentation with instructions for manual SDK inclusion

0.0.2 (2026-01-29)

  • Extract WeChat JS-SDK module as standalone package
  • High-level config() and share() APIs
  • Automatic SDK loading and initialization
  • SPA mode with auto re-initialization on URL changes
  • iOS WeChat signature URL handling
  • Full TypeScript support
  • Comprehensive unit tests
  • Multiple bundle formats (ESM, CJS, IIFE)

License

MIT