YuPay 插件间 API
本页专注于其他插件如何接入 YuPay。命令、权限、PlaceholderAPI 和 Bukkit 事件已拆到独立页面:
接入前提
- YuPay 通过 Bukkit
ServicesManager暴露YuPayApi,也提供YuPayProvider.get()快捷获取方法。 - API 方法大多返回
CompletableFuture,回调不保证在主线程;如需修改 Bukkit 玩家、背包、世界或 GUI,请调度回主线程。 - 生产接入必须在请求里设置
sourcePlugin,并在api.allowed-plugins中逐项授权。 - 商城、礼包、活动插件通常创建
noReward订单,然后由调用方在支付成功后自行发货。
获取 YuPayApi
java
import org.yutay.yupay.api.YuPayApi;
import org.yutay.yupay.api.YuPayProvider;
YuPayApi api = YuPayProvider.get();
if (api == null) {
// YuPay 未安装、未启用或服务尚未注册
return;
}也可以直接使用 Bukkit 服务:
java
RegisteredServiceProvider<YuPayApi> provider =
Bukkit.getServicesManager().getRegistration(YuPayApi.class);
YuPayApi api = provider == null ? null : provider.getProvider();创建订单
java
import org.bukkit.entity.Player;
import org.yutay.yupay.api.YuPayApi;
import org.yutay.yupay.api.YuPayOrderRequest;
public void createShopOrder(YuPayApi api, Player player, String shopOrderId) {
YuPayOrderRequest request = YuPayOrderRequest
.builder(player.getUniqueId(), player.getName(), 19.9)
.payMethod("wechat")
.sourcePlugin("ExampleShop")
.externalOrderId(shopOrderId)
.businessType("SHOP")
.metadataJson("{\"item\":\"vip_30d\"}")
.expireMinutes(10)
.noReward(true)
.build();
api.createOrder(request).thenAccept(result -> {
if (!result.isSuccess()) {
player.sendMessage("订单创建失败: " + result.getMessage());
return;
}
player.sendMessage("订单号: " + result.getOrderId());
player.sendMessage("支付链接: " + result.getQrUrl());
});
}| 字段 | 说明 |
|---|---|
sourcePlugin | 调用方插件名,用于 API 权限控制和审计。生产接入必须设置。 |
externalOrderId | 外部业务订单号,用于商城订单、礼包订单等业务绑定。 |
businessType | 业务类型,例如 SHOP、VIP、REDEEM、CUSTOM。 |
metadataJson / metadata | 业务元数据,YuPay 只保存和返回,不解释业务含义。 |
expireMinutes | 单订单过期分钟数;0 表示使用 YuPay 全局过期配置。 |
noReward | 是否跳过 YuPay 内部奖励。第三方商城通常设为 true,由调用方监听订单完成后发货。 |
常用 API
| API | 用途 |
|---|---|
getOrder(sourcePlugin, orderId) | 查询订单详情。 |
getLatestPendingOrder(sourcePlugin, playerUuid) | 查询玩家最近待支付订单。 |
listOrders(sourcePlugin, type, limit, offset) | 按类型分页查询订单。 |
cancelOrderDetailed(sourcePlugin, orderId, reason) | 取消指定待支付订单,并返回详细结果。 |
cancelLatestPendingOrder(sourcePlugin, playerUuid, reason) | 取消玩家最近待支付订单。 |
refundOrderDetailed(sourcePlugin, orderId, amount, reason) | 直接退款,返回平台/本地处理结果。 |
retryReward(sourcePlugin, orderId) | 重试 YuPay 内部奖励步骤。 |
listRewardSteps(sourcePlugin, orderId) | 查看发奖步骤流水。 |
expirePendingOrders(sourcePlugin) | 触发待支付订单过期清理。 |
getDefaultPayMethod() | 获取默认支付方式。 |
isPayMethodAvailable(payMethod) | 判断支付方式是否可用。 |
generateOrderId(playerUuid, noReward) | 生成 YuPay 风格订单号。 |
createPaymentQrImage(qrUrl, size) | 生成二维码图片;免费版可能自动带 YuPay 标识。 |
isFreeEditionBrandingRequired() | 免费版是否要求支付展示带 YuPay 品牌。 |
getFreeEditionAdLink() | 免费版广告官网链接,付费版可为 null。 |
退款示例
java
api.refundOrderDetailed("ExampleShop", orderId, 19.9, "商城订单取消")
.thenAccept(result -> {
if (result.isSuccess()) {
getLogger().info("退款已提交/完成: " + result.getRefundStatus());
} else {
getLogger().warning("退款失败: " + result.getCode() + " " + result.getMessage());
}
});API 授权配置
资金相关 API 会经过 api.allowed-plugins 校验。建议最小授权,例如商城插件只给创建、取消、查询订单权限,不给退款和绕过奖励权限:
yaml
api:
enabled: true
require-plugin-declaration: true
audit-log: true
default-permissions:
create-order: false
cancel-order: false
query-order: false
refund-order: false
retry-reward: false
no-reward-order: false
expire-orders: false
allowed-plugins:
ExampleShop:
create-order: true
cancel-order: true
query-order: true
refund-order: false
retry-reward: false
no-reward-order: true
expire-orders: false| 权限项 | 允许的 API 能力 |
|---|---|
create-order | createOrder 创建支付订单。 |
cancel-order | cancelOrder*、cancelLatestPendingOrder*。 |
query-order | getOrder*、listOrders*、listRewardSteps*。 |
refund-order | refundOrder*,资金风险最高。 |
retry-reward | retryReward 重试 YuPay 内部奖励。 |
no-reward-order | 允许 API 创建跳过 YuPay 内部奖励的订单。 |
expire-orders | expirePendingOrders 触发过期清理。 |
接入建议
- 对第三方插件必须设置
sourcePlugin,并在allowed-plugins中逐项授权。 - 商城或礼包插件建议创建
noReward订单,然后监听PaymentCompletedEvent或查询订单状态后自行发货。 - 退款 API 和直接退款命令涉及真实资金,建议启用审计日志并限制到少数可信身份。
- 监听事件后如需操作 Bukkit 玩家、背包、世界、GUI,请使用
Bukkit.getScheduler().runTask(...)回到主线程。