You are an expert at implementing authentication systems for Chinese applications. You handle WeChat Login, Alipay Login, phone SMS verification, and real-name verification — the four pillars of Chinese user authentication.
In China, email/password login is secondary. Users expect WeChat scan-to-login or phone SMS verification. If you don't support these, you lose 80% of potential users.
MethodUser PreferenceImplementation ComplexityTrust LevelWeChat Login⭐⭐⭐⭐⭐MediumHigh (verified identity)Phone SMS⭐⭐⭐⭐LowMedium (SIM-based)Alipay Login⭐⭐⭐MediumHigh (real-name verified)Email/Password⭐⭐LowLow (anonymous)
text
Step 1: Redirect to WeChat
GET https://open.weixin.qq.com/connect/qrconnect?
appid=APPID&
redirect_uri=REDIRECT_URI&
response_type=code&
scope=snsapi_login&
state=STATE
Step 2: User scans QR code with WeChat
Step 3: WeChat redirects back with code
REDIRECT_URI?code=CODE&state=STATE
Step 4: Exchange code for access_token
GET https://api.weixin.qq.com/sns/oauth2/access_token?
appid=APPID&
secret=SECRET&
code=CODE&
grant_type=authorization_code
Step 5: Get user info
GET https://api.weixin.qq.com/sns/userinfo?
access_token=ACCESS_TOKEN&
openid=OPENID&
lang=zh_CN
javascript
// Frontend (Mini Program)
wx.login({
success: (res) => {
// res.code → send to your backend
wx.request({
url: 'https://your-api.com/auth/wechat/miniprogram',
method: 'POST',
data: { code: res.code }
})
}
})
// Backend (Node.js)
const axios = require('axios')
async function wechatMiniProgramLogin(code) {
// Step 1: Exchange code for session_key + openid
const { data } = await axios.get(
'https://api.weixin.qq.com/sns/jscode2session',
{
params: {
appid: process.env.WX_APPID,
secret: process.env.WX_SECRET,
js_code: code,
grant_type: 'authorization_code'
}
}
)
// data: { openid, session_key, unionid? }
// Step 2: Find or create user by openid
let user = await User.findOne({ wechatOpenid: data.openid })
if (!user) {
user = await User.create({ wechatOpenid: data.openid })
}
// Step 3: Generate JWT
const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '7d' })
return { token, user }
}
javascript
// iOS/Android → WeChat SDK → get code → backend exchange
// Same flow as web, but uses SDK instead of QR code
// User taps "微信登录" → WeChat app opens → auto-redirect back with code
ProviderPrice/条ReliabilitySpeedBest For阿里云SMS¥0.045⭐⭐⭐⭐⭐<3sProduction腾讯云SMS¥0.045⭐⭐⭐⭐⭐<3sProduction华为云SMS¥0.04⭐⭐⭐⭐<5sAlternative容联云¥0.04⭐⭐⭐<5sBudget
javascript
const Core = require('@alicloud/pop-core')
const client = new Core({
accessKeyId: process.env.ALI_ACCESS_KEY,
accessKeySecret: process.env.ALI_ACCESS_SECRET,
endpoint: 'https://dysmsapi.aliyuncs.com',
apiVersion: '2017-05-25'
})
async function sendSMS(phone, code) {
const result = await client.request('SendSms', {
PhoneNumbers: phone, // +8613800138000
SignName: '你的应用名', // Must be approved
TemplateCode: 'SMS_123456', // Must be approved
TemplateParam: JSON.stringify({ code })
}, { method: 'POST' })
return result.Code === 'OK'
}
// Rate limiting: 1 SMS per minute per phone, 5 per hour
const smsLimiter = {
window: 60, // seconds
maxPerWindow: 1,
maxPerHour: 5,
maxPerDay: 10
}
javascript
// 1. Generate 6-digit code
function generateCode() {
return Math.floor(100000 + Math.random() * 900000).toString()
}
// 2. Store in Redis with TTL
await redis.setex(`sms:${phone}`, 300, code) // 5 min TTL
// 3. Verify
async function verifyCode(phone, inputCode) {
const storedCode = await redis.get(`sms:${phone}`)
if (!storedCode) return { valid: false, reason: 'expired' }
if (storedCode !== inputCode) return { valid: false, reason: 'wrong' }
await redis.del(`sms:${phone}`) // One-time use
return { valid: true }
}
text
Level 1: ID card number + name (基础实名)
→ Check against public security database
→ Cost: ¥0.8-2.0 per check
→ Providers: 阿里云/腾讯云/百度云
Level 2: ID card + face recognition (增强实名)
→ ID check + liveness detection + face comparison
→ Cost: ¥1.5-5.0 per check
→ Required for: financial, healthcare, education apps
javascript
// Level 1: ID Card Verification (阿里云)
async function verifyIdCard(name, idNumber) {
const client = new Core({ /* ... */ })
const result = await client.request('VerifyIdCard', {
Name: name, // 张三
IdCardNumber: idNumber // 110101199001011234
})
return result.Result === '1' // 1=match, 0=no match
}
// Level 2: Face Recognition (腾讯云)
async function verifyFace(idCardImage, selfieImage) {
const result = await tencentCloudClient.request('CompareFace', {
ImageA: idCardImage, // Base64 ID card photo
ImageB: selfieImage, // Base64 selfie
QualityControl: 1 // Enable quality check
})
return result.Similarity > 80 // >80 = same person
}
ScenarioLevel RequiredRegulationSocial features (comment/post)Level 1网络安全法Financial servicesLevel 2金融监管HealthcareLevel 2医疗法规EducationLevel 1教育部规定E-commerce (seller)Level 1电商法Live streaming (host)Level 2网信办规定Gaming (anti-addiction)Level 1版署规定
javascript
// Unified auth endpoint
router.post('/auth/:method', async (req, res) => {
const { method } = req.params
switch (method) {
case 'wechat':
// WeChat OAuth2 flow
return handleWechatLogin(req, res)
case 'phone':
// SMS verification
return handlePhoneLogin(req, res)
case 'alipay':
// Alipay OAuth2 flow
return handleAlipayLogin(req, res)
default:
return res.status(400).json({ error: 'Unsupported method' })
}
})
// Account linking: same user can have multiple auth methods
// User schema:
{
phone: '+8613800138000',
wechatOpenid: 'oXXXX',
wechatUnionid: 'uXXXX', // Cross-app identity
alipayUserId: '2088XXXX',
realNameVerified: false,
realNameLevel: 0 // 0=none, 1=ID, 2=ID+face
}
Auth MethodPrerequisitesKey APIUser Data ReturnedWeChat WebMP account + 网页授权open.weixin.qq.com/connect/qrconnectopenid, nickname, avatarWeChat MiniMini Programjscode2sessionopenid, unionidPhone SMSSMS provider accountSendSms APIphone number onlyAlipay支付宝开放平台alipay.system.oauth.tokenuser_id, avatarReal-name L1Cloud providerVerifyIdCardmatch/no-matchReal-name L2Cloud providerCompareFacesimilarity score