@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()andshare()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/wechatQuick 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.comorhttps://test.r.ads.sohu.com, callingconfig()is optional - the library will auto-configure with defaults when you use features likeshare()
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): voidExample - 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(): GlobalConfigisConfigured()
Check if global configuration has been set.
function isConfigured(): booleanLow-level APIs
For advanced use cases, you can use the low-level APIs:
isWechat()
Check if the current environment is WeChat browser.
function isWechat(): booleanExample:
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 | nullresetSDK()
Reset SDK state (useful for testing or manual re-initialization).
function resetSDK(): voidOriginal 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.comhttps://test.r.ads.sohu.com
How It Works
When you call config() without providing getSignature on a supported domain:
- The library automatically detects the current domain
- Uses the built-in signature function that requests
/wechat/ticket - Converts the API response to the standard
SignatureResultformat
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%3D123API 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
fetchAPI if available (modern browsers) - Automatically falls back to
XMLHttpRequestin older environments - Response format is automatically converted to match
SignatureResultinterface
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):
- Custom
getSignaturefunction - Complete override domainConfigsfor current domain - Per-domain customization- 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:
- Accept the page URL as a query parameter (default key:
url) - 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 globalSohuWechat
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 returnsWxSDK | nullinstead of throwing errors share(),init(), andinitSDK()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.comandhttps://test.r.ads.sohu.com, you can now use the library without callingconfig()at all getSignatureis now optional on supported domains- Automatic signature fetching from
/wechat/ticket?url={current_url}endpoint on supported domains - Built-in request uses
fetchAPI with automatic fallback toXMLHttpRequestfor 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
sdkUrlconfiguration option fromGlobalConfig - 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()andshare()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
