承接 wizcodepl/lunar-tpay 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

wizcodepl/lunar-tpay

Composer 安装命令:

composer require wizcodepl/lunar-tpay

包简介

Tpay (OpenAPI) payment driver for Lunar PHP — authorize, redirect, webhook-driven capture.

README 文档

README

Lunar Tpay

lunar-tpay

tests pint phpstan packagist license

Tpay (OpenAPI) payment driver for Lunar PHP.

Authorize → redirect customer to tpay → JWS-verified webhook updates the order.

Installation

composer require wizcodepl/lunar-tpay
php artisan vendor:publish --tag=lunar-tpay-config
TPAY_CLIENT_ID=...
TPAY_CLIENT_SECRET=...

# Base URLs — omit on production (defaults to https://openapi.tpay.com / https://secure.tpay.com).
# For sandbox / staging:
TPAY_API_BASE_URL=https://openapi.sandbox.tpay.com
TPAY_CERT_BASE_URL=https://secure.sandbox.tpay.com

TPAY_RETURN_URL_SUCCESS=https://your-shop.com/order/ok
TPAY_RETURN_URL_ERROR=https://your-shop.com/order/error

Get sandbox credentials at register.sandbox.tpay.com and generate Open API keys in Merchant Panel → Integration → API.

In your Lunar config/lunar.php, register the driver:

'payments' => [
    'types' => [
        'tpay' => ['driver' => 'tpay'],
    ],
],

The webhook route POST /tpay/notify is registered automatically. Set this URL in your tpay merchant panel.

Usage

$result = Payments::driver('tpay')
    ->cart($cart)
    ->authorize();

if ($result->success) {
    return redirect()->away($result->message);  // tpay redirect URL
}

The PaymentAuthorize.message field carries the redirect URL — that's a Lunar API quirk (the DTO doesn't have a dedicated redirectUrl field).

You can preselect a payment method (BLIK, card, specific bank) via withData():

Payments::driver('tpay')
    ->cart($cart)
    ->withData(['pay' => ['groupId' => 150]])  // 150 = BLIK
    ->authorize();

When omitted, tpay shows its own payment-method picker on the redirect page.

Webhook authentication — JWS x509

Tpay signs every notification with its private key (RFC 7515 detached JWS, RS256). We verify against the publicly-fetched Tpay signing certificate, chained up to the Tpay root CA. Both certificates live at:

Production Sandbox
Signing cert https://secure.tpay.com/x509/notifications-jws.pem https://secure.sandbox.tpay.com/x509/notifications-jws.pem
Root CA https://secure.tpay.com/x509/tpay-jws-root.pem https://secure.sandbox.tpay.com/x509/tpay-jws-root.pem

Certs are fetched once and cached for 24h. Notifications without a valid X-JWS-Signature header are rejected with 403 SIGNATURE_INVALID. Legacy md5sum verification is intentionally not supported — JWS is the modern, asymmetric path with no shared secret to leak.

Testing

This package uses real sandbox tests rather than mocks. The philosophy mirrors how Stripe, PayPal, and AWS PHP SDKs do it: real OAuth, real POST /transactions, real GET /transactions/{id} against the sandbox.

Run locally

cd packages/lunar-tpay
composer install

export TPAY_CLIENT_ID="your-sandbox-client-id"
export TPAY_CLIENT_SECRET="your-sandbox-secret"

composer test         # unit + sandbox e2e
composer format       # Pint auto-fix
composer format:check # Pint check (CI mode)
composer analyse      # PHPStan level 5

Without these env vars the e2e sandbox tests skip cleanly with a clear message — CI without secrets stays green.

What's covered

Test Tests
TpayClientTest sandbox OAuth + create/get transaction round-trip + error handling
TpayPaymentDriverTest driver registration in Lunar PaymentManager + sandbox-backed authorize() flow + meta persistence
TpayJwsVerifierTest JWS verifier negative paths (empty/malformed/wrong-alg/SSRF guard)
TpayWebhookControllerTest controller logic (status mapping, order lookup, response codes) — verifier swapped with a deterministic stub via the container so we don't need a real tpay signature for controller-level tests

The full positive-path JWS verification needs a real tpay-signed payload, which only happens after a real sandbox transaction fires its webhook against a publicly-reachable URL. Validate that scenario manually after deploying to a staging URL.

Why no MockClient / VCR cassettes

For payment flows the temptation is to record API responses (à la VCR) and replay them. We chose against this because:

  • Sandbox is free and reliable. tpay's OpenAPI sandbox is stable.
  • Recorded fixtures drift silently when the API changes — and payment schemas change more often than people expect.
  • Real sandbox calls catch credential / cert / DNS issues that mocks can't.

The downside is that running tests requires creds — solved by skip-on-empty.

What's intentionally not in v1.0

  • Refundsrefund() returns PaymentRefund(false, …). Use the tpay merchant panel for now.
  • Retry queue — single attempt; failure is logged and dispatched as a Lunar PaymentAttemptEvent. Wrap with your own retry policy if needed.
  • Filament admin UIOrder.meta.tpay is the source of truth; surface it in your panel however you prefer.

License

MIT — see LICENSE.

wizcodepl/lunar-tpay 适用场景与选型建议

wizcodepl/lunar-tpay 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 102 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 05 月 05 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「ecommerce」 「payments」 「laravel」 「polish」 「lunar」 「tpay」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 wizcodepl/lunar-tpay 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 wizcodepl/lunar-tpay 我们能提供哪些服务?
定制开发 / 二次开发

基于 wizcodepl/lunar-tpay 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 102
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 47
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-05-05