收藏
回答

获取不限制的小程序码为什么很多时候生成的都是第一次生成的scene值?

我请求scene值生成小程序码请求参数: {
  scene: 'mdcp=NNMI3LY&wx=20040939&t=58404',
  page: 'pages/tuangou/getcoupons/getcoupons',
  env_version: 'release'
},但是每次生成小程序码解析后的scene是mdcp=UQYHHGG&wx=20040939&t=25412,这个是我之前生成的,这是什么原因呀?跪求大佬解释下?

'use strict'
;
const db = uniCloud.database()


// 添加配置常量
const CONFIG = {
    appid: '',
    secret: '',
    page: ''
}


// 添加错误处理工具函数
const handleError = (message, details = null) => {
    console.error(message, details);
    return {
        code: -1,
        message,
        details: details || ''
    }
}


// 生成13位随机数字字符串的函数
function generateRandomNumber() {
    let result = '';
    for(let i = 0; i < 13; i++) {
        result += Math.floor(Math.random() * 10);
    }
    return result;
}


exports.main = async (event, context) => {
    try {
        // 参数验证
        if (!event.picihao || !event.wxcode) {
            return handleError('缺少必要参数')
        }


        // 先查询可用券
		const cmd = db.command
        const qrData = await db.collection('coupons-quuid')
            .where({
				use_branch: null,
                use: 0,
                picihao: event.picihao
            })
            .limit(1)
            .get()


        // 添加日志,帮助调试
        console.log('查询结果:', {
            picihao: event.picihao,
            hasData: !!qrData.data,
            dataLength: qrData.data?.length,
            firstRecord: qrData.data?.[0]
        })


        // 检查是否有可用数据
        if (!qrData.data || qrData.data.length === 0) {
            return handleError('没有可用的券数据')
        }


        const dbdata = qrData.data[0]
        
        // 在数据库查询后立即添加日志
        console.log("数据库查询结果:", {
            quuid: dbdata.quuid,
            picihao: event.picihao,
            wxcode: event.wxcode
        });
        
        // 直接更新方式
        try {
            const updateResult = await db.collection('coupons-quuid')
                .doc(dbdata._id)
                .update({
                    use_branch: event.use_branch || '',
                    use_time: formatDate(),
                    update_time: Date.now()
                })


            if (!updateResult.updated && !updateResult.affectedDocs) {
                return handleError('更新数据失败')
            }


            console.log('更新成功:', updateResult)


            // 获取access_token
            const tokenResponse = await uniCloud.httpclient.request(
                `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${CONFIG.appid}&secret=${CONFIG.secret}&_t=${Date.now()}`,
                {
                    dataType: 'json',
                    timeout: 10000,
                    headers: {
                        'Cache-Control': 'no-cache, no-store, must-revalidate',
                        'Pragma': 'no-cache',
                        'Expires': '0'
                    }
                }
            )


            if (!tokenResponse.data?.access_token) {
                throw new Error('获取access_token失败')
            }


            // 先生成随机数,后续都使用这个值
            const randomNumber = generateRandomNumber();


            // 优化scene参数
            const scene = `mdcp=${dbdata.quuid}&wx=${event.wxcode}&t=${randomNumber}`
            if (scene.length > 32) {
                console.warn('场景值超过32字符,将被截断')
            }


            // 对scene进行URL编码,这样可以看到实际生成的值
            const encodedScene = encodeURIComponent(scene.substr(0,32));


            const wxacodeParams = {
                scene: scene.substr(0,32),  // 保持原样发送给微信接口
                page: CONFIG.page,
                check_path: true,
                env_version: "release",
                width: 430,
                is_hyaline: true
            }


            // 添加scene参数日志,同时显示编码前后的值
            console.log("生成的scene参数:", {
                原始scene: scene,
                截断后scene: scene.substr(0,32),
                URL编码后scene: encodedScene,
                quuid: dbdata.quuid,
                wxcode: event.wxcode,
                随机数: randomNumber  // 使用之前生成的随机数
            });


            // 记录请求日志
            console.log("生成小程序码请求参数:", {
                scene: wxacodeParams.scene,
                page: wxacodeParams.page,
                env_version: wxacodeParams.env_version,
            })


            // 调用生成小程序码API
            const codeResponse = await uniCloud.httpclient.request(
                `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${tokenResponse.data.access_token}&_t=${Date.now()}`,
                {
                    method: 'POST',
                    data: wxacodeParams,
                    headers: {
                        'content-type': 'application/json',
                        'Cache-Control': 'no-cache, no-store, must-revalidate',
                        'Pragma': 'no-cache',
                        'Expires': '0'
                    },
                    dataType: 'buffer',
                    timeout: 20000
                }
            )


            // 添加响应内容检查
            if (codeResponse.status !== 200) {
                console.error("微信接口返回错误:", codeResponse);
                return handleError('微信接口返回错误');
            }


            // 检查返回的文件名是否匹配我们的scene
            console.log("返回的文件名:", codeResponse.headers['content-disposition']);


            // 响应处理
            const contentType = codeResponse.headers['content-type']
			console.log("2",contentType);
            try {
                // 检查数据是否为Buffer
                if (!Buffer.isBuffer(codeResponse.data)) {
                    console.error("返回数据不是Buffer类型:", typeof codeResponse.data);
                    return handleError('返回数据格式错误');
                }
                
                // 使用更安全的方式转换base64
                let base64Image;
                try {
                    base64Image = codeResponse.data.toString('base64');
                } catch (e) {
                    console.error("Buffer转base64失败:", e);
                    return handleError('图片转换失败');
                }
                
                // 根据实际内容类型设置正确的MIME类型
                const mimeType = 'image/jpeg';
                // 只输出base64字符串的前100个字符
                console.log("3", "转换成功,base64前100个字符:", base64Image.substring(0, 100));
                console.log("3.1", "base64数据总长度:", base64Image.length);


                return {
                    code: 0,
                    data: {
                        img: `data:${mimeType};base64,${base64Image}`,
                        code: dbdata,
                        scene: wxacodeParams.scene
                    }
                }
            } catch (error) {
                console.error("转换base64失败:", error);
                return handleError('生成小程序码失败', error.message);
            }


        } catch (err) {
            console.error('更新失败:', err)
            return handleError('数据更新失败', err.message)
        }


    } catch (error) {
        console.error('执行错误:', error)
        return handleError(error.message, error.stack)
    }
}


// 修改日期格式化函数,返回北京时间
function formatDate() {
    const d = new Date()
    // 获取当前时间的时间戳
    const timestamp = d.getTime()
    // 加上8小时的毫秒数,转换为北京时间
    const beijingDate = new Date(timestamp + 8 * 60 * 60 * 1000)
    return beijingDate.toISOString()
        .replace('T', ' ')
        .replace(/\.\d+Z$/, '')
} 
回答关注问题邀请回答
收藏

3 个回答

登录 后发表内容