The given payload is invalid.?

EasyWeChat\Kernel\Exceptions\DecryptException
The given payload is invalid.

$user_info = $mp->encryptor->decryptData($session_key, $request->iv, $request->encryptedData);
EasyWechat 小程序解密消息 有时会出现The given payload is invalid. 数据无效,请教有没有什么解决办法?

有梦想的闲鱼那也是闲鱼
hankin
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 35

注意检查是不是session_key不一致或者过期导致的

5年前 评论
hankin

@mojiajuzi 这种情况是偶尔出现的

5年前 评论
hankin

@南冥之鱼three 没有呢

5年前 评论

兄弟解决了吗?我也出现这个问题

5年前 评论

@richWang 这边已经处理完了这个问题,关键问题还是code的原因 小程序-用户信息,
处理方式就是:

  1. 用户登录以后,保存用户的session_key,然后建立session_key与用户登录的状态变量给前端。
  2. 如果用户登录后,其他地方有需要解密的数据,直接使用已保存的session_key进行解密
  3. 如果后续有获取新的code记得同步更新session_key
5年前 评论

@mojiajuzi 我在测试中也遇到这个问题;
我认为可能不是session_key时效的问题。如果是时效的问题,应该换成下面的代码也会报错才对,但是实际上,替换之后,并没有报错

        $decrypted = json_decode($decrypted, true);
        // $decrypted = json_decode($this->pkcs7Unpad($decrypted), true);
5年前 评论

@Nixus 我这边处理后,再也没有出现这个问题

5年前 评论

@mojiajuzi 请问怎么处理的?这个错误,好奇怪啊

5年前 评论

@Nixus 之前的回答有

5年前 评论

请问解决了吗 我目前也是这个问题

4年前 评论

@mojiajuzi 你好 我目前也是这个问题 我做的操作是 第一次登陆过去code和session_key 然后缓存code和session_key在缓存有效期以内都是用这个seesion_key 去解密用户数据 。但是 现在是直接报 the given payload is invalid 我用的package是 easywechat 请问你遇到过这种问题吗

4年前 评论
DemonLi 4年前

@CHERISHNA

  1. code只能使用一次,缓存时没有意义的。
  2. session_key 官方文档上并没有说明有有效期,因此session_key的有效性需要前端去校验,如果前端校验过期了,需要重新使用code进行授权
    文档的内容如下:

wx.login 调用时,用户的 session_key 可能会被更新而致使旧 session_key 失效(刷新机制存在最短周期,如果同一个用户短时间内多次调用 wx.login,并非每次调用都导致 session_key 刷新)。开发者应该在明确需要重新登录时才调用 wx.login,及时通过 auth.code2Session 接口更新服务器存储的 session_key。

微信不会把 session_key 的有效期告知开发者。我们会根据用户使用小程序的行为对 session_key 进行续期。用户越频繁使用小程序,session_key 有效期越长。

开发者在 session_key 失效时,可以通过重新执行登录流程获取有效的 session_key。使用接口 wx.checkSession可以校验 session_key 是否有效,从而避免小程序反复执行登录流程。

当开发者在实现自定义登录态时,可以考虑以 session_key 有效期作为自身登录态有效期,也可以实现自定义的时效性策略。

4年前 评论
fuck 4年前
xdeepu

我也出现了这个情况,检查后发现是 $decrypted 为空的原因

$decrypted = AES::decrypt( base64_decode($encrypted, false), base64_decode($sessionKey, false), base64_decode($iv, false) );

4年前 评论

easywechat包,同样问题

4年前 评论

我也是这个问题 大佬们有方法吗

4年前 评论

我在这里说下吧,微信小程序验证用户登录态的那个接口是不精确的,无法100%的判断用户登录态是否过期,所以后端会偶然出现解密失败,现在我这里是让前端写出死循环来规避这个问题,如果失败,前端一直重试。

4年前 评论
  $user_session_info=$app->auth->session($data['code']);

将这user_session_info 缓存起来就可以了,不用每次都获取,而且一直用 wx.login 获取的code

4年前 评论
Violet_Ice紫冰 4年前
Violet_Ice紫冰

我现在也是这个问题。一套流程下来,没有任何停顿,就是解不出用户数据。有不同的报错,我知道有成功过,但是我没看见过成功的数据,随即的成功率。

4年前 评论

这个问题解决了吗请问,我也是出了这个问题

4年前 评论

@DemonLi 方便贴一下代码吗?

4年前 评论

`

·/*
* 获取微信绑定手机号
* @code  $code string
* @param $encryptedData string
* @param $iv string
* @return $code 成功码
* @return $msg
* @return $data  用户数据  
*/

public function getPhone(){
    $data = \request()->post();
    $miniConfig = config('miniProgram');
    // 根据 code 获取微信 openid 和 session_key
    $miniProgram = Factory::miniProgram($miniConfig);
    $callbackData = $miniProgram->auth->session($data['code']);

    if (isset($callbackData['errcode'])) {
        return $this->response->errorUnauthorized('code已过期或不正确');
    }

    $openId = $callbackData['openid'];
    $sessionKey = $callbackData['session_key'];
    $user = DB::table('customer')->where('openid', $openId)->first();
    if(!$user){
        $uid = DB::table('customer')->insertGetId([
            'openid' => $openId,
            'session_key' => $sessionKey,
            'created_at' => date('Y-m-d H:i:s')
        ]);

        $user = DB::table('customer')->find($uid);
    }else{
        DB::table('customer')->where('openid', $openId)->update(['session_key' => $sessionKey]);
    }

    //如果注册过的,就更新下下面的信息
    $token = $this->createUserToken($user->id);
    $expire_at = time()+ 60*60*24*30;
    $userToken = DB::table('customer_token')->insertGetId([
        'uid' => $user->id,
        'token' => $token,
        'create_at' => time(),
        'expire_at' => $expire_at
    ]);
    $decryptedData = $miniProgram->encryptor->decryptData($sessionKey, $data['iv'], $data['encryptedData']);
    dump($decryptedData);die;
    $phone = $decryptedData['phoneNumber'];
    $status = DB::table('customer')->where('id', $user->id)->update(['mobile' => $phone]);
    if($status){
        return array('code' => 200, 'msg' => '设置成功', 'data' => ['token' => $token, 'openid' => $openId]);
    }

    return array('code' => 10011, 'msg' => '设置失败', 'data' => null);
}

`

是这样的 前端先拿到了code,然后通过getPhoneNum 那个方法拿到了 iv 和 enctData ,然后 把这三一起传给我了 ,然后 我拿code换到了sessionkey 然后用easyWeChat 插件去解析数据 就报The given payload is invalid. @mojiajuzi 麻烦了 :grinning:

4年前 评论

@DemonLi

在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态。

建议检查一下前端是在什么时候调用login方法获取code的

4年前 评论

:joy:解决了,把一个接口分开调用了,好了,可以解析了,看来不能偷懒啊@mojiajuzi 谢谢

4年前 评论

原因已经彻底排查出来

  1. 【小程序】账户和【微信开放平台】需要是同一主体

  2. 并且还需要去【微信开放平台后台】注册账户并且到【微信开放平台后台】后台绑定【小程序】的appid
    微信开放平台网址:open.weixin.qq.com/
    其中,小程序的appid使用微信公众平台的小程序登录账户获取。贴上全文代码

    public function wxMiniLogin(Request $request)
     {
         $validator = Validator::make($request->all(), [
             'code' => 'string|required',
             'nickName' => 'string|required',
             'gender' => 'int|required',
             'avatarUrl' => 'string|required',
             'iv' => 'string|required',
         ]);
         if ($validator->fails()) {
             $this->errorJson(Define_Const::FAIL,$validator->errors());
         }
         $param = $request->all();
         $appId = isset($param['appId'])?$param['appId']:'wx34d33d54374a4833';
         $iv = $param['iv'];
         $encryptData = $param['encryptedData'];
         //配置微信appid的参数
         $wxModel = new Wechat();
         $res = $wxModel::where('wechat_app_id',$appId)->first()-> toArray();
         if (empty($res)){
             $this->errorJson(Define_Const::FAIL,'数据库没有当前小程序的密钥');
         }
         $config = [
             'app_id'=>$res['wechat_app_id'],
             'secret'=>$res['wechat_secret'],
             'response_type' => 'array',
         ];
         $app = Factory::miniProgram($config);
         $data = $app->auth->session($param['code']);
    
         if (isset($data['errcode'])) {
             $this->errorJson(Define_Const::FAIL,'code已过期或不正确',[]);
         }
         $openid = $data['openid'];
         $unionid = $data['unionid'];
         $sessionKey = $data['session_key'];
    }
3年前 评论

问题解决了。绑定手机之前先利用checksession 检查 是否过期。过期重新获取。没过期。使用之前缓存 的session_key

3年前 评论

@DemonLi 我也遇到同样问题,大佬你解决了吗

3年前 评论

我也遇到同样问题,最后解决方法是保证获取用来生成session_key的code在获取encryptedData和iv之前就可以

3年前 评论
宋高峰 3年前

我也试了大半天,妈的是前端先执行getPhoneNumber,再执行wx.login()导致的。。。。解决方案通俗一点,先让前端执行wx.login()拿到code了,再执行getPhoneNumber拿encryptedData和iv

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!