• 注册
  • 查看作者
  • 宫论项目开发记录

    记录2023年项目进度周期。

    刷新置顶
  • 2
  • 732
  • 0
  • 21.24w
  • 小小乐小可鸭鸭

    请登录之后再进行评论

    登录
  • 0
    小小乐lv.2实名用户
    2025年8月29日
    1、移动端首页新增自定义meta字段选项:width=device-width:页面宽度与设备屏幕宽度相同,保证自适应。 initial-scale=1:初始缩放比例为1(即页面初始加载时不缩放)。 maximum-scale=1:用户可缩放的最大比例为1(即不能放大)。 minimum-scale=1:用户可缩放的最小比例为1(即不能缩小)。 user-scalable=no:禁止用户缩放页面(双指缩放等无效)。 viewport-fit=cover:针对 iPhone X 及以上带“刘海屏”的设备,页面内容会延伸至屏幕的安全区域,适配全屏显示。viewport-fit:有 auto(默认)、contain(内容不会被安全区遮挡)、cover(内容延伸到整个屏幕)。允许网页以“Web App”模式(即全屏模式)运行,隐藏 Safari 浏览器的工具栏和地址栏。
    2、为了确保移动端的配色一致性,会通过: root进行如下参数的后台接管配置:--xinle_color 主题主色,用于整个网站的主要颜色。 获取方式:xinle_get_option('xinle_mobile_defalut_color') --xinle-navbar-bg 导航栏背景色。 获取方式与主色一致。 --xinle-navbar-text-color 导航栏文字颜色。 获取方式:xinle_get_option('xinle_mobile_defalut_color_text') --f7-tabbar-link-active-color 底部 TabBar 激活时的链接颜色(活跃状态)。 获取方式与主色一致。 --f7-navbar-link-color 导航栏链接文字颜色。 获取方式与导航栏文字颜色一致。 --f7-navbar-font-size 导航栏字体大小,单位为 vw(相对于视口宽度)。 --f7-bars-text-color 所有 bars(导航栏、工具栏等)上的文字颜色。 获取方式与导航栏文字颜色一致。 --f7-toolbar-height 底部菜单栏高度,固定为 49px。 --f7-page-bg-color 页面背景颜色。 获取方式:xinle_get_option('xinle_mobile_defalut_page_bg_color’)。
    3、APP初始化首页的时候,会通过后台获取如下配置:获取当前登录用户的ID,并赋值给 $user_id。 $current_user 通常是通过 wp_get_current_user() 得到的用户对象。通过自定义函数 xinle_get_option 获取 WordPress 后台的“移动端Tab栏配置”选项,赋值给 $tab_config。 这个配置一般是控制移动端底部导航栏(TabBar)的内容和结构。通过 xinle_get_option 获取“页面配置”选项(一般为数组或对象),然后用 json_encode 转换为 JSON 字符串,赋值给 $routesJson。 这个 JSON 数据会传递给前端 JavaScript,用于动态渲染页面或路由。调用自定义函数 xinle_is_chat_list() 获取聊天会话消息列表。通常返回当前用户的聊天会话数据。
    4、APP端的视图窗口现已通过配置项 xinle_mobile_tab_config 进行读取和动态生成,该配置项能够灵活定义视图的相关属性并对其行为进行控制。目前支持的参数包括以下几项:key 用于标识视图的唯一性,以确保不同视图之间的区分;is_login 用于设置视图的访问权限,若该参数为真,则该视图仅对登录用户开放,并会强制要求用户完成登录操作;icon 指定视图的菜单图标,支持自定义图标样式以增强视觉效果;name 为视图的名称,用于显示在菜单或其他位置,帮助用户快速识别视图功能;active 定义视图的类名,主要用于调整样式或交互效果。
    5、视图主容器的处理,读取$tab_config(移动端底部Tab栏的配置数组),每次循环处理一个Tab页面。获取每个Tab的 key 和 page_name。 通过 xinle_is_config 获取该Tab的详细配置。 根据配置的布尔值,生成对应的class类名字符串(如隐藏导航栏、顶部下拉刷新、无限加载、需要登录等)。 只有第一个Tab设置为激活状态(tab-active)。 如果配置了隐藏头部,则加上 hide 类。输出每个Tab的最外层 div,ID为Tab的key,class为 view tab,如果是第一个Tab还会带 tab-active。 里面有页面容器、顶部导航栏。 导航栏左侧、右侧、标题都可以通过后台配置自定义内容(支持WordPress的shortcode)。页面内容区的class会根据配置动态组合,比如支持下拉刷新(ptr-content)、无限加载(infinite-scroll-content)、需要登录(is_login)等。
    6、主视图功能进一步优化,现已支持通过后台灵活设置更多参数,以满足不同场景的需求。具体来说,若当前Tab页配置了顶部下拉刷新功能,则会自动输出下拉刷新动画的HTML结构,提供更直观的交互体验;如果后台已指定该Tab页的具体页面文件地址(例如 /wp-content/themes/你的主题/xxx.php),系统将自动require该文件内容,完成页面内容的集成展示,确保模块加载的便捷性与一致性。而对于未配置具体页面地址的情况,则会智能显示一个加载动画以及提示信息,例如“后台未设定模块地址”,并附带一个跳转链接,方便用户快速定位到后台设置页面进行配置调整。最后,系统会自动关闭HTML标签,并自增变量,顺畅进入下一个Tab页的循环处理,确保每个模块都能按照设定逻辑高效加载与呈现。
    7、当前,APP页面的所有组件均通过后台进行配置管理。在首页初始化时,系统会通过读取xinle_page_config来生成相应的页面。在后台配置页面时,需要设置以下参数:首先是route['key'],即页面组件的唯一标识符;其次是route['componentUrl'],这是页面的读取路径,必须经过标准化的Framework7构建才能被识别。此外,还有route['admin'],此参数用于限定页面访问权限,仅允许管理员访问;最后是route['login'],该参数确保页面仅在用户登录后才能访问。为了确保页面能够正确构建并响应,所有页面组件都必须在后台进行适当配置,否则前端将无法正常访问。
    8、动态生成 Framework7 路由配置的处理逻辑如下:首选通过DOMContentLoaded确保所有 DOM 元素加载完成后再执行代码,避免未加载导致的报错。变量定义visitedPages:用于记录已访问页面(目前没用到,可用于后续功能如页面缓存等)。 app_path:存储移动端页面的基础路径,方便后续拼接组件路径。 routesData:从 PHP 传来的路由 JSON 数据,包含每个页面的配置(如 key、componentUrl、login、admin 等)。遍历每个路由配置,生成 Framework7 的路由对象数组。 path:每个页面的访问路径。 componentUrl:组件页面的实际路径。 beforeEnter:路由进入前的钩子函数,用于权限校验。
    9、Framework7路由配置现在支持权限检测处理,系统会通过beforeEnter来检测当前页面组件访问权限:如果当前路由需要登录(login==true),且用户没登录(!xinle.is_login),则: 调用登录函数 xinle_login()。 阻止跳转,reject()如果页面需要管理员权限,且未登录,先强制登录。如果已登录但不是管理员,则弹窗提示无权访问,并阻止跳转。所有权限校验通过后,允许页面跳转。注:对每个页面实现登录和管理员权限控制,无权限时自动拦截跳转,并弹窗或跳转登录。支持后续扩展页面缓存、跳转方向等功能。
    10、APP端的初始化工作:1. 绑定应用根节点 el: '#app' Framework7 会把页面的主要内容绑定到这个元素( <div id="app"></div>)。 2. 基础配置 name: '奇峰药业' 应用名称。 theme: 'ios' 使用 iOS 风格主题。 infiniteScroll: true 启用无限滚动。 panel: { swipe: true } 允许侧边栏通过滑动打开。 view: { pushState: true, iosSwipeBack: true } pushState: true 启用浏览器历史记录(地址栏变化)。 iosSwipeBack: true 启用 iOS 风格的左滑返回上一页。 3. 路由配置 routes: [ ... ] 路由规则数组,决定页面跳转和内容加载的方式。 3.1. 动态路由(...routes) 由你之前的代码动态生成,每个路由都包含权限校验(登录、管理员)、页面路径和组件路径。 跳转到这些页面时,都会先执行 beforeEnter 权限验证。
    11、在应用实例初始化阶段,当用户通过点击链接或导航菜单跳转页面时,Framework7将按照以下流程进行处理:首先,根据用户跳转的路径匹配对应的路由配置,并执行beforeEnter权限校验(如果设置了相关逻辑),判断用户是否需要登录或具备管理员权限等条件。若权限不满足,系统将弹窗提示或跳转至登录页面,以阻止当前页面跳转操作。权限通过后,系统会加载对应的页面组件。对于未匹配的路径,系统会通过通配符路由进行处理,展示404页面或加载指定的外部页面。此外启用了pushState功能,浏览器地址栏会随着页面跳转动态更新。
  • 0
    小小乐lv.2实名用户
    2025年8月28日
    1、移动端目前实现了对浏览器返回事件(popstate)的监听,利用history.back()、history.pushState()等API对历史记录进行操作时,会触发popstate事件,从而执行绑定的回调函数,最终调用xinle_page_back()方法以完成页面返回的逻辑处理。而在APP环境下(通过检测userAgent中是否包含Html5Plus判断),不会绑定页面上的.back按钮事件,而是通过APP的原生返回事件进行处理,确保在不同环境下都能实现稳定的返回功能。
    2、xinle_page_back负责页面路由后退返回机制,具体的执行流程如下:检查页面上是否存在 layui 的遮罩层(即 .layui-m-layershade)。 如果存在遮罩层,优先关闭所有 layer 弹窗(layer.closeAll()),并终止后续返回操作(return false;)。 这样可以防止用户误操作导致弹窗未关闭直接跳转页面。 首页特殊处理: 如果当前用户处于首页(user.is_home 为 true),可以在这里做特殊处理(如弹窗提示或日志记录)。 获取当前视图对象: 获取框架下当前的视图实例(app.views.current),通常用于 SPA 或前端路由管理框架。 判断参数并返回页面: 如果传入了 url 参数,则直接返回到指定页面,并强制刷新(force: true)。 如果没有传入 url,则默认返回到上一个页面。
    3、安卓返回键处理(plusready 事件) 1. 监听 APP 环境准备就绪 通过 document.addEventListener('plusready', ...),确保代码只在 APP(Html5Plus)环境下运行。 2. 获取当前 Webview 使用 plus.webview.currentWebview() 获取当前页面的 Webview 实例,后续返回操作都基于此 Webview。 3. 监听安卓物理返回键 plus.key.addEventListener('backbutton', ...) 监听安卓设备的物理返回键事件。 4. 判断 Webview 是否可以后退 webview.canBack(function(e){...}) 判断当前 Webview 是否有历史记录可返回。 5. 处理流程如下: a. 如果当前在首页(user.is_home) 直接调用 main.moveTaskToBack(false),把 APP 退到后台(返回桌面),而不是直接退出 APP。 b. 如果有弹窗 检查是否有 .modal-overlay-visible 或 .login-screen.modal-in 元素(即页面有弹窗)。 如果有,优先关闭所有弹窗(myApp.closeModal()),并移除 .popup-overlay 的某些 class(此处建议补全 class 名称)。 c. 如果有 Fancybox 弹窗 检查 .fancybox-is-open,如果有,关闭 Fancybox 弹窗($.fancybox.close())。 d. 否则正常页面后退 如果 Webview 可以后退(e.canBack),执行 webview.back() 返回上一页。 如果不能后退(已到最顶层页面),同样调用 main.moveTaskToBack(false),让 APP 退到后台。
    4、移动端目前在页面初始化时,会执行一系列页面路由监听操作,以确保用户操作和页面状态的实时响应。这些监听事件包括以下几种:pageInit(页面初始化),用于加载页面初始内容及相关逻辑;routeBack(页面行为:后退),当用户执行页面后退操作时触发;routeChange(页面行为:前进),响应用户的页面前进操作;pageBeforeIn(页面即将进入),在页面正式进入前预先处理相关逻辑;pageAfterIn(页面已进入),用于处理页面进入后的状态更新;pageBeforeOut(页面即将离开),在页面离开前执行清理或保存操作;pageAfterOut(页面已离开),确保页面离开后的后续逻辑处理;pageBeforeRemove(页面即将被移除),用于监听页面被移除前的最后处理环节。这些事件的组合使用能够有效提升页面切换的流畅性和用户体验,同时为开发者提供灵活的页面状态管理能力。
    5、移动端在触发(pageBeforeIn:页面即将进入时)会触发以下处理:判断当前页面是不是首页或主Tab页面(通过判断页面名称是在一个预设的数组里)。 如果是首页或Tab页面: 会把浏览器地址栏的路径重置为根路径 /,但不会刷新页面,这样可以避免路由混乱; 同时把一个全局变量(比如 user.is_home)设置为 true,表示当前用户正处于首页; 然后调用一个初始化首页的函数,把首页内容重新渲染出来,确保首页功能正常。 如果不是首页或Tab页面: 只把那个全局变量设置为 false,标记当前页面不是首页。
    6、移动端路由监听:当页面完成切换并“进入”后,会自动触发 pageAfterIn 事件。 2. 获取并保存当前页面内容区域 代码通过 $('.page-content.' + page.name + '_content') 获取当前页面的内容区域,并赋值给全局变量 user.page_content,方便后续操作或渲染。 3. 打印调试信息 在控制台输出:“页面已进入:” 以及页面的名称和路由地址,方便开发时定位和调试当前页面状态。 4. 记录页面历史路由 通过 page.route.url 获取当前页面的路由地址(URL)。 判断该 URL 是否已经存在于 page_history 数组中: 如果不存在,则将当前页面的 URL 添加到 page_history,用于记录用户访问过的页面,方便后续做页面回退、历史导航等操作。
    7、移动端路由监听:当页面即将被销毁、移除(比如返回、跳转到其他页面等)时,自动触发 pageBeforeRemove 事件。 2. 控制台打印调试信息 在控制台输出:“页面即将被移除:” 以及当前页面的名称,方便开发过程中追踪页面的生命周期。 3. 从历史记录中移除当前页面的路由 获取当前页面的路由地址(page.route.url),赋值给变量 pageUrl。 在 page_history 数组中查找该 URL 的位置(indexOf)。 如果找到了(index !== -1),说明历史记录中有这个页面的路由: 通过 splice 方法把这个路由地址从 page_history 数组中删除,保持历史记录的正确性,避免重复和无效数据。
    8、当移动端首页的 DOM 加载完成后(即触发 jQuery 的 $(document).ready() 方法),开始执行预设的函数内容以确保页面功能的正常运行。首先,初始化聊天会话页面,通过调用 xinle_update_view_messages() 方法实现聊天列表的加载与消息内容的显示,同时支持页面的自动刷新,以便用户在进入页面时即可看到最新的聊天信息,优化交互体验。接着,处理 URL 哈希值以实现页面跳转逻辑。具体流程如下:通过 window.location.hash 获取当前窗口的哈希值(如 #chat),然后去掉哈希符号 #,提取实际路径(如 chat)。为了统一页面入口路径并简化后续的页面管理,使用 window.history.pushState(null, null, '/') 将浏览器地址栏的路径设置为根路径 /,这一操作不会触发页面刷新。最后,根据处理后的路径调用 xinle_page_open(path) 方法,加载对应的页面内容或模块。
    9、APP端新增页面路由访问事件 xinle_page_open,负责处理页面访问请求,确保页面切换逻辑高效且流畅。其执行流程如下:首先,函数会获取当前视图对象和路由管理器,这两个核心对象是后续页面操作的基础,确保所有页面操作都基于当前视图和路由进行。随后,函数会检查自定义的历史记录数组 page_history,判断目标页面是否已经打开过。如果发现该页面 URL 已存在于历史记录中,则直接调用 xinle_page_back(url) 返回到之前打开的页面,避免重复打开,并终止函数执行。接着,函数会进一步判断当前页面的 URL 是否与目标页面一致,如果当前页面就是用户要打开的页面,则仅输出一条警告信息,避免页面重复加载,提升性能。
    如果目标页面不在当前页面但已存在于路由的历史记录中,函数会采取三步处理措施:首先,删除页面残留的 DOM 元素,避免内容冲突或重复;其次,从路由历史记录中移除该页面,确保历史记录的准确性;最后,如果该页面是动态注册的路由,则尝试移除相关路由配置(若移除失败会输出警告信息)。在完成上述检查与清理后,函数将通过路由的导航方法 navigate 打开目标页面,并传递相关参数(如动画效果、回调函数等),以实现页面的顺利切换。
    10、APP端新增了一个用于刷新当前页面的路由处理方法(xinle_page_refresh),其执行流程设计如下:首先,通过 app.views.current 获取当前激活的视图对象(View),在 Framework7 框架下,通常只有一个主视图,这一步确保了操作的目标视图是当前正在使用的视图。接着,方法会判断是否传入了 url 参数:如果传入了 url,则将其作为需要刷新的目标页面地址;如果未传入 url,则会自动获取当前路由对象的 URL,将当前页面的地址作为默认刷新目标。随后,方法调用视图对象的路由器(View.router.navigate())来重新加载目标页面,并传递两个关键参数——reloadCurrent: true 和 ignoreCache: true。其中,reloadCurrent: true 强制重新加载当前页面,而非简单地跳转;ignoreCache: true 则确保忽略页面缓存,从服务器端重新获取页面内容,以保证页面内容的最新状态。刷新操作完成后,无论是当前页面还是指定的其他页面,都会根据目标 URL 重新加载,用户看到的始终是最新的页面内容。
    11、宫论APP端的页面路由处理已实现全面监听,对于页面的访问、后退、销毁以及初始化等操作均设置了对应的监听器以执行相应的响应处理。在页面请求阶段,通过xinle_page_open方法接管并执行处理;当用户触发页面后退时,则由xinle_page_back方法负责响应;而页面刷新操作则交由xinle_page_refresh方法进行处理。整个路由的响应逻辑完全依托于Framework7框架进行管理,确保页面切换的流畅性与稳定性。
  • 0
    小小乐lv.2实名用户
    2025年8月27日
    1、在APP端完成了xc_hook_app_plus初始化行为动作后,系统会自动触发【xc_hook_app_webview】监听器。由于当前宫论APP采用了PWA模式运行,webviews对象的行为需要进行全局监听处理,以确保页面事件能够根据实际需求随时进行动态调整。为此,系统专门封装了一个独立的方法,用于统一管理和控制webviews对象的监听逻辑。
    2、当触发 xc_hook_app_webview 时,系统会通过 plus.webview.currentWebview() 获取当前页面的 webviews 对象,并将其赋值到全局变量 webviews 中,方便后续页面直接通过该全局对象进行操作和处理。目前,webviews 已新增对外部链接点击(overrideUrlLoading)的处理逻辑。当用户在 webviews 中点击链接时,系统会监听该链接是否属于宫论内部链接。如果检测到不是宫论链接,则会触发拦截机制,禁止外部跳转,确保所有的跳转操作均通过系统内置方法处理,进一步提升安全性和控制力。此外,系统还对以 "tel:" 开头的 URL 进行专门监听,通过调用 plus.runtime.openURL 实现页面跳转,并强制跳转到手机的拨号界面,便于用户直接进行电话拨打操作。
    3、新增方法plus_open_url,专门用于处理APP端的页面跳转逻辑,主要覆盖了APP启动图跳转以及消息通知跳转的场景。该方法首先会通过xinle_isplus对用户环境进行验证,确认是否处于plus环境,如果验证结果为非plus环境,则直接返回false,避免后续操作。接下来,对传入的type变量进行判断,根据不同类型执行对应的跳转策略:如果type为webviews,则调用plus.runtime.openWeb,通过内置的WebSocket视图窗口实现页面跳转;如果type为web,则使用plus.runtime.openURL直接打开浏览器链接;而当type为page时,则触发内置的页面访问处理器xinle_page_open,完成APP内部页面的跳转。此外,为了优化移动端页面的用户体验,页面跳转过程中还支持通过F7框架实现流畅的移动端页面加载效果。
    4、APP端计划新增支持多种登录方式,包括原生手机一键登录、iOS苹果登录以及微信登录等。这些登录功能均通过对应的SDK进行调用。为提升后续维护效率和统一管理,决定封装一个方法——plus_login_auth,用于处理登录相关的逻辑。该方法不仅包括鉴权、SDK调用,还负责API对象的统一管理。使用时需传递一个type变量,用以标识登录请求的来源,例如weixin表示微信登录,univerify表示一键登录。在具体执行业务逻辑时,会通过xinle_isplus进行校验,判断当前客户端是否处于APP环境。如果校验未通过,则直接返回错误,确保登录流程的安全性和规范性。
    5、新增方法 plus_check_app,用于检测当前设备是否已安装指定的应用程序。此方法需要传递应用的包名或通用名称作为参数,系统将通过内置查询机制进行判断。如果检测到应用已安装,则返回 true;若未安装,则返回 false。此功能尤其适用于某些特定场景,例如调用支付宝进行支付时,若用户设备上未安装支付宝应用,则系统会主动拦截相关请求,并提示用户安装对应的应用程序以解决问题。通过这种方式,能够有效提升用户操作的流畅性,同时避免因缺少必要应用而导致的功能异常或用户体验下降。
    6、plus_login_auth已支持微信APP登录请求,具体执行流程如下:判断当前环境是否支持微信登录 首先判断 type == 'weixin',说明本次请求是微信登录。 使用 plus_check_app(type) 检查当前设备是否安装了微信客户端。 如果未安装,弹出提示“微信客户端未安装,无法使用”,流程终止。 检查微信SDK是否初始化 判断 app_login_auth['weixin'] 是否已初始化。 如果未初始化,弹出提示“未初始化微信SDK,无法发起登录鉴权”,流程终止。 发起微信授权登录 调用 app_login_auth['weixin'].authorize(...) 方法,开始微信授权流程。 授权请求携带参数: scope: 'snsapi_userinfo' state: 'authorize test' appid: xc.wechat_app_id 处理授权结果 授权成功回调(第一个 function 参数): 显示“登录中”加载提示。 输出授权成功的 code 到控制台。 向后端接口 xc.global_url + "/api.php" 发送 POST 请求,携带参数: type: 'xc_app_login_weixin' code: e.code 后端返回结果后,隐藏加载提示,并根据返回内容进行处理: 如果 msg.code == 0(登录成功): 如果返回的 msg.link 存在,说明需要注册账户: 弹出“进入注册流程”提示。 1秒后跳转到 msg.link 注册页面。 如果没有 msg.link,说明登录成功: 执行 xc_login_ok_hook(msg),进行登录成功后的处理(如保存用户信息、跳转主页等)。 输出返回内容到控制台。 如果 msg.code != 0(登录失败): 弹出失败提示,输出返回内容到控制台。 授权失败回调(第二个 function 参数): 输出授权失败信息到控制台。 弹出“授权失败”提示,终止流程。 流程结束。
    7、plus_login_auth已支持univerify(一键登录请求),具体执行流程如下:判断 app_login_auth['univerify'] 是否存在,或者 univerify_login_error 是否被定义。 如果 univerify_login_error 被定义,弹出其内容作为提示。 否则提示“当前设备不支持一键登录”。 以上任一条件满足,流程终止。 用户协议和隐私协议检测 通过 xinle_is_config 方法分别检测用户协议和隐私协议配置,便于后续展示。 控制台输出用户协议的链接。 设置协议默认勾选状态 默认情况下,defaultCheckBoxState 设为 true(已勾选)。 如果设备厂商为“Huawei”,则设为 false(未勾选)。 发起一键登录授权 调用 app_login_auth['univerify'].login 方法,打开一键登录授权界面。 登录成功后回调,拿到授权信息: openid:用户唯一标识 access_token:访问令牌 控制台输出登录成功的 openid 和 access_token。 显示“正在处理登录请求”的等待弹窗。 与后端交互进行登录处理 通过 AJAX POST 请求将 openid 和 access_token 发送到后端 /login.php,请求类型为 xinle_app_login_univerify。 后端返回数据后,关闭等待弹窗,并关闭授权界面。 处理后端返回结果 如果 msg.code == 0(登录或注册成功): 如果 msg.register 存在,说明新账户注册成功,弹窗提示“账户注册成功”,1.5秒后刷新首页。 如果没有 msg.register,说明直接登录成功,弹窗提示“账户登录成功”,1.5秒后刷新首页。
    8、univerify(一键登录)功能现已全面升级,支持通过univerifyStyle直接自定义页面样式。此前,样式调整需要通过APP进行初始化配置,每次修改都需发布新的APP版本才能生效,导致维护和管理流程较为繁琐。而现在,系统引入了内置的PLUS事件机制,配置调整可以实时生效。
    9、集成了plus事件中的plus_camera功能,实现了调用手机系统摄像头进行拍照或录制视频的操作。该方法需要传递两个关键变量:filter和time。其中,filter用于指定操作类型,支持两种模式——“image”和“video”,分别对应拍照图片和录制视频;time为可选参数,用于设置录制视频的时长,最大支持60秒,可根据实际需求进行自定义。在调用摄像头功能前,系统会先通过xinle_isplus验证用户是否处于APP环境中,若用户不在APP环境,则会返回对应的错误提示;若处于APP环境中,则会进一步通过plus_is_permission检测用户是否已授予应用所需权限。如果用户未开放摄像头权限,系统将终止操作并返回相应的错误信息。
    10、通过plus_camera发起的拍照的执行流程如下:用摄像头的 captureImage 方法进行拍照。 如果拍照成功: 关闭之前可能存在的权限提示(Toast)。 控制台打印照片的路径,方便调试。 用 H5+ 的文件系统API解析照片路径,获取文件对象。 读取这个文件内容为base64格式。 将base64数据转成Blob对象,再进行上传操作(通过自定义函数)。 如果解析路径或读取文件失败,会关闭提示,并输出错误信息。 如果拍照失败: 关闭权限提示(Toast)。 输出拍照失败的原因。 如果失败原因是“没有权限”,就弹出一个对话框,询问用户是否前往手机设置页面开启相机权限。 用户同意就跳转到设置页面。 用户取消就不做处理。
    11、APP端新增了一个名为plus_gallery的方法,用于打开系统相册以选择图片或视频。该方法需要传递两个关键变量:filter用于指定选择类型(视频或图片,默认值为图片);number用于指定选择的数量,若选择视频则数量固定为1,若选择图片则可以自由设置,但受系统限制,最多可选择9张图片。此功能首先会通过xinle_isplus方法验证当前环境是否为APP端,若检测到不在APP环境内,则直接返回错误信息,终止操作。随后,系统会通过plus_is_permission方法检测用户是否已授予应用所需权限。如果用户未开启相册权限,操作将无法继续,系统会返回相应的错误提示,确保流程的安全性和用户隐私的保护。
  • 0
    小小乐lv.2实名用户
    2025年8月26日
    1、在用户打开APP时,系统会执行一个名为 plusReady 的初始化动作,其主要功能是定义一个全局变量 app_plus,并将其默认值设置为 false,以此假定当前运行环境不支持 plus(即非APP环境)。当页面加载时,系统会调用 plusReady(callback) 方法进行进一步处理。如果此时 window.plus 已存在,则表明 plus 环境已经准备就绪,系统会立即将 app_plus 设置为 true,并执行传入的回调函数;如果 window.plus 尚未存在,则系统会监听 plusready 事件,当事件触发时,同样将 app_plus 设置为 true,然后执行回调函数。通过 app_plus 变量,后续可以方便地验证用户是否处于 APP 环境:若值为 true,则说明当前为 APP 环境;若值为 false,则表示非APP环境。
    2、一旦APP完成初始化,系统将通过plusReady回调触发一个关键事件:xc_hook_app_plus。此方法主要负责处理APP首次启动时的初始化操作。首先,系统会检测当前用户是否已登录。如果用户已登录,则会通过plus.push.getClientInfo().clientid获取用户的推送标识码,同时利用plus.device.getDeviceId()获取设备的唯一标识码。接下来,系统会发起一个与后端交互的AJAX请求,将上述两个参数传递到xc_hook_app_plus接口进行处理。其中clientid是用户推送唯一标识,触发APP通知消息需要用到这个。getDeviceId则是设备标识,客户端的身份。
    3、后端API接口收到UUID和clientid数据包后,会执行如下处理:首程序会判断当前用户ID是否为空。如果为空,说明没有用户登录或识别,程序会直接结束,不做任何操作。获取客户端标识信息程序会从前端提交的数据中获取clientid和uuid两个值,这两个值通常用于标识设备或客户端。如果这两个值没有传递,则默认为空。处理clientid绑定关系如果获取到clientid,程序会检查是否有其他用户已经绑定了相同的clientid。如果查到有其他用户绑定了这个clientid,而且不是当前用户,则会把这些用户的clientid信息删除,确保这个clientid只属于当前用户。然后,程序会将clientid写入当前用户的资料,并同时更新到浏览器的cookie里,方便前端后续使用。处理uuid绑定关系如果获取到uuid,程序会检查是否有其他用户已经绑定了相同的uuid。如果查到有其他用户绑定了这个uuid,而且不是当前用户,则会把这些用户的uuid信息删除,确保这个uuid只属于当前用户。然后,程序会将uuid写入当前用户的资料,并同时更新到浏览器的cookie里。
    4、新增了xinle_fingerprint_update钩子,专门负责更新用户指纹设备信息。由于宫论业务涉及到第三方交易体系,对用户客户端的管控要求极为严格,因此每个客户端和设备的敏感操作都会被记录其指纹信息,以确保操作的安全性和可追溯性。其中,APP端通过UUID记录设备指纹,而其他客户端则通过浏览器指纹进行追踪。为满足这一需求,封装了一个HOOK用于处理指纹信息的更新动作,该钩子在执行更新时不仅需要确保操作的安全性和可靠性,还需具备一定的灵活性,以应对复杂的使用场景。只有在满足所有安全验证条件的情况下,更新动作才能被成功触发,从而进一步强化对用户敏感操作的防护机制。
    5、新增了数据表 xinle_security,该表用于专门处理设备指纹信息的存储与管理。该表的设计旨在支持多种终端设备的指纹数据记录,便于后续的数据分析和风控处理。其结构及参数设置如下:
    * id:作为表的主键,类型为 BIGINT UNSIGNED,并设置为自动递增,确保每条记录具有唯一性。
    * ip:用于存储用户的 IP 地址,支持 IPv4 和 IPv6 格式,增强了对多种网络环境的兼容性。
    * time:记录每条数据的创建时间,默认值为当前时间,便于追踪数据的生成时刻。
    * update_time:记录每条数据的最后更新时间,默认值为当前时间,并设置为在数据更新时自动刷新,确保记录时间的实时性。
    * h5_fingerprint:可选字段,用于存储 H5 端设备的指纹信息,适配移动端浏览器场景。
    * wx_fingerprint:可选字段,用于存储微信端设备的指纹信息,支持微信小程序或内嵌浏览器的场景。
    * app_fingerprint:可选字段,用于存储独立 APP 的设备指纹信息,覆盖移动应用的场景。
    * pc_fingerprint:可选字段,用于存储 PC 端设备的指纹信息,适配桌面浏览器或客户端应用的场景。
    * uuid:可选字段,存储设备的唯一标识,用于区分不同设备,进一步提升数据的唯一性和可追溯性。
    6、xinle_fingerprint_update已完成封装,当触发客户端指纹更新请求的时候,会执行以下动作:首先,定义数据表名为 xinle_security,初始化一个空数组 $security。 获取当前用户ID,如果没有登录,则返回“用户未登录”提示,并结束流程。 会话与指纹获取 检查PHP会话状态,如果未开启,则自动启动Session。 从Cookie中获取 fingerprint(设备指纹)和 uuid(APP设备指纹),如果指纹不存在,则返回“指纹不存在”,流程结束。 收集安全信息 通过函数获取当前用户的IP地址,存入 $security['ip']。 查询数据库中是否已有该用户的指纹记录。 根据访问环境(微信、APP、H5、PC)将指纹分别存入不同字段: 微信环境:wx_fingerprint APP环境:app_fingerprint(并可处理uuid,uuid为APP端独有) H5环境:h5_fingerprint PC环境:pc_fingerprint 如果环境不匹配,返回“环境异常”,流程结束。 如果Cookie里有 uuid,也一并存入 $security['uuid']。 数据库操作:更新或新增指纹记录 如果数据库已存在该用户的指纹记录: 更新指纹信息和更新时间。 如果更新失败,返回“指纹更新失败”,流程结束。 更新成功,返回“更新指纹成功”。 如果数据库不存在该用户的指纹记录: 写入新的指纹信息。 如果写入失败,返回“指纹写入失败”,流程结束。 写入成功,返回“写入指纹成功”。
    7、APP初始化动作(xc_hook_app_plus)在完成uuid和推送标识处理动作后,还会通过 plus.oauth.getServices执行一键登录SDK的初始动作,具体执行流程如下:调用授权服务列表接口 plus.oauth.getServices(function(services) {...}, function(e){...}) 异步获取可用的第三方登录授权服务列表。 2. 遍历服务列表 对返回的 services 数组进行 forEach 遍历。 每个服务对象 obj 按 id 存入 app_login_auth 对象,方便后续调用。 3. 一键登录服务预处理 如果服务ID为 'univerify'(即一键登录服务): 调用 preLogin 方法进行预登录操作。 预登录成功时: 控制台输出“手机一键登录初始化成功”。 记录当前时间 univerify_login_time。 可以显示一键登录选项给用户。 预登录失败时: 控制台输出“初始化一键登录失败”及错误信息。 记录错误信息到 univerify_login_error。 可以选择不显示一键登录或置灰。
    8、在APP初始化阶段,通过获取当前页面的WebView对象来管理开屏窗口(开屏广告页)。开屏窗口的关闭会触发以下操作:版本更新检查根据配置判断是否需要检查APP版本更新,若需要则弹出更新提示或进入更新流程。开屏广告点击跳转记录用户点击广告的信息(时间、链接、类型等),存储在本地。开屏窗口关闭时,校验点击时间是否在20秒内(防止过期或误跳转)。若通过校验,根据点击类型和目标地址完成跳转。跳转后清除记录,避免重复跳转或误操作。防止误操作限制广告点击生效时间为20秒,并清除记录,防止多次点击或误触导致异常跳转。注:通过统一管理开屏窗口,确保版本更新、广告跳转和用户操作的准确性与可靠性。
    9、为了加快下次 APP 启动速度,后端获取的以下数据会通过 app_plus_storage 方法写入手机设备的本地缓存: 启动图配置信息 系统默认背景颜色 版本配置参数 下次启动时,APP会优先读取本地缓存的数据,而不是等待后端响应。这种机制确保启动过程更快、更流畅,同时后端的数据更新仅用于保证下次启动时数据及时生效,而非当前启动直接使用。
    10、宫论APP现已全面支持原生微信支付和支付宝支付功能。在启动APP时,系统会自动调用 plus.payment.getChannels 方法,以获取设备支持的支付通道列表。该方法能够有效地检测并返回当前设备所支持的支付方式。在获取到支付通道列表后,系统会遍历该列表,并将每个通道对象存储到 app_payment_list 中,确保后续支付操作的便捷性和高效性。接下来,系统会根据具体需求,通过指定支付通道 ID(例如 'desiredChannelId'),进行针对性的初始化操作,从而确保支付功能的正常运行。如果在获取支付通道列表时发生错误,系统会及时捕获并打印日志报错信息。
    11、xc_hook_app_plus完成封装,当APP启动的时候系统会执行以下操作:用户身份验证与设备绑定:确保推送服务和设备信息的唯一性。安全机制强化:通过设备指纹记录和更新,增强风控能力。登录流程优化:集成一键登录服务,简化用户操作。开屏窗口管理:优化广告跳转与版本更新流程,防止误操作。启动性能优化:利用本地缓存加速启动,提升流畅性。支付功能支持:初始化支付通道,满足多样化支付需求。
  • 0
    小小乐lv.2实名用户
    2025年8月25日
    1、服务器的PHP版本已经成功升级至8.4的最高版本,这将为APP端接口的后续优化奠定坚实的基础。未来,计划将所有接口迁移至高性能架构,以显著提升并发请求的处理能力,确保在高负载下系统依然稳定运行。由于此次升级跨度较大,需密切关注现有接口的兼容性问题,特别是涉及第三方SDK扩展的部分,必须确保它们能够顺利适配新版本,以避免在生产环境中出现功能异常或性能下降的情况。通过这种全面升级,提高了系统的灵活性和扩展性。
    2、鉴于当前后端并发性能的瓶颈以及前端组件版本较为老旧的问题,宫论APP端的项目将全面升级并脱离现有框架体系。后端的APP请求接口将完全由新版本的程序进行处理,同时为了保障现有功能的平稳过渡,现有的HOOK钩子功能将继续保留并支持。新版本的后端架构将基于【Swoole、Redis、WebSocket、Workerman、PHP8.4】进行全新构建,通过这些技术的结合,进一步提升系统的并发处理能力、运行效率以及稳定性。注:现有的接口请求仍旧保存,但是会逐步过渡到新架构。
    3、服务器的 wwwroot 文件夹中新增了一个名为 APP 的目录,后续所有的 API 接口和前端组件页面都将通过该目录下的主题架构程序进行统一处理。其中前端APP页面架构将选用了 Framework7(版本号 v8.3.4),Framework7是一个专为构建移动端应用程序(包括 iOS 和 Android)而设计的前端框架。Framework7 提供了丰富的原生应用风格 UI 组件和流畅的交互效果,例如滑动菜单、弹窗、标签页等,能够大幅提升用户体验。此外,它在开发 PWA(渐进式 Web 应用)和 Hybrid App(混合应用)方面也表现出色,既能满足现代化移动端开发的需求,又具备高度的灵活性和扩展性。
    4、新程序架构现已成功集成Codestar Framework配置组件,与之前使用的LightSNS主题采用的是相同的配置框架。这一选择是由于我们需要将大量现有配置平滑过渡到新程序中,因此后台设置仍然沿用原有的配置方式,以便于配置的迁移和管理。值得注意的是,此次集成的Codestar Framework版本为2.3.1,采用了内置hook的方式进行挂载。
    5、程序目录架构设计如下:
    * log:日志存储目录,所有系统运行及调试过程中生成的日志文件都会存放于此,方便后续的排查与分析。
    * configure:项目配置文件目录,通过 Codestar 平台集成的后台配置选项也存储于此,便于管理和修改项目的全局配置。
    * mobile:移动端页面组件目录,主要用于集成移动端相关的页面组件,所有 APP 的前端组件均在此目录中构建与维护。
    * api:统一接口管理目录,负责前后端交互的所有请求,集中处理接口的定义、管理及调试,确保数据交互的高效与安全。
    * functions:全局自定义函数与脚本的存放中心,包括 Redis、Swoole 等多种配置及自定义逻辑,提供系统级别的功能支持。
    * assets:前端资源扩展目录,用于存储 JS 和 CSS 文件,所有前端页面的脚本及样式扩展均在此处集中管理,提升代码可维护性与复用性。
    * sdk:第三方扩展包集合目录,所有外部引入的 SDK、工具包和依赖文件均统一存放于此,方便统一管理和更新。
    * admin:后台配置管理目录,用于集中管理后台的所有配置选项,同时内置的一些原生扩展功能也在此目录集成,支持后台的灵活配置和扩展开发
    6、完成了FontAwesome 7.0图标组件的集成工作,APP端的所有图标资源将统一通过该图标库调用。FontAwesome 7.0 拥有多达数千甚至上万个图标资源,能够全面覆盖页面设计中的图标需求,提供了极大的灵活性与丰富性。为优化页面加载性能,图标组件的加载采用异步方式处理,通过 wp_enqueue_script 实现延迟加载机制,确保在页面其他内容完全加载完毕后再执行图标库的加载,有效避免因资源加载过多导致的页面阻塞问题。
    7、新版本的APP在实现上全面采用HTML5+(plus)技术进行交互处理,页面构建方面选择了Framework7框架,以提升开发效率和用户体验。前后端数据交互模式采用分离式设计,确保数据传输的独立性和安全性。对于需要调用原生SDK的功能模块(如APP内支付、地图分享、硬件功能调用、相册读取等),通过plus事件机制发起操作,并通过回调方法实时监控和处理相关响应。这一套设计防范的优势,可以做到前后端分离、离线支持、页面实时更新、跨平台解决方案。
    8、在APP初始化过程中,系统会自动加载【PLUS】脚本库,该脚本库是整个应用底层交互功能的重要核心。所有涉及APP原生交互的请求都会通过该脚本库进行统一集成处理。脚本库内部封装了多种底层事件处理逻辑,例如【APP统一支付功能、统一分享操作、SDK登录请求的管理、手机摄像头与相册的获取操作、设备权限检测与权限集成处理】等。无论是涉及用户操作还是设备交互的功能请求,均通过这一脚本库进行处理,为APP的功能稳定性和交互一致性提供了强有力的支持。
    9、新增方法【xinle_plus_app:前端向APP发送通讯请求】:该函数用于移动端环境下,向 APP 发送事件或数据。只有在 APP 环境下(由 xinle_isplus() 判断),才允许发送;否则会提示“仅支持APP环境操作”。执行流程如下:环境判断: 首先调用 xinle_isplus() 判断当前是否在 APP 环境。 如果不是 APP 环境,则调用 xinle_msg('仅支持APP环境操作') 给用户提示,并返回 false,函数结束。 数据处理: 如果传入的 data 参数为空,则自动赋值为 { type: 'test' },即默认发送类型为 'test' 的事件。 如果传入的 data 参数是字符串类型,则尝试将其解析为 JSON 对象: 如果解析成功,继续后续处理。 如果解析失败,输出“数据格式错误,无法解析 JSON”,并返回 false,函数结束。 发送消息: 调用 uni.postMessage 方法,向 APP 发送消息,消息内容是 { data: data }。这里 uni 应该是 APP 的 JSBridge(通讯桥),负责前端页面和 APP 之间的数据交互。
    10、新增APP端本地数据缓存管理方法(很多数据需要持久化,并且仅限于当前设备,那么就会用到本地缓存):app_plus_storage,执行流程:判断是否为APP环境 首先,调用 xinle_isplus() 判断当前环境是否为APP(H5+环境)。 如果不是APP环境,函数直接返回 false,后续操作不会执行。 2. 根据操作类型进行分支处理 A. 如果操作类型是 update 使用 plus.storage.setItem(key, value) 方法,将指定的键值对存储到本地。 如果该键已存在,则更新其值。 存储没有明确容量限制,但建议单个键值不要超过10Kb。 存储成功后,返回 true。 B. 如果操作类型是 delete 使用 plus.storage.removeItem(key) 方法,删除指定键名及其对应的值。 删除成功后,返回 true。 C. 如果操作类型是 get 使用 plus.storage.getItem(key) 方法,获取指定键名对应的值。 如果获取到值,则返回该值。 如果没有获取到值(即返回 null),则返回 false。 3. 如果操作类型不是上述三种 如果传入的 type 既不是 update、delete、也不是 get,则直接返回 false。 4. 总结 添加/更新操作(update): 成功返回 true。 删除操作(delete): 成功返回 true。 获取操作(get): 成功返回键值,失败返回 false。 其他情况或不是APP环境: 返回 false。
    11、APP涉及到非常多的权限处理,用户可能允许或者禁用,在执行APP某些操作的时候,需要对其进行权限检查,确保其是否具备操作条件,因此单独封装一个方法:plus_is_permission来检测对应的应用权限。permissions:权限键值。如果权限为未确定状态则返回false,否则返回true。该方法主要是依赖调用 plus.navigator.checkPermission(permissions) 检查该权限的当前状态,返回值可能为 'granted'(已授权)、'denied'(拒绝)、'undetermined'(未确定)等。
  • 0
    小小乐lv.2实名用户
    2025年8月22日
    1、在使用add_post_meta函数创建自定义文章字段时,会自动触发一个名为xc_add_post_meta_callback的回调函数。在这个回调函数内部,会执行update_post_redis动作,将新创建的自定义字段同步写入到Redis缓存中。这一过程确保了系统中的Redis缓存参数与数据库表数据的一致性。该同步操作是通过add_action挂载实现的,以确保在每次字段更新时都能及时反映到缓存中,保持数据的实时同步和一致性。
    2、新增了一个名为xc_update_post_meta_hook的钩子,当用户进行自定义文章字段的更新操作时,无论是使用update、add还是delete方法,该钩子都会被触发。通过挂载这个钩子,可以同步执行一些预设的回调操作,从而实现更灵活的功能扩展。使用这个钩子时,需要传递五个变量:post_id、meta_key、meta_value、type,其中type代表执行的动作类型,可能的值为add、update或delete。这种设计为开发者提供了更高的可控性,能够在文章字段更新时执行特定的逻辑处理,确保数据的一致性和功能的扩展性。
    3、当对WordPress文章自定义字段(meta)操作时,会触发相应的钩子:新增字段时,触发add_post_meta钩子。更新字段时,触发updated_post_meta钩子。删除字段时,触发delete_post_meta钩子。这些钩子触发的时候,系统会自动执行如下操作。缓存同步:每次 meta 字段变动(增/删/改),都会同步到 Redis,保存数据实时更新。 自定义业务逻辑:通过 xc_update_post_meta_hook(),可以实现更多扩展,比如消息推送、数据分析等。 流程自动化:所有操作都是自动响应,不需要手动干预,提高了系统的智能化和可维护性。
    4、在对xc_reids进行重构优化时,发现即使在swoole环境下运行数小时后,系统仍然会出现间歇性崩溃的情况。为了应对这一问题,引入了try-catch机制来捕捉和记录错误。在执行connect、select和ping等操作时,每一步都有可能触发Exception错误,利用xc_log_error_warn将这些错误日志详细记录下来,由于异步redis在整个系统中扮演着至关重要的角色,必须确保其稳定性,否则异步进程的执行将面临诸多潜在问题,影响系统的整体性能和可靠性。
    5、在协程 Redis 模块中,进一步的优化,特别是针对连接不稳定的情况,增加了一个循环重试机制。具体来说,当连接失败时,系统会最多尝试三次重新连接。在每次失败后,程序会暂停 500 毫秒(通过 usleep 函数实现),以便给系统一些恢复时间。这一重试机制仅限于协程 Redis 环境中,每次连接失败后都会详细记录日志,确保问题可追溯。如果经过三次重试依然无法成功连接,系统将记录相应的错误日志,并抛出异常,最终返回 null,以确保调用方能够适当地处理这种异常情况。对于普通的非协程环境,逻辑保持不变,确保稳定性和一致性。
    6、新版xc_redis的处理流程如下:静态变量初始化 声明 static $redis = null;,用于保存 Redis 实例(普通环境下实现复用)。 获取连接参数 通过 xc_get_option() 获取 Redis 的连接参数(IP、端口、数据库编号)。 设置超时时间 $timeout = 5。 判断协程环境 检查是否已加载 swoole 扩展。 判断当前是否为 Swoole 协程环境(Swoole\Coroutine::getCid() > 0)。 尝试连接 Redis(try/catch 保护) 将 $redis = null;,准备开始连接。 4.1 协程环境下(Swoole\Coroutine\Redis) 如果处于 Swoole 协程环境且存在 Swoole\Coroutine\Redis 类: 设置最大重试次数 $maxRetry = 3,初始化 $retry = 0。 进入重试循环 while ($retry < $maxRetry): 检查 Swoole\Coroutine\Redis 是否有 create 方法,有则调用,否则直接 new 一个对象。 尝试连接 Redis,如果连接失败,抛出异常。 尝试选择数据库,如果失败,抛出异常。 尝试 ping 检查连接健康,如果失败,抛出异常。 如果以上步骤全部成功,直接返回 Redis 实例。 如果捕获到异常,记录错误日志,$retry++,并在未到最大次数时等待 300 毫秒(usleep(300000))。 如果三次重试都失败,记录错误日志,并抛出异常。 4.2 非协程环境(普通 Redis) 如果静态变量 $redis 已经是一个 Redis 实例: 检查连接是否有效(isConnected)。 或通过 ping 检查连接健康。 如果连接正常,直接返回 Redis 实例。 如果异常或连接失效,清空 $redis,准备重新连接。 如果 $redis 不是 Redis 实例(或连接失效): 新建 Redis 实例 $redis = new Redis()。 连接 Redis 服务器。 选择数据库。 返回 Redis 实例。 5. 异常处理 如果在任何步骤出现异常: 记录错误日志(包括时间、异常信息)。 返回 null。
    7、为了提升用户行为记录的性能,决定构建一套基于Redis的解决方案,专门用于管理用户的历史行为数据。当用户在进行收藏、点赞、浏览、关注等操作时,这些行为会被Redis实时记录和管理。通过这种方式,能够有效地支持排行榜设计规范,利用分数机制不仅可以调取用户每日的行为记录,还能生成用户行为排行榜。例如,可以快速生成今日点赞排行榜,以及某用户当天的点赞详情列表。由于整个过程都依赖Redis进行数据处理,系统的执行效率得到了显著提升,确保数据管理的流畅和快速响应。
    8、通过 Redis 来记录用户的历史行为:xc_redis_set_user_history。具体的执行流程如下:检查 $user_id、$action_type、$page_id 是否为空。 如果有任何参数为空,则记录错误日志并直接返回,不执行后续逻辑。 构建 Redis 键名 构造哈希表键名:xc_redis:user:{user_id}:{action_type}:hash 构造有序集合键名:xc_redis:user:{user_id}:{action_type}:sorted_set 获取 Redis 实例 调用 xc_redis() 获取 Redis 连接实例。 获取当前时间戳 用 time() 获取当前的 Unix 时间戳,作为记录分数。 判断页面历史记录是否已存在 用 $redis->hExists($hash_key, $page_id) 检查哈希表中是否已存在该页面 ID。 如果存在,只需要更新有序集合(即刷新访问时间):zAdd(sorted_set_key, timestamp, page_id) 如果不存在,先在哈希表中添加该页面 ID,再在有序集合中添加:hSet(hash_key, page_id, 1) 和 zAdd(sorted_set_key, timestamp, page_id) 判断历史记录数量是否超过限制 用 $redis->zCard($sorted_set_key) 获取当前有序集合的数量。 如果数量超过 100: 用 $redis->zRange($sorted_set_key, 0, $count - 101) 获取最早的多余记录(即只保留最新的 100 条)。 遍历这些旧页面 ID,分别从有序集合和哈希表中删除:zRem 和 hDel
    9、新增了查询指定用户历史行为记录的功能,支持分页处理,方法名为 xc_redis_get_user_history,其具体执行流程如下:首先进行参数校验,检查传入的 $user_id 和 $action_type 是否为空,若发现为空,则会记录日志并直接返回 false,避免后续操作。接着构造 Redis 键名,生成对应的有序集合键,格式为:xc_redis:user:{user_id}:{action_type}:sorted_set,确保数据按用户及行为类型进行区分管理。然后,通过调用 xc_redis() 方法获取 Redis 实例以建立连接。根据是否存在分页参数 $page,分为两种处理方式:若未传入分页参数,则使用 zRevRange 方法获取该用户所有的历史记录,按倒序排列并带上分数;若传入分页参数 $page,则进一步判断 $limit 是否为空,若为空则读取系统默认的分页数量,随后根据 $page 和 $limit 计算出偏移量 $offset = ($page - 1) * $limit,通过 zRevRange 按分页读取记录,同样以倒序排列并附带分数。获取到结果后,检查其是否为空,若为空则返回 false。最后,处理后的数据将以 [page_id => 时间戳] 的关联数组格式返回
    10、新增方法:xc_redis_delete_user_history,专门用于删除指定用户的历史行为记录(可选择删除特定页面记录或全部记录)。该方法的执行流程设计如下: 首先,对输入参数进行校验。如果传入的 $user_id 或 $action_type 参数为空,则记录错误日志并直接返回 false,避免无效操作。接着,依据用户 ID 和行为类型,动态生成对应的 Redis 键名,包括哈希表键名和有序集合键名,确保数据定位准确性。然后,通过调用 xc_redis() 方法获取 Redis 实例,为后续操作提供连接支持。为了确保数据一致性与原子性,方法中使用 $redis->multi() 开启 Redis 事务,准备执行批量操作。 在删除逻辑中,根据 $page_id 的值进行分支处理。如果 $page_id 为空,表示需要删除该用户的所有历史记录,此时将清空对应的哈希表和有序集合;如果 $page_id 不为空,则只删除与特定页面相关的历史记录。无论哪种情况,均在事务中操作,以避免中途失败导致数据残留。 最后,提交事务并获取执行结果,判断操作是否成功,并将结果返回。
    11、新增方法:xc_redis_user_is_history,用于判断用户是否对某个页面执行过指定行为(如收藏、浏览)。该方法的执行流程如下:首先进行参数校验,若任意参数为空,则直接返回 false,避免不必要的逻辑执行。接着,按照特定规则构造 Redis 的 hash 键,格式为:xc_redis:user:{user_id}:{action_type}:hash,其中 {user_id} 表示用户 ID,{action_type} 表示行为类型。随后,通过调用 xc_redis() 方法获取 Redis 实例,确保后续操作基于有效的 Redis 连接。在检查指定页面是否存在于 Redis hash 中时,使用 $redis->hExists($hash_key, $page_id) 方法进行判断,若返回 true,表示该页面存在于用户的行为记录中;否则返回 false,表明用户未对该页面执行过指定行为。
  • 0
    小小乐lv.2实名用户
    2025年8月21日
    1、通过 get_post_metadata 注册并接管自定义文章元数据的读取和处理逻辑,目前已通过 xc_get_post_meta_callback 实现对特定元数据键的过滤,以动态决定是否启用 Redis 缓存功能。宫论系统原本预设了多个自定义文章模型,例如用于工单管理、朋友圈动态等内容的封装和处理,这些内容依赖于大量的自定义字段。由于本次对 Redis 缓存系统进行了重构优化,因此在元数据处理逻辑上也同步进行了改进,旨在提高数据读取效率,减少对数据库的直接访问,从而提升整体系统的性能和响应速度。
    2、通过使用 add_filter 注册自定义钩子,可以接管文章自定义元字段的返回值。在这一过程中,需要传递四个关键变量:$metadata(元数据值)、$post_id(文章的 ID)、$meta_key(元数据键)以及 $single(是否返回单个元数据值)。这些参数均由系统方法自动传递并继承而来。在实际的业务逻辑处理中,这四个变量起着至关重要的作用,通过它们可以灵活地实现对元数据的定制化处理,确保数据的正确性和功能的扩展性,从而满足具体的业务需求。
    3、在通过内置方法接管自定义文章元字段的查询时,会对参数 single 进行验证处理。如果该参数值为 false,则表明系统需要返回该文章ID对应的所有自定义元字段,而不是单一字段。然而,由于当前Redis缓存采用的是字典模式,暂时无法支持以列表形式返回全部字段,因此在这种情况下系统将执行一个默认的回调处理逻辑,跳过此次缓存处理,并通过原生方式直接读取数据并响应请求。需要注意的是,跳过处理的实现方式非常简便,只需对元数据(metadata)进行翻译操作即可触发默认回调,从而完成所需的处理逻辑。
    4、针对某些敏感的自定义字段(如商品库存数量、商品出售价格等),为了确保数据的准确性并避免在极端情况下Redis返回的数据与实际情况不符,这类字段的查询必须通过直接调用wpdb进行数据库查询,并禁用缓存机制。为实现这一功能,系统在后台新增了一个字段参数:redis_wp_cache_filter_postmeta(自定义文章过滤缓存字段列表)。该字段支持通过分号(;)分隔多个字段名称。在接管postmeta查询的过程中,系统会自动检查查询字段是否存在于该列表中。如果匹配成功,则会跳过缓存逻辑,直接回源数据库进行查询,确保数据的实时性和准确性。
    5、xc_get_post_meta_callback_cache的接管流程具体如下:首先,系统会优先检测当前的single参数是否为false,如果检测结果为false,则直接跳过缓存逻辑,回源进行处理。接下来,系统会进一步判断本次查询的键值是否属于后台预定义的过滤列表名单。如果键值在名单中,则会通过wpdb直接发起数据库查询操作,并将查询结果返回。在返回结果时,系统会对数据进行检查,如果查询结果存在,则会调用maybe_unserialize函数对数据进行反序列化处理,确保即便存储的是序列化的数组,依然能够正常解析和使用。若上述条件均不满足,则系统会启用edisHASH缓存模式接管该查询请求,通过缓存进行处理并返回结果,从而提高查询效率并减少数据库压力。
    6、新增get_post_redis方法:此方法负责从Redis缓存中优先获取自定义文章元数据,若Redis中尚未缓存相关内容,则自动从数据库中检索并写回Redis,以有效提升后续查询的效率。该方法含有两个主要变量:ppst_id对应的文章ID,meta则用于指定元数据的键名。查询过程中,先尝试从Redis取值,若获取到的信息完整且有效,就会直接返回对应的用户元数据信息;倘若Redis中未查到结果,则改为访问数据库进行检索,并在成功获取后同步将数据写回Redis供后续使用,最终再返回用户元数据。若两处均未能获取到目标信息,将返回false表示查询失败。
    7、get_post_redis的整理处理流程如下:调用 get_post_redis($post_id, $meta),传入文章ID和元数据键名(meta,允许为空)。 2. 连接 Redis 函数内部先通过 xc_redis() 获取 Redis 实例,为后续操作做准备。 3. 判断是否要获取全部元数据 如果 $meta 没传(为 null),说明你想取这个文章的所有元数据: 直接从 Redis 的哈希表 postmeta:$post_id 获取所有字段和值。 把每个值用 maybe_unserialize 处理(这样即使是序列化的数组/对象也能还原)。 关闭 Redis 连接。 返回这个完整的元数据数组。 4. 只获取单个元数据时的流程 如果传了 $meta,表示只想取指定的元数据字段: 先尝试从 Redis 的哈希表里读取 postmeta:$post_id 里的对应键($meta)。 如果 Redis 里有这个值(不为 null 或空字符串): 关闭 Redis。 反序列化并返回该值。 如果 Redis 里该键值是空字符串(''): 关闭 Redis。 返回 false(说明之前已经查过数据库,确实没有这个数据)。 如果 Redis 里没有缓存这个字段(即查出来是 false/null): 用 $wpdb 从 WordPress 数据库的 postmeta 表查询对应的数据。 如果数据库查到了值: 用 update_post_redis 把这个值(序列化处理后)写入 Redis。 关闭 Redis。 反序列化后返回数据。 如果数据库也没有查到值: 用 update_post_redis 把这个字段写入 Redis,值设为空字符串(''),防止下次还要查数据库。 关闭 Redis。 返回 false。 5. 兜底返回 如果所有情况都没命中,最后返回 false。
    8、在符合特定条件时,xc_get_post_meta_callback_cache 会通过 get_post_redis 发起 Redis 的字典查询操作以获取相关数据。如果查询结果存在,该函数会进一步验证返回值的类型:首先通过 is_serialized 和 is_array 检查该值是否为序列化字符串或数组格式。如果验证通过,则会利用 maybe_unserialize 对序列化字符串进行反序列化操作,同时将数据还原为数组形式以确保数据结构的完整性和可用性。若返回的值并非上述类型,则无需额外处理,直接返回从 Redis 中读取到的原始值。
    9、宫论自定义文章元字段的接管业务逻辑封装完毕,执行流程如下:通过 add_filter('get_post_metadata', 'xc_get_post_meta_callback', 10, 4),系统注册了元数据读取钩子,接管所有文章元字段的查询。 每次有文章元数据读取请求时,系统会自动传递四个参数: $metadata:元数据的原始值(一般为空,需返回处理后的值) $post_id:文章ID $meta_key:元数据字段名 $single:是否只获取单个字段值(true/false) 2. 处理参数 single,决定查询模式 如果 $single 为 false,说明要获取该文章的所有自定义元字段(类似于 get_post_meta($post_id) 的场景)。 由于当前 Redis 只支持字典模式缓存单个字段,不支持批量列表查询,所以此时: 直接跳过缓存,交由 WordPress 默认逻辑处理(即数据库查询)。 返回 $metadata,触发原生回调,系统后续自动用数据库结果响应。 3. 判断是否需要跳过缓存(敏感字段过滤) 后台配置有一个过滤字段列表 redis_wp_cache_filter_postmeta,用于指定哪些字段必须直接查数据库,禁止缓存。 在查询时,判断 $meta_key 是否在这个过滤列表中: 如果命中(如库存、价格等敏感字段),直接用 $wpdb 查询数据库,得到值后处理并返回。 若查询结果存在序列化内容,则用 maybe_unserialize 还原为原始结构(如数组)。 如果查询不到,返回 false。 4. 普通字段启用 Redis 缓存查询 如果 $single 为 true 且 $meta_key 不在过滤列表中,则启用 Redis 缓存优化。 此时通过 get_post_redis($post_id, $meta_key) 发起查询,流程如下: 优先从 Redis 哈希表 postmeta:$post_id 读取指定字段的值。 如果 Redis 有值且不为空,直接用 maybe_unserialize 处理后返回。 如果 Redis 有该字段但值为空字符串,说明数据库也没有该数据,直接返回 false。 如果 Redis 没有缓存该字段,则用 $wpdb 查询数据库。 如果数据库查到,写入 Redis 缓存(序列化处理),然后返回数据。 如果数据库查不到,写入 Redis 空值,返回 false。 5. 返回数据类型校验 对于 Redis 返回的数据,如果类型为序列化字符串或数组,使用 maybe_unserialize 还原,确保前端或调用端能正确使用。 非数组/非序列化内容,直接原样返回。
    10、为提升缓存的一致性与可靠性,新增了名为“xc_updated_post_meta_callback”的回调动作过滤钩子。当通过update_post_meta函数更新自定义文章的元字段时,系统将在完成数据表更新后自动触发该回调。该回调会进一步调用update_post_redis更新动作,向Redis发送请求以同步更新对应的字典缓存。这种设计能够确保数据库与缓存之间的数据同步性,避免因数据更新延迟或遗漏导致的缓存不一致问题,从而有效提高系统的稳定性和数据的准确性。
    11、同样地,当通过delete_post_meta函数发起自定义文章元字段的删除请求时,系统在完成清理操作后,会自动触发挂载的过滤钩子xc_delete_post_meta_callback。该钩子负责将删除操作的行为同步到delete_post_redis的清理流程中,并通过Redis对相关字典缓存进行同步移除处理。此机制确保在使用Redis返回查询结果时,缓存中不再包含已删除的元字段数据,避免过时信息的干扰。系统在检测到缓存结果为空时,会自动转向使用wpdb发起实时查询,以确保返回的数据真实、可靠。这种设计不仅提高了数据的一致性,还优化了查询的灵活性与准确性。
  • 0
    小小乐lv.2实名用户
    2025年8月20日
    1、xc_get_user_meta_callback_cache已完成封装处理:获取所有字段时,直接返回原始数据,不做任何处理。 如果 meta_key 在过滤列表里,说明该字段不使用 Redis 缓存,直接查数据库并返回结果。 如果 meta_key 不是 WordPress 内置字段(wp_ 或 session_tokens),则从 Redis 缓存读取数据,并做序列化处理后返回。 其它情况(比如内置字段),直接返回原始数据,交给 WordPress 默认流程处理。这个函数优先用 Redis 缓存获取用户 meta 数据,特殊字段和敏感字段则直接查数据库,内置字段保持 WordPress 默认处理方式。
    2、在系统处理用户自定义元字段更新的过程中,主要涉及到三个核心操作:通过 update_user_meta 更新字段内容,通过 delete_user_meta 删除字段数据,以及通过 add_user_meta 新增字段。当这些操作被触发时,系统会借助 add_action 机制接收对应的回调通知。这些通知会进一步触发与 Redis 相关的处理逻辑,确保用户元字段在底层 SQL 数据库与 Redis 缓存之间保持数据的一致性与同步性,从而提升系统的整体稳定性和性能。
    3、在用户元字段发生更新时,系统会自动触发 xc_update_user_meta_hook 钩子,该钩子会将涉及的用户对象、元字段名称、元字段值以及具体的操作类型(如新增、删除或更新)作为参数传递至钩子中进行集中处理。一旦用户字段发生变动,系统需执行一系列关键任务,包括推送通知、清理缓存、记录日志以及其他与业务逻辑相关的操作。为了确保这些操作的高效性和主流程的流畅性,系统将采用 Swoole 异步任务机制执行相关任务,从而有效减少对主线程的阻塞,并提升整体性能。
    4、当 xc_update_user_meta_hook 钩子被触发时,系统会首先检测元字段的 meta_key 值是否为 chat_list。如果确认 meta_key 为 chat_list,则意味着用户的聊天会话记录表发生了变动。此时,系统会调用 xc_swoole_asyn 执行异步请求,并通过 xc_del_redis 方法清理与用户聊天会话页面相关的 Redis 缓存数据。这一流程的设计,确保了用户聊天页面数据的实时性与准确性,同时降低了同步操作对系统性能的影响。
    5、系统已经实现了对 WordPress 用户元数据(usermeta)读写操作的全面接管,其核心逻辑是:在调用 get_user_metadata 进行数据读取时,对于部分特定字段直接从数据库查询,而其他字段则通过 Redis 缓存获取;在执行 add_user_meta、update_user_meta 和 delete_user_meta 操作时,系统会自动同步更新 Redis 缓存状态。此外,通过 xc_update_user_meta_hook 钩子,系统能够在用户元数据发生变动后实现统一通知与功能扩展,从而为后续业务逻辑的灵活调整提供了强大的支持和保障。
    6、宫论用户自定义字段,目前已完全通过内置redis进行接管处理,整个执行流程如下: 当系统调用 get_user_meta 获取用户元数据时,会先查 Redis 缓存。 如果 Redis 命中,则直接返回,避免数据库查询,提高访问速度。 针对敏感字段(如余额),有后台配置的过滤列表,这些字段强制走数据库查询,确保数据安全和准确性。 2. 读写操作的全面接管 用户元数据的新增、更新、删除操作(add/update/delete),都会同步操作 Redis 缓存和数据库,确保两者数据一致。 所有写操作通过 WordPress 的钩子机制集中处理,方便统一管理和扩展。 3. 钩子机制与异步任务处理 每次用户元数据变动,都会触发 xc_update_user_meta_hook 钩子,把变动的用户、字段名、字段值和操作类型传递给后续处理逻辑。 后续处理包括推送通知、清理缓存、记录日志等。 这些任务通过 Swoole 异步机制执行,避免阻塞主线程,提高系统性能。 4. 聊天会话字段特殊处理 当变动字段是 chat_list 时,系统会自动清理相关的 Redis 聊天缓存,保证聊天页面数据实时更新。 5. 灵活平衡性能与安全 普通自定义字段优先用 Redis 缓存,敏感字段和 WordPress 内置字段则直接查数据库,兼顾性能和数据安全。 整个流程支持后台灵活配置敏感字段列表,业务可扩展性强。 6. 统一扩展与保障 通过自定义钩子和异步任务,所有用户元数据变动都能统一处理,方便后续扩展和维护。 既提升了系统响应速度,也保障了关键数据的一致性和安全性。简要总结: 系统通过 Redis 缓存优化用户元数据读取,敏感字段强制数据库查询,所有写操作同步缓存和数据库,并用钩子与异步任务机制统一处理后续业务,整体实现性能与安全的平衡。
    7、由于宫论的大量字段是通过 option 来读取,而当前的读取方式是直接通过 get_option 方法,这种方式会直接通过 wpdb 执行 SQL 请求,对性能造成了较大的影响。因此,决定引入 Redis 来接管对 option 的处理,从而尽可能减少 SQL 查询的执行。具体实现上,首先通过 pre_option 挂载过滤器来接管 option 的读取流程,然后注册方法 xc_pre_option_callback,用于重写和处理 option 的读取逻辑。这样一来,后续的 get_option 请求将优先通过 Redis 的内置方法进行处理,从而显著优化性能,降低对数据库的直接访问频率。
    8、在使用Redis缓存可能引发一些难以预料的问题,特别是在处理系统级别的参数选项时。因此,在管理get_option的过程中,采取了一些预防措施。首先,对于所有带有wp前缀的参数,选择不进行缓存处理,而是直接通过原生的wpdb进行读取和响应,以确保数据的准确性和一致性。此外,在后台新增了一个可选字段:redis_wp_cache_filter_option,允许用户自行定义哪些字段需要排除在Redis缓存之外。用户可以通过分号分隔多个字段名称,将需要忽略缓存的字段添加到此选项中。这些字段将在读取时直接通过wpdb进行处理,以避免潜在的缓存问题,确保系统的稳定运行。
    9、新增了一个名为 get_option_redis 的 Redis 数据处理方法。该方法的核心功能是通过传递指定的 key 参数,系统自动调用内置的 Redis 方法来读取对应的缓存数据。如果缓存中存在该 key 的数据,系统会进一步对返回值进行检查,分别使用 is_serialized 和 is_array 方法来判断数据是否为数组结构类型。如果检测结果表明数据为数组结构类型,系统将调用 array(maybe_unserialize($redis_meta)) 方法对其进行解析处理,确保数据格式符合 WordPress 的设计规范标准。之所以需要这一解析步骤,是因为在某些情况下,缓存中可能存储的是序列化的数组参数,若不对其进行解序列化和转义处理,可能会导致参数异常或系统错误。
    10、后台新增了一个重要的选项:xc_option_redis_open,用于控制是否启用缓存机制。管理员可以通过这个选项来决定是否使用Redis缓存系统,以优化性能和提升数据处理速度。如果选择不启用,那么系统将会跳过xc_pre_option_callback的正则处理环节,从而减少潜在风险。考虑到option涉及到系统众多敏感参数,未经过适当过滤可能会导致安全隐患,因此这个开关的设计旨在提供一个快速恢复的途径。当系统出现问题时,管理员可以直接在后台关闭此选项,确保系统稳定运行。一旦问题修复完成,可以重新启用该功能,以充分利用Redis的性能优势。
    11、宫论option已完成对redis的缓存的业务处理:拦截get_option调用: 通过pre_option过滤器,挂载自定义回调xc_pre_option_callback,所有的get_option请求都会优先进入此回调。 判断缓存开关: 首先检查后台xc_option_redis_open开关是否启用。未启用时直接返回,走原生数据库查询流程。 2. 敏感字段与缓存排除机制 系统字段排除: 对所有以wp_为前缀的option参数,直接跳过缓存,使用原生wpdb数据库读取,避免缓存系统级参数导致数据混乱。 自定义排除字段: 后台通过redis_wp_cache_filter_option字段,允许管理员自定义需要跳过缓存的option名称(分号分隔)。这些字段在读取时同样直接查数据库。 3. Redis缓存读取逻辑 缓存优先读取: 通过自定义的get_option_redis方法,根据option名称作为key,从Redis读取数据。 数据格式兼容处理: 判断Redis返回值是否序列化(is_serialized),如果是则使用maybe_unserialize进行反序列化,保证与WordPress原生option数据格式兼容。 如果数据为数组,确保返回类型正确,防止类型错乱导致功能异常。 缓存未命中处理: 如果Redis无此数据,则回退到数据库读取,并将结果写入Redis缓存,便于后续请求加速。
  • 0
    小小乐lv.2实名用户
    2025年8月19日
    1、前端新增了基于WebSocket的支付订单付款成功回调通知监听功能。具体实现是,当前端接收到payment_success消息数据包时,会将相关订单数据包转发至【xc_hook_payment_success】钩子进行统一处理,确保所有支付成功的消息均通过该钩子完成后续操作。需要特别注意的是,APP端支付由于采用SDK发起并处理,支持实时的付款成功回调通知,因此无需额外监听处理。而对于H5、公众号以及小程序支付,由于无法直接触发实时回调通知,需要借助WebSocket来监测付款是否成功,从而实现统一的支付结果处理逻辑。这一改动有效提升了支付成功信息的实时性和处理效率,为不同端的支付场景提供了更一致的处理方案。
    2、在xc_hook_payment_success触发时,系统会首先通过xc.is_h5方法来检查用户是否处于H5客户端环境。若用户正处于H5客户端环境,系统会通过layer弹出提示框,简明扼要地告知用户订单付款已成功,并显示支付金额,例如:“订单付款成功,支付金额: ' + payment.pay_amount + '元”。这种提示旨在迅速让用户了解其付款状态。而在非H5环境中,系统则会通过解析payment对象来获取更详细的信息,包括支付环境(如h5、app、微信浏览器、微信小程序)、支付方式(例如微信支付、支付宝、余额支付)、支付凭证、支付用户信息以及支付金额。这些信息对于后续页面的跳转和处理至关重要。
    3、xc_hook_payment_success 在成功获取支付订单数据信息后,会通过 unified_payment_content 元素选择器判断用户当前是否处于统一支付页面。若确认用户正处于统一支付页面,则会立即触发一系列页面交互逻辑:首先,将页面中的支付标识状态更新为“支付成功”,并同步修改对应的文字提示内容,以直观告知用户支付已完成。接着,该逻辑会定位并获取页面的支付定时器,并对其进行移除处理,以避免不必要的计时操作对用户体验造成干扰。随后,系统会对统一支付页面进行“成功”状态标记,明确标识当前付款已完成,防止用户因误操作或系统错误导致重复付款的问题。与此同时,页面还会进一步触发交互提示,包括展示支付完成的相关信息以及播放提示音效。
    4、xc_hook_payment_success目前预留了一个回调事件,当前仅用于处理统一支付订单的回调逻辑,后续将进一步扩展其功能,通过回调事件实现更加复杂的页面交互。未来的应用场景可能包括:在支付完成后跳转到对应的支付订单详情页,同时对路由进行重写,确保用户在返回时能够直接跳过商品详情页,提升使用体验。根据实际付款订单的类型,系统将执行不同的处理逻辑,以满足多样化的业务需求。后续开发中会根据具体情况集成相应的功能模块,确保系统的灵活性和可扩展性。
    5、服务器内置的 Swoole 版本从 4.X 升级至 6.0.2,此次升级的主要目的是更好地支持通过协程机制连接 Redis。在 4.X 版本中,无法使用 Swoole\Coroutine\Redis::create 方法来创建 Redis 的协程连接,限制了协程在 Redis 操作中的优势。而在 6.0.2 版本中,不仅全面支持协程连接 Redis,还能够充分发挥协程的异步非阻塞特性,大幅提升 Redis 操作的效率和性能。通过这一升级,系统在高并发场景下的任务调度和缓存数据处理能力得到了显著增强,同时也为后续的功能扩展和性能优化奠定了更坚实的基础。
    6、对 Swoole 服务器进行重构,加入了协程处理能力。这一改进旨在优化任务转发的效率,使系统能够利用协程机制来处理 Redis 缓存数据的调用。与传统的任务处理方式相比,协程提供了更高效的资源管理和并发处理能力。在传统的 task 模式下,任务执行过程中无法有效调用协程来进行 Redis 的任务调度处理,这可能导致资源的浪费和性能的瓶颈。而通过引入协程,系统能够在任务执行时灵活地进行异步 I/O 操作,显著提升了 Redis 数据处理的速度和效率
    7、对xc_redis() 方法进行了彻底重构,以实现更加灵活和高效的 Redis 连接处理。新版本的 xc_redis() 方法支持两种连接方式:首先,当系统处于 Swoole 协程环境下时,将优先使用 Swoole\Coroutine\Redis 来建立协程连接,以充分发挥协程的异步非阻塞特性,提升 Redis 操作的效率和性能;其次,当处于普通环境时,则采用传统的 Redis 连接方式,并复用已存在的 Redis 实例,以减少资源开销并提高连接的稳定性。此外,为了增强系统的容错能力,如果在 Redis 连接或操作过程中发生异常错误,系统会自动触发日志写入,将异常信息记录下来,以便后续排查问题。
    8、对 xc_swoole_asyn 方法的异步业务逻辑进行了优化,进一步提升了系统的稳定性与执行效率。优化后,方法会通过 extension_loaded('swoole') 函数动态检测当前环境是否加载了 Swoole 扩展。如果检测到 Swoole 已加载,系统会智能切换为同步方式执行业务逻辑,并通过 call_user_func_array 调用目标函数,以确保逻辑执行的快速响应和高效处理。与此同时,当异步请求发生执行失败的情况时,系统将自动捕获异常并触发日志写入机制,错误信息会以【日志标识:swoole_error】记录在日志文件中。
    9、新增了一个处理 Redis 键的清理方法:xc_del_redis($key)。此函数旨在通过提供的键名(支持通配符 :*)批量删除 Redis 中与之匹配的所有键。当成功删除匹配的键时,函数将返回 true;如果 Redis 服务不可用或提供的参数无效,则返回 false。该函数的设计初衷是为了便捷地管理和清理 Redis 数据库中的键,例如可以使用像 "user:*" 这样的通配符模式,快速定位并删除所有相关的用户数据。这种通配符支持不仅提高了操作的灵活性,也在一定程度上简化了对 Redis 数据库的维护工作。
    10、新增了一个名为 xc_user_meta_callback 的 WordPress 接管函数,该函数是一个自定义的回调方法,主要用于拦截并动态调整用户元数据的获取流程。当系统通过 get_user_meta 函数请求用户自定义元字段时,该接管函数会优先检查 Redis 缓存中是否存在相关数据。如果缓存命中,则直接通过 Redis 读取数据,避免传统的 SQL 查询操作,从而显著减少数据库的压力,优化系统的响应性能。这一机制特别适用于高频访问的用户数据场景,能够有效提升整体服务的效率和稳定性。
    11、在接管用户自定义元字段查询的过程中,为了保障数据的准确性和安全性,对于某些敏感字段(如账户余额等),不允许直接通过 Redis 缓存读取,以避免潜在的数据不一致问题。为此,接管函数中新增了一个过滤机制,允许后台管理员自定义配置一个过滤字段组。接管函数会根据该配置自动识别并排除这些敏感字段,对于过滤列表中的字段强制回退到通过 WPDB 查询数据库表的方式读取数据。这种设计既兼顾了性能优化,又确保了核心数据的安全性和一致性,为系统的稳定运行提供了双重保障。
  • 0
    小小乐lv.2实名用户
    2025年8月18日
    1、商户年审续费支付回调处理:1、首先判断支付类型是否为“商户续费”。 如果是“商户续费”,则执行以下操作: 2. 查询当前用户的商户信息。 从商户表(wp_xc_merchant)里,根据用户ID查询出当前用户的商户记录。 3. 获取用户的商户申请信息。 通过 get_user_meta() 函数,获取该用户的 merchant_apply 元数据。 4. 更新商户的状态。 将该商户的状态改为“续费”(renew),并更新续费时间为当前时间。 5. 通知商户管理员。 调用统一通知事件,向商户管理员发送“商户申请”相关的通知,并传递订单信息。 6. 触发付款成功的钩子。 调用付款成功的钩子函数,通知系统该用户的续费付款已成功,并传递相关参数。
    2、“转账”(transfer)支付回调处理:判断支付类型是否为“转账”(transfer) 如果支付类型为“transfer”,则执行以下操作: 2. 查询转账订单信息 调用 sql_inquire_db_id('xc_transfer', $pay_order); 查询转账表(xc_transfer)中,订单号为 $pay_order 的记录,获取该转账订单的数据。 3. 计算订单有效期结束时间 通过配置项 xc_xc_transfer_validity_period 获取转账有效期(单位小时),并转换成秒,加到当前时间,得到转账有效期的结束时间 $end_time。 4. 构造要更新的数据 准备一个数组 $update_data,包含: time:当前时间(转账发生时间) state_time:有效期截止时间 state:状态设为 'yes_pay'(已支付) 5. 构造更新条件 用 $where 数组指定要更新的记录的 ID,即刚刚查询到的转账订单的 ID。 6. 更新转账订单状态 调用 xc_update_sql('xc_transfer', $update_data, $where); 将转账订单表中指定 ID 的记录,更新为已支付状态,并设置时间。
    3、对xc_hook_pay_ok方法进行了重构优化,使其支持通过数组结构返回处理结果,以提升上级方法对数据的接收效率和响应能力。该方法固定返回两个关键参数:code和msg。其中,code用于标识处理状态,1表示处理失败或任务未完全完成,可能中途被中断,此时可通过msg参数获取具体的失败原因;0则表示处理成功,意味着业务逻辑已顺利执行完毕。通过采用数组结构的返回逻辑,确保数据结构清晰、结果易于解析,使得上级方法能够快速响应并作出相应的业务决策,显著提升系统的可维护性和执行效率。
    4、xc_hook_pay_ok方法主要用于处理后续的业务回调,属于通用回调的处理逻辑。该回调的触发前提是交易业务已经在上层完成封装并处理完毕,因此在调用此方法时,仅需传递一个固定变量【ID】即可。至于其他必要的参数,如支付付款人、支付金额、支付方式等信息,则通过内部统一订单查询的方式获取对应的订单详情,并从中提取所需数据。如果在查询订单信息时出现异常或失败,系统会根据具体情况返回相应的错误信息,确保调用方能够及时了解问题并采取进一步措施。这样的处理既简化了调用接口的复杂度,又提高了数据获取的准确性和安全性。
    5、鉴于xc_hook_pay_ok属于业务回调,内部集成了多种事件处理功能,例如计数器更新和消息通知等,这些功能的执行依赖于接口的响应等待,可能会导致进程阻塞。为了优化这一流程,决定对其执行机制进行重大调整,采用Swoole实现异步处理。此调整旨在提升系统的响应效率和资源利用率。在执行异步操作时,我们会对运行环境进行安全性检测,确保环境符合异步处理的条件,只有在环境具备异步执行的安全条件时才会进行异步处理,否则将继续采用同步执行方式,以保证系统的稳定性和可靠性。
    6、xc_hook_pay_ok新增了外部回调通知功能,优化了支付成功后的消息处理流程。系统在通过统一订单查询方法获取到支付订单数据后,会自动注册一个xc_do_action钩子,并以__FUNCTION__作为唯一标识挂载到系统内部的动作处理机制中。对于需要接收支付成功回调通知的外部第三方,只需按照动作钩子标准注册对应的函数即可,无需额外复杂配置。系统会在支付成功时,自动将相关消息转发到对应的回调方法,同时传递支付订单的唯一ID主键,确保数据的准确性与可追溯性,便于第三方集成与定制化开发。
    7、针对付款成功的回调钩子,新增了一项安全校验机制,以确保支付订单的状态准确无误。具体而言,当回调触发时系统会对订单数据的状态字段(state)进行严格检查,如果状态不等于“ok”,则判定该订单未实际完成付款,系统会直接返回错误码 code=1,并附带相应的错误提示信息,从而有效避免未成功付款的订单误触发回调通知的情况。同时,为防止高并发环境下重复执行回调操作,此回调逻辑还引入了基于 Redis 的分布式锁保护机制。锁的有效期设置为 30 秒,在锁定期间如果获取锁失败,系统将直接返回对应的错误信息,且不会继续执行后续的取锁动作。考虑并发请求场景下的安全性,确保回调逻辑的唯一性与稳定性,有效杜绝重复处理或异常触发的情况,从而提升了支付系统的可靠性与安全性。
    8、在付款回调钩子的设计中,首先会通过上锁保护机制,避免因并发导致的重复触发问题。与此同时,为了确保回调动作的唯一性和可追溯性,系统在所有回调流程执行完毕后,会对支付订单进行一个标记处理。具体实现为:获取当前回调钩子的函数名称,并结合订单ID生成唯一标识,随后将该标识写入Redis缓存,设定有效期为30天,以标记该支付订单已完成回调动作。这一标记的作用是防止后续重复触发回调流程。在每次回调执行前,系统会优先检查Redis中是否存在对应的标记,如果已存在,则系统会终止后续回调动作,并及时返回明确的错误提示信息,确保逻辑闭环和数据一致性。
    9、在付款成功的回调钩子中,会自动触发三个基础Redis计数器以实现数据统计与归集。首先是计数器“payment”,其主要功能是统计平台的总交易额,用于记录整个平台的支付情况,确保交易数据的整体掌控;其次是计数器“payment_pay_select”,该计数器则是按照支付类型对支付情况进行分类统计,例如余额支付、微信支付、支付宝支付等,每种支付方式都会单独进行数据累积。这种分类统计方式不仅可以帮助平台快速核对不同支付渠道的收入情况,还能有效提高账目清晰度。举例来说,如果今日通过微信支付的订单收入统计为3900元,那么服务商平台的资金流水也应与此金额完全匹配,从而保证平台的账务管理准确无误。
    10、支付回调钩子功能不仅能够触发支付类别和支付总金额的计数器统计,还通过 type 参数精准获取支付订单的具体类型,从而对不同类型的订单金额进行分类统计。例如,系统可以独立统计商户保证金和淘货交易订单的实际支付金额。这些统计操作均通过统一的计数方法实现,并支持多维度查询,包括按日统计以及范围查询,如上周与本周拍卖实际成交金额的对比分析。同时,该功能不仅局限于订单类型金额的基数统计,还进一步扩展到支付完成后的用户交易金额处理:买家支付的交易金额和卖家获得的收入金额都会实时触发计数器处理。这种细致的统计逻辑为业务数据的精准分析和多维度比对提供了强大的支持,确保数据能够及时反馈并服务于后续运营决策。
    11、在完成对支付金额的计数统计后,系统会通过WebSocket消息机制实时触发通知,具体由 xc_wss_user 负责实现付款成功的消息推送。该通知旨在告知付款人其支付订单的金额已成功完成付款。消息结构设计如下:{"type":"payment_success","pay_order":"' . $pay_order . '","pay_type":"' . $pay_type . '","pay_ment":"' . $pay_ment . '","pay_sell":"' . $pay_sell . '"}。其中包含了支付订单号、支付订单金额、付款用户、收款用户以及付款类型等关键信息。无论任何订单的付款成功,系统都会自动触发此类WebSocket通讯消息,从而实现统一的前端回调机制。保证消息传递的实时性,也为后续业务逻辑处理提供了可靠的数据支撑。
  • 0
    小小乐lv.2实名用户
    2025年8月15日
    1、在支付类型为tao_goods的情况下,当数据表回调成功完成后,系统将自动触发xc_push_hook进行统一消息发送处理。该处理通过内置接口,将消息以【公众号消息、站内信消息、APP消息通知】的形式发送给卖家用户。消息的标题为:“您出售的淘货,已经被人买走了。”正文内容包括商品名称(通过截断描述获取),出售时间(当前日期),以及实付款金额(xxxx元)。此外,消息还提醒卖家:“请尽快给买家发货吧,有问题及时和对方联系。”这种多渠道的消息通知机制旨在确保卖家及时了解交易进展,并迅速采取后续行动。
    2、在发送淘货站内信消息时,通过短代码形式来获取当前订单的地址,即【[xc_link type=xc_tao]/order.php?order='xc_tao[0]->shop_order】。这一机制确保在触发xc_im_push消息时,消息卡片中包含订单链接,使得卖家在收到付款通知时可以直接点击卡片进入订单详情页查看具体信息。为了便于维护,订单跳转的处理都是通过内置方法进行集成处理。如果链接发生变化,只需在短代码的地方进行调整即可,无需更改整个系统逻辑。注:私信卡片消息支持短代码处理,具备自动解析条件。
    3、淘货支付订单的系统回调处理完成处理:代码会将对应订单的支付信息(如支付方式、支付金额、支付流水号、支付时间等)更新到淘货表,并把订单状态标记为“已支付”。然后,代码会将收藏表中与该订单相关的记录状态更新为“已售出”。接着,代码会查询最新的订单数据,准备后续的通知和推送内容。如果设置了微信公众号推送,系统会向卖家推送一条“订单已被购买”的消息,提醒卖家及时发货。如果设置了短信通知,系统会向卖家的手机发送一条订单付款成功的提醒。如果设置了APP站内消息推送,系统会在APP内向卖家发送一条订单付款的通知,内容包括订单号、买家昵称、付款金额和订单详情链接。最后,代码会执行一个付款成功的钩子函数,用于触发其他扩展功能。
    4、如果支付类型为:transfer则说明订单是转账类型,支付业务回调的处理流程如下:查询订单信息 首先,通过 sql_inquire_db_id('xc_transfer', $pay_order); 查询转账表 xc_transfer 中,订单号为 $pay_order 的记录,获取该订单的详细信息。 计算有效期截止时间 代码使用 xc_get_option('xc_xc_transfer_validity_period') 获取设置的有效期(单位小时),并将其转换为秒后加到当前时间,得出订单的截止时间 $end_time。 准备更新数据 构建一个数组 $update_data,包括: 当前时间 time 截止时间 state_time 订单状态 state,标记为 yes_pay(已支付) 准备更新条件 构建一个 $where 数组,指定要更新的订单记录的主键 id。 更新订单状态 调用 xc_update_sql 方法,把上述数据更新到 xc_transfer 表中,标记该订单为已支付,并设置新的截止时间。 触发付款成功钩子 调用 xc_hook_pay_ok 方法,传入用户ID、支付方式、订单号、支付选择等参数,执行付款成功的扩展逻辑,比如积分奖励、通知等。 触发转账成功钩子 调用 xc_transfer_ok_hook 方法,传入用户ID和订单号,执行转账成功后的扩展逻辑,比如生成转账凭证等。 推送转账提醒 调用 xc_push_hook 方法,向用户推送一条类型为 transfer_remind 的通知,提醒用户转账相关事宜
    5、当支付订单类型为“identify”时,订单即被判定为鉴定藏品费用支付成功,后续将执行以下流程:首先,系统会判断支付类型是否为“鉴定订单”(identify),只有在满足该条件时,才会继续进行后续处理。接着,系统将从配置中读取“专家处理时长”(单位为分钟),并将当前时间加上该时长,计算出订单的截止时间。随后,系统会将订单的支付方式、支付订单号、支付金额、截止时间,以及订单状态(更新为“已支付”)写入数据库的wp_xc_identify表中,以确保数据记录的完整性和准确性。完成更新后,系统会根据订单号重新查询订单详情,获取最新的订单信息,为后续操作提供数据支持。与此同时,系统将向负责该订单的专家发送一条“鉴定待处理”的通知,提醒专家及时处理该订单。最后,系统还会调用一个“支付成功”的钩子函数,通知用户订单支付已成功,用户将收到相关的支付成功消息提示。这一步不仅可以用于用户的消息推送,还可进一步触发积分奖励等后续操作,提升用户体验。
    6、支付付款订单为consignment_return(用户取消寄售回收并支付服务费),系统将更新寄售订单的状态。具体操作如下:首先,根据订单号(pay_order)定位wp_xc_consignment表中对应的订单记录,并对以下字段进行更新:将pay_order字段更新为本次支付的交易号(transaction_id),记录当前操作时间到state_time字段,并将订单状态字段state设置为wait_return(待退回),以标识该订单进入待退回流程。接着,系统会再次查询订单详情,根据订单号获取寄售订单的完整信息,为后续的通知操作提供数据支持。随后,系统将向该订单对应的管理员(通过consignment[0]->admin字段关联)发送类型为“consignment_wait_return”的通知,提醒管理员及时处理退回相关事宜。同时,系统会调用xc_hook_pay_ok函数,向该订单关联的用户(通过consignment[0]->user_id字段关联)推送支付成功的事件通知,包括积分奖励或消息推送等内容,确保用户及时了解支付状态及后续处理安排。
    7、保证金付款订单支付成功,将执行以下步骤: 查询数据库:使用 $wpdb->get_results 函数从 wp_xc_consignment 数据库表中获取与订单号 $pay_order 对应的记录。查询结果保存在变量 $consignment 中。 触发付款成功钩子:调用 xc_hook_pay_ok 函数,传入 $consignment[0]->user_id、$pay_type、$pay_order 和 $pay_select 作为参数。此函数可能用于处理付款成功后的业务逻辑,例如更新订单状态或记录交易信息。 准备通知内容:构建一个 HTML 格式的通知内容,包含保证金缴纳通知的标题、订单号 $pay_order、缴纳金额 $pay_money,以及提示用户可以开始出价的信息。同时,生成一个查看拍品详情的链接,链接地址通过 bzg_auction_link($pay_order) 函数生成。 发送即时消息通知:调用 xc_im_push 函数,将构建的内容 $content 发送给用户。接收方的用户 ID 是 $xc_pay[0]->user_id,而发送方的用户 ID 是通过 xc_get_option('xc_bail_user') 获取的。实现保证金缴纳成功后的通知推送功能。
    8、如果支付类型为“bzg_payment”,即标志着当前处理的是中拍藏品的支付流程。通过查询数据库wp_xc_bzg表,获取与支付订单$pay_order对应的记录。这一步是为了确认订单的存在以及获取相关的订单信息。 然后,系统更新订单状态,将订单的state字段设置为yes_pay,并记录当前的时间到state_time字段中。这个步骤确认了订单的支付成功状态,并更新数据库以反映这一变化。 在订单状态更新成功后,调用xc_hook_pay_ok函数。这是一个付款成功的钩子函数,传递的参数包括完成支付的用户$xc_bzg[0]->done_user、支付类型$pay_type、支付订单$pay_order和支付选择$pay_select。这个钩子函数用于执行支付成功后的其他操作,如通知用户或者记录日志。 随后,调用xc_bzg_payment_hook函数,传入支付订单$pay_order。这是一个专门处理拍卖付款成功的钩子函数,可于执行特定于拍卖业务的后续处理。 最后,通过xc_push_hook函数发送统一通知事件,传递的参数包括用户ID $xc_bzg[0]->user_id、事件类型'bzg_payment'和支付订单$pay_order。用于触发系统中的通知机制,通知相关的用户支付已成功完成。
    9、在处理余额充值到账回调时,系统会调用 xc_hook_pay_ok 方法,并传入用户ID、支付类型、订单号和支付方式。这一步骤的主要目的是执行付款成功后的相关逻辑,例如发送消息通知、给予用户积分奖励等,以确保用户在充值成功后能够及时收到反馈和奖励。 当拍卖付款成功时,系统会调用 xc_bzg_payment_hook 方法,传入订单号。这一步骤主要用于处理与拍卖相关的业务逻辑,确保在拍卖付款成功后,能够及时进行相应的后续处理,比如更新拍卖状态或通知相关人员。 在判断支付方式时,系统会根据订单的支付方式(pay_select)来确认本次充值是通过微信支付(wxpay)还是支付宝支付(alipay),并设置相应的中文提示内容($pay_ti),以便在后续操作中能够正确显示支付信息和提示内容。 在账户余额变更方面,系统会调用 xc_update_money 方法,为用户的余额进行充值。此方法需要传入用户ID、操作类型(如'recharge')、订单号、充值金额,并指定操作为'add'(增加余额),备注中会注明'账户余额充值(支付方式)',以便于后续的查询和核对。
    10、商户入驻缴费支付回调处理流程,代码会判断当前支付类型是否为“商户入驻缴费”(即 $pay_type == 'merchant')。如果不是这个类型,后面的逻辑不会执行。 查询商户信息 接着,系统会通过用户ID($user_id)在商户表(wp_xc_merchant)中查询该用户的商户信息。查询结果会保存在 $xc_merchant 变量中。 计算有效期 然后,系统会计算商户的有效期时间。有效期是当前时间加上一年(即 31536000 秒),用于后续更新商户信息。 更新商户状态 系统会把商户的状态更新为“待审核”(audit),并记录状态变更时间和新的有效期时间。这一步会直接更新数据库中的商户信息。 通知管理员 商户状态更新后,系统会通知管理员(通过 xc_push_hook 函数),提示有新的商户入驻申请,并附带订单号作为标识。 付款成功后处理 最后,系统会调用付款成功的钩子函数(xc_hook_pay_ok),进一步处理缴费成功后的相关业务,比如发送消息、后续审核等。
    11、商户消保金充值回调处理流程:代码判断当前支付类型是否为“商户消保金充值”(即 $pay_type == 'merchant_bail')。只有当支付类型为此时,后续逻辑才会执行。 判断支付方式,生成说明文字 根据实际选择的支付方式(微信或支付宝),生成一段充值说明文字($pay_ti)。 如果是微信支付,说明为“微信充值商户消保金”; 如果是支付宝支付,说明为“支付宝充值商户消保金”。 查询商户信息 通过当前用户ID($user_id)从商户表(wp_xc_merchant)中获取商户信息,并保存到 $xc_merchant 变量。 计算新的消保金金额 把商户原有的消保金($xc_merchant[0]->bail)与本次充值金额($pay_money)相加,得到新的消保金总额,赋值给 $bail。 更新商户消保金 在商户表中更新该商户的消保金字段(bail),将其设置为新的金额($bail)。 记录充值流水 向消保金流水表(wp_xc_merchant_bail)插入一条记录,内容包括: 用户ID 订单号 类型(add,表示充值) 充值金额 说明文字 支付方式 时间 调用付款成功钩子 最后,调用付款成功的钩子函数(xc_hook_pay_ok),以便处理支付成功后的相关业务(如通知、后续操作等)。
  • 0
    小小乐lv.2实名用户
    2025年8月14日
    1、在xc_payment_success_hook中,新增了一个Redis安全锁机制,以确保请求处理的过程中能够有效避免重复操作或冲突。具体实现中,当请求正在处理时,会执行解锁动作。如果解锁失败,则整个执行过程将被终止,并返回“上锁保护:请等待几秒后再执行”的错误提示。此锁的有效期设置为30秒,超过时间后会自动释放,以防止长期锁定导致的系统阻塞。锁的标识采用函数名称加订单主键ID的组合,以确保唯一性和针对性。此外,为了保证流程的完整性和安全性,内部在执行完毕后,也会主动进行锁的释放操作,确保后续请求可以正常进行。这一机制有效提升了系统的稳定性和安全性。
    2、为xc_payment_success_hook新增了异步处理能力,这一功能是可选的,具体通过unasyn变量进行控制。若希望使用Swoole进行异步执行,需要将该变量设置为false。默认情况下,系统采用同步处理方式。当变量标记为false时,系统会将执行请求转发至Swoole服务器进行响应和处理。在转发过程中,系统会通过内置方法检测是否满足异步执行的条件。需要特别注意的是,若选择启用异步处理,务必确保不会影响到同步返回的正常处理流程。
    3、在_payment_success_hook被触发时,系统会根据传递的ID进行订单的统一查询处理。如果查询失败,系统将返回错误并终止执行。查询成功后,订单数据将被赋值到名为【payment】的数组中,后续的处理将通过该数组提取参数。回调处理操作涉及多个重要字段的获取:首先,付款用户需要接收到消息通知,以确保信息的及时传达;其次,支付订单将通过变量进行关联回调操作,以确保流程的正确执行;然后,结算金额需要验证一致性,以保证交易的准确性;最后,商户订单号将用于对关联交易订单号执行回调操作,以确保交易的顺利完成。通过这些步骤,系统能够有效地处理支付成功后的各项事宜。
    4、在xc_payment_success_hook触发后,系统不再进行严格的订单效验处理,也不会对服务商的数据进行核验处理。现阶段,该HOOK仅在获取支付订单数据后,验证其支付状态是否为wait_pay。如果支付状态不符合预期,将返回错误信息;如果支付状态正确,则直接进入执行流程。需要注意的是,在执行该HOOK之前,必须确保支付数据包的安全性和可靠性,因为此HOOK现已跳过相关的核验步骤。除了处理支付商户的回调外,该HOOK还允许管理员在系统故障情况下,强制将某些支付订单标记为支付成功,并确保其关联订单号能够被执行。即使用户未实际付款,超级管理员也可以通过此HOOK强制将订单状态更改为已付款,以便维护系统的正常运行。
    5、为了更好地区分支付订单的业务状态,xc_pay支付订单数据表新增了一个状态:callback(回调订单)。当微信或支付宝的服务商通过回调接口通知服务器付款成功后,服务器会对订单数据进行一致性校验。如果校验通过,订单状态将标记为callback,表示订单已经完成付款,但尚未进行业务回调处理,需要进一步处理。这一改动是为了避免之前的不严谨做法——将订单直接标记为ok(已完成付款),即使业务回调未成功。在旧的标记方式下,可能出现回调失败但订单仍被视为已完成处理的情况,这显然不符合实际业务流程的要求。通过引入callback状态,我们能够更精确地反映订单的处理阶段,确保每个订单在回调成功后才真正完成整个业务流程。
    6、在完成xc_payment_success_hook的基础处理部分后,系统将根据pay_type识别支付订单的来源,并根据不同的来源执行相应的支付业务逻辑处理。当订单的回调处理完成后,系统会触发消息通知回调。通过websocket的方式,实时将付款成功的消息传递给在线用户,及时告知对方订单的付款处理已完成。随后,系统还会触发支付成功的统计回调处理,这一部分将在后续封装对应的方法,旨在记录和分析各种付款订单的数据统计信息,并及时更新相关的redis缓存,以确保数据的准确性和实时性。
    7、在处理支付订单时,如果订单类型为淘货订单(pay_type为tao_goods),系统会执行一系列操作来确保订单的正确处理。首先,进行淘货订单变更:将支付方式(如支付宝、微信等)设置为pay_select,将支付金额设定为pay_money,并将支付平台的交易号(如微信或支付宝的订单号)设置为pay_order。支付时间则记录为当前时间,即支付完成的时间,状态则更新为 'yes_pay',以表明订单已支付成功。接下来,系统会对收藏表进行回调操作,标记订单已售出。具体操作是在“收藏表”(wp_xc_collect)中,将与该订单号(shop_order等于$pay_order)相关的收藏记录状态更新为 'finish',此举表示该订单的商品已售出或交易完成。最后,系统会查询订单详情,为后续的业务操作做准备。这包括返回用户信息、安排发货以及写入日志等步骤,以确保整个流程的顺利进行和信息的准确记录。
    8、新增了一个名为xc_hook_pay_callback的回调钩子。这个钩子在订单数据表的回调处理完成后会自动触发。在触发时,它会携带支付订单号的主键ID值。该回调钩子返回一个标准的数组结构,允许通过返回值判断回调工作是否完成。其中,返回值中的code字段表示执行状态:返回1时表示执行失败,回调动作未按预期进行;返回0时表示执行成功。msg字段则提供具体的返回信息,可能包括错误原因或中断原因等详细描述。注:这个回调钩子,是在完成支付业务的回调、关联交易订单回调后才会触发。
    9、xc_hook_pay_callback方法的设计旨在高效处理计数器的维护、WebSocket消息通知的发送以及Redis缓存的更新。这一方法属于统一支付订单的回调范畴,专注于辅助功能,而非直接处理交易订单的具体内容。为了提高系统的响应效率,避免因复杂操作导致的进程阻塞,该方法采用完全异步的执行方案。由于其默认的异步特性,在回调过程中会进行is检测,以判断当前是否处于异步进程。如果检测结果显示已经处于异步状态,则直接执行后续操作,避免不必要的转发,节省系统资源并提升整体性能。
    10、在触发xc_hook_pay_callback时,系统会通过统一订单查询获取对应支付订单的信息。如果查询失败或者获取的信息中订单状态不为“ok”,系统将返回相应的错误信息。由于回调钩子执行后会处理一个websocket消息通知,为了防止误触发导致前端用户接收到错误信息,系统会对支付订单状态进行严格的核验检查。只有订单状态确认支付成功后,才会发送相应的消息通知,并执行关联的redis操作(比如计数器的维护、缓存更新处理动作)。
    11、当成功触发回调钩子后,系统会在读取到订单数据后,首先获取交易订单的实际付款金额字段【pay_amount】。接下来,会启动一系列的计数器进行处理。首先,pay_amount会通过xc_redis_count统计平台的总交易额,这是一个全局的统计,无论是通过微信、支付宝还是余额支付,只要付款成功,就会被纳入统计。平台可以通过这个计数器获取每日或特定时间范围内的交易金额总和。其次,系统会根据支付类型,记录不同类型的支付金额,比如微信支付、支付宝支付和余额支付等,这样可以清楚地了解各个支付渠道的交易情况。最后,系统还会根据交易订单的类型进行统计处理,比如淘货交易、拍卖交易、余额充值等,每种交易场景对应的付款统计数据各不相同。通过这些统计,平台可以更精细化地分析交易数据,为运营决策提供有力支持。
  • 0
    小小乐lv.2实名用户
    2025年8月13日
    1、宫论支付请求钩子 xc_payment_hook 在完成参数校验后,会通过 xc_payment_sdk_hook 获取对应的支付数据包,并将其处理结果保存到 payment_sdk 中。随后,系统会对 payment_sdk 返回的 code 进行检查:如果返回的 code=1,则表示发生错误,系统会直接返回对应的错误信息并终止整个执行流程,无需再进行后续处理;而如果返回的 code=0,则表示校验通过,系统将进入下一步的执行流程。值得一提的是,payment_sdk 已完成封装处理,能够根据支付请求发起相应的支付业务请求,并对支付流程进行有效管理。如果在支付业务请求过程中发生异常或者错误情况,系统会直接返回 code=1,并由 xc_payment_hook 对异常情况进行解析和处理,从而确保支付流程的稳定性与安全性。
    2、在xc_payment_sdk_hook成功获取到支付数据包后,系统会启动一个基于Redis的锁机制,以确保支付流程的安全性和稳定性。这个锁的有效期设定为20秒,旨在防止短时间内的重复支付操作。如果在锁定期间有重复的支付请求,系统将主动拦截并阻止其执行,并提示用户:“支付失败:订单已被锁定支付中!”。为了进一步避免重复支付的情况,订单在生成后会享有20秒的保护期,期间任何重复请求都会被锁定。成功获取锁后,系统会通过xc_update_sql更新支付订单表,其中更新的内容包括meta自定义元字段、各种支付扩展订单信息,以及商户支付订单(payment_order),这些信息均由SDK生成并返回。此外,还会记录本次支付的请求类型(pay_select),以确保支付信息的完整性和准确性。通过这样的设计,系统能够有效管理支付订单,减少重复支付风险,确保支付过程的顺利进行。
    3、对支付宝回调接口(/pay/ali_notify.php)进行了重构与优化处理。当支付订单完成付款时,支付宝会触发这个回调接口,将支付成功的消息传递至该接口,通知系统订单已完成结算处理。为了确保安全性和系统的稳定性,此次重构重点解决了之前明文传输导致的信息公开问题,显著降低了潜在的安全风险。此外,原有的数据处理方式未采用HOOK机制,存在诸多弊端,因此在重构中全面引入HOOK机制,以提高灵活性和可扩展性,确保接口处理符合统一支付体系的要求。通过这些改进,系统在安全性、可靠性和扩展性方面都有了显著提升。
    4、支付宝回调文件在加载过程中,并不涉及到宫论核心库的加载,而是直接使用require_once语句加载核心支付SDK。接下来,通过use Yansongda\Pay\Pay对SDK进行初始化处理。随后,系统会调用内部封装的curl函数,向宫论服务器发送请求以获取相应的config配置信息。如果请求失败或服务器返回错误,系统将立即触发错误日志报警机制,将请求异常或返回的错误信息记录到相应的日志文件中,方便后续排查和解决问题。如果请求成功并顺利获取到配置信息,系统则会将返回的配置信息赋值到config变量中,以便后续使用。
    5、系统在收到config配置参数后,首先调用Pay::config($config)进行初始化设置,确保所有必要参数正确配置以准备后续操作。紧接着,系统会通过Pay::alipay()->callback()方法执行回调操作,该方法负责接收并处理外部回调信息。回调过程中,系统首先进行严格的签名验证,确保数据的真实性和完整性。在签名验证通过的情况下,系统将对接收到的加密字符串进行解密,确保信息能够被正确读取和理解。解密成功后,系统会将解密后的字符串转化为JSON格式,以便后续处理。最后,系统使用json_decode函数将JSON字符串转化为可操作的数组结构,便于进一步的数据处理和分析,并将最终处理结果存储到result变量中,以供后续使用。此流程确保了数据的安全性和可靠性,为业务逻辑的准确执行提供了坚实基础。
    6、支付宝回调脚本在成功获取支付订单数据后,会通过内部的解密机制将数据转化为json字符串,并将其以日志形式写入到log文件中,以便记录每次回调的详细信息。在统一支付系统尚未完全稳定的阶段,这种日志记录将持续进行,确保每笔支付订单都可以通过日志进行追溯和查询。为了保障系统的安全性,nginx执行了一个拦截动作,禁止外部下载.log日志文件。任何试图通过URL直接访问日志文件的请求都会被拒绝,从而确保日志信息仅限于服务器内部处理和使用。
    7、在完成日志记录的工作后,系统会立即返回“success”状态给支付宝,以确认本次支付订单的回调已成功接收,从而避免再次发送回调消息数据包的情况。根据支付宝官方文档的说明,如果系统没有回复“success”标识,支付宝会按照设定的间隔不断重发回调请求,直到48小时后才会停止。这意味着如果没有及时回复确认,可能会导致大量重复请求,给服务器带来不必要的负担。因此,在业务处理完成后,务必及时回复确认,以确保系统的稳定性和高效性,避免因请求过多而导致的服务器压力过大。
    8、在接收到result回调数组后,系统将从中提取以下关键参数:out_trade_no,即商户生成的唯一订单号;trade_no,即支付宝提供的支付订单号;以及total_amount,即本次订单的支付金额。随后,系统会通过wpdb语句查询支付订单表wp_xc_pay,以匹配支付订单号和付款金额一致的交易订单,同时确保其状态为wait_pay,即等待付款中。如果查询成功,系统将把返回的结果保存到payment中,供后续订单回调处理时使用。此外,系统会将返回的对象转换为数组结构,以便简化后续的处理流程。
    9、在成功获取到支付订单数据后,我们会通过xc_update_sql函数触发订单回调处理。首先,将支付订单的状态(state)标记为“ok”,表示已完成付款。接下来,根据实际支付情况,将支付订单类型(pay_select)设置为“alipay”,因为用户可能在初始选择时选择了微信支付,但最终使用支付宝完成了交易,因此需要在回调时进行相应的修改。支付金额(pay_amount)则直接从回调接口返回的数据中读取,确保金额准确无误。同时,将支付宝交易订单号(pay_order)记录下来,这个订单号是唯一的,用于标识具体交易。最后,付款时间(pay_time)会被标记为当前时间,以确保交易记录的时间准确无误。这一系列操作确保支付订单的信息完整和准确,方便后续的处理和查询。
    10、新增了一个名为xc_payment_success_hook的回调钩子脚本,此钩子将在支付订单明确完成付款后自动触发。该钩子采用标准的数组结构进行返回,其中code表示处理回调业务的状态:如果处理成功则返回code=0,处理失败则返回code=1。通过msg字段可以了解具体的处理结果。为了确保数据的准确传递,该数组需要传递两个必需的变量参数:首先是id,即对应的支付订单号;其次是payment,表示支付订单的类型,可能的固定值包括wxpay、aliapy和money。此外,还有一个可选参数allback,它是支付服务商返回的支付成功消息数据包。
    11、在xc_payment_success_hook触发时,系统会通过统一订单查询方法获取相关支付订单的信息。若支付订单状态不为wait_pay,系统将立即返回code=1和msg=处理失败:支付订单不处于待付款状态。接下来,系统会继续验证并提取回调allback数组,该数组中的alipay和wxpay是必需的参数,如果没有传递则返回处理失败:allback不能为空。当allback传递成功后,系统会提取其中的三个关键变量:支付订单号、商户单号和付款金额,这些信息将在后续的业务回调中被使用。
  • 0
    小小乐lv.2实名用户
    2025年8月12日
    1、在处理微信付款动作时,xc_payment_sdk_hook首先会通过is_h5方法验证请求是否来自H5浏览器。若验证为H5浏览器,则会采用\Yansongda\Pay\Pay::wechat()->h5($order)来发起SDK请求,与微信商户平台进行支付对接。在此过程中,order参数用于封装订单数据包,具体包含以下信息:out_trade_no代表支付订单号,需由商户自行生成并确保唯一;subject为商品标题,用户支付时可见的付款内容;amount表示支付金额,需将原金额乘以100以转换为分;scene_info则包含付款方式的两个参数,其中payer_client_ip用于标识当前客户端IP,而h5_info选择wap以标记支付来源为H5。此过程确保支付请求的准确性和安全性。
    2、在使用xc_payment_sdk_hook发起支付请求时,系统会将请求结果保存到response数组中。对于微信H5支付,验证处理是否成功只需检查response['h5_url']参数即可。如果服务商返回了此参数,表明支付请求已成功发起,此时h5_url就是用于支付的链接,用户可以直接跳转至该地址进行订单支付处理。若返回了该参数,系统会直接返回code=0,msg=支付数据包完成封装,并将response的内容设置为response['h5_url']。前端在接收到响应结果后,会立即进行订单的回调处理,以确保支付流程的顺利进行。
    3、通过xc_payment_sdk_hook发起微信H5支付的时候,如果结果没有返回$response['h5_url']则说明,微信商户平台拒绝了本次订单支付,拒绝的原因有很多。这里会直接返回错误:code=1、msg=支付失败:SDK接口发生异常(联系管理员处理)。同时会触发一个日志的写入,记录本次支付失败的原因。日志格式如下:[时间 - ' . date("Y-m-d H:i:s") . '] [返回错误 - h5_url字段未返回] [支付类型 - ' . $method . '] [支付场景 - ' . $environment . ' ] [操作用户 - ' . $user_id . '] [支付订单 - ' . $id . ']。注:日志通过xc_log_error_warn进行写入,记录对应错误,方便后续进行排查处理。
    4、在执行微信H5付款请求时,采用了try-catch机制来有效捕获异常,以确保支付过程的顺利进行,避免因接口故障、参数错误或鉴权失败等问题导致支付失败,从而使系统无法识别错误信息,影响用户的支付体验。我们设置了两个主要的异常捕获机制。首先是\Yansongda\Pay\Exception\InvalidResponseException,这是针对服务商返回的错误异常,SDK已经自动集成了相应的错误输出处理。其次是Exception,这是用于捕获内置异常,通常是由接口或SDK内部错误引发的。这两种错误捕获机制都会返回统一的错误信息,其中包括code=1和msg=支付失败:服务商请求出现异常(' . $e->getMessage() . '),以便于及时识别和处理支付问题,提升用户体验。
    5、不管是什么支付场景,只要通过try-catch返回了异常错误,都会触发对应的日志写入动作。日志大体格式如下:[时间 - ' . date("Y-m-d H:i:s") . '] [返回错误 - ' . $e->getMessage() . '] [支付类型 - ' . $method . '] [支付场景 - ' . $environment . ' ] [操作用户 - ' . $user_id . '] [支付订单 - ' . $id . ']该错误日志通过xc_log_error_warn函数进行写入,只要支付响应通过SDK发起,就会被触发。当接口出现异常时,日志将成为识别问题根源的关键工具,有助于迅速定位和解决错误。通过这种详细的日志记录机制,能够有效保障支付过程的透明性和可靠性。
    6、整个微信H5支付处理流程如下:获取客户端IP: $ip = $_SERVER['REMOTE_ADDR'];:获取客户端的IP地址,用于支付请求中。 订单信息准备: 准备订单数组$order,包括: out_trade_no:外部订单号。 description:订单描述。 amount:金额信息(微信支付要求金额以分为单位,因此需要乘以100)。 scene_info:场景信息,包括客户端IP和H5支付类型(Wap)。 支付请求: 使用try-catch结构进行错误处理,确保请求过程中的异常被捕获。 \Yansongda\Pay\Pay::wechat()->h5($order);:发起微信H5支付请求,传入订单信息。 响应处理: 检查响应中是否存在h5_url字段: 如果存在: 设置结果数组$result,包含支付成功的消息和H5支付链接。 返回结果。 如果不存在: 记录错误日志,包含时间、错误信息、支付类型、支付场景、用户ID和订单ID等信息。 设置结果数组$result,包含支付失败的消息。 返回结果。 异常处理: 捕获InvalidResponseException异常: 记录错误日志,包含时间、异常消息、支付类型、支付场景、用户ID和订单ID等信息。 设置结果数组$result,包含支付失败的消息。 返回结果。 捕获一般Exception: 记录错误日志,类似于上面的异常处理。 设置结果数组$result,包含支付失败的消息。 返回结果。
    7、微信APP支付与微信公众号支付在发起SDK支付时,整体处理流程基本一致,但在具体参数和请求方式上存在一定差异。APP支付通常通过 \Yansongda\Pay\Pay::wechat()->app($order) 来发起接口请求并进行处理,而微信公众号支付则是通过 \Yansongda\Pay\Pay::wechat()->mp($order) 来完成相关操作。无论是返回的结构还是响应的日志处理,这两种支付方式都与微信H5支付保持一致。然而,需要特别注意的是,微信公众号支付对用户登录有强制要求,这是因为支付过程中涉及到 weixin_uid 的获取,而这一关键信息依赖于用户的 openid。若用户未登录,将无法获取对应的 openid,从而导致支付流程被强制中断。因此,在实施微信公众号支付时,确保用户登录是一个不可忽视的重要环节。
    8、xc_payment_sdk_hook已成功封装并处理多种订单支付方式:首先,余额支付方式已实现内部直接处理,确保高效流畅,并在出现异常时及时返回错误信息,以保障用户体验。其次,在微信支付方面,系统会智能检测当前设备环境,进而发起合适的SDK请求,现已支持微信H5支付、微信公众号支付及微信APP支付。支付过程中如遇错误,将通过日志详细记录,以便后续分析与解决;若支付请求成功发起,则会返回相应的响应信息。此外,支付宝支付同样具备设备环境检测功能,能够根据客户端情况发起合适的SDK支付请求,目前支持H5支付和APP支付。支付成功时,将返回响应信息,而在发生错误时,会通过日志进行详细记录,确保问题的可追溯性与解决。此封装处理不仅提升了系统的支付能力,还增强了用户体验的稳定性与可靠性。
    9、使用xc_payment_sdk_hook发起SDK支付请求时,若支付订单数据成功处理并返回可直接支付的response数据包,系统会自动触发一个redis计数器。通过宫论内置的xc_redis_count方法对支付成功调用次数进行统计,该计数器标识为payment_sdk_success。这不仅能精确记录SDK的调用次数,还支持区域性查询,提供本周、上月、今年、昨日等不同时间跨度的统计数据,使后台能够方便地了解支付发起成功的调用频率和趋势。这种灵活的统计方式有助于优化支付流程和提升服务质量。注:仅在SDK发起支付请求成功才会执行触发,如果发生错误则跳过。
    10、在xc_payment_sdk_hook中新增了一个Redis缓存机制,以优化支付流程。当SDK成功返回支付订单数据包时,系统会自动生成一个Redis键值【payment_sdk_response:ID】,其中最关键的部分是id,它与支付订单相对应。这一机制确保了如果用户在支付过程中途退出,后续再次请求支付时,系统会自动检查缓存是否存在。如果缓存存在,则直接获取支付数据包并重新发起付款请求,而无需重新生成支付订单或修改订单信息。这不仅提高了系统的响应速度,还减少了不必要的订单重复生成。为了保证数据的时效性和避免缓存过期导致的错误,设置了缓存有效期为24小时,超过此时间系统会自动清理过期缓存,确保数据的准确性和安全性。
    11、在使用 xc_payment_sdk_hook 发起支付请求时,系统会首先通过 Redis 检测键【payment_sdk_response:ID】是否存在。如果该键存在,则说明该订单已经发起过支付,此时系统会直接返回对应的支付订单数据包,而不再通过 SDK 发起新的支付请求。这种机制可以有效减少重复支付请求,提高处理效率。若 Redis 中存在该缓存,只需重新调用相应的支付数据包,再次发起支付即可。为确保支付的可靠性,后续将在支付回调动作中接入一个额外的步骤:一旦确认付款成功,系统会立即移除对应的 Redis 缓存。这一流程旨在确保订单支付的准确性和安全性,同时优化系统资源的利用。
  • 0
    小小乐lv.2实名用户
    2025年8月11日
    1、在使用 xc_payment_sdk_hook 发起支付请求时,如果订单的付款类型不是余额(money),系统会执行一系列步骤以确保支付流程的顺利进行。首先,通过 require_once 加载支付 SDK 环境,以便将支付接口成功集成到当前的客户端环境中。这一步骤确保支付功能可以在当前应用中无缝运行。接着,系统会通过 xc_payment_config_hook 获取支付订单的数据包,并将其结果保存到 config 中,以便后续处理。最后,利用 \Yansongda\Pay\Pay::config($config) 对支付 SDK 进行初始化,这为后续的支付请求发起做好了充分的准备。通过这种方式,系统能够灵活地处理不同类型的支付请求,确保支付过程的安全和稳定。
    2、在完成pay的初始动作处理后,系统将依据method支付场景和设备环境,执行相应的支付发起流程。不同支付类型和支付场景对应的支付动作和业务逻辑各具特色。例如,在APP支付场景中,系统需要先获取支付数据包,然后将其传递给APP的SDK以发起支付请求。对于H5支付,则需要提供支付参数以生成支付跳转链接,用户通过该链接在浏览器中完成支付请求。微信支付和支付宝的调用数据各不相同,其内部需要根据不同的支付场景进行详细区分和处理,确保每个支付请求都能被准确地执行。
    3、当支付订单选择使用支付宝作为付款方式,并且发起支付请求的渠道是H5时,系统将通过\Yansongda\Pay\Pay::alipay()->h5进行支付请求的前置工作。在这个过程中,需要传递四个关键参数变量:首先是out_trade_no,它代表支付订单号,商户单号会通过系统内置的方式进行自动生成和处理;其次是total_amount,表示本次付款的金额,单位为人民币元,确保准确无误以避免支付差错;第三个参数是subject,包含商品的描述信息或商品名称,以便用户明确知道所支付的项目;最后是quit_url,这是一个固定值,用于指向支付订单的回调地址,也就是完成付款后将跳转的页面地址,默认情况下设定为首页。这些参数的有效传递和处理是确保支付流程顺利进行的重要环节。
    4、在通过SDK发起支付宝H5支付的过程中,执行结果会被保存到response数组中。如果返回字段getStatusCode为200,意味着SDK已成功完成验证,并且支付宝接口顺利返回了支付数据包。在这种情况下,系统会利用对象的getBody方法获取完整的数据信息,并从中提取出getContents。随后,系统将返回code=0和msg,表示支付数据包已成功封装处理。同时,提取到的getContents会通过response附加返回。前端在接收到响应数据后,可以直接利用response进行H5支付请求的处理。
    5、在通过SDK获取支付订单数据包的过程中,如果支付宝SDK返回的状态码不是200,这意味着接口未能成功获取有效数据,可能是由于参数设置错误、鉴权失败或权限不足等原因导致。在这种情况下,系统会立即触发错误返回,并显示以下信息:code=1、msg=支付失败:SDK接口发生异常(' . $response->getStatusCode() . ')。需要注意的是,支付失败的原因可能有多种,因此需要进一步通过getStatusCode查询官方接口文档,以便更详细地了解错误码产生的具体原因并进行针对性处理。这里直接返回对应错误码,后面将对其进行解析处理,直接返回对应的错误详情。
    6、新增支付错误日志写入机制,优化了通过SDK发起支付时的错误记录流程。当支付过程中出现错误时,系统将自动调用xc_log_error_warn函数,将相关信息写入支付日志中,以便后续进行问题追踪和分析。日志条目清晰地标识为“payment”,并采用统一格式记录详细信息,包括时间戳、返回状态码、支付类型、操作用户及支付订单号。具体格式:'[时间 - ' . date("Y-m-d H:i:s") . '] [返回状态 - ' . $response->getStatusCode() . '] [支付类型 - ' . $method . '] [操作用户 - ' . $user_id . '] [支付订单 - ' . $id . ']
    7、因为sdk执行过程中,有各种不可控因素。支付又是非常重要的,必须确保每一步都可追踪。因此通过Yansongda\Pay发起支付请求的时候,会采用try-catch进行异常监听处理,如果SDK因为网络或者内部错误,导致请求出现失败的时候,会通过Exception进行捕获异常处理,并最终通过xc_log_error_warn进行错误日志写入动作,日志格式如下:'[时间 - ' . date("Y-m-d H:i:s") . '] [返回错误 - ' . $e->getMessage() . '] [支付类型 - ' . $method . '] [操作用户 - ' . $user_id . '] [支付订单 - ' . $id . ']。同同时内部返回错误付失败:SDK请求出现异常(' . $e->getMessage() . ')
    8、通过try-catch处理异常的时候,会判断错误来源是否为SDK自身返回错误:如果错误标识来源为:\Yansongda\Pay\Exception\InvalidResponseException $e。则说明其错误是SDK自身捕获到的异常,一般是服务商返回的异常。此时系统同样会通过xc_log_error_warn来写入对应的错误日志,与之前的日志基本格式一样,但是在返回msg的时候,会返货错误提示:支付失败:服务商请求出现异常(' . $e->getMessage() . ')。
    9、xc_payment_sdk_hook不仅支持支付宝H5支付处理,还提供了支付宝APP支付的功能。两种支付方式的发起步骤相似,但处理结果有所区别。在H5支付的场景中,当支付请求数据被发送后,支付宝会返回一个HTML格式的构建体,前端页面接收到这个构建体后,会自动跳转到支付页面,从而完成支付流程。而在APP支付场景中,支付宝返回的是一个加密字符串。接收该加密字符串后,系统会触发PLUS事件,调用应用内置的支付宝SDK来处理该字符串。当参数被验证为安全可靠时,系统将弹出支付窗口供用户进行支付操作。
    10、通过内置SDK发起支付宝付款的执行流程如下:SDK引用和配置: require_once xc_get_option('xc_sdk_composer');:引入SDK,确保支付库被加载。 $config = xc_payment_config_hook();:获取支付配置。 \Yansongda\Pay\Pay::config($config);:设置支付配置。 条件检查: 检查支付方式是否为alipay且是否为H5支付($method == 'alipay' && $is_h5)。 支付请求: 使用try-catch结构进行错误处理,确保请求过程中的异常被捕获。 \Yansongda\Pay\Pay::alipay()->h5([...]);:发起支付宝H5支付请求,传入订单号、金额、主题等信息。 响应处理: 检查响应状态码是否为200: 如果是200: 获取响应体内容。 设置结果数组$result,包含支付成功的消息和数据包。 返回结果。 如果不是200: 记录错误日志,包含时间、状态码、支付类型、用户ID和订单ID等信息。 设置结果数组$result,包含支付失败的消息。 返回结果。 异常处理: 捕获InvalidResponseException异常: 记录错误日志,包含时间、异常消息、支付类型、用户ID和订单ID等信息。 设置结果数组$result,包含支付失败的消息。 返回结果。 捕获一般Exception: 记录错误日志,类似于上面的异常处理。 设置结果数组$result,包含支付失败的消息。 返回结果。
    11、xc_payment_sdk_hook除了支付宝付款外,也已经支持wxpay(微信付款)。当用户订单选择的是微信支付时,系统会通过method参数来判断并进入专门的微信支付处理逻辑。微信支付目前支持三种支付模式:H5网页版支付、公众号支付和APP支付。系统会智能检测用户的设备环境,并根据具体情况发起相应的支付请求,以确保用户体验的流畅和便捷。在发起支付请求之前,系统会进行一系列初始化操作。首先,通过require_once加载必要的SDK文件,然后调用xc_payment_config_hook来获取支付的相关配置,最后通过Yansongda\Pay\Pay::config($config)进行支付SDK的初始化。
  • 1
    小小乐lv.2实名用户
    2025年8月8日
    1、在执行xc_payment_hook过程中,系统首先会检查当前支付订单的备注信息(remark)是否为空。备注信息是订单的重要来源,必须在任何情况下进行传递。如果备注为空,系统将立即返回错误,阻止支付流程继续进行。当备注信息不为空时,系统会使用mb_strlen函数来获取备注的长度。若备注长度超过100个字符,系统将返回错误提示,指示支付失败并说明原因:备注信息不能超过100字。接下来,系统会通过xc_is_html函数检测备注中是否包含非法字符串,以防止安全隐患的发生。如果检测到备注中存在HTML或其他非法字符,系统将直接返回错误提示,指出支付失败的原因:备注信息不能包含HTML。这一系列检测确保订单备注的安全性和合规性,为支付流程的顺利进行提供保障。
    2、在支付场景的保护机制中,后台可以灵活地设定每个场景所支持的支付类型。例如,余额充值时,仅允许使用微信和支付宝进行付款。而如果用户在微信小程序环境中进行操作,则仅能使用微信支付。每个支付场景都可以单独配置,确保支付过程中的安全性和适配性。在实际支付过程中,系统会检查当前启用的支付类型。如果支付配置为空,系统将返回错误信息:“支付失败:不支持(' . $method . ')付款”。此外,如果用户尝试使用支付宝付款,但检测到环境为微信端,系统将返回错误:“支付失败:微信环境禁用支付宝付款”。
    3、在支付过程中,系统通过xc_payment_hook触发支付操作,并依据不同的支付类型执行相应的拦截处理。当请求为余额支付(money)时,首先使用xc_is_login检查用户的登录状态。如果用户尚未登录,则立即返回错误信息:支付失败,余额支付必须先登录。接下来,系统通过xc_is_security进行安全环境验证,确保用户设备的安全性;若验证结果显示环境不安全,则返回提示:设备环境不安全,需要短信验证,并指示跳转:login,迫使前端进行登录操作。最后,系统通过get_user_meta获取用户余额信息,如果余额低于支付金额,则返回支付失败信息,指出账户余额不足,并显示当前可用额度为 ' . $money . ' 元。
    4、当用户选择使用微信支付(wxpay)进行当前支付订单时,如果通过xc_is_wechat检测到用户处于微信客户端环境(包括小程序或微信网页版),系统会要求用户进行登录。这是因为在公众号支付和小程序支付中,需要获取用户的openid作为必要信息。如果用户尚未登录,系统将返回支付失败的信息:“支付失败:微信环境需登录后才能支付[' . xc_is_login() . '-' . $user_id . ']”。一旦用户成功登录,系统将通过get_user_meta方法来获取weixin_uid。如果无法成功获取到该信息,系统将返回错误提示:“支付失败:公众号支付需要提供openid”。这一流程确保了支付过程的安全性和顺利进行。
    5、在完成上述拦截处理动作后,系统还引入了第三方事件的拦截处理机制。通过封装的xc_payment_before_hook发起外部拦截请求接管动作,该HOOK负责在挂载拦截需要执行检测时发起并执行拦截操作。系统在接受响应结果后,会对返回值进行判断:如果is_payment的值不是数组,或者code等于1,则系统会直接阻断支付过程,并返回外部拦截器的错误信息。这一机制确保支付流程的安全性和准确性,同时提供了灵活的处理方式以应对不同场景,如淘货和拍卖等场景,可以通过预留的钩子进行单独处理。这种设计为系统的扩展性和定制化提供了强大的支持。
    6、在xc_payment_before_hook执行过程中,必须传递一个ID变量,该变量是当前支付订单的主键值。此拦截钩子会在内部使用统一查询方法来获取该订单的详细支付信息,并返回一个标准化的数组结构,以确保处理结果能够被上级系统正确接收和解析。其中,数组中的code字段用于表示执行状态:如果值为1,则表示执行失败,此时当前支付请求将被拦截并不允许继续进行,具体的失败原因可以通过msg字段获取;如果code值为0,则表示支付请求通过了外部检测,允许继续执行。此外,该HOOK内部会调用挂载钩子机制,允许任何第三方拦截事件通过挂载方法接入并处理拦截请求,从而实现灵活的扩展和集成。
    7、在xc_payment_hook完成before_hook的拦截处理后,拦截动作就告一段落,接下来便进入支付业务的处理阶段。鉴于支付场景的复杂性,目前我们已支持多种支付类别,包括微信APP支付、微信小程序支付、微信H5支付、微信公众号支付、支付宝APP支付、支付宝H5支付以及余额支付。每种支付类别所需的参数和SDK都不尽相同,若将其整合到xc_payment_hook中进行维护,将会导致系统复杂性剧增。因此,建议单独封装一个方法——xc_payment_sdk_hook,以便专门处理各类支付的复杂交互。这一方法将负责与各个服务商进行通信,确保返回有效的支付数据包,从而简化支付处理过程并提高系统的可维护性。
    8、在使用xc_payment_sdk_hook获取当前支付数据包时,需要传入两个关键变量参数。首先是id,即通讯令牌,这个令牌通过MD5加密转换为token,如果该值为空,将无法生成令牌,从而无法获取对应的支付订单数据包。其次是method,即支付场景标识,通常有三个选项:wxpay代表微信支付,alipay代表支付宝支付,money代表余额支付。不同的支付场景需要调用不同的SDK,并采用不同的请求方式来执行。该方法的返回结果为一个标准的code+msg数组结构,帮助开发者轻松获取支付操作的状态信息及相关提示。通过准确传递这些参数,可以确保支付过程的顺利进行及数据的安全传输。
    9、在初始化阶段,xc_payment_sdk_hook会进行一系列环境检测,并将结果存储在变量中,以便后续使用。首先,通过xc_is_app函数检测当前客户端设备是否在APP环境中运行;接着,通过xc_is_h5函数判断是否在H5浏览器中运行;然后,通过xc_is_wechat函数识别当前客户端是否在微信浏览器中;最后,通过xc_is_miniprogram函数确认是否在微信小程序中运行。完成这些检测后,系统会将获取到的环境信息存储到environment变量中,后续的操作将依赖于这个变量来确定当前客户端的具体环境,以便进行相应的处理和优化。
    10、获取当客户端环境后,系统会初始化结果数组:设置支付方式、支付环境和支付令牌等基本信息。 获取当前用户ID:通过调用函数 xc_is_login() 检查当前登录的用户并获取其ID。 准备数据库查询:使用 $wpdb 构建查询语句,以支付订单ID为条件从数据库中获取对应的支付记录。 执行查询并验证结果: 执行查询语句以获取支付订单信息。 检查查询结果是否为空。如果为空,说明支付订单不存在,设置错误代码和消息,并返回结果。 设置支付信息: 如果支付订单存在,从查询结果中获取用户ID和支付金额,并设置到结果数组中。 生成一个新的支付订单号,并将其存入结果数组。
    11、xc_payment_sdk_hook在执行余额付款操作的时候,整个执行流程相对简单,不需要额外调用SDK处理。执行流程为:更新余额:调用函数 xc_update_money_hook(),传入用户ID、支付类型、支付ID、总金额等参数,执行余额扣减操作。返回结果存储在 $money_notes 中。 处理余额更新结果: 检查 $money_notes['code'] 是否等于 1。如果是,表示余额扣减失败,直接返回 $money_notes 作为响应,结束流程。 支付成功后的回调处理: 引入支付成功的回调处理文件 /www/wwwroot/www.acocoa.com/wp-content/module/public/function/acocoa/global/pay/callback.php。 初始化 $payment 数组,设置支付单号、支付方式、支付时间以及支付状态。 生成支付单号,设置支付方式为“余额支付”,记录当前时间为支付时间,并标记支付状态为成功。 执行支付成功回调: 调用 xc_payment_callback_hook() 函数,传入订单ID和支付信息,执行支付成功后的回调操作。 检查回调结果 $callback_hook['code'] 是否等于 1。如果是,表示回调失败,返回 $callback_hook 作为响应。 返回支付成功结果: 如果回调成功,设置结果数组 $result 的 code 为 0,msg 为“订单支付成功!”。 返回 $result 作为最终响应。
  • 0
    小小乐lv.2实名用户
    2025年8月7日
    1、xc_payment_refund_hook已完成重构的处理:整个执行的流程如下:退款请求初始化: 生成退款订单号 refund_order。 获取当前登录用户ID user_id。 输入校验: 检查退款金额是否为有效数字。 确认退款说明不为空且不包含非法字符。 查询订单信息: 使用 wpdb 查询订单记录,检查订单是否存在。 订单状态检查: 验证订单状态是否允许退款(必须为 'ok')。 检查退款金额是否超过支付金额。 退款权限检查: 根据退款类型(卖家、系统、管理员)检查权限。 订单锁: 使用 xc_lock 为订单加锁,避免重复退款请求。 退款处理: 根据支付方式(余额、微信、支付宝)执行不同的退款流程。 余额退款: 更新用户余额。 更新订单状态为 'refund',记录退款信息。 调用退款成功回调钩子 xc_payment_refund_ok_hook。 微信退款: 初始化微信SDK,配置退款参数。 捕获退款结果,根据状态更新订单信息。 处理退款成功、处理中、异常等不同状态。 支付宝退款: 初始化支付宝SDK,配置退款参数。 捕获退款结果,根据状态更新订单信息。 处理退款成功、请求成功但未确认等不同状态。 异常处理: 捕获异常并记录错误日志。 更新订单元数据中的失败次数。 根据失败次数处理系统退款请求。 返回结果: 根据处理结果返回相应的状态码和消息。
    2、鉴于退款过程中可能出现异常回调的情况(例如,退款申请已成功,但由于对方账户出现问题,导致退款失败),需要为此类特殊情况设计一个专门的处理机制。因此,计划封装一个独立的HOOK,以便在发生退款异常时进行回调处理。无论是微信支付还是支付宝,当退款异常发生时,都会主动触发这个名为xc_payment_refund_fail_hook的HOOK。对于第三方支付平台,如果退款操作因异常而失败,需要进一步的监听和处理措施,例如主动联系对方以完成退款操作。为此类特殊情况预留一个钩子是合理的,这样在后期需要进行监听时,可以直接通过这个钩子来完成相关的业务处理。
    3、xc_payment_refund_fail_hook触发场景如下:在处理退款到银行过程中,若发现用户的银行卡已作废或被冻结,导致原路退款无法成功时,将会触发此钩子。此外,若用户的收款账户在退款时已被注销或冻结,导致无法接收退款,也会触发此钩子。为确保准确处理,该钩子需要传递两个重要变量:首先是type,固定值为wxpay或alipay,用于判断当前操作是微信支付还是支付宝支付;其次是refund_order,即退款的订单号,通过这个订单号可以读取支付订单表中的相关信息,以便进一步处理和解决退款问题。
    4、xc_payment_refund_fail_hook在设计上采用了标准的数组结构进行数据返回,这一设计旨在确保信息的清晰传递和处理的一致性。在执行该钩子函数之前,会首先对result数组进行初始化,保证后续所有的返回信息都通过这个数组进行处理。数组中的code字段用于指示处理状态:当code为1时,意味着执行过程中出现了异常或失败,具体的失败原因则可以通过msg字段来获取详细信息。这种设计不仅可以帮助开发者迅速定位问题,还能提高故障处理的效率。相反,如果返回的code为0,则表示执行成功,意味着整个业务流程已经顺利完成。值得注意的是,返回时组合使用code和msg字段能够确保处理结果的统一性,这样上级系统或接口可以直接接收到明确的响应状态,减少了二次解析和处理的复杂性,提升了系统的响应速度和准确性。
    5、宫论统一支付:对xc_payment_hook进行了全面的重构和优化。该HOOK负责处理宫论所有的支付请求,然而之前的设计未引入回调机制和日志系统,显得相对落后,不符合当前HOOK标准。考虑到该HOOK直接涉及到财务结算,是平台极为重要的业务环节,因此安全性、可靠性和稳定性成为重中之重。基于后端的整体新要求,我们进行了全面的重构和优化处理,以确保该HOOK及其附属挂载的方法能够满足现代支付需求。此次重构不仅提升了系统的处理效率,还增强了其在面对复杂支付场景时的应变能力。
    6、在业务扩展过程中,xc_payment_hook已不再需要传递固定的变量参数,因为传统的参数传递方式无法适应不断变化的业务需求。为了解决这一问题,现采用数组结构进行参数传递。通过这种方式,除了核心参数外,业务方还可以根据具体需求传递额外的特定参数,从而更好地满足不同业务场景的处理需求。核心参数仍然保持不变,包括:token(支付凭证令牌)、method(支付方式,如微信支付、余额支付、支付宝等)、remake(订单备注信息)以及address_key(订单收货地址编码)。这种灵活的参数传递方式大大提升了系统的适应性和扩展性。
    7、在进行付款业务之前,会执行一系列严格的安全校验步骤,以确保交易的安全性和准确性。首先,会使用empty函数检测token令牌的存在性。token是一个特有的加密机制,在所有支付订单数据包中采用非明文传递方式。当发起支付请求时,会生成一个token用于前后端交互。如果检测到token不存在,会立即返回错误信息:支付失败,原因是token令牌不存在。接下来,我们会通过token令牌从redis缓存中读取支付订单的数据信息,以验证其有效性。如果无法成功获取数据,我们会返回错误信息:支付失败,原因是token令牌无效。最后,会获取支付IP和fingerprint指纹信息,并将这些信息与当前客户端的信息进行对比。如果发现不一致,会返回错误信息:支付失败,原因是订单生成和支付设备不是同一个。这一系列的安全效验处理,确保每笔交易的安全和可靠性,防止任何可能的欺诈行为。
    8、成功读取到token令牌数据后,系统会首先获取ID主键(即当前订单的待支付记录)。接下来,通过wpdb函数查询对应的支付订单数据,并将其赋值给变量pay。如果在这个过程中出现问题导致数据获取失败,系统会立即返回【支付失败:支付订单不存在】的错误信息。如果数据获取成功,系统会进一步解析并检查订单的state状态;若订单状态不是wai_pay,则返回【支付失败:订单不可支付状态】的错误提示。此外,系统还会读取当前时间戳,并与pay['close'](即订单的截止付款时间)进行比较。如果当前时间已经超过了规定的付款截止时间,系统则会返回【支付失败:订单超时无法付款】的提示,以确保支付流程的准确性和及时性。
    9、在完成订单数据提取后,接下来将处理支付场景。首先,所有支付场景都必须通过后台配置来确保正确运作,可以通过调用 xc_is_pay_config 方法来读取支付场景的配置。如果读取失败,则意味着该场景尚未集成,系统会将其视为非法请求,并返回提示信息:“支付失败:支付场景未配置”。此外,支付场景还可以通过 open 字段进行临时关闭控制。如果某个场景被关闭,系统将返回:“支付失败:支付场景已被暂停”。在某些场景中,游客支付是可选的,但通常只有非游客才能进行支付。在处理非游客支付场景时,系统会验证用户的登录状态,如果用户未登录,则会返回:“支付失败:请登录后再操作”。最后,系统还需验证付款人和当前用户是否为同一人,如果不一致,则会返回:“支付失败:订单你无权操作”。这一系列的配置和验证机制旨在确保支付过程的安全性和合规性。
    10、在完成基础效验之后,系统将进入权限检测阶段。这一阶段的首要任务是确认支付订单中是否存在收款方,因为订单可能涉及第三方交易,如卖家或商户。如果检测到订单中确实有卖家存在,系统会调用xc_is_blacklist函数来评估双方关系的状态。在这种情况下,若付款用户已将卖家列入黑名单,或者卖家已将用户列入黑名单,系统将返回相应的错误信息,进而阻止付款流程的继续。紧接着,系统会通过is_account_status检查当前用户的账户支付功能是否被限制。如果账户确实存在限制,系统同样会拦截付款操作,并提示用户当前的账户状态,以确保交易的安全和合规。通过这些细致的检测和限制措施,系统有效地保障了交易双方的利益,防止潜在的纠纷和风险。
    11、在后台支付场景中,address参数决定了是否需要收货地址。对于余额充值、资源包购买等虚拟产品的到账充值,收货地址是不必要的。然而,在涉及实物商品交易时,收货地址则是必不可少的。因此,系统可以根据具体的支付场景来选择是否启用收件地址功能。若启用了收件地址但未设置相关信息,系统会直接返回错误提示,支付失败:收件地址不能为空。同样地,如果设置了收件地址但在读取用户地址时出现异常,系统也会返回错误提示,支付失败:收货地址异常。在成功获取收件地址后,系统将进行与支付订单的address_key键值匹配处理。如果匹配过程中出现异常,则会返回错误提示,支付失败:收货地址匹配错误。通过这种方式,确保了支付流程的准确性和可靠性。
  • 0
    小小乐lv.2实名用户
    2025年8月6日
    1、在xc_payment_refund_hook发起支付宝订单退款请求时(即$payment['pay_select'] == 'alipay'),系统首先通过require_once命令加载xc_sdk_composer,以确保SDK成功集成到当前客户端环境中。由于退款操作的执行需要依赖SDK的请求功能,这一步骤至关重要。接着,系统会通过调用xc_payment_config_hook来获取相关的支付配置信息。考虑到退款操作的高风险性,涉及到的证书、秘钥等参数都必须谨慎处理。这个HOOK是一个封装良好的配置组,包含了执行退款请求所需的所有必要信息。配置成功获取后,系统会返回一个包含这些信息的config数组,确保后续退款流程的顺利进行。
    2、在完成支付宝退款的相关配置和SDK集成引入后,系统将通过\Yansongda\Pay\Pay::config($config)进行SDK脚本的初始化。初始化成功后,我们可以利用\Yansongda\Pay\Pay::alipay()->refund方法来发起退款处理请求。在处理退款请求时,需要提供一系列参数信息,包括:refund_amount,即本次退款的金额;out_trade_no,代表商户交易订单号或支付订单号;out_request_no,作为退款订单号的唯一编码。此外,还需提供退款的原因,这部分信息会被发送给用户。退款请求发起后,处理结果将被记录到变量refund_result中,以便后续查询和分析。
    3、支付宝的退款处理机制与微信的退款处理机制基本相似,都是通过调用$refund_result->toArray来获取处理结果的数据包,然后将其转化为数组结构,以便进行后续的解析和处理。然而,两者的返回结构存在一定的差异,这就要求我们在处理时需要进行额外的判断。首先,需要检查refund_result是否存在;如果不存在,或者返回的code不等于10000,则表明退款请求失败,需要采取相应的应对措施。如果refund_result存在并且返回的code为10000,则意味着退款处理成功,此时就需要执行相应的业务回调处理以确保后续流程的正常进行。
    4、通过SDK带起支付宝退款请求时,如果接口返回错误,则会触发如下处理:通过xc_log_error_warn写入错误日志:refund_error。具体的错误格式如下:[退款时间 - ' . date("Y-m-d H:i:s") . '] [退款渠道 - ' . $payment['pay_select'] . '] [错误码:' . $refund_result['code'] . ' - ' . $refund_result['sub_msg'] . '] [退款单号 - ' . $payment['id'] . ']';此日志详细记录了退款失败的具体情况,以便于运维人员进行问题排查。接下来,系统会返回code=1和msg,msg中包含接口返回的具体错误信息。需要注意的是,导致退款失败的原因可能有多种,因此必须根据系统返回的信息进行相应的判断。日志的记录不仅是为了追溯问题,也是为了在未来的退款操作中提供参考和改进依据。
    5、当SDK返回状态码为10000时,表明本次支付宝退款请求已成功发起。接下来,我们需要仔细检查返回值中的fund_change,以确认退款是否真正完成。值得注意的是,支付宝的退款处理标识主要依赖于fund_change,而微信则通过status进行验证,这种差异导致两者的退款处理必须单独分开。具体而言,如果fund_change存在且其值为Y,则表示退款已明确成功。如果fund_change不存在或其值不等于Y,这意味着虽然退款请求已成功发起,但退款是否完成仍不确定,此时需通过后续的回调机制进行进一步处理。
    6、当支付宝SDK明确返回“Y”时,表明退款处理已成功完成,此时系统将执行xc_update_sql回调操作,对支付订单表进行一系列参数更新。首先,meta字段将被更新,以包含本次退款信息的详细参数,以确保所有相关信息都记录在案。其次,state字段将被修改为“refund”,明确标识该订单已经完成退款处理,从而避免后续可能出现的重复退款行为。refund_order字段将与SDK发起的退款订单号保持一致,这样后续可以通过该退款编号轻松查询具体的退款信息。接下来,refund_amount字段记录本次退款的具体金额,精确到小数点后两位,以确保财务数据的准确性。refund_time字段将记录退款处理的具体时间,为后续审计和查询提供时间参考。最后,return_content字段则保存本次退款金额,确保所有相关财务数据都得到妥善记录和管理。通过以上步骤,系统能够确保退款过程的透明性和准确性。
    7、当支付宝订单成功发起退款后,系统将依次执行以下操作以确保流程的完整性与数据的一致性。首先,会触发数据库相关的数据表更新操作,以记录退款状态的变更。同时,系统会通过xc_unlock进行解锁操作,确保后续的请求能够正常执行。无论解锁动作是否执行成功,都必须有释放锁的机制,以避免因锁定导致后续流程的阻塞。其次,系统会触发xc_payment_refund_success_hook回调动作,通过内置的方法启动计数器功能,同时将退款相关消息精准下发至第三方事件接口。需要注意的是,无论退款行为的具体类型如何,此回调动作都是必须执行的,以确保所有退款成功的操作能够被统一处理。最后,在完成上述所有处理流程后,系统会返回统一的响应结果:code=0以及msg=支付宝订单退款成功,以明确告知退款操作已成功完成并结束。
    8、当支付宝返回的状态字段(fund_change)主要为非Y时,表明本次退款操作存在异常。虽然退款请求已成功发起,但系统无法确认是否已经完成。这种情况下,系统会启动内置的定时计划,以检测具体的退款状态。在这个过程中,系统会通过xc_update_sql进行订单的回调处理,其参数基本上与退款成功时相同,但关键的支付状态会被更改为【wait_refund:等待退款】而不是退款成功。系统设有专门的定时计划来监控处于wait_refund状态的订单。如果退款最终失败或成功,将触发相应的业务逻辑。处理完成后,系统会返回一个响应:code=0,msg=订单退款请求已提交。如果在三天内仍未收到退款,建议用户联系平台客服进行进一步处理。
    9、除了SDK自身返回的异常错误之外,退款SDK还可能因为网络故障、参数异常或接口故障等原因导致异常返回。因此,在通过Pay::alipay()->refund发起支付宝退款请求时,采用了try-catch机制来捕获这些异常。这种处理方式确保在出现错误时,系统能够返回包含code和msg的数组结构信息,从而在同步执行退款请求时,用户能够立即收到明确的提示信息。这种设计避免了由于异常未被捕获而导致前端无法处理信息的情况,防止用户在点击操作时产生无反应的错觉,提升了用户体验和系统的可靠性。
    10、当使用支付宝SDK发起退款请求时,如果遇到异常错误,会通过Exception捕获并返回详细的错误信息。整个流程与微信退款的逻辑保持一致,主要是通过xc_log_error_warn记录相关错误日志,便于后续问题的排查和分析。此外,会通过meta字段更新退款失败的次数。对于来自系统的退款请求,如果累计退款次数达到后台设定的限制,则该订单会被视为退款成功,并触发相应的处理逻辑,标记退款为成功状态,并执行相应的回调操作。而对于非系统发起的退款请求,则仅进行xc_update_sql的数据表更新处理。这样设计的目的是确保在各种情况下都能有效管理退款流程,确保系统的稳定性和数据的准确性。
    11、通过xc_payment_refund_hook发起的支付退款处理流程如下:SDK加载与配置获取: 通过 require_once 加载 xc_sdk_composer,确保支付宝SDK成功集成。 调用 xc_payment_config_hook() 获取支付配置信息,返回一个 config 数组。 SDK初始化与退款请求: 使用 \Yansongda\Pay\Pay::config($config) 初始化SDK。 调用 \Yansongda\Pay\Pay::alipay()->refund 发起退款请求,需提供 refund_amount、out_trade_no、out_request_no 和退款原因等参数。 处理退款结果: 将 refund_result 转化为数组结构。 检查 refund_result 是否存在及其 code 是否为10000,若不满足条件则视为退款失败。 错误处理: 记录错误日志,格式包括时间、渠道、错误码、错误信息及退款单号。 返回包含错误信息的响应。 确认退款完成: 检查 fund_change 字段,若存在且为 "Y" 则退款成功。 若 fund_change 不存在或不为 "Y",则需后续回调确认。 成功退款后的数据更新: 执行 xc_update_sql 更新数据库,修改订单状态为 "refund"。 更新 meta、state、refund_order、refund_amount、refund_time 和 return_content 字段。 退款成功后的回调与解锁: 更新数据库后,执行 xc_unlock 释放锁。 触发 xc_payment_refund_success_hook 回调。 返回成功响应。 异常退款处理: 若 fund_change 非 "Y",启动定时计划监控退款状态,更新订单状态为 "wait_refund"。 若退款最终成功或失败,触发相应业务逻辑。 返回提示用户退款请求已提交。 异常捕获机制: 使用 try-catch 捕获异常,确保返回明确的错误信息。 记录异常日志,更新退款失败次数。 异常处理与系统稳定性: 捕获异常后,记录日志并更新 meta 字段中的失败次数。 若系统发起的退款请求累计失败次数达到限制,标记为退款成功并触发相应处理逻辑。 对于非系统发起的退款请求,更新数据库记录。
  • 0
    小小乐lv.2实名用户
    2025年8月5日
    1、在xc_payment_refund_success_hook回调钩子中,系统会执行一系列处理动作,主要是通过xc_redis_count发起计数器处理。计数器被设计为三个层次:首先是“refund”,这是一个全局统计计数器,用于记录平台总的退款金额;其次是根据支付方式进行细分的计数器,比如“refund_' . refund['payment']['type']”,可以进一步在统计报表中分析不同支付方式的退款金额,如支付宝和微信的退款金额;最后是基于支付场景的计数器“type”,记录不同订单付款类型的退款数量,例如“tao”代表淘货场景的退款,“recharge_money”代表余额充值场景的退款。通过这种多层次的计数器设计,可以实现更细致的退款数据统计和分析,帮助平台更好地进行财务管理和业务决策。
    2、在成功完成三个关键计数器写入操作后,将会启动相应的消息发送处理。具体而言,通过xc_notify_hook系统将通知传达给付款用户,告知其订单已进入退款流程。消息发送支持多种渠道,包括内置站内信(交易助手)、短信、邮件、微信公众号以及APP通知,确保用户能够及时获取退款信息。每条通知都拥有唯一标识payment_refund,便于追踪与管理。通知内容直接调用之前封装的模板,因此无需在此进行修改,仅对触发机制进行了优化,以确保消息能够更迅速、准确地到达用户手中。注:完成上述的操作后,将会触发code=0的状态返回,告知系统回调任务已完成处理。
    3、xc_payment_refund_success_hook由于涉及到Redis计数器的处理和消息通知的发送,这两个操作都相对耗时,尤其是消息通知部分,因为它需要调用多个外部接口,可能会在意外情况下导致进程阻塞的风险。为了提高系统的稳定性和响应速度,回调接口决定完全采用异步方案执行。在触发时,会首先验证当前环境是否具备Swoole执行的条件。如果条件允许,则主动将任务交给Swoole异步服务器处理,这样的转发过程仅需约0.1秒即可完成,大大提升了系统的处理效率和可靠性。通过这种方式,确保了在高负载情况下依然能够快速响应,避免阻塞问题对整体业务流程的影响。
    4、为了确保外部接口或事件能够及时收到退款消息通知并进行相应的业务处理,在退款成功的回调HOOK中加入了第三方通知的业务逻辑。在返回code=1的处理状态之前,系统会通过hook_after脚本注册一个方法,利用xc_do_action进行回调方法的注册处理。这一机制旨在将退款成功的消息传递给第三方事件,所传递的参数包括退款编号、退款原因、退款方式等关键信息。第三方只需按照标准注册并挂载对应的方法,即可顺利接收到这份消息通知,从而实现高效的业务联动和处理。
    5、xc_payment_refund_success_hook完成封装处理,整个流程如下:初始化: 设置返回结果为一个包含 code 和 msg 的空数组。 禁用缓存,获取支付订单信息以确保数据一致性。 计数器处理: 使用 xc_redis_count 进行计数器操作,包括: 全局退款金额统计。 按支付方式细分的退款金额统计。 基于支付场景的退款数量统计。 消息通知: 通过 xc_notify_hook 发送通知给付款用户,支持多种渠道(站内信、短信、邮件等)。 使用 payment_refund 作为唯一标识来管理通知。 异步执行: 验证环境是否支持 Swoole。 如支持,任务交由 Swoole 异步服务器处理,提高系统响应速度。 第三方通知: 在返回 code=1 之前,注册第三方通知逻辑。 使用 xc_do_action 传递退款信息给第三方事件,确保业务联动。
    6、xc_payment_refund_success_hook微信退款处理流程已完成封装:执行流程如下,SDK初始化与配置: 引入 xc_sdk_composer,加载支付SDK。 获取支付配置并进行初始化。 构建退款请求参数: 创建包含订单号、退款号、退款原因和金额的订单数组。 发起退款请求: 调用 Yansongda\Pay\Pay::wechat()->refund($order) 发起退款请求。 将结果转换为数组形式。 退款结果处理: 接口返回内容不可识别: 记录日志,释放锁,返回错误信息。 退款关闭(CLOSED): 记录日志,释放锁,返回错误信息。 退款处理中(PROCESSING): 更新订单状态为 wait_refund。 调用 xc_payment_refund_ok_hook,执行退款成功的回调。 释放锁,返回处理中的提示信息。 退款异常(ABNORMAL): 更新订单状态为 fail_refund。 调用xc_payment_refund_success_hook 和 xc_payment_refund_abnormal_hook。 记录日志,释放锁,返回异常处理提示。 退款成功(SUCCESS): 更新订单状态为 refund。 调用 xc_payment_refund_success_hook,执行退款成功的回调。 释放锁,返回退款成功信息。 日志记录与锁处理: 在每个关键步骤中,进行日志记录以便于追踪问题。 每次处理完成后,确保锁被释放以避免阻塞其他操作。
    7、在进行微信退款操作时,考虑到执行过程中可能出现多种意外错误,这些错误可能由SDK引发,也可能由请求故障引发。为了确保退款过程的一致性,需要对这些意外错误进行有效的监控和处理。因此,在SDK初始化阶段,系统会采用try-catch机制来捕捉异常错误。这样可以保证所有错误都能被Exception捕获,并进行相应的错误处理。通过这种方式,确保整个请求过程始终能够返回包含code和msg的标准数组结构,确保信息传递的完整性和一致性。
    8、、在退款操作中,当系统检测到异常时,会触发Exception处理机制,以便对错误进行有效监控。此时,系统会将错误信息记录到日志文件中,确保每个细节都被妥善保存。日志的格式非常清晰,具体包括:退款时间、退款渠道、错误信息以及退款单号等关键数据。日志格式为;[退款时间 - ' . date("Y-m-d H:i:s") . '] [退款渠道 - ' . $payment['pay_select'] . '] [错误 - ' . $e->getMessage() . '] [退款单号 - ' . $payment['id'] . ']该日志通过宫论统一日志写入方法:xc_log_error_warn执行,记录本次退款异常的具体错误,方便后续的排查处理。
    9、在执行退款处理时,如果捕获到异常,将记录退款失败的错误次数,并将其写入到meta[refund]字段中。该字段为一个子数组结构,包含三个参数:(number:失败次数,初始值为1,若已有失败记录则自动累加;fail:执行失败的原因,直接从getMessage错误信息中获取;time:当前的日期时间,包括时分秒)。同时,后台配置了一个名为xc_pay_retund_number_fail的字段,用于设定退款错误的最大允许次数。如果错误次数低于此配置参数,则不会立即判定退款失败,而是将错误次数和原因记录到meta字段中,并通过xc_update_sql函数进行后续处理回调。
    10、在处理异常退款的情况下,如果退款是由系统发起并且累计退款次数达到了后台设定的限制,那么该订单将被视为退款成功。这一流程设计的原因在于,与人工退款不同,人工退款操作会直接返回错误异常,用户可以明确看到具体的失败原因,从而可以及时联系官方处理多次失败的退款。而系统退款的特点是会自动重复尝试处理,因此需要特别对其进行管理。当标记退款时,系统会将状态设置为fail_refund,并记录对应的失败原因,然后执行退款成功的回调动作。这种机制旨在确保系统退款的有效性和透明度,同时减少用户在面对退款问题时的困扰。
    11、在通过xc_payment_refund_hook发起退款处理时,设计了一套严格的锁机制以确保操作的安全性。锁名由当前HOOK标记和支付订单主键组合而成,其有效期设定为60秒。在执行退款操作时,系统会尝试获取该锁以确保操作的独占性。如果获取锁失败,则立即返回错误提示。这一机制旨在保护退款操作的敏感性,防止并发执行可能导致的各种不可控问题。与此同时,无论退款操作是成功还是发生错误,系统都会在处理结束时释放锁,以保证后续操作的顺利进行。通过这种方式,我们确保在执行过程中避免并发行为,提升系统的稳定性和安全性。
  • 0
    小小乐lv.2实名用户
    2025年8月4日
    1、在执行xc_payment_refund_hook时,系统会根据付款类型选择相应的退款逻辑处理。如果付款方式是微信支付(即pay_select等于wxpay),则系统会进行一系列的初始化步骤。首先,通过require_once加载xc_sdk_composer,将微信支付的SDK集成到当前环境中,这是后续退款操作所需的关键步骤。接着,系统通过xc_payment_config_hook读取支付SDK所需的配置参数,并将这些参数赋值给config变量。这些配置参数是后续通过SDK发起退款请求时必不可少的。通过这些初始化动作,确保退款流程能够顺利进行并符合微信支付的要求。
    2、在完成SDK的集成和支付参数的封装处理后,下一步是进行SDK的初始化操作。通过调用Yansongda\Pay\Pay::config($config)方法,我们需要对配置参数进行详细的核验检查,以确保其准确无误。如果初始化过程出现任何问题,系统将返回相应的错误信息,帮助定位问题所在。若初始化成功,则可以继续进行请求参数的封装工作。在发起退款请求时,需要准备一个包含详细信息的order数组。该数组包括商户的支付订单号(out_trade_no)、商户退款订单号(out_refund_no)、退款原因(reason)、以及金额信息(amount),其中金额信息涵盖了退款金额、原支付金额和金额单位(默认CNY人民币)。这些信息是向服务商接口发起退款请求时必不可少的参数,确保请求能够顺利进行。
    3、在执行微信退款的过程中,首先完成了SDK的初始化,然后将退款信息封装成一个order数组。接下来,通过调用\Yansongda\Pay\Pay::wechat()->refund(order)这一内置方法,发起微信支付的退款请求,并同步接收响应结果,存储在变量refund_result中。随后,通过refund_result->toArray()将结果转换为数组结构,以便进行后续的处理。通过这种方式,可以直接对$refund_result进行验证,以确认退款操作是否成功。整个流程确保了退款请求的顺利进行以及结果的可靠性。注:默认返回的结构体包含请求头,如果需要对请求头状态进行验证,需要对原生数据包进行二次解析处理。
    4、在执行微信退款请求时,如果SDK成功返回了处理结果数组,系统会首先接收到退款处理结果的信息。接着,通过is_array和isset函数对返回结果进行验证:如果返回结果是数组,并且其中的status处理状态不为空,系统将继续进行业务逻辑处理。然而,如果返回结果中有任何一项缺失或为空,系统将触发异常错误,立即返回code=1,并显示msg:请求出现异常,接口反馈信息不完整的提示。一旦确认有返回结果,系统会进一步验证status状态,并根据具体的返回状态来执行相应的业务逻辑。这样确保了每一步的处理都符合预期,减少了因数据不完整导致的错误。
    5、当检测到$refund_result['status']为CLOSED时,意味着服务商反馈当前支付订单已被关闭,因此不支持退款操作,系统会立即返回错误信息:'code' => '1', 'msg' => '退款失败:返回状态(CLOSED:退款已关闭)。如果状态为PROCESSING,则表明退款正在处理中,资金到账可能会有一定的延迟。系统将继续监控退款进度,并返回提示信息【订单退款请求已提交\n,如果超过三天未到账,请联系平台客服进行处理。】如果状态为ABNORMAL,表示退款失败,需要人工介入,系统将返回信息:单退款请求已提交\n,需要平台手动进行退款,预计在72小时内完成处理。最后,如果状态为SUCCESS,则表示退款已经成功处理。
    6、退款过程中,如果【status】状态获取失败,除了会直接返回异常,还将会触发日志写入。日志格式如下:[退款时间 - ' . date("Y-m-d H:i:s") . '] [退款渠道 - ' . $payment['pay_select'] . '] [错误 - 接口返回内容不可识别] [退款单号 - ' . $payment['id'] . ']该日志通过xc_log_error_warn进行记录,唯一标识为:refund。此日志详细记录了退款失败时的异常情况,为后续问题排查提供了重要依据,通过分析日志内容,可以有效识别并解决问题。注:该日志不会触发报警,只是记录错误。不会再发生错误的时候报警通知管理员。
    7、除了status获取失败会触发日志写入,以下状态也会触发日志写入:【CLOSED:订单已关闭,退款无法完成】日志格式:[退款时间 - ' . date("Y-m-d H:i:s") . '] [退款渠道 - ' . $payment['pay_select'] . '] [错误 - 返回状态(CLOSED:退款已关闭)] [退款单号 - ' . $payment['id'] . ']。【ABNORMAL:退款异常】日志格式如下:[退款时间 - ' . date("Y-m-d H:i:s") . '] [退款渠道 - ' . $payment['pay_select'] . '] [错误 - 返回状态(ABNORMAL:退款异常),疑是银行卡被冻结,需要平台手动退款] [退款单号 - ' . $payment['id'] . ']。只要发生退款不成功,就会触发日志写入。记录其错误原因,以便后续进行处理。
    8、当用户对支付订单发起退款请求时,如果系统返回以下三种状态,则认定退款成功,并触发相应的回调操作:首先,状态为“PROCESSING”时,表示退款订单已被接收,但由于某些原因需要延迟处理。这种情况下,虽然退款时间可能会有所延迟,但仍被视为成功退款,仅涉及结算时间问题。其次,状态为“ABNORMAL”时,意味着退款过程中出现异常,可能是由于清算问题,如银行卡冻结限额或微信无法打款等。这种情况也被视为退款成功,但需标记为异常,并需人工介入处理以解决潜在问题。最后,状态为“SUCCESS”时,表示退款已明确成功,并已将款项原路退回至支付账户,整个过程无异常情况发生。通过这些状态反馈,系统能够更好地管理和跟踪退款流程,确保用户的退款请求得到及时处理。
    9、当微信退款返回【PROCESSING】状态时,意味着退款正在处理中,结果可能会有延迟。在这种情况下,系统会将该退款视为一种成功状态,并通过xc_update_sql对支付订单进行回调处理。具体操作包括将订单状态设置为(wait_refund),同时记录相关信息如退款订单号、退款时间和退款金额等。接下来,系统会执行数据表的更新操作,以确保所有相关信息准确无误。一旦上述操作完成,该订单的退款流程便已基本完成。之后,系统会通过定时计划定期检测退款状态,如果查询到退款成功,系统会自动将订单状态更新为refund;若退款明确失败,系统则会将状态调整为等待人工退款,从而确保及时跟进处理。
    10、新增了一个名为 xc_payment_refund_success_hook 的回调接口,用于在支付订单发生退款操作时触发相应的回调事件。这一机制的设立旨在为业务回调处理和第三方消息的下发提供统一的解决方案,因为交易订单通常涉及的方面非常广泛,因此需要一个集中的回调事件来加以管理。根据当前的处理机制,无论是退款中、退款成功还是退款失败(需要人工处理),都会激活这个HOOK。在HOOK内部,封装了一系列的处理逻辑,以确保各种退款场景都能得到妥善处理。该HOOK需要传递两个关键变量:1、id,即完成退款的订单ID;2、status,表示退款的具体状态,包括三种可能:success(退款成功)、wait_refund(等待结算,退款中)、fail_refund(退款失败,等待人工处理)。这种设计能够更好地应对复杂的交易场景,确保每个退款事件都能被准确追踪和处理。
    11、xc_payment_refund_success_hook作为一个重要的回调接口,首先会进行初始化操作。该接口的返回结果是一个数组结构,包含【code+msg】两个字段。其中,code表示处理状态:如果在执行过程中途退出,统一返回1;如果完整执行完毕,则返回code=0。在发生错误时,可以通过msg字段了解具体原因。在初始化阶段,系统会将result设置为空数组,以便后续能返回相应的数组信息。完成数组的初始化后,系统会通过统一订单状态获取对应的支付订单信息。为了确保数据的一致性和准确性,这个获取过程会强制禁用缓存,避免因缓存导致的结果不一致。由于涉及到退款操作,处理必须严谨。如果在获取支付订单信息的过程中出现失败,系统将直接返回错误信息,并终止回调流程。如果获取成功,则会提取支付订单信息,以便后续的业务逻辑中使用。
  • 加载更多评论
    单栏布局 侧栏位置: