跪拜 Guibai
← All articles
Backend · JavaScript · Node.js

WeChat Pay V3 for Mini Programs: A Complete Node.js Integration Walkthrough

By 东方红杉 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

WeChat Pay is the only payment rail for mini programs inside China's ecosystem, and the V3 API's signature and callback requirements break in predictable ways that English documentation rarely catalogs. Missing the cent-based amount unit, skipping idempotency on callbacks, or trusting the frontend for the order total are mistakes that directly cost money or block transactions in production.

Summary

WeChat Pay V3 integration demands a precise sequence: bind the merchant account to the mini program AppID, configure the API certificate and a 32-byte symmetric key, then implement a seven-step payment flow where the backend exchanges a login code for an openid, calls the JSAPI unified order endpoint, and returns signed parameters to the frontend. The frontend invokes wx.requestPayment and must independently verify the order status afterward — callbacks alone are not reliable. The guide provides copy-paste Node.js code using the wechatpay-node-v3 SDK, which handles signature generation and callback decryption, avoiding the most common integration failures.

Every amount is in cents, not yuan; a single unit mistake produces a 100x error. The callback endpoint must be a public HTTPS POST URL, and the backend must return a success acknowledgment or WeChat will retry indefinitely, requiring idempotency on the handler. The merchant certificate private key and APIv3 key are the two security artifacts that matter; the legacy V2 key and WeChat Pay public key are irrelevant for a pure V3 integration and can be ignored.

A pre-launch checklist and a pitfall list drawn from real projects cover the recurring failures: signature mismatches from case errors, callbacks blocked by firewalls, and the risk of trusting the frontend for the payment amount. The entire stack assumes a verified non-individual mini program and a merchant account in good standing; cross-entity bindings need extra paperwork and still restrict some features.

Takeaways
Payment amounts in every WeChat Pay V3 interface are in cents; passing yuan produces a 100x discrepancy.
Only two API security items are needed for V3: the merchant API certificate (private key) and a 32-character APIv3 key; the V2 key and WeChat Pay public key are unnecessary.
The APIv3 key must be exactly 32 characters and cannot be retrieved in plaintext after saving, so store it permanently at generation time.
Mini program payment reuses JSAPI payment and does not require a separate payment authorization directory, unlike Official Account JSAPI.
The backend must never trust the frontend for the payment amount; it must calculate the total from the product ID server-side.
After wx.requestPayment returns, the frontend must actively query the backend for the order's true trade_state; callbacks can be delayed, lost, or forged.
The payment callback endpoint must be a public HTTPS POST URL without port numbers or query parameters, and the handler must return a success acknowledgment or WeChat will retry indefinitely.
Callback handlers require idempotency because WeChat may deliver the same notification multiple times.
Signature verification failures are most often caused by parameter case mismatches, wrong certificate serial numbers, or an APIv3 key that does not match the one set in the merchant platform.
Cross-entity bindings between a merchant account and mini program require additional review and a signed joint operation commitment letter, and some payment features remain restricted.
Conclusions

The guide's emphasis on ignoring the V2 key and WeChat Pay public key is a quiet but valuable efficiency tip: most official documentation still surfaces all four API security options without clarifying which are dead weight for a V3-only integration, leading developers to waste time configuring irrelevant credentials.

Generating the APIv3 key directly in the browser console with crypto.getRandomValues is a pragmatic zero-dependency trick that sidesteps the friction of installing OpenSSL or running a Node script, though the resulting key's entropy depends on the browser's CSPRNG implementation.

The insistence on frontend-side order status verification after wx.requestPayment — rather than relying solely on the asynchronous callback — reflects a defensive posture born from real-world failures where callbacks arrived minutes late or not at all, a detail that tutorial-style guides often gloss over.

The checklist item 'order status is based on the query interface result, not dependent on the frontend callback status' encodes a security boundary: the frontend callback can be spoofed or misread, so the source of truth must always be a server-to-server query.

Concepts & terms
APIv3 Key
A 32-character symmetric encryption key set in the WeChat Pay merchant platform, used to decrypt asynchronous payment callback notifications and to download platform certificates for signature verification.
JSAPI Payment
WeChat's in-app browser payment interface, originally for Official Accounts but reused by mini programs. It requires an openid and returns a prepay_id that the frontend uses to invoke the payment cashier.
prepay_id
A short-lived token returned by the WeChat Pay unified order endpoint after a successful order placement. The backend uses it to generate the signed parameter package that wx.requestPayment requires.
notify_url
A publicly accessible HTTPS POST endpoint that WeChat Pay calls asynchronously to deliver the final payment result. It must not contain port numbers or query parameters, and the handler must return a success acknowledgment to stop retries.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗