情景简述:
最近公司在做"通过微信走步排名,领取活动相关奖励"的功能,中间,自然就涉及到了,微信走步数据的相关解密操作,功能已做完,做个总结。注意,下文只涉及到后端数据处理,怎么获取,这里是由前端提供!
一、基础部分,准备相关的参数
/**
* 每次进入小程序,把前端推送的走步数据,存入到【组成员表】
*/
public function save_member_steps()
{
$request = $this->get;
//$request['step_data'] = "M4OKJ5Q6yR0dwVtDX/P+/DJJuFs1oWmjZ9I8h8HJFSn6WslrGcxUXpXxq46W1g28AAaDGAf0z79zycv/g5VqY";
//$request['iv'] = "QUzF4rjjsKhakdjjE8Px9w==";
//$request['openid'] = "oqahZ5LbBsdf099ikjdKoruXtPI";
// 获取相关的参数,并判断
$userid = isset($request['userid']) ? $request['userid'] : 0;
if(!$userid){
return $this->export->get_export($this->errors[506]['error_code'], $this->errors, []);
}
// 从微信获取步数
$step_data_str = isset($request['step_data']) && !empty($request['step_data']) ? strval($request['step_data']) : '';
if(!$step_data_str){
return $this->export->get_export($this->errors[512]['error_code'], $this->errors, []);
}
// 获取步数微信端参数
$iv = !empty($request['iv']) ? strval($request['iv']) : '';
// 获取步数微信端参数
$openid = !empty($request['openid']) ? strval($request['openid']) : '';
$this->load->dao('active_step_dao');
// 解密微信端获取步数数据
$step_datas = $this->process_wx_step_data($openid, $iv, $step_data_str);
// 步数数据更新到user_step_everyday_log表
$update_everyday_log = $this->update_step_log_data($userid, $step_datas);
return $update_everyday_log ? true : false;
}
/**
* 获取用户的走步数据,更新到成员表
* @param $openid
* @param $iv
* @param $step_data_str
* @return array
*/
public function process_wx_step_data($openid, $iv, $step_data_str)
{
// 从微信记录里获取数据,比对一下,是否正确,如果不正确,更新【组成员步数】,团表里的总步数累加
$this->load->service('user_wechat_service');
$step_data = $this->user_wechat_service->auth_step_data($openid, $iv, $step_data_str, 1);
$stepInfoList = [];
if(isset($step_data['stepInfoList']) && !empty($step_data['stepInfoList'])){
$stepInfoList = $step_data['stepInfoList'];
foreach ($stepInfoList as $key=>$val) {
$stepInfoList[$key]['time'] = date('Y-m-d', $val['timestamp']);
}
$stepInfoList = array_column($stepInfoList, null, 'time');
}
return $stepInfoList;
}
二、核心部分,负责处理微信端数据
/**
* 获取微信端用户【走步】数据
* @param $openid 用户小程序openid
* @param $iv 小程序返回的iv字段
* @param $step_data_str 小程序返回的走步加密字段
* @param $plat_type 1 用户端 2 教练端
* @return array
*/
public function auth_step_data($openid, $iv, $step_data_str, $plat_type)
{
if (empty($openid) || empty($iv) || empty($step_data_str) || empty($plat_type)) {
return [];
}
$decrypt_data = $this->_get_encrypted_data($openid, $step_data_str, $iv, $plat_type);
return $decrypt_data;
}
/**
* 对微信加密的数据进行解密
* @param $openid
* @param $encrypted_data
* @param $iv
* @return string
*/
private function _get_encrypted_data($openid, $encrypted_data, $iv, $plat_type)
{
$result = '';
if (empty($openid) || empty($encrypted_data) || empty($iv) || empty($plat_type)) {
return $result;
}
$this->load->dao('user_wechat_dao');
$user = $this->user_wechat_dao->get_userid($openid, $plat_type);
if (empty($user)) {
return $result;
}
$this->load->config('dict/wechat_config');
$dict_name = $plat_type == self::PLAT_TYPE_USER ? 'dict_wechat_user' : 'dict_wechat_coach';
$app_config = $this->config->item($dict_name);
$result = $this->_decrypt_data($app_config['app_id'], $user['sessionkey'], $encrypted_data, $iv);
return $result;
}
/**
* 解密数据
* @desc VALIDATE_LEN_NUM = 24;
* @param $appid
* @param $session_key
* @param $encrypted_data
* @param $iv
* @return mixed|string
*/
private function _decrypt_data($appid, $session_key, $encrypted_data, $iv)
{
$result = '';
if (strlen($session_key) != self::VALIDATE_LEN_NUM || strlen($iv) != self::VALIDATE_LEN_NUM) {
return $result;
}
$aes_key = base64_decode(str_replace(' ','+',$session_key));
$aes_iv = base64_decode(str_replace(' ','+',$iv));
$aes_cipher = base64_decode(str_replace(' ','+',$encrypted_data));
$data = openssl_decrypt($aes_cipher, "AES-128-CBC", $aes_key, 1, $aes_iv);
$data = json_decode($data, TRUE);
if (empty($data)) {
return $result;
}
if (!isset($data['watermark']['appid']) || $data['watermark']['appid'] != $appid) {
return $result;
}
return $data;
}
三、写在最后的话
代码中部分地方属于文件配置,不便贴出来,但也不影响看。微信"走步数据"解析处理,关键点在于"解密数据",这里是个难点,涉及到一些函数,需理解认真分析,其他就没有了!