首页 / 资讯中心 / 文章详情

仿720云krpano全景制作源码拆解:支付、打赏与场景红包实现

仿720云krpano全景制作源码拆解:支付、打赏与场景红包实现 ★ FEATURED ARTICLE
简介这套基于krpano框架的仿720云全景制作网站最新版源码面向需要搭建全景展示与商业化平台的开发人员适用于房地产、旅游、展览等行业的全景项目。资源共1982个文件含659个php后端代码、492个png图片素材、162个js脚本、103个xml场景配置另有css、swf、html等前端资源压缩包整体约89.06MB目录结构清晰便于部署和二次开发。内置微信支付、在线打赏、场景红包等互动功能并附带krpano工具及批处理脚本可实现全景生成、部署与自定义配置。已有499人学习下载对熟悉krpano和Web开发的人员而言这是一套可直接支撑商业化全景网站运营的完整方案。1. 一套仿720云的krpano全景制作源码凭什么能直接收钱做全景交付这几年krpano 是绕不开的引擎但大多数拿到的源码包只解决“全景能看”。这套仿720云全景制作源码用的是 krpano 框架把全景制作、后台管理、微信支付、在线打赏、场景红包串成了一条完整的商业链路。也就是说你搭好之后访客看全景、扫码付费、解锁内容、给创作者打赏这一套交互都有对应落法。适合三类人接全景私活的开发者需要一个能给甲方演示“能收钱”的3D看房方案准备做全景平台的小团队缺一套能直接改的 PHP 后台以及想研究 krpano 热点和微信支付签名逻辑的独立开发者。我按“拆目录 → 跑流程 → 接支付 → 排坑”的顺序把它过了一遍下面把实际操作和翻车经验写出来。2. 先拆目录再看链路入口文件、krpano 核心与支付模块各自负责什么拿到源码包第一件事不是急着装环境而是先把目录过一遍。搞清楚每个目录是干嘛的后面出了问题你才知道去哪个文件里查。2.1 目录与文件职责一套典型源码包的布局长什么样这类全景源码包的结构大同小异我拆过的几个版本基本都遵循同一套分层逻辑。用代码块把常见布局整理出来. ├── admin/ # 后台管理入口负责项目、订单、红包配置 ├── upload/ # 全景图与封面存放目录需要可写权限 ├── krpano/ # krpano 核心库含 viewer 与各类插件 ├── pay/ # 微信支付相关下单、回调、退款都在这里 ├── config.php # 数据库、支付参数、上传路径的全局配置 └── index.php # 前台入口接收项目 ID 参数并渲染播放器先看 pay 目录里面有没有 notify.php这是微信支付回调的入口直接决定你能不能收到钱。再看 upload 目录的权限很多源码包默认是 755上传全景图时写不进去后台就会报错。admin 和前台分开的好处是后台只处理项目配置前台只负责播放器渲染职责清晰。支付模块单独放一个目录是因为下单和回调这两个动作既可能被后台触发比如后台测试订单也可能被前台触发用户扫码独立出来两边都能调用。2.2 全景运行链路index 入口如何驱动 krpano 渲染场景全景展示的底层逻辑不复杂前台页面读取项目 ID后端把项目配置拼成 XMLkrpano viewer 根据 XML 渲染场景。一个典型的 krpano XML 结构长这样krpano scene namescene_hall title客厅 image typesphere hfov360 vfov120 sphere urlupload/pano/hall.jpg/ /image hotspot namego_kitchen typescene ath30 atv0 linkedscenescene_kitchen onclickloadscene(get(name));/ hotspot namereward_btn typeimage urlupload/icon/reward.png ath10 atv10 onclickshowReward();/ /scene /krpanoimage 标签里的 sphere 定义了一张 360 度全景图hotspot 标签就是常说的 krpano 热点可以是跳转场景的按钮也可以是触发打赏弹窗的图标。onclick 里调用的 loadscene 是 krpano 内置函数第二个热点则调用页面里注册的 JS 函数 showReward。这套源码里前台页面一般是这样初始化 player 的function createPanoViewer(xmlUrl) { var viewer document.createElement(div); viewer.id panoViewer; document.body.appendChild(viewer); embedpano({ xml: xmlUrl, target: panoViewer, html5: auto, mobilescale: 1.0 }); return viewer; }embedpano 是 krpano 的 JS 接口xml 参数指定加载哪个配置文件target 指定挂载到页面上哪个 DOM 节点html5 设为 auto 表示移动端优先用 html5 渲染而不是 flash。这个参数在现在很关键因为新手机浏览器基本都禁了 flash不写 auto 可能会出现安卓手机上白屏。2.3 前后台数据接缝PHP 接口如何给前端喂数据常见做法是数据库里一张项目表、一张场景表、一张热点表再加订单表和打赏记录表。前台加载时调一个接口一次性返回项目基础信息、场景列表、热点坐标再在 PHP 端把数据拼成上面那种 XML 输出。一个简化的接口处理逻辑如?php require_once config.php; $id isset($_GET[id]) ? intval($_GET[id]) : 0; if ($id 0) { echo krpano项目ID无效/krpano; exit; } $project db_query_one(SELECT * FROM pano_project WHERE id $id); $scenes db_query_all(SELECT * FROM pano_scene WHERE project_id $id); // 遍历场景生成 krpano 可识别的 scene 与 hotspot 节点 echo generateProjectXml($project, $scenes);这里必须用 intval 或预处理语句处理 ID而不是直接把 $_GET[id] 拼接进 SQL。全景源码的接口往往是公网可访问的曾经见过有人把项目 ID 参数直接拼 SQL结果被注入把整张表删了这类问题在交付源码时一定要避开。generateProjectXml 函数做的事就是把数据库行转换为 XML 字符串。这一步是整个后台与前台之间的接缝热点的坐标、跳转关系、打赏按钮的显示与否全部在这一层决定。3. 复现一次完整项目从上传全景图到生成带打赏的 3D 链接目录结构和链路看明白了就进入实操。这一章按新建一个全景项目的完整流程走一遍如果你拿到的是这套源码照着做就能跑通。3.1 环境准备与全局配置PHP 版本、伪静态、上传权限先把运行环境列出来。这类源码包通常基于 PHP MySQL要求不算高但有几个硬条件要满足项目要求说明PHP 版本7.0 及以上低于 7.0 可能不支持某些语法MySQL5.6 及以上需要支持 utf8mb4 字符集伪静态Apache 或 Nginx 均可后台链接和前台短链接需要伪静态支持目录权限upload/ 与 pay/ 可写全景图上传和支付日志写入依赖写权限config.php 是全局配置打开后需要改这几个地方?php define(DB_HOST, localhost); define(DB_NAME, pano_db); define(DB_USER, root); define(DB_PASS, your_password); define(APPID, wx8888888888888888); define(MCH_ID, 1600000000); define(API_V3_KEY, your_api_v3_key_here); define(CALLBACK_URL, https://yourdomain.com/pay/notify.php);APPID、MCH_ID、API_V3_KEY 这三个是微信支付的核心参数CALLBACK_URL 是微信服务器回调你的地址。很多人在本地测试时把 CALLBACK_URL 填成 http://127.0.0.1微信服务器根本访问不到支付回调必然失败。这个细节放到第 5 章避坑部分细说。3.2 后台新建全景项目上传全景图并生成场景后台一般会提供“新建项目”表单填写项目名称、封面图、选择全景图文件提交后生成项目 ID。上传接口处理全景图时常见做法是检查扩展名并生成新文件名?php if ($_FILES[pano_file][error] UPLOAD_ERR_OK) { $ext strtolower(pathinfo($_FILES[pano_file][name], PATHINFO_EXTENSION)); $allowed array(jpg, jpeg, png, webp); if (!in_array($ext, $allowed)) { exit(不支持的文件格式); } $newname uniqid(pano_, true) . . . $ext; $dest UPLOAD_PATH . /pano/ . $newname; move_uploaded_file($_FILES[pano_file][tmp_name], $dest); // 把 $newname 写入项目表 }这段代码里有两个关键点。第一扩展名做了白名单判断不允许传 .php 或 .exe否则等于给攻击者开了一扇后门。第二文件名用 uniqid 重新生成避免用户上传的文件名直接落到服务器上防止路径穿越和重名覆盖。3.3 场景热区与 krpano 热点两种配置方式让你少走弯路场景热区是用户与全景交互的第一入口。常见的热点类型有三种跳转到另一个场景、弹窗显示图文、触发打赏支付。krpano 热点在 XML 里用 hotspot 标签定义但不同源码包的生成方式不一样。第一种是写死在 XML 文件里。优点是加载快、结构直观缺点是改了热点位置要重新生成文件不适合给运营人员使用。第二种是后台配置热区前台加载时动态生成。热点表存了场景 ID、热点名称、坐标、跳转目标PHP 端遍历输出?php foreach ($hotspots as $h) { echo hotspot name . $h[name] . type . $h[type] . . url . $h[icon] . ath . $h[ath] . atv . $h[atv] . ; if ($h[type] scene) { echo linkedscene . $h[target_scene] . ; } echo /; }这样后台就能通过表单修改 ath、atv 坐标和控制跳转目标不用动代码。ath 是水平角度atv 是垂直角度单位为度。如果热点出现在全景图的正上方或正下方通常是这两个角度没配对。3.4 前台初始化用项目 ID 加载动态 XML用户访问分享链接时URL 一般长这样https://yourdomain.com/?id123。前台 JS 通过 URL 参数拿到项目 ID再请求动态 XML 生成接口var params new URLSearchParams(location.search); var projectId params.get(id); if (projectId) { createPanoViewer(api/tour.php?id projectId); } else { alert(缺少项目 ID); }这里我一般会在前端加一个 loading 状态因为全景图体积大动态 XML 接口也要跑 SQL 查询不加 loading 用户会以为页面卡死了。krpano 自身有 onxmlcomplete 回调可以在加载完成后再关闭 loading体验会好很多。4. 微信支付接入JSAPI 下单、回调验签与在线打赏的实现位置支付是这套源码里最有商业价值的部分。微信支付接口对接的完整链路是前端点击按钮后端生成预支付订单用户确认支付微信服务器回调后端后端验签并更新订单状态再通知前端刷新页面。4.1 支付参数配置APPID、商户号、APIv3 密钥都在哪设置微信支付接口的参数从哪来先理清楚参数含义获取位置APPID公众号或小程序的唯一标识微信公众平台 → 开发 → 基本配置MCH_ID微信支付商户号微信支付商户平台 → 账户中心API_V3_KEYAPIv3 版本密钥商户平台 → API 安全 → 设置密钥商户证书apiclient_cert.pem 等文件商户平台 → API 安全 → 申请证书APIv3 密钥是 32 字节的随机字符串不是 APIv2 那套 API 密钥很多人在这里搞混导致下单时返回签名错误。证书文件要放在 pay/cert/ 目录下并且不要允许浏览器直接访问该目录否则证书泄漏等同于支付密钥泄露。4.2 下单与签名金额要按分处理JSAPI 下单的核心逻辑是用商户私钥对请求参数签名然后 POST 到微信支付接口。代码示意?php $params array( appid APPID, mchid MCH_ID, description $goodsName, out_trade_no date(YmdHis) . rand(1000, 9999), notify_url CALLBACK_URL, amount array(total intval($amount * 100)), payer array(openid $openid), ); // 按 APIv3 规则序列化并请求微信支付下单接口 $resp requestWechatPay(/v3/pay/transactions/jsapi, $params); echo json_encode($resp);amount.total 单位是分必须用 intval($amount * 100) 转成整数。如果直接传浮点数比如 9.99在序列化时可能变成 9.990000000000002微信支付那边直接报参数错误。out_trade_no 是商户订单号我习惯用时间戳加随机数拼接保证唯一同时便于追踪。下单成功后前端会拿到一个 pay_params 对象里面包含 appId、timeStamp、nonceStr、package、signType、paySign。前端把这个对象传给微信 JSAPI 的 WeixinJSBridge.invoke 或 wx.chooseWXPay拉起支付界面。4.3 回调验签先从 HTTP 头里取签名再从 resource 里取订单回调是出问题最多的地方。微信支付回调会把签名放在 HTTP 头里把订单数据放在请求体里验签顺序做错的概率非常高。?php $signature $_SERVER[HTTP_WECHATPAY_SIGNATURE]; $timestamp $_SERVER[HTTP_WECHATPAY_TIMESTAMP]; $nonce $_SERVER[HTTP_WECHATPAY_NONCE]; $body file_get_contents(php://input); // 1. 拼接验签原文 $message $timestamp . \n . $nonce . \n . $body . \n; // 2. 用平台证书验签 $valid verifyWechatSign($message, $signature); if (!$valid) { http_response_code(401); exit(FAIL); } // 3. 验签通过后再解密 resource $data decryptResource(json_decode($body, true)[resource]); // 4. 更新订单状态返回 SUCCESS echo {code:SUCCESS,message:成功};验签原文的拼接顺序是固定的时间戳、换行、随机串、换行、请求体、换行。很多人漏掉最后的换行符导致验签一直失败。验签通过后订单数据在 resource 字段里是加密的需要用 APIv3 密钥做 AES-GCM 解密解出来才能拿到 out_trade_no 和 transaction_id。最后一步也很关键处理完业务后响应体必须返回 JSON 格式的 SUCCESS 字符串。如果没有返回 SUCCESS微信会认为回调失败然后每隔一段时间重试重试持续好几天。如果你发现订单被重复处理多半是回调返回格式不对。4.4 在线打赏与场景红包两种资金流向的落库差异这两个功能名字像但资金流向相反。功能资金方向核心表用户触发方式在线打赏用户 → 站长/创作者打赏记录表点击打赏按钮输金额付款场景红包站长/创作者 → 用户红包发放记录表点击场景中的红包领取到零钱在线打赏走的是微信支付 JSAPI 下单用户付款后钱进商户号后台记录打赏人、金额、留言。场景红包则要平台方给用户发钱走的是微信商家转账到零钱接口需要开通对应的产品权限。如果源码里的“场景红包”是用户扫码付款领取虚拟红包那就还是收款逻辑端看落库方式。5. 避坑与常见问题支付回调、上传权限、krpano 授权五个大坑从环境搭建到上线运营这五个问题出现频率最高每一个我都实际踩过。按“现象 → 原因 → 解决”写方便你对照排查。5.1 现象手机上支付成功但页面没反应现象是用户扫码付完钱页面还停留在原地订单后台能看到但前台没跳转。原因通常是回调地址填错或不可达。微信服务器回调的是 CALLBACK_URL很多人在本地测试填了局域网 IP 或 127.0.0.1微信那边访问不到支付状态就无法同步。解决方法是把 CALLBACK_URL 改成公网可访问的 HTTPS 地址并且回调接口返回 SUCCESS让微信停止重试。5.2 现象付费内容解锁后刷新即失效现象是用户付了钱看到付费内容一刷新又需要付费。原因是解锁状态存了 session 或 cookie而全景页面在微信里打开时微信内置浏览器对 cookie 的处理在不同机型上表现不一样。解决方法是解锁状态按微信 openid 查询数据库支付成功后把 openid 和项目 ID 写入一张解锁表每次加载时查表判断是否已解锁。5.3 现象前台白屏后台却正常后台管理能用前台打开是白屏多半是 krpano 核心文件加载路径有问题。源码包里的 krpano 目录通常按相对路径引用但部署到二级目录或用了 CDN 后路径就断了。在浏览器控制台里如果看到 krpano.js 的 404就是把路径写死了。解决方法是把 krpano 核心库的路径改成相对于站点根目录的绝对路径或者统一走 config 里的变量。5.4 现象场景红包被同一用户反复领取红包被刷的翻车现场往往是考证了领取次数没有数据库层的唯一约束。只在代码里判断“这个用户是否领过”并发请求同时进来两个请求都通过判断红包就被领了两次。解决方法是给红包领取记录表加 UNIQUE 约束比如 UNIQUE(user_id, redpack_id)数据库兜底同时在查询时用事务锁住红包行。5.5 现象后台能进前台分享链接打不开前台链接变成 http://yourdomain.com/?id123 这种短链时需要伪静态支持。Apache 环境要配 .htaccessNginx 环境要配 rewrite 规则。如果把项目放在子目录而伪静态规则写的是根路径链接就会 404。解决方法是先看后台配置里的站点根目录再对应调整 rewrite 规则我的习惯是 Nginx 下统一写成 try_files $uri $uri/ /index.php?$query_string。6. 把打赏功能做厚自定义金额校验、防重复点击与支付成功的视角联动支付跑通只是开始在线打赏真正体验好不好看的是细节。这一章给两个我在实际项目里加上去的功能自定义金额的二次校验以及支付成功后的全景视角联动。6.1 自定义金额前端校验只是第一道门很多全景源码的打赏金额是写死的比如只能选 1 元、5 元、10 元。做私活时甲方经常要求让用户自己输入金额实现不复杂但校验要做两层。function submitReward(projectId, customAmount) { var amount parseFloat(customAmount); if (isNaN(amount) || amount 0.01 || amount 10000) { alert(金额需在0.01到10000之间); return; } // 后端创建订单再拉起支付 createOrder(projectId, Math.round(amount * 100)); }自定义金额最怕的是用户输入 0.001 之类的特殊值前端四舍五入到分后端如果不校验就会生成一个 0 元的支付单。我的习惯是后端在下单接口里同样做一次范围校验金额小于 1 分直接拒绝。6.2 防重复点击与支付完成后的视角联动支付按钮重复点击是另一个实际高频问题。用户点了一下没反应又点一下结果创建了多个订单。处理方式是把按钮置灰等支付结果回调再恢复。function createOrder(projectId, amountInFen) { payBtn.disabled true; fetch(pay/create_order.php, { method: POST, body: JSON.stringify({ project_id: projectId, amount: amountInFen }) }) .then(function(res) { return res.json(); }) .then(function(data) { invokeWechatPay(data.pay_params); }) .catch(function() { payBtn.disabled false; alert(订单创建失败请重试); }); }支付成功后除了显示“感谢打赏”还可以让全景视角转到特定方向让用户看到打赏者的头像墙或滚动留言这个交互能明显提升打赏意愿。krpano 的 JS 接口支持直接调用镜头控制viewer.call(lookto(0, 0, 100)); viewer.call(set(active_reward_panel, 1));lookto 的三个参数分别是水平角度、垂直角度和缩放值。第一个参数 0 表示转到正前方第二个 0 表示水平视线第三个 100 表示视野大小。配合一套打赏动画比单纯弹窗提示“谢谢”有感知得多。我从接触 krpano 全景平台源码到现在交付给甲方的每一套系统都要把支付闭环、红包去重、解锁验证这三件事单独走一遍测试清单支付回调的返回格式、红包领取的唯一约束、解锁状态的数据库落点缺一个都不敢上线。希望这篇拆解帮你在自己的项目里少走点弯路。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站