When mini program API requests fail, most people’s first reaction is “Is the certificate expired?” In actual troubleshooting, the issue is rarely expiration; instead, it’s often one of these easily overlooked requirements: insufficient TLS version, incomplete certificate chain, or domain not added to the allowed list.
The TLS version requirement is particularly隐蔽 (hidden)—it may work on some devices but fail completely on others, leading users to mistakenly believe it’s an intermittent issue.
Platform Requirements Checklist (Self-Check Item by Item)
| Requirement | Description | Consequence of Non-Compliance |
|---|---|---|
| HTTPS Required | Plain HTTP requests are not supported | url not in domain list |
| TLS ≥ 1.2 | TLS 1.0 / 1.1 are rejected by Apple ATS | iOS reports -1200 |
| Certificate must be issued by a trusted CA | Self-signed certificates are not trusted | ssl handshake failed |
| Complete Certificate Chain | Missing intermediate certificates cause direct failure on Android | CertPathValidatorException |
| Domain must be ICP filed | Requirement for domestic mini programs | Review rejection |
| No IP addresses or non-443 ports | Must use a domain name + port 443 | Request fails |
| Domain must be added to request legitimate domains | Requests are only allowed after backend configuration | url not in domain list |
| Certificate must not be expired | Expiration causes total failure | Widespread errors |
Error Message Reference
# WeChat Developer Tools
Not in the following request legitimate domain list: https://api.example.com
request:fail url not in domain list
# Real Device / Production
request:fail ssl handshake failed
request:fail -2:net::ERR_CERT_AUTHORITY_INVALID
# iOS (ATS Requirement)
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred
and a secure connection to the server cannot be established."
# Android
javax.net.ssl.SSLHandshakeException:
java.security.cert.CertPathValidatorException: Trust anchor for
certification path not found.
iOS error -1200 essentially means “TLS version does not meet standards”; Android’s “Trust anchor” highly points to “incomplete certificate chain.” The causes are completely different and require separate handling.
Verification Commands
# ① Verify if TLS 1.2 is available
openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2
# ② Verify if TLS 1.0 is still enabled (should be disabled)
openssl s_client -connect api.example.com:443 -servername api.example.com -tls1
# ③ Check chain integrity —— Verify return code should be 0 (ok)
openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null
| grep 'Verify return code'
# ④ List supported protocols and ciphers
nmap --script ssl-enum-ciphers -p 443 api.example.com
# ⑤ Test with curl forcing TLS 1.2
curl -v --tlsv1.2 https://api.example.com/
# ⑥ Certificate expiration date
openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null
| openssl x509 -noout -enddate
Nginx Configuration
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3; # Do not include TLSv1 / TLSv1.1
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
}
Note that ssl_certificate must be the fullchain. Using only cert.pem will result in an incomplete certificate chain, manifesting as “works in browser, fails in mini program.”
Decision Tree
Mini Program Request Fails
├─ url not in domain list → Go to mini program backend and add domain to request legitimate domains
├─ iOS reports -1200 → Insufficient TLS version → Keep only 1.2/1.3 in ssl_protocols
├─ Android reports cert path error → Incomplete certificate chain → Switch to fullchain
├─ ssl handshake failed → Self-signed certificate or protocol mismatch
├─ Works in DevTools, fails on real device → DevTools has "Ignore valid domain names" checked
└─ Worked before, suddenly all fail → Certificate expired
Why Interface Services Are More Vulnerable to Trust Chain Changes
Websites and APIs face completely different situations regarding this issue: Websites can guide users to switch browsers, but APIs cannot.
The client environment is out of your control—system versions, trust stores, and OpenSSL versions are all uncontrollable. You cannot force upgrades nor explain issues one by one. Therefore, when trust chains diverge, interface services suffer much heavier consequences than websites.
- Old device trust stores not updated: New roots are not trusted, leading to direct failures
- Client OpenSSL version too old: 1.0.x has known validation defects; even with trusted new roots and complete chains, failures still occur
- Inconsistent compatibility strategies across platforms: At any given time, some devices work while others fail, and you cannot distinguish them on the server side
The combination of these three factors makes mini program interface faults the most troublesome: you cannot reproduce them, nor can you remotely guide users to self-check.
Therefore, what the server side can do is ensure its part is unambiguous:
- Configure a complete certificate chain (fullchain); do not rely on the client to fill gaps
- Keep only TLS 1.2 / 1.3; do not leave room for protocol negotiation fallbacks
- Include certificate expiration in monitoring; do not wait for user feedback
Scenario Deduction: After renewing the certificate, the mini program starts reporting invalid certificate errors
Symptom: Server-side access via browser works normally, but the mini program encounters certificate-related request failures, occurring only on some user devices.
- First, confirm why the browser appears “normal” → Browsers automatically complete the certificate chain and cache intermediate certificates; the mini program client lacks this mechanism, so missing chains lead to direct failure. This step is crucial to rule out “the server actually has issues, but they are masked by the browser.”
- Reproduce real verification using command line → Add
-verify_return_errorto enforce strict validation. A non-zero return code indicates the chain is indeed incomplete. - Identify which level is missing → The server only configured the site certificate without issuing the intermediate certificate together.
- Fix → Change the certificate file to contain both the site certificate and the intermediate certificate, then reload the service.
- Re-verify → Use the same command again to confirm the return code is 0, and retry mini program requests on real devices across multiple network environments.
# Key: Must include -verify_return_error, otherwise browser-like completion hides the problem
echo | openssl s_client -connect api.example.com:443 -servername api.example.com
-verify_return_error 2>&1 | grep -E 'Verify return code|depth'
# Check how many certificates the server actually sends
echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null
| grep -c 'BEGIN CERTIFICATE'
# Confirm TLS version is no lower than 1.2
echo | openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2 2>&1
| grep -E 'Protocol|Cipher'
Root Cause: Incorrect verification method—judging certificate validity via a browser, which automatically completes missing intermediate certificates, masking the problem as “normal.”
Two key takeaways:
- To determine if a certificate chain is complete, use command lines with strict validation, not browsers.
The single parameter-verify_return_erroris the dividing line between “looks normal” and “is truly normal.” - Certificate issues for interfaces should be troubleshooted before business logic issues.
Failures like this on the mini program side do not return business status codes; logs often only show a generic request failure message. If you start checking interface logic first, you will waste significant time in the wrong direction.
8 Common Pitfalls
- TLS 1.0/1.1 not disabled: Nginx defaults may still have them enabled; Apple ATS rejects them, causing direct iOS failures.
- Self-signed certificates: Work during development, but always fail on real devices.
- Incomplete certificate chain: Works in browsers but fails on Android; this is the most typical “some devices don’t work” scenario.
- Domain not added to request legitimate domains: There are limits on the number of configurable items and modification frequencies in the backend; avoid frequent changes.
- DevTools has “Ignore valid domain names” checked: Everything works locally, but issues surface during submission or on real devices—the most frequent pitfall.
- Using IP addresses or non-443 ports: Must use a domain name configured in the backend + port 443.
- WeChat caches old configurations: After changing certificates or domains, some clients may still use old connections; clear cache or wait for生效 (effectiveness).
- No one monitors certificate expiration: Mini programs do not send advance warnings;务必 (must) include expiration in monitoring; do not wait for user feedback.
Real Customer Feedback (From Similar Product Reviews and Consultations on Cloud Markets)
The following excerpts are from real buyer reviews and consultations for similar operations services on Alibaba Cloud / Tencent Cloud / Huawei Cloud markets (service providers include our store and peers, provided solely for reference of real feedback, not fictional tickets from this site):
s****2 Rating: 5.0 Feb 28, 2023 11:04 Mai****8 Rating: 5.0 Jun 29, 2020 17:44 4****6 Rating: 5.0 Jan 07, 2019 14:56
a****8 Rating: 5.0 Aug 22, 2025 14:43 r****8 Rating: 5.0 May 22, 2025 15:34 t****c Rating: 5.0 Apr 18, 2025 13:58 Cai****Kang Rating: 5.0 Aug 31, 2024 12:05 2****2 Rating: 5.0 Feb 21, 2024 11:08