Files
OMS/app/ome/lib/rpc/request.php
2025-12-28 23:13:25 +08:00

560 lines
19 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Copyright © ShopeX http://www.shopex.cn. All rights reserved.
* See LICENSE file for license details.
*/
/**
* RPC请求基类
* 各个同步点先组织应用级参数然后统一调用本类的公共方法向框架发起RPC
* @author shopex.cn
* @access public
* @copyright www.shopex.cn 2010
*/
class ome_rpc_request {
/**
* RPC应用层发起业务过滤
* 此方法控制发起前的过滤(禁止向未绑定的店铺发起),写入日志记录,还可以决定是否队列发起
* @access public
* @param string $method RPC远程服务接口名称
* @param array $params 业务参数
* @param array $callback 异步返回参数
* @param string $title 发起的标题
* @param string $shop_id 前端店铺
* @param int $time_out 发起超时时间(秒)
* @param array $write_log 日志记录
* @param boolean $queue 是否放入队列方式稍后发起默认为false:非队列 true:队列
* @param array $addon 附加参数
* @param Bool $center 请求平台false矩阵 true:licence中心
* @param String $http_method HTTP请求方式,POST或GET
* @return boolean
*/
public function request($method,$params,$callback=array(),$title,$shop_id=NULL,$time_out=10,$queue=false,$addon='',$write_log=array(),$center=false,$http_method='POST'){
$return_value = array('rsp'=>'fail','res'=>'','data'=>'');
//过滤此次同步前端店铺
if($node = $this->_check_node($shop_id, $method)){
$Ofunc = kernel::single('ome_rpc_func');
$params['to_node_id'] = $node[0]['node_id'];
$params['node_type'] = $node[0]['node_type'];
$app_xml = $Ofunc->app_xml();
$params['from_api_v'] = $app_xml['api_ver'];
$params['to_api_v'] = $Ofunc->fetch_shop_api_v($node[0]['node_id']);
}else{
$return_value['res'] = '店铺节点不存在';
return $return_value;
}
//检查是否过滤指定回写操作
if ($this->_check_request_config($shop_id, $method)) {
return false;
}
//生成日志ID号
$oApi_log = app::get('ome')->model('api_log');
$log_id = $oApi_log->gen_id();
//设置callback异常返回参数为空时的默认值
if($callback && $callback['class'] && $callback['method']){
$rpc_callback = array($callback['class'],$callback['method'],array('log_id'=>$log_id,'shop_id'=>$shop_id));
}else{
$rpc_callback = array('ome_rpc_request','callback',array('log_id'=>$log_id,'shop_id'=>$shop_id));
}
if ($queue == true){
//队列发起(此时不记录同步日志,队列后台执行时再记录)
$param = array();
$param['api_title'] = $title;
$param['params'] = $params;
$param['method'] = $method;
$param['rpc_callback'] = $rpc_callback;
$this->api_queue($method, $param, $addon);
}else{
//非队列发起记录同步日志并立即发起RPC
if (!empty($addon) && is_array($addon)){
$api_params = array_merge($params, $addon);
}else{
$api_params = $params;
}
if (isset($write_log['log_type'])){
$log_type = $write_log['log_type'];
}else{
$log_type = ome_rpc_func::method2type($method);
}
$log_type = $log_type ? $log_type : 'other';
$oApi_log->write_log($log_id,$title,'ome_rpc_request','rpc_request',array($method, $api_params, $rpc_callback),'','request','running','',$addon,$log_type,$addon['bn']);
$this->rpc_request($method, $params, $rpc_callback, $time_out,$write_log,$center,$http_method);
}
return $log_id;
}
/**
* RPC开始请求
* 业务层数据过滤后,开始向上级框架层发起
* @access public
* @param string $method RPC远程服务接口名称
* @param array $params 业务参数
* @param int $time_out 发起超时时间(秒)
* @return RPC响应结果
*/
public function call($method, $params, $shop_id, $time_out=2) {
//过滤此次同步前端店铺
if ($node = $this->_check_node($shop_id, $method)) {
$params['to_node_id'] = $node[0]['node_id'];
$params['node_type'] = $node[0]['node_type'];
if(in_array($node[0]['node_type'], ome_shop_type::shopex_shop_type())){
$Ofunc = kernel::single('ome_rpc_func');
$app_xml = $Ofunc->app_xml();
$params['from_api_v'] = $app_xml['api_ver'];
$params['to_api_v'] = $Ofunc->fetch_shop_api_v($node[0]['node_id']);
}
} else {
return false;
}
//检查是否过滤指定回写操作
if ($this->_check_request_config($shop_id, $method)) {
return false;
}
return $this->rpc_request($method, $params, null, $time_out);
}
/**
* RPC开始请求
* 业务层数据过滤后,开始向上级框架层发起
* @access public
* @param string $method RPC远程服务接口名称
* @param array $params 业务参数
* @param array $callback 异步返回
* @param int $time_out 发起超时时间(秒)
* @param array $write_log 日志记录
* @param Bool $center 请求平台false矩阵 true:licence中心
* @param String $http_method HTTP请求方式,POST或GET
* @return RPC响应结果
*/
public function rpc_request($method,$params,$callback,$time_out=5,$write_log=array(),$center=false,$http_method='POST'){
if($center===false){
if (empty($callback)) {
//实时请求
$rst = app::get('ome')->matrix()->set_realtime(true)
->set_timeout($time_out)
->call($method, $params);
return $rst;
} else {
if (isset($params['gzip'])){
$gzip = $params['gzip'];
}else{
$gzip = false;
}
$callback_class = $callback[0];
$callback_method = $callback[1];
$callback_params = (isset($callback[2])&&$callback[2])?$callback[2]:array();
if (isset($params[1]['task'])){
$rpc_id = $params[1]['task'];
}
$rst = app::get('ome')->matrix()->set_callback($callback_class,$callback_method,$callback_params)
->set_timeout($time_out)
->call($method,$params,$rpc_id,$gzip);
}
}else{
return $this->center_request($method,$params,$write_log,$http_method,$time_out);
}
}
public function center_request($method,$params,$write_log=array(),$http_method='POST',$time_out=10)
{
$url = MATRIX_RELATION_URL;
$sys_params = array(
'app' => $method,
'certi_id' => base_certificate::get('certificate_id'),
'from_node_id' => base_shopnode::node_id('ome'),
'from_api_v' => $params['from_api_v'],
'to_node_id' => $params['to_node_id'],
'to_api_v' => $params['to_api_v'],
'v' => $params['from_api_v'],
'timestamp' => date('Y-m-d H:i:s',time()),
'format' => 'json',
);
$query_params = array_merge($sys_params,$params);
$query_params['certi_ac'] = self::licence_sign($query_params,'ome');
$log_title = $write_log['log_title'];
$original_bn = $write_log['original_bn'];
if ($http_method == 'POST'){
$http = kernel::single('base_httpclient');
$response = $http->set_timeout($time_out)->post($url,$query_params,$headers);
$response = json_decode($response,true);
$rsp = array('rsp'=>'fail','msg'=>'','data'=>'');
if (!isset($response['res'])){
$rsp['msg'] = '请求超时';
}else{
$rsp['rsp'] = $response['res'];
$rsp['msg'] = $response['msg'];
$rsp['data'] = $response['info'];
}
//$logObj = kernel::single('omeapilog_log');
$log_type = $write_log['log_type'];
$log_type = $log_type ? $log_type :'other';
//$status = $rsp['rsp'] == 'success' ? 'success' : 'fail';
//$addon['msg_id'] = $rsp['msg_id'];
//$msg = $rsp['msg'];
//$logObj->write_action_log($log_title,$method,$query_params,$log_type,$status,$original_bn,$msg='',$addon);
return $rsp;
}else{
$query_str = array();
foreach ($query_params as $key=>$value){
$query_str[] = $key.'='.$value;
}
$query_str = implode('&',$query_str);
$src = $url.'?'.$query_str;
header('Location:'.$src);
exit;
//echo '<title>'.$log_title.':'.$original_bn.'</title><iframe width="100%" height="95%" frameborder="0" src="'.$src.'" ></iframe>';
}
}
/**
* licence生成加密串
* @access public
* @param $params
* @return String
*/
static public function licence_sign($params){
$str = '';
ksort($params);
foreach($params as $key => $value){
$str.=$value;
}
$token = base_certificate::token();
return md5($str.$token);
}
/**
* RPC异步返回数据接收
* @access public
* @param object $result 经由框架层处理后的同步结果数据
* @return 返回业务处理结果
*/
public function callback($result){
if (is_object($result)){
$callback_params = $result->get_callback_params();
$status = $result->get_status();
$msg = $result->get_result();
$err_msg = $result->get_err_msg();
$data = $result->get_data();
$request_params = $result->get_request_params();
$msg_id = $result->get_msg_id();
}else{
return true;
}
if($status == 'succ'){
$api_status = 'success';
}else{
$api_status = 'fail';
}
if($msg !=''){
$msg = '('.$msg.')'.$err_msg;
}
$rsp ='succ';
if ($status != 'succ' && $status != 'fail' ){
$msg = 'rsp:'.$status .'res:'. $msg. 'data:'. $data;
$rsp = 'fail';
}
//错误等级
if (isset($data['error_level']) && !empty($data['error_level'])){
$addon['error_lv'] = $data['error_level'];
}
$log_id = $callback_params['log_id'];
$oApi_log = app::get('ome')->model('api_log');
$oApi_log->update_log($log_id, $msg, $api_status, null, $addon);
//$log_detail = $oApi_log->dump($log_id, 'msg_id,params');
//只有接口类型为库存更新时才调用库存callback函数
return array('rsp'=>$rsp, 'res'=>$msg, 'msg_id'=>$msg_id);
}
/**
* RPC同步返回数据接收
* @access public
* @param json array $res RPC响应结果
* @param array $params 同步日志ID
*/
public function response_log($res, $params){
$response = json_decode($res, true);
if (!is_array($response)){
$response = array(
'rsp' => 'running',
'res' => $res,
);
}
$status = $response['rsp'];
$result = $response['res'];
if($status == 'running'){
$api_status = 'running';
}elseif ($result == 'rx002'){
//将解除绑定的重试设置为成功
$api_status = 'success';
}else{
$api_status = 'fail';
}
$log_id = $params['log_id'];
$oApi_log = app::get('ome')->model('api_log');
//更新日志数据
$oApi_log->update_log($log_id, $result, $api_status);
if ($response['msg_id']){
//更新日志msg_id及在应用级参数中记录task
/*
$log_info = $oApi_log->dump($log_id);
$log_params = unserialize($log_info['params']);
$rpc_key = $params['rpc_key'];
$log_params[1]['task'] = $rpc_key;
$update_data = array(
'msg_id' => $response['msg_id'],
'params' => serialize($log_params),
);*/
$update_data = array(
'msg_id' => $response['msg_id'],
);
$update_filter = array('log_id'=>$log_id);
$oApi_log->update($update_data, $update_filter);
}
//只有接口类型为库存更新时才调用库存callback函数
}
/**
* 更新库存回写状态
*/
function save_stock_callback($log_id,$oApi_log){
$log_info = $oApi_log->dump($log_id,'msg_id,params');
$log_params = unserialize($log_info['params']);
if($log_params[2][1]=='stock_update_callback') {
$list_quantity = json_decode($log_params[1]['list_quantity'],true);
$all_list_quantity = json_decode($log_params[1]['all_list_quantity'],true);
$oApiLogToStock = kernel::single('ome_api_log_to_stock');
$oApiLogToStock->save_callback(
$all_list_quantity,'success',
$params['shop_id'],$response['res'],$log_info
);
$oApiLogToStock->save_callback(
$list_quantity,$api_status,
$params['shop_id'],$response['res'],$log_info
);
}
}
/**
* 店铺绑定关系过滤
* 检查店铺shop_id为空时标识所有店铺是否可访问远端API接口服务并返回可用的node_id
* @access private
* @param string $shop_id 店铺标识ID
* @param string $method RPC远程调用接口名称
* @return boolean
*/
private function _check_node($shop_id,$method){
$node = $this->_get_node($shop_id);
if($node){
$request_whitelist = kernel::single('ome_rpc_request_whitelist');
$t_node = $node;
foreach($t_node as $k=>$v){
$res = $request_whitelist->check_node($v['node_type'],$method);
if(!$res){
unset($node[$k]);
}
}
if($node){
return $node;
}else{
return false;
}
}else{
return false;
}
}
/**
* 检查指定店铺及回调方法是否被禁止
*
* @param String $shop_id 店铺ID
* @param $method 调用方法
* @return boolean true 禁止 false 允许
*/
private function _check_request_config($shop_id, $method) {
$method = strtolower($method);
if ($method == 'store.items.quantity.list.update') {
$request_auto_stock = app::get('ome')->getConf('request_auto_stock_' . $shop_id);
//如无设置,缺省置为 true
if (empty($request_auto_stock)) {
$request_auto_stock = 'true';
app::get('ome')->setConf('request_auto_stock_' . $shop_id, 'true');
}
//如已经关闭了库存回写功能,返回 true
if ($request_auto_stock == 'false') {
return true;
}
}
return false;
}
/**
* 通过shop_id获取结点信息
* @access private
* @param $shop_id
* @return array 店铺绑定的节点数据
*/
private function _get_node($shop_id){
$shopObj = app::get('ome')->model('shop');
$node = array();
if(empty($shop_id)){
$shop_info = $shopObj->getList('node_id,node_type', '', 0, -1);
if($shop_info){
foreach($shop_info as $v){
if ($v['node_id']){
$node[] = array(
'node_id' => $v['node_id'],
'node_type' => $v['node_type'],
);
}
}
}
}else{
$shop_info = $shopObj->dump($shop_id,'node_id,node_type');
if ($shop_info['node_id']){
$node[] = array(
'node_id' => $shop_info['node_id'],
'node_type' => $shop_info['node_type']
);
}
}
return $node;
}
/**
* RPC同步日志队列
* @access public
* @param string $queue_title 队列标题
* @param array $queue_params 队列参数
* @param array $addon 附加参数
*
*/
public function api_queue($queue_title,$queue_params,$addon=''){
$oQueue = app::get('base')->model('queue');
$queueData = array(
'queue_title'=>$queue_title,
'start_time'=>time(),
'params'=>array(
'sdfdata'=>$queue_params,
'addon' => $addon,
),
'status' => 'hibernate',
'worker'=> __CLASS__.'.run',
);
$oQueue->save($queueData);
}
/**
* 执行API同步日志队列
* @param $cursor_id
* @param $params
*/
function run(&$cursor_id,$params){
$oApi_log = app::get('ome')->model('api_log');
if (!is_array($params)){
$params = unserialize($params);
}
$Sdf = $params['sdfdata'];
$addon = $params['addon'];
$title = $Sdf['api_title'];
$method = $Sdf['method'];
$params = $Sdf['params'];
$rpc_callback = $Sdf['rpc_callback'];
//附加参数
if (!empty($addon) && is_array($addon)){
$api_params = array_merge($params, $addon);
}else{
$api_params = $params;
}
$log_type = ome_rpc_func::method2type($method);
$log_id = $rpc_callback[2]['log_id'];
$oApi_log->write_log($log_id,$title,'ome_rpc_request','rpc_request',array($method,$api_params,$rpc_callback),'','request','running','',$addon,$log_type,$addon['bn']);
kernel::single('ome_rpc_request')->rpc_request($method,$params,$rpc_callback);
}
/**
*
* @param $url
* @param $params
* @param $time_out
*
* @return String
*/
function direct_request($url,$params,$time_out=5){
$headers = array(
'Connection'=>$time_out,
);
$core_http = kernel::single('base_httpclient');
$res = $core_http->post($url,$params,$headers);
$res = 'direct_request:' . $res;
kernel::log($res);
$res2 = 'direct_request content:' . $url."\n".json_encode($params);
kernel::log($res2);
return $res;
}
/**
* 返回验证字符串
*
* @param $params
*
* @return String
*/
function make_sign($post_params){
return base_certificate::getCertiAC($post_params);
}
}