YuPay

YuPay

YuPay 是一款专为 Minecraft 服务器设计的免费现代化支付插件,完整集成微信支付与支付宝支付,提供一套涵盖赞助管理、玩家激励与数据统计的综合解决方案。
Spigot/Bukkit/Paper/Leaves/Leaf/Folia/Hybird/Mohst/Arclight/Youer etc 作者 Vicuna 支持版本 1.8.x - 1.26.x
服务器使用量
6
服务玩家数
3
下载量
未统计
插件详细介绍

🎮 YuPay —— 专为 Minecraft 服务器打造的现代化赞助支付插件

> 让赞助管理不再是腐竹的噩梦。

> 微信支付、支付宝、卡密、退款、排行榜、PAPI、多语言、订单审计、跨服发奖、开发者 API —— 从玩家扫码到奖励到账,从异常排查到退款复核,YuPay 帮你把服务器赞助流程做成一套完整闭环。

---

📌 YuPay 是什么?

YuPay 是一款面向 Minecraft 服务器腐竹的现代化赞助支付插件。

它的目标很简单

让玩家赞助更方便,让腐竹收款更安全,让奖励发放更自动,让每一笔订单都有记录可查。

YuPay 支持 微信支付 与 支付宝 官方接口对接,玩家在游戏内发起赞助后即可扫码支付。支付成功后,插件会自动完成订单确认、验签、奖励发放、排行榜刷新、PAPI 数据更新和日志记录。

资金不经过第三方代收平台,直接进入你自己的微信 / 支付宝商户账户。

> ⚠️ YuPay 面向“玩家自愿赞助服务器运营”场景。请确保你的使用方式符合当地法律法规、服务器运营规范以及微信支付 / 支付宝平台规则。

---

✨ 核心亮点速览

| 模块 | 你能获得什么 |

|---|---|

| 💳 官方支付 | 微信支付 + 支付宝,支持扫码支付,资金直达商户账户 |

| 🧾 订单系统 | 订单创建、取消、过期、成功、异常、退款、补发全生命周期记录 |

| 🎁 自动奖励 | 经济奖励 + 自定义命令,支持单笔、累计、近期累计等多层触发 |

| 🔁 补发机制 | 支付状态与发奖状态分离,玩家可自助补发,管理员可重试奖励 |

| 🔑 卡密系统 | 免费码、付费码、礼包码、激活码、次数限制、过期时间、核销日志 |

| 💵 退款系统 | 退款申请、管理员审核、直接退款、部分退款、退款状态同步 |

| 📊 数据统计 | 个人总额、全服总额、排行榜、历史订单、订单详情、回调流水 |

| 🌐 多语言 | 默认中文 / 英文,可扩展任意语言,支持玩家个人语言偏好 |

| 🔌 PAPI 支持 | 个人、全服、排行榜、卡密多维度占位符 |

| 🛡️ 安全审计 | 签名验证、IP 白名单、请求体限制、敏感日志脱敏、API 授权审计 |

| 🧩 开发者 API | Bukkit ServicesManager API + 完整事件监听,方便商城 / 菜单 / 跨服系统集成 |

| 🌍 跨服发奖 | 支持共享数据库队列,多子服领取发奖任务,适合群组服网络 |

| ⚡ 性能友好 | 异步订单处理、HikariCP 连接池、Undertow 回调服务、启动健康检查 |

| 📚 插件 Wiki / 使用文档 | 插件文档 |

---

🧭 一次完整赞助流程

玩家只需要输入一条命令

/donate 50 wechat map

然后 YuPay 会自动完成

  • 校验玩家权限、金额上下限、每日限额、支付渠道可用性
  • 创建本地订单并写入数据库
  • 调用微信 / 支付宝接口生成支付二维码
  • 按配置展示支付方式:
  • 可点击链接
  • 聊天栏文本二维码
  • 背包地图二维码
  • 玩家扫码完成支付
  • 支付平台向服务器回调
  • YuPay 验证签名、校验金额、确认订单状态
  • 写入回调流水与订单快照
  • 自动发放经济奖励和命令奖励
  • 更新排行榜、PAPI 数据和玩家历史记录
  • 若发奖失败,可由玩家或管理员重试补发

腐竹不需要手动确认收款,不需要手动发奖励,也不需要翻聊天记录对账。

---

💳 官方双通道支付

YuPay 支持两种主流支付方式

| 支付渠道 | 支持能力 |

|---|---|

| 微信支付 | Native 扫码支付、支付回调、退款、退款回调、退款查询 |

| 支付宝 | 扫码支付、公钥模式、证书模式、支付回调、退款、退款查询 |

支持配置默认支付方式

pay:
  default-method: "wechat"

玩家也可以在命令中指定支付方式

/donate 10 wechat
/donate 10 alipay

如果玩家不指定支付方式,则使用服主配置的默认渠道。

---

🧾 不只是收款:完整订单生命周期

YuPay 将订单状态和发奖状态分离管理,让排障更加清晰。

支付订单状态

| 状态 | 含义 |

|---|---|

| PENDING | 待支付 |

| SUCCESS | 支付成功 |

| CANCELLED_LOCAL | 玩家本地取消 |

| CLOSED | 平台订单关闭 |

| FAILED | 支付失败 |

| EXPIRED | 待支付订单过期 |

| AMOUNT_MISMATCH | 回调金额与订单金额不一致 |

| HELD / PAID_AFTER_CANCELLED | 取消后到账等历史异常状态 |

| RESOLVED_REWARDED | 异常订单已人工判定并补发 |

| RESOLVED_REFUNDED | 异常订单已人工判定并退款 |

| RESOLVED_IGNORED | 异常订单已人工判定忽略 |

发奖状态

| 状态 | 含义 |

|---|---|

| PENDING | 等待发奖 |

| PROCESSING | 正在处理 |

| DONE | 已完成 |

| FAILED | 发奖失败 |

| SKIPPED | 无奖励赞助或无需发奖 |

这意味着

即使玩家已经付款成功,但命令奖励因为权限插件、经济插件、服务器瞬时异常导致失败,YuPay 也能保留订单成功状态,并允许后续重试补发。

---

🔁 自助补发与管理员补发

玩家可使用

/yp retry
/yp retry <订单号>

当订单已支付成功但奖励未完成时,玩家可以自行提交补发请求。

管理员也可以使用

/yp order retry-reward <订单号>
/yp order steps <订单号>

查看发奖步骤流水并手动重试。

YuPay 会记录每一步奖励执行状态,避免重复发放。

---

🎁 四层奖励系统,运营玩法随便搭

YuPay 的奖励系统支持多层触发,既能满足普通赞助奖励,也能做充值档位、累计成就、限时活动。

| 奖励类型 | 触发时机 | 适合场景 |

|---|---|---|

| 基础奖励 | 每次支付成功 | 每笔赞助都送基础礼包 |

| 单笔达标 | 单次金额达到门槛 | 50 元档、100 元档、300 元档 |

| 累计达标 | 历史累计金额达到门槛 | VIP、SVIP、永久称号 |

| 近期累计 | 指定时间范围内累计达标 | 周末冲榜、节日活动、限时礼包 |

| 退款命令 | 退款完成后 | 通知管理员、撤销标记、记录日志 |

基础奖励

commands:
  on-success:
    - "give {player} diamond 1"
    - "effect give {player} minecraft:speed 30 1"

单笔达标奖励

commands:
  on-single-achieved:
    - amount: 50
      commands:
        - "say {player} 单笔赞助达到 50 元!"
        - "give {player} minecraft:gold_block 5"

累计达标奖励

commands:
  on-total-achieved:
    - total: 500
      commands:
        - "lp user {player} parent set svip"
        - "give {player} minecraft:netherite_block 5"

限时累计奖励

commands:
  on-recent-achieved:
    - time: 86400000
      total: 200
      commands:
        - "give {player} minecraft:enchanted_golden_apple 5"

> `time` 单位为毫秒

> 24 小时 = 86400000

> 7 天 = 604800000

可用变量

| 变量 | 含义 |

|---|---|

| {player} | 玩家名 |

| {amount} | 支付金额 |

| {points} | 经济奖励数量 |

| {order} | 订单号,主要用于退款命令 |

---

💛 无奖励赞助

有些玩家只是想支持服务器,不想领取任何道具或权限。

YuPay 支持无奖励赞助

/donate 10 -n

玩家添加 -n 参数后,该订单会正常收款、记录、统计,但不会触发经济奖励和命令奖励。

适合

  • 纯支持服务器运营
  • 不影响生存平衡
  • 避免 P2W 争议
  • 公益服 / 原版服赞助场景

---

💰 Vault + PlayerPoints 双经济支持

YuPay 支持两类经济奖励

| 类型 | 说明 |

|---|---|

| vault | 对接 Vault,兼容 EssentialsX、CMI 等主流经济插件 |

| playerpoints | 对接 PlayerPoints 点券系统 |

配置示例

economy:
  enabled: true
  type: "vault"
  rate: 100.0

表示

1 元 = 100 游戏币 / 点数

还支持管理员进行两种经济之间的换算

/yp convert <玩家> <vault|points> <vault|points> <数量>

---

🔑 卡密系统:活动码、礼包码、付费激活码都能做

YuPay 的卡密系统不是简单的“输入兑换码领奖励”,而是一套可支付、可核销、可追踪的兑换系统。

卡密可以配置

| 能力 | 说明 |

|---|---|

| 免费核销 | 玩家输入卡密后直接领取奖励 |

| 付费核销 | 玩家输入卡密后需扫码支付指定金额 |

| 经济奖励 | 核销后发放 Vault 货币或 PlayerPoints 点数 |

| 命令奖励 | 核销后执行任意控制台命令 |

| 使用次数 | 每张卡密可限制最大核销次数 |

| 过期时间 | 支持永久、相对时间、指定日期 |

| 状态管理 | 启用、禁用、用尽、过期 |

| 日志追踪 | 每次核销都有记录可查 |

| 支付锁 | 付费卡密支付中会加锁,防止多人同时抢占 |

免费礼包码

/yp code create --code FREEGIFT --max-uses -1 --economy vault --eco-amount 1000 --remark "新手福利"

付费激活码

/yp code create --code PREMIUM --amount 50 --economy vault --eco-amount 5000 --commands "lp user {player} parent set vip" --max-uses 100 --expire 30d

纯命令卡密

/yp code create --code WELCOME --commands "give {player} diamond 5; say {player} 欢迎回来!"

卡密管理命令

| 命令 | 功能 |

|---|---|

| /yp code create ... | 创建卡密 |

| /yp code remove <卡密> | 彻底移除卡密 |

| /yp code disable <卡密> | 禁用卡密 |

| /yp code enable <卡密> | 启用卡密 |

| /yp code modify <卡密> <字段> <值> | 修改卡密属性 |

| /yp code info <卡密> | 查看卡密详情 |

| /yp code list [页数] | 查看卡密列表 |

| /yp code logs [卡密] [页数] | 查看核销日志 |

| /yp code redeem <卡密> | 玩家核销卡密 |

---

💵 退款系统:从申请到平台退款全流程打通

退款不再靠手动转账、不再靠聊天记录确认。

YuPay 支持完整退款流程

| 功能 | 说明 |

|---|---|

| 玩家申请退款 | 玩家提交退款请求 |

| 管理员审核 | 管理员通过或拒绝 |

| 直接退款 | 管理员直接对订单发起退款 |

| 部分退款 | 可指定退款金额 |

| 退款流水 | 记录退款单号、状态、金额、渠道 |

| 退款查询 | 查询平台退款结果 |

| 退款重试 | 对失败 / 未知退款进行重试 |

| 手动确认 | 必要时手动确认退款结果 |

| 状态同步 | 定时查询平台退款状态 |

| 退款命令 | 退款完成后执行自定义命令 |

玩家申请退款

/yp refund request <订单号> [金额]

管理员查看待审核

/yp refund pending

审核通过 / 拒绝

/yp refund approve <请求ID>
/yp refund reject <请求ID>

管理员直接退款

/yp refund <订单号> [金额]

退款流水查询

/yp refund list
/yp refund info <退款单号>
/yp refund query <退款单号>
/yp refund retry <退款单号>
/yp refund confirm <退款单号>

---

📊 数据统计:对账、排行、历史一目了然

YuPay 内置常用运营统计命令。

排行榜

/ytop

显示全服赞助排行榜 Top10。

查询个人 / 全服总额

/ytotal
/ytotal <玩家名>
/ytotal all

玩家订单列表

/yp orders
/yp history

单个订单详情

/yp order <订单号>

管理员订单中心

/yp order info <订单号>
/yp order abnormal [页数]
/yp order risk [页数]
/yp order list <abnormal|pending|cancelled|risk|reward_failed|refund_failed|success> [页数]
/yp order player <玩家名|UUID> [页数]
/yp order steps <订单号>
/yp order callbacks <订单号|recent|failed|duplicate> [页数]
/yp order refunds <订单号> [页数]
/yp order mark-reviewed <订单号> [备注]
/yp order resolve <订单号> <reward|refund|ignore|hold>
/yp order expire

这套订单中心非常适合处理

  • 玩家说“我付了但没到账”
  • 取消后平台仍然到账
  • 金额异常
  • 发奖失败
  • 回调重复
  • 平台退款状态不明确
  • 多服网络中发奖节点异常

---

🌐 多语言系统:同一服务器,不同玩家不同语言

YuPay 默认提供

  • 简体中文
  • English

并支持服主自定义任意语言。

配置示例

language:
  mappings:
    zh_cn:
      file: "messages.yml"
      aliases: [zh, cn, chinese]
      client-locales: ["zh_cn", "zh_*"]
    en:
      file: "messages_en.yml"
      aliases: [english, eng]
      client-locales: ["en_*"]

玩家可自行切换语言

/yp lang en
/yp lang zh_cn

语言偏好会写入数据库,下次进服自动生效。

首次加入服务器时,YuPay 会尝试根据玩家客户端语言匹配合适语言文件。

---

🔌 PlaceholderAPI 占位符

YuPay 内置多维度 PAPI,占位符标识为

%yupay_xxx%

个人维度

%yupay_is_banned%
%yupay_total%
%yupay_total_orders%
%yupay_success_orders%
%yupay_rank%
%yupay_has_paid_in_<time>%
%yupay_recent_amount_gt_<time>_<amount>%
%yupay_orders_in_<time>%
%yupay_success_orders_in_<time>%
%yupay_amount_in_<time>%
%yupay_is_limited%
%yupay_daily_remaining%
%yupay_lang%
%yupay_pay_methods_count%
%yupay_pay_methods_list%

全服维度

%yupay_server_total%
%yupay_server_total_orders%
%yupay_server_success_orders%
%yupay_server_orders_in_<time>%
%yupay_server_success_orders_in_<time>%
%yupay_server_amount_in_<time>%

排行榜维度

%yupay_top_<rank>_name%
%yupay_top_<rank>_amount%
%yupay_top<rank>_name%
%yupay_top<rank>_amount%

<rank> 支持 1 到 10。

卡密维度

%yupay_code_total%
%yupay_code_active%
%yupay_code_<code>_status%
%yupay_code_<code>_amount%
%yupay_code_<code>_economy_type%
%yupay_code_<code>_economy_amount%
%yupay_code_<code>_used%
%yupay_code_<code>_max_uses%
%yupay_code_<code>_expire%
%yupay_code_<code>_expire_formatted%
%yupay_code_<code>_remark%
%yupay_code_<code>_locked%
%yupay_code_<code>_redeemed%
%yupay_code_<code>_can_redeem%

参数说明

| 参数 | 说明 |

|---|---|

| <time> | 毫秒,例如 24 小时 = 86400000 |

| <amount> | 金额阈值,单位元 |

| <rank> | 排行榜名次,1-10 |

| <code> | 卡密字符串,会自动大写匹配 |

金额类占位符统一保留两位小数,例如

99.50
100.00

可用于

  • 计分板
  • BossBar
  • 菜单 GUI
  • 聊天前缀
  • 称号系统
  • 物品 Lore
  • 排行榜展示
  • 活动进度展示

---

🌍 跨服发奖:适合群组服网络

如果你运营的是多子服网络,YuPay 支持跨服发奖队列。

设计目标是

> 支付回调可以由任意服务器接收,但奖励由目标服务器通过共享数据库队列领取执行。

支持路由模式

| 模式 | 说明 |

|---|---|

| LOCAL | 当前服务器直接发奖 |

| SERVER | 固定交给指定服务器发奖 |

| PLAYER_ONLINE | 玩家在哪个子服在线,就由哪个子服发奖 |

| ANY | 任意在线子服都可领取发奖任务 |

推荐生产环境使用

database:
  type: "mysql"

cross-server:
  enabled: true
  server-id: "lobby-1"
  security:
    require-shared-secret: true
    shared-secret: "请改成足够长的随机字符串"

查看跨服状态

/yp crossserver status
/yp crossserver queue

---

🛡️ 安全能力

YuPay 对支付类插件最重要的安全问题做了完整处理。

| 安全能力 | 说明 |

|---|---|

| 支付回调验签 | 微信 / 支付宝回调都会进行签名验证 |

| 金额校验 | 回调金额必须与订单金额匹配 |

| 幂等处理 | 避免重复回调导致重复发奖 |

| 回调 IP 白名单 | 支持 CIDR 白名单限制来源 |

| 请求体限制 | 防止异常大请求压垮回调服务 |

| 敏感日志脱敏 | 密钥、签名、平台交易号、IP 等可脱敏 |

| 回调流水 | 可记录平台回调处理结果、哈希、状态 |

| 安全审计日志 | API 拒绝、回调异常、退款等敏感行为单独记录 |

| API 权限控制 | 外部插件调用 YuPay API 需要按插件名授权 |

| 事件监听审计 | 可检查哪些插件正在监听 YuPay 资金相关事件 |

| 地图支付锁 | 地图二维码支付期间限制玩家乱丢 / 切换关键物品 |

安全审计命令

/yp audit
/yp audit listeners
/yp audit security

健康检查命令

/yp health
/yp health summary
/yp health full

---

🧩 给开发者的 API 与 Bukkit 事件

YuPay 提供两种开发者接入方式

  • YuPayApi:适合商城插件、菜单插件、网页充值系统、跨服系统主动创建订单、查询订单、退款、补发奖励。
  • Bukkit 事件:适合监听支付流程,在订单创建前拦截、支付完成后联动、退款完成后同步数据。

---

1. 在其他插件中依赖 YuPay

如果你的插件需要调用 YuPay API,建议在 plugin.yml 中声明依赖:

depend: [YuPay]

如果只是可选支持 YuPay,可以写

softdepend: [YuPay]

Gradle 本地依赖示例

dependencies {
    compileOnly files("libs/YuPay.jar")
}

将 YuPay.jar 放入你插件项目的 libs/ 目录即可编译。

---

2. 获取 YuPayApi 实例

YuPay 会通过 Bukkit ServicesManager 注册 YuPayApi。

推荐写法

import org.bukkit.plugin.java.JavaPlugin;
import org.yutay.yupay.api.YuPayApi;
import org.yutay.yupay.api.YuPayProvider;

public final class MyShopPlugin extends JavaPlugin {

    private YuPayApi yuPayApi;

    @Override
    public void onEnable() {
        yuPayApi = YuPayProvider.get();

        if (yuPayApi == null) {
            getLogger().warning("未检测到 YuPay,支付功能将不可用。");
            return;
        }

        getLogger().info("已成功接入 YuPay API。");
    }

    public YuPayApi getYuPayApi() {
        return yuPayApi;
    }
}

也可以直接通过 Bukkit ServicesManager 获取:

import org.bukkit.Bukkit;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.yutay.yupay.api.YuPayApi;

RegisteredServiceProvider<YuPayApi> provider =
        Bukkit.getServicesManager().getRegistration(YuPayApi.class);

YuPayApi api = provider == null ? null : provider.getProvider();

---

3. YuPay API 授权配置

YuPay 默认会检查外部插件是否有权调用 API。

第三方插件创建订单时必须声明 sourcePlugin,通常传入自己插件的名字:

.sourcePlugin(getName())

然后服主需要在 config.yml 中授权:

api:
  enabled: true
  require-plugin-declaration: true
  audit-log: true

  allowed-plugins:
    MyShop:
      create-order: true
      cancel-order: true
      query-order: true
      refund-order: false
      retry-reward: false
      no-reward-order: false
      expire-orders: false

权限说明

| 权限项 | 说明 |

|---|---|

| create-order | 允许创建支付订单 |

| cancel-order | 允许取消待支付订单 |

| query-order | 允许查询订单、订单列表、发奖步骤 |

| refund-order | 允许通过 API 发起退款 |

| retry-reward | 允许通过 API 重试发奖 |

| no-reward-order | 允许创建无奖励订单 |

| expire-orders | 允许通过 API 主动过期待支付订单 |

如果未授权,API 调用会返回失败结果,并在 YuPay 安全审计中记录拒绝原因。

---

4. 创建支付订单

示例:商城插件为玩家创建一笔 30 元的微信订单。

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.yutay.yupay.api.YuPayOrderRequest;
import org.yutay.yupay.api.YuPayOrderResult;

import java.util.LinkedHashMap;
import java.util.Map;

public void createShopOrder(Player player, String shopOrderId) {
    if (yuPayApi == null) {
        player.sendMessage("§c支付系统暂不可用。");
        return;
    }

    Map<String, Object> metadata = new LinkedHashMap<>();
    metadata.put("shopOrderId", shopOrderId);
    metadata.put("itemId", "vip_30d");

    YuPayOrderRequest request = YuPayOrderRequest
            .builder(player.getUniqueId(), player.getName(), 30.00)
            .payMethod("wechat")
            .sourcePlugin(getName())
            .externalOrderId(shopOrderId)
            .businessType("SHOP")
            .metadata(metadata)
            .expireMinutes(15)
            .noReward(false)
            .build();

    yuPayApi.createOrder(request).thenAccept(result -> {
        if (!result.isSuccess()) {
            Bukkit.getScheduler().runTask(this, () -> {
                player.sendMessage("§c订单创建失败:" + result.getMessage());
            });
            return;
        }

        Bukkit.getScheduler().runTask(this, () -> {
            player.sendMessage("§a订单创建成功!");
            player.sendMessage("§7订单号:§f" + result.getOrderId());
            player.sendMessage("§7支付方式:§f" + result.getPayMethod());
            player.sendMessage("§7金额:§f" + result.getAmount());
            player.sendMessage("§e请使用以下二维码链接完成支付:");
            player.sendMessage("§b" + result.getQrUrl());
        });
    }).exceptionally(error -> {
        Bukkit.getScheduler().runTask(this, () -> {
            player.sendMessage("§c创建订单时发生异常:" + error.getMessage());
        });
        return null;
    });
}

> 注意:createOrder 返回的是 CompletableFuture,回调不一定在 Bukkit 主线程。

> 如果要给玩家发消息、操作背包、执行 Bukkit API,建议使用 Bukkit.getScheduler().runTask(...) 切回主线程。

---

5. YuPayOrderRequest 参数说明

| 方法 | 说明 |

|---|---|

| builder(UUID, String, double) | 创建请求,传入玩家 UUID、玩家名、金额 |

| payMethod(String) | 支付方式,例如 wechat 或 alipay,不填则使用 YuPay 默认支付方式 |

| orderId(String) | 自定义 YuPay 订单号,不填则自动生成 |

| noReward(boolean) | 是否为无奖励订单 |

| sourcePlugin(String) | 调用方插件名,用于 API 授权和安全审计 |

| externalOrderId(String) | 外部系统订单号,例如商城订单号 |

| businessType(String) | 业务类型,例如 SHOP、VIP、REDEEM、CUSTOM |

| metadataJson(String) | 自定义 JSON 元数据 |

| metadata(Map<String, ?>) | 以 Map 方式传入元数据,YuPay 会转为 JSON |

| expireMinutes(int) | 当前订单过期分钟数,0 表示使用 YuPay 全局配置 |

---

6. YuPayOrderResult 返回值说明

| 方法 | 说明 |

|---|---|

| isSuccess() | 是否创建成功 |

| getOrderId() | YuPay 订单号 |

| getPayMethod() | 实际使用的支付方式 |

| getAmount() | 订单金额 |

| getQrUrl() | 支付二维码链接 |

| getMessage() | 失败原因 |

---

7. 查询订单

yuPayApi.getOrder(getName(), orderId).thenAccept(record -> {
    if (record == null) {
        getLogger().info("订单不存在:" + orderId);
        return;
    }

    getLogger().info("订单号:" + record.getOrderId());
    getLogger().info("玩家:" + record.getPlayerName());
    getLogger().info("金额:" + record.getAmount());
    getLogger().info("支付状态:" + record.getStatus());
    getLogger().info("发奖状态:" + record.getRewardStatus());
    getLogger().info("支付方式:" + record.getPayMethod());
    getLogger().info("外部订单号:" + record.getExternalOrderId());
    getLogger().info("业务类型:" + record.getBusinessType());
});

常用字段

| 方法 | 说明 |

|---|---|

| getOrderId() | YuPay 订单号 |

| getPlayerUuid() | 玩家 UUID |

| getPlayerName() | 玩家名 |

| getAmount() | 金额 |

| getStatus() | 支付状态 |

| getRewardStatus() | 发奖状态 |

| getPayMethod() | 支付方式 |

| isNoReward() | 是否无奖励 |

| getQrUrl() | 二维码链接 |

| getFailReason() | 失败原因 |

| getRefundStatus() | 退款状态 |

| getRefundAmount() | 已退款金额 |

| getSourcePlugin() | 来源插件 |

| getExternalOrderId() | 外部订单号 |

| getMetadataJson() | 元数据 JSON |

| isCreatedByApi() | 是否由 API 创建 |

| getBusinessType() | 业务类型 |

| getExpireTime() | 过期时间戳 |

---

8. 查询订单列表

yuPayApi.listOrders(getName(), "success", 20, 0).thenAccept(records -> {
    for (var record : records) {
        getLogger().info(record.getOrderId() + " - " + record.getStatus());
    }
});

| type | 说明 |

|---|---|

| pending | 待支付订单 |

| cancelled | 已取消订单 |

| success | 支付成功订单 |

| reward_failed | 发奖失败订单 |

| risk | 风险订单 |

| abnormal | 异常订单 |

---

9. 取消订单

yuPayApi.cancelOrderDetailed(getName(), orderId, "玩家在商城界面取消支付")
        .thenAccept(result -> {
            if (result.isSuccess()) {
                getLogger().info("订单取消成功:" + orderId);
            } else {
                getLogger().warning("订单取消失败:" + result.getCode() + " - " + result.getMessage());
            }
        });

也可以取消玩家最近一笔待支付订单

yuPayApi.cancelLatestPendingOrder(getName(), player.getUniqueId(), "玩家取消最近订单")
        .thenAccept(result -> {
            player.sendMessage(result.isSuccess() ? "§a已取消最近订单。" : "§c取消失败:" + result.getMessage());
        });

---

10. 发起退款

yuPayApi.refundOrderDetailed(getName(), orderId, 10.00, "商城售后退款")
        .thenAccept(result -> {
            if (result.isSuccess()) {
                getLogger().info("退款已受理:订单=" + result.getOrderId()
                        + ", 本次退款=" + result.getRefundAmount()
                        + ", 累计退款=" + result.getTotalRefunded()
                        + ", 退款状态=" + result.getRefundStatus());
            } else {
                getLogger().warning("退款失败:" + result.getCode() + " - " + result.getMessage());
            }
        });

退款需要在 YuPay 配置中给调用插件开启

api:
  allowed-plugins:
    MyShop:
      refund-order: true

---

11. 重试发奖

当订单已经支付成功,但发奖状态为失败时,可以通过 API 重试:

yuPayApi.retryReward(getName(), orderId).thenAccept(result -> {
    if (result.isSuccess()) {
        getLogger().info("已提交发奖重试:" + orderId);
    } else {
        getLogger().warning("发奖重试失败:" + result.getCode() + " - " + result.getMessage());
    }
});

需要授权

api:
  allowed-plugins:
    MyShop:
      retry-reward: true

---

12. 查询发奖步骤

yuPayApi.listRewardSteps(getName(), orderId).thenAccept(steps -> {
    for (var step : steps) {
        getLogger().info("步骤:" + step.getStepKey()
                + ", 类型:" + step.getStepType()
                + ", 状态:" + step.getStatus()
                + ", 尝试次数:" + step.getAttempts()
                + ", 错误:" + step.getLastError());
    }
});

发奖步骤字段

| 方法 | 说明 |

|---|---|

| getOrderId() | 订单号 |

| getStepKey() | 步骤键 |

| getStepType() | 步骤类型 |

| getStatus() | 步骤状态 |

| getAttempts() | 尝试次数 |

| getDetail() | 步骤详情 |

| getLastError() | 最近错误 |

| getCreatedTime() | 创建时间 |

| getUpdatedTime() | 更新时间 |

---

13. 主动过期待支付订单

yuPayApi.expirePendingOrders(getName()).thenAccept(result -> {
    getLogger().info("已过期待支付订单数量:" + result.getAffected());
});

需要授权

api:
  allowed-plugins:
    MyShop:
      expire-orders: true

---

14. 支付方式工具方法

String defaultMethod = yuPayApi.getDefaultPayMethod();

boolean wechatAvailable = yuPayApi.isPayMethodAvailable("wechat");
boolean alipayAvailable = yuPayApi.isPayMethodAvailable("alipay");

String orderId = yuPayApi.generateOrderId(player.getUniqueId(), false);

如果第三方插件想自己展示二维码图片,也可以使用

BufferedImage image = yuPayApi.createPaymentQrImage(qrUrl, 256);

免费版可能会自动在二维码图中加入 YuPay 品牌标识,可通过:

boolean required = yuPayApi.isFreeEditionBrandingRequired();
String adLink = yuPayApi.getFreeEditionAdLink();

判断是否需要展示品牌信息。

---

Bukkit 事件监听

YuPay 的事件位于

org.yutay.yupay.event

使用方式与普通 Bukkit 事件完全一致。

---

1. 注册监听器

import org.bukkit.plugin.java.JavaPlugin;

public final class MyPlugin extends JavaPlugin {

    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(new YuPayListener(this), this);
    }
}

监听器示例

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.yutay.yupay.event.*;

public final class YuPayListener implements Listener {

    private final MyPlugin plugin;

    public YuPayListener(MyPlugin plugin) {
        this.plugin = plugin;
    }

    @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
    public void onPrePayment(PrePaymentEvent event) {
        Player player = event.getPlayer();

        // 示例:低于 1 元的订单禁止创建
        if (event.getAmount() < 1.0) {
            event.setCancelled(true);
            event.setCancelReason("§c最低赞助金额为 1 元。");
            return;
        }

        // 示例:强制某个世界只能使用支付宝
        if ("activity".equalsIgnoreCase(player.getWorld().getName())) {
            event.setPayMethod("alipay");
        }

        // 示例:超过 100 元自动改为链接模式
        if (event.getAmount() >= 100.0) {
            event.setOutputMode("link");
        }
    }

    @EventHandler
    public void onOrderCreated(PaymentOrderCreatedEvent event) {
        plugin.getLogger().info("YuPay 订单已创建:"
                + event.getOrderId()
                + ", 玩家=" + event.getPlayerName()
                + ", 金额=" + event.getAmount()
                + ", 支付方式=" + event.getPayMethod()
                + ", 二维码=" + event.getQrCodeUrl());
    }

    @EventHandler
    public void onPaymentCompleted(PaymentCompletedEvent event) {
        plugin.getLogger().info("YuPay 支付完成:"
                + event.getPlayerName()
                + " 支付 " + event.getAmountRmb()
                + " 元,订单号:" + event.getOrderId());

        Player player = event.getPlayer();
        if (player != null) {
            player.sendMessage("§a感谢赞助,订单已完成!");
        }

        // 示例:支付完成后联动其他系统
        Bukkit.dispatchCommand(
                Bukkit.getConsoleSender(),
                "say " + event.getPlayerName() + " 刚刚完成了一笔赞助!"
        );
    }

    @EventHandler
    public void onPaymentFailed(PaymentFailedEvent event) {
        plugin.getLogger().warning("YuPay 支付失败或取消:"
                + event.getOrderId()
                + ", 玩家=" + event.getPlayerName()
                + ", 原因=" + event.getReason());
    }

    @EventHandler
    public void onRefundCompleted(RefundCompletedEvent event) {
        plugin.getLogger().info("YuPay 退款完成:"
                + event.getOrderId()
                + ", 玩家=" + event.getPlayerName()
                + ", 退款金额=" + event.getRefundAmount());
    }

    @EventHandler
    public void onRedeemCodeRedeemed(RedeemCodeRedeemedEvent event) {
        plugin.getLogger().info("YuPay 卡密已核销:"
                + event.getCode()
                + ", 玩家=" + event.getPlayerName()
                + ", 支付金额=" + event.getAmountPaid()
                + ", 订单=" + event.getOrderId());
    }

    @EventHandler
    public void onRedeemCodeLifetime(RedeemCodeLifetimeEvent event) {
        plugin.getLogger().info("YuPay 卡密状态变化:"
                + event.getCode()
                + ", " + event.getOldStatus()
                + " -> " + event.getNewStatus());
    }

    @EventHandler
    public void onPlayerPointsChanged(PlayerPointsChangedEvent event) {
        plugin.getLogger().info("YuPay 经济变化:"
                + event.getPlayerUUID()
                + ", 类型=" + event.getEconomyType()
                + ", 变化=" + event.getDelta()
                + ", 新余额=" + event.getNewBalance());
    }
}

---

2. PrePaymentEvent:支付创建前拦截

PrePaymentEvent 在玩家通过 /donate 等游戏内命令创建订单前触发,可取消,也可修改部分参数。

> 注意:第三方插件直接调用 YuPayApi#createOrder 创建订单时,不会经过玩家命令流程,因此不依赖 PrePaymentEvent。API 调用方应自行在创建订单前完成自己的业务校验。

可读取 / 修改

| 方法 | 说明 |

|---|---|

| getPlayer() | 发起支付的玩家 |

| getAmount() / setAmount(double) | 金额 |

| getPayMethod() / setPayMethod(String) | 支付方式 |

| getOrderId() / setOrderId(String) | 订单号 |

| isNoReward() / setNoReward(boolean) | 是否无奖励 |

| getOutputMode() / setOutputMode(String) | 输出模式,link / text / map |

| setCancelled(boolean) | 是否取消 |

| setCancelReason(String) | 取消后提示给玩家的原因 |

示例:禁止某玩家创建赞助订单。

@EventHandler(priority = EventPriority.HIGHEST)
public void onPrePayment(PrePaymentEvent event) {
    if (event.getPlayer().getName().equalsIgnoreCase("BadPlayer")) {
        event.setCancelled(true);
        event.setCancelReason("§c你暂时无法使用赞助功能。");
    }
}

---

3. PaymentOrderCreatedEvent:订单创建成功

当 YuPay 成功向支付平台创建订单,并获得二维码链接后触发。

可读取

| 方法 | 说明 |

|---|---|

| getPlayerUUID() | 玩家 UUID |

| getPlayerName() | 玩家名 |

| getAmount() | 金额 |

| getPayMethod() | 支付方式 |

| getOrderId() | 订单号 |

| getQrCodeUrl() | 支付二维码链接 |

| isNoReward() | 是否无奖励订单 |

示例

@EventHandler
public void onOrderCreated(PaymentOrderCreatedEvent event) {
    plugin.getLogger().info("订单创建成功:" + event.getOrderId());
}

---

4. PaymentCompletedEvent:支付成功并完成发奖

当支付成功,并且 YuPay 内部奖励逻辑处理完成后触发。

可读取

| 方法 | 说明 |

|---|---|

| getPlayerUUID() | 玩家 UUID |

| getPlayerName() | 玩家名 |

| getAmountRmb() | 支付金额 |

| getPointsEarned() | 获得的经济奖励数量 |

| getPayMethod() | 支付方式 |

| getOrderId() | 订单号 |

| isNoReward() | 是否无奖励 |

| getTimestamp() | 事件时间戳 |

| isPlayerOnline() | 玩家是否在线 |

| getPlayer() | 在线时返回 Player,否则返回 null |

示例:支付完成后发全服广播。

@EventHandler
public void onPaymentCompleted(PaymentCompletedEvent event) {
    Bukkit.broadcastMessage("§6感谢 §e" + event.getPlayerName()
            + " §6赞助服务器 §e" + event.getAmountRmb() + " 元!");
}

---

5. PaymentFailedEvent:支付失败或取消

可读取

| 方法 | 说明 |

|---|---|

| getPlayerUUID() | 玩家 UUID |

| getPlayerName() | 玩家名 |

| getOrderId() | 订单号 |

| getReason() | 失败或取消原因 |

| getPayMethod() | 支付方式 |

示例

@EventHandler
public void onPaymentFailed(PaymentFailedEvent event) {
    plugin.getLogger().warning("订单失败:" + event.getOrderId()
            + ", 原因:" + event.getReason());
}

---

6. RefundCompletedEvent:退款完成

当外部支付平台退款成功,并且 YuPay 内部状态已经更新后触发。

可读取

| 方法 | 说明 |

|---|---|

| getOperatorUUID() | 操作者 UUID |

| getOperatorName() | 操作者名称 |

| getOrderId() | 原支付订单号 |

| getRefundAmount() | 本次退款金额 |

| getOriginalAmount() | 原订单金额 |

| getPlayerUUID() | 被退款玩家 UUID |

| getPlayerName() | 被退款玩家名 |

| isRedeemRefund() | 是否为卡密相关退款 |

示例

@EventHandler
public void onRefundCompleted(RefundCompletedEvent event) {
    Bukkit.getLogger().info("[YuPay] 订单 " + event.getOrderId()
            + " 已退款 " + event.getRefundAmount() + " 元");
}

---

7. RedeemCodeRedeemedEvent:卡密核销完成

可读取

| 方法 | 说明 |

|---|---|

| getCode() | 卡密 |

| getPlayerUUID() | 玩家 UUID |

| getPlayerName() | 玩家名 |

| getAmountPaid() | 核销时支付金额,免费卡密为 0 |

| getEconomyType() | 经济类型 |

| getEconomyAmount() | 经济奖励数量 |

| hasCommands() | 是否绑定命令奖励 |

| getOrderId() | 关联订单号,免费卡密可能为空 |

示例

@EventHandler
public void onRedeem(RedeemCodeRedeemedEvent event) {
    plugin.getLogger().info(event.getPlayerName()
            + " 核销了卡密 " + event.getCode());
}

---

8. RedeemCodeLifetimeEvent:卡密状态变化

当卡密进入 DEPLETED、EXPIRED、DISABLED 等状态时触发。

可读取

| 方法 | 说明 |

|---|---|

| getCode() | 卡密 |

| getOldStatus() | 旧状态 |

| getNewStatus() | 新状态 |

示例

@EventHandler
public void onCodeStatusChange(RedeemCodeLifetimeEvent event) {
    plugin.getLogger().info("卡密状态变化:"
            + event.getCode()
            + " " + event.getOldStatus()
            + " -> " + event.getNewStatus());
}

---

9. PlayerPointsChangedEvent:YuPay 经济变动

当 YuPay 内部发放 Vault 或 PlayerPoints 经济奖励后触发。

可读取

| 方法 | 说明 |

|---|---|

| getPlayerUUID() | 玩家 UUID |

| getEconomyType() | 经济类型,通常为 vault 或 playerpoints |

| getDelta() | 本次变化数量 |

| getNewBalance() | 新余额,未知时为 -1 |

示例

@EventHandler
public void onEconomyChanged(PlayerPointsChangedEvent event) {
    plugin.getLogger().info("玩家 " + event.getPlayerUUID()
            + " 的 " + event.getEconomyType()
            + " 变化:" + event.getDelta());
}

---

API 与事件使用建议

  • 如果你要“主动创建支付订单”,使用 YuPayApi#createOrder。
  • 如果你要“监听玩家通过 YuPay 命令发起支付”,使用 PrePaymentEvent。
  • 如果你要“支付完成后同步商城订单状态”,监听 PaymentCompletedEvent。
  • 如果你要“玩家取消或订单失败后回滚业务状态”,监听 PaymentFailedEvent。
  • 如果你要“退款后撤销外部权益”,监听 RefundCompletedEvent。
  • 如果你要“卡密核销后同步外部系统”,监听 RedeemCodeRedeemedEvent。
  • CompletableFuture 回调中如需操作 Bukkit API,请切回主线程。
  • 不建议在事件监听器里执行耗时数据库或网络请求;如有耗时逻辑,请自行异步处理。

[/md]

[md]

---

⚙️ 环境要求

| 项目 | 要求 |

|---|---|

| 服务端 | Spigot / Paper / 兼容 Bukkit API 的分支 |

| Minecraft 版本 | 1.8+ 主流版本,具体以实际服务端测试为准 |

| Java | Java 8 或更高 |

| 可选前置 | Vault、PlayerPoints、PlaceholderAPI、ProtocolLib |

可选前置说明

| 插件 | 用途 |

|---|---|

| Vault | 发放 Vault 经济奖励 |

| PlayerPoints | 发放点券奖励 |

| PlaceholderAPI | 启用 PAPI 占位符 |

| ProtocolLib | 地图二维码支付锁与更安全的地图交互控制 |

---

🚀 两分钟上手

  • 将 YuPay.jar 放入服务器 plugins/ 目录
  • 启动服务器,等待自动生成配置文件
  • 打开 plugins/YuPay/config.yml
  • 配置微信支付或支付宝参数
  • 将支付平台后台的异步通知地址配置为你的公网回调地址
  • 放行回调端口,默认 8080
  • 执行重载:
/yp reload
  • 运行健康检查:
/yp health full
  • 使用小额订单测试:
/donate 0.01

确认支付成功、回调正常、奖励到账后,即可正式使用。

---

🔧 常用配置速查

支付核心

pay:
  default-method: "wechat"
  order-subject: "赞助-{player}-{amount}元"
  min-amount: 0.01
  max-amount: -1
  max-daily-amount: -1

待支付订单自动过期

pay:
  pending-expire:
    enabled: true
    minutes: 15
    check-interval-seconds: 60
    batch-size: 100

回调服务器

callback:
  port: 8080
  host: "0.0.0.0"
  io-threads: 2
  worker-threads: 8
  max-body-size: 65536
  allowed-ips: []
  access-log: false

数据库

database:
  type: "sqlite"

或使用 MySQL

database:
  type: "mysql"
  mysql:
    host: "localhost"
    port: 3306
    database: "minecraft"
    username: "root"
    password: "password"

二维码展示

qrcode:
  default-output-mode: "map"
  text-qr-size: 12
  text-black-char: "██"

可选输出模式

| 模式 | 说明 |

|---|---|

| link | 发送可点击支付链接 |

| text | 发送聊天栏字符二维码 |

| map | 发送背包地图二维码 |

---

🎮 常用命令

> 以下命令按推荐别名展示。实际别名可在 config.yml 的 commands 节点中自定义。

玩家命令

| 命令 | 功能 |

|---|---|

| /donate <金额> [支付方式] [输出模式] [-n] | 发起赞助 |

| /ytop | 查看赞助排行榜 |

| /ytotal [玩家|all] | 查询赞助总额 |

| /yp history [页数] | 查看自己的赞助历史 |

| /yp orders [页数] | 查看自己的订单列表 |

| /yp order <订单号> | 查看自己的订单详情 |

| /yp cancel [订单号] | 取消待支付订单 |

| /yp retry [订单号] | 自助重试补发奖励 |

| /yp lang <语言> | 切换语言 |

| /yp code redeem <卡密> | 核销卡密 |

| /yp refund request <订单号> [金额] | 申请退款 |

管理员命令

| 命令 | 功能 |

|---|---|

| /yp reload | 重载配置 |

| /yp config | 查看核心配置 |

| /yp set <选项> <值> | 在线修改配置项 |

| /yp ban <玩家|all> [原因] | 禁止赞助 |

| /yp unban <玩家|all> | 解除禁止 |

| /yp convert <玩家> <来源> <目标> <数量> | Vault / PlayerPoints 互转 |

| /yp health [summary|full] | 健康检查 |

| /yp audit [listeners|security] | 事件监听 / 安全日志审计 |

| /yp crossserver [status|queue] | 查看跨服发奖状态 |

| /yp order ... | 订单中心 |

| /yp code ... | 卡密管理 |

| /yp refund ... | 退款管理 |

---

🔐 权限节点

玩家权限

| 权限 | 说明 |

|---|---|

| yupay.command.pay | 发起赞助 |

| yupay.command.top | 查看排行榜 |

| yupay.command.total | 查询赞助总额 |

| yupay.command.history | 查看历史订单 |

| yupay.command.orders | 查看订单列表 |

| yupay.command.cancel | 取消待支付订单 |

| yupay.command.retry | 自助补发 |

| yupay.command.code | 使用卡密入口 |

| yupay.code.redeem | 核销卡密 |

| yupay.command.refund | 使用退款入口 |

| yupay.refund.request | 申请退款 |

管理权限

| 权限 | 说明 |

|---|---|

| yupay.reload | 重载配置 |

| yupay.ban | 黑名单管理 |

| yupay.convert | 货币转换 |

| yupay.audit | 审计 |

| yupay.order | 订单管理 |

| yupay.health | 健康检查 |

| yupay.crossserver | 跨服发奖状态 |

| yupay.code.admin | 卡密管理 |

| yupay.refund | 退款管理 |

| yupay.admin | 管理员总权限 |

---

🗄️ 数据表

YuPay 会自动创建并维护所需数据表。

| 表 | 用途 |

|---|---|

| yu_payments | 支付订单 |

| yu_total_levels | 累计奖励档位记录 |

| yu_banned_players | 赞助黑名单 |

| yu_player_lang | 玩家语言偏好 |

| yu_redeem_codes | 卡密主表 |

| yu_redeem_logs | 卡密核销日志 |

| yu_refund_logs | 退款操作日志 |

| yu_refund_requests | 退款审核请求 |

| yu_refunds | 平台退款流水 |

| yu_reward_steps | 发奖步骤流水 |

| yu_payment_callbacks | 支付 / 退款回调流水 |

| yu_cross_server_rewards | 跨服发奖队列 |

| yu_schema_migrations | 数据库迁移记录 |

支持自定义表名前缀,适合多插件共用数据库场景。

---

🧯 常见问题

支付成功但奖励没到账

先让玩家执行

/yp retry

管理员可继续排查

/yp order info <订单号>
/yp order steps <订单号>
/yp order callbacks <订单号>

重点检查

  • 订单是否为 SUCCESS
  • 发奖状态是否为 FAILED
  • Vault / PlayerPoints 是否正常加载
  • 命令奖励中是否有错误命令
  • LuckPerms、CMI、EssentialsX 等插件是否可用

---

玩家取消订单后又付款了怎么办?

YuPay 会以支付平台成功回调为准进行幂等处理。

管理员可以查看异常订单

/yp order abnormal
/yp order risk

并根据实际情况处理

/yp order resolve <订单号> reward
/yp order resolve <订单号> refund
/yp order resolve <订单号> ignore
/yp order resolve <订单号> hold

---

回调服务器启动失败

检查

  • 端口是否被占用
  • 防火墙是否放行
  • 云服务器安全组是否放行
  • 支付平台后台 notify-url 是否填写正确
  • 是否使用了内网 IP 或 localhost

可执行

/yp health full

快速查看问题。

---

地图二维码无法使用

检查

  • 是否安装 ProtocolLib
  • ProtocolLib 版本是否兼容当前服务端
  • qrcode.default-output-mode 是否为 map
  • 玩家背包是否有空位

如果 ProtocolLib 不可用,建议临时切换:

qrcode:
  default-output-mode: "link"

---

微信 / 支付宝配置失败

建议先执行

/yp health full

重点检查

  • 微信商户号、AppID、证书序列号
  • 微信 API v3 密钥
  • 微信平台公钥 / 商户私钥路径
  • 支付宝 app-id
  • 支付宝商户私钥
  • 支付宝公钥或证书模式配置
  • notify-url 是否仍为示例地址

---

🏆 为什么腐竹会需要 YuPay?

因为它解决的是服务器运营最麻烦的几件事

  • 玩家付款后,奖励能不能自动到账?
  • 付款成功但没到账,能不能查清楚?
  • 玩家取消订单后又付款,怎么处理?
  • 退款有没有审核流程?
  • 多个子服如何统一收款和发奖?
  • 排行榜和赞助数据怎么展示?
  • 商城插件能不能接入支付?
  • 出问题时,能不能快速定位?

YuPay 不只是“收钱插件”,而是一套围绕 Minecraft 服务器赞助场景设计的完整支付运营系统。

---

💬 交流与支持

插件交流群:1080918424

遇到问题时,建议带上

  • 控制台日志
  • config.yml 关键配置截图
  • /yp health full 输出
  • 订单号
  • 支付渠道
  • 是否使用 MySQL / 跨服模式

这样更容易快速定位问题。

---

💛 支持作者

爱发电:https://afdian.com/a/vicuna

如果 YuPay 帮你节省了对账、发奖、退款和排查问题的时间,欢迎支持作者继续维护。

---

一句话总结

YuPay 把 Minecraft 服务器赞助从“手动收款 + 手动发奖 + 手动对账”,升级成“官方支付 + 自动发奖 + 完整审计 + 可扩展 API”的现代化运营系统。

把繁琐的赞助流程交给 YuPay,腐竹就能把时间留给真正重要的事:

做好服务器,服务好玩家。

测试支持版本
1.8.x 1.26.x
版本分布
基本信息
插件名称 YuPay
作者 Vicuna
平台 Spigot/Bukkit/Paper/Leaves/Leaf/Folia/Hybird/Mohst/Arclight/Youer etc
支持版本 1.8.x - 1.26.x
点赞数 未统计
最近版本
1.5.1.1 3
1.5.1.0 1