中文

Home / Articles

Migrating to WeChat Pay APIv3: the three days behind a 'signature error'

2026-09-18 · WeChat PayBackend

In October we migrated one of our storefronts from legacy WeChat Pay code to APIv3. The engineering itself is not complicated; the hard part was a seemingly mystical failure: every unified-order request returned "signature error, please check and try again", even though we had verified the signature string against the documentation three times. This post records the full three-day investigation so others can avoid the same detours.

The conclusion first: two keys, one confusion

WeChat Pay's "key" is actually two different things: the legacy APIv2 MD5 key (a 32-character string) and the APIv3 key (another string, used only for callback decryption and refunds — it never participates in order signing). Our old configuration table had both filled in, and the legacy code used the v2 one. The new v3 path requires the merchant certificate's private key for RSA-SHA256 signing — the APIv3 key has nothing to do with that step.

The trap was that on day one we assumed "signature error" meant the v3 key was wrong, so we kept rotating the two string keys. The error never moved. It was only on day two, after we set the keys aside and verified our own signature string against the public key extracted from apiclient_cert.pem, that we confirmed the signature string was fine — what was wrong was a key that should never have been involved in signing at all.

What the signature string actually consists of

An APIv3 request signature string is five lines, none optional:

Sign this string with the merchant private key using SHA256withRSA, then Base64-encode. When we finally printed each segment to logs and compared line by line, we found the timestamp in one build was in milliseconds — three extra digits, enough for server-side verification to fail, while the API returned nothing more specific than "signature error".

Lesson: error messages only tell you something is wrong, never where. Printing and diffing each input is the only reliable debugging method.

Newer merchant accounts don't issue an APIv2 key at all

Another easy-to-miss fact: relatively new merchant accounts no longer issue APIv2 keys by default. If any v2 logic remains (older payment SDKs implement only v2), signature verification will fail no matter what you paste, because the key simply does not exist. The quick check: log into the merchant platform, open Account Center → API Security, and see whether the APIv2 key can still be set. If the entry is disabled or unsupported, a full v3 migration is mandatory.

Similarly, the certificate toolkit may include pub_key_xxx.pem alongside apiclient_cert.pem / apiclient_key.pem. That is the WeChat platform public key, used to verify callbacks — do not confuse it with the merchant certificate's public key. Some newer accounts run in "public key mode", where /v3/certificates returns 404 permanently; callback verification must then use the platform key file rather than the certificate-download endpoint.

Three pitfalls on the callback side

Once ordering worked, callbacks became disaster area two. The pitfalls, in order:

The configuration we settled on

After the migration we collapsed payment configuration into four fields: merchant ID, certificate path, private key path, and the APIv3 key. Every field is visible and editable in our admin panel, and the save routine preserves any field the form does not submit — otherwise a single accidental save wipes production keys, an incident far worse than a signature error.

Final step before launch: run a real 0.01 CNY payment through the entire loop, reconcile by out_trade_no query results, and keep logs for at least 90 days. Every line of every signature string and every verification result goes to disk. Those logs saved us again during a later key rotation.

Looking back, the biggest gain from those three days was not a working payment flow but a debugging habit: distrust your intuition about the word "key". Break it into "which key, used at which step" — and the problem is already half solved.

Related reading

Between bulk generation and human editing: our content pipeline

Bulk-generated content gets flagged; purely manual is slow and expensive. Our pipeline: machine drafts, human authority, realistic cadence.

2026-10-28 · ContentMethod

A hands-on method for evaluating AI cutout edge quality

Hair, glassware, cluttered shelves: the three hard scenes for AI cutouts. A reproducible edge-quality evaluation method, plus what our tool bake-off found.

2026-10-24 · AI ToolsEvaluation

Static-site SEO fundamentals: sitemap, internal links, and crawl speed — measured

No tricks: five baseline moves that doubled Google's indexing speed on our static sites within three weeks — each with its own verification method.

2026-10-22 · SEOWeb