carllee/line-pay-offline-v4 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

carllee/line-pay-offline-v4

Composer 安装命令:

composer require carllee/line-pay-offline-v4

包简介

LINE Pay Offline V4 API SDK for PHP. Supports POS payment, capture, void, refund operations with Laravel support.

README 文档

README

CI PHP Version License

Modern, type-safe LINE Pay Offline V4 API SDK for PHP.

🌐 Language / 語言 / 言語 / ภาษา: English | 繁體中文 | 日本語 | ภาษาไทย

Features

  • PHP 8.1+ with strict types and enums
  • Laravel Integration - ServiceProvider, Facade, IoC support
  • POS/Kiosk Terminal Support - For retail and food service
  • One-Time Key Payment - Scan customer's barcode
  • Full API Coverage - Payment, capture, void, refund
  • Type-Safe Enums - Currency, PaymentStatus, etc.
  • PHPStan Level Max - Strict static analysis
  • Built on Core SDK - Shares code with Online SDK

Requirements

  • PHP 8.1 or higher
  • Composer
  • ext-json
  • ext-openssl

Installation

composer require carllee/line-pay-offline-v4

Payment Flow

sequenceDiagram
    participant U as Customer (App)
    participant P as POS/Server
    participant L as LINE Pay API
    
    U->>P: Show Barcode (OneTimeKey)
    P->>L: POST /v3/payments/oneTimeKeys/pay
    alt Success
        L-->>P: 200 OK (ReturnCode 0000)
        P->>U: Payment Success
    else Timeout / Network Error
        L-->>P: Timeout / 500 Error
        Note over P,L: CRITICAL: Must Check Status
        P->>L: GET /v3/payments/orders/{orderId}
        L-->>P: Status: COMPLETE
        P->>U: Payment Success
    end
Loading

Quick Start

"✨ Developer Experience: This SDK uses DTOs and Enums. Your IDE will provide full autocompletion for request parameters and response fields, eliminating 'magic string' typos."

<?php

use LinePay\Offline\Config\LinePayOfflineConfig;
use LinePay\Offline\LinePayOfflineClient;
use LinePay\Offline\Enums\Currency;

// Create configuration
$config = new LinePayOfflineConfig(
    channelId: getenv('LINE_PAY_CHANNEL_ID'),
    channelSecret: getenv('LINE_PAY_CHANNEL_SECRET'),
    merchantDeviceProfileId: 'POS-001',  // Your POS terminal ID
    merchantDeviceType: 'POS',           // Device type
    env: 'sandbox'                        // or 'production'
);

// Create client
$client = new LinePayOfflineClient($config);

// Request payment with customer's barcode (oneTimeKey)
$response = $client->requestPayment([
    'amount' => 100,
    'currency' => 'TWD',
    'oneTimeKey' => '12345678901245678', // From customer's LINE Pay barcode
    'orderId' => 'ORDER-' . time(),
    'packages' => [
        [
            'id' => 'PKG-001',
            'amount' => 100,
            'products' => [
                ['name' => 'Coffee', 'quantity' => 1, 'price' => 100]
            ]
        ]
    ]
]);

if ($response['returnCode'] === '0000') {
    echo "Payment successful!\n";
    echo "Transaction ID: " . $response['info']['transactionId'] . "\n";
}

Laravel Integration

The package supports Laravel Package Discovery. Just install it via composer, and the ServiceProvider and Facade will be registered automatically.

Configuration

Publish the config file:

php artisan vendor:publish --tag=linepay-offline-config

Add to your .env:

LINE_PAY_CHANNEL_ID=your-channel-id
LINE_PAY_CHANNEL_SECRET=your-channel-secret
LINE_PAY_MERCHANT_DEVICE_ID=POS-001
LINE_PAY_MERCHANT_DEVICE_TYPE=POS
LINE_PAY_ENV=sandbox
LINE_PAY_TIMEOUT=40

Using Dependency Injection

namespace App\Http\Controllers;

use LinePay\Offline\LinePayOfflineClient;
use LinePay\Offline\Enums\Currency;

class POSController extends Controller
{
    public function __construct(
        private LinePayOfflineClient $linePay
    ) {}

    public function processPayment(string $oneTimeKey)
    {
        $response = $this->linePay->requestPayment([
            'amount' => 100,
            'currency' => 'TWD',
            'oneTimeKey' => $oneTimeKey,
            'orderId' => 'ORDER-' . time(),
            'packages' => [
                ['id' => 'PKG-001', 'amount' => 100, 'products' => [
                    ['name' => 'Coffee', 'quantity' => 1, 'price' => 100]
                ]]
            ]
        ]);

        return response()->json($response);
    }
}

Using Facade

use LinePay\Offline\Laravel\LinePayOffline;

// Request payment
$response = LinePayOffline::requestPayment($request);

// Check status
$status = LinePayOffline::checkPaymentStatus($orderId);

// Refund
$response = LinePayOffline::refundPayment($orderId, 50);

API Methods

Request Payment

Request payment using customer's one-time barcode:

$response = $client->requestPayment([
    'amount' => 100,
    'currency' => 'TWD',
    'oneTimeKey' => '12345678901245678',
    'orderId' => 'ORDER-001',
    'options' => [
        'payment' => [
            'capture' => true  // Capture immediately (default)
        ],
        'extra' => [
            'branchId' => 'BRANCH-001',
            'branchName' => 'Main Store'
        ]
    ]
]);

Check Payment Status

Check payment status (use after timeout):

$status = $client->checkPaymentStatus('ORDER-001');
// Returns: COMPLETE, FAIL, or REFUND
echo "Status: " . $status['info']['status'];

Capture Payment

Capture an authorized payment:

$response = $client->capturePayment(
    orderId: 'ORDER-001',
    amount: 100,
    currency: Currency::TWD
);

Void Authorization

Cancel an authorization before capture:

$response = $client->voidAuthorization('ORDER-001');

Refund Payment

Refund a completed payment:

// Full refund
$response = $client->refundPayment('ORDER-001');

// Partial refund
$response = $client->refundPayment('ORDER-001', 50);

Query Authorizations

Query authorization information:

$auths = $client->queryAuthorizations(orderId: 'ORDER-001');
// or
$auths = $client->queryAuthorizations(transactionId: '1234567890123456789');

Retrieve Payment Details

Get detailed payment information:

$details = $client->retrievePaymentDetails(orderId: 'ORDER-001');

Error Handling

use LinePay\Core\Errors\LinePayError;
use LinePay\Core\Errors\LinePayTimeoutError;
use LinePay\Core\Errors\LinePayConfigError;

try {
    $response = $client->requestPayment($request);
    
} catch (LinePayTimeoutError $e) {
    // Timeout occurred - ALWAYS check payment status
    $status = $client->checkPaymentStatus($orderId);
    
    if ($status['info']['status'] === 'COMPLETE') {
        // Payment was successful despite timeout
        handleSuccessfulPayment($status);
    } else {
        // Payment failed or still processing
        handleFailedPayment($status);
    }
    
} catch (LinePayError $e) {
    // API error
    echo "Error Code: " . $e->getReturnCode() . "\n";
    echo "Error Message: " . $e->getReturnMessage() . "\n";
    
} catch (LinePayConfigError $e) {
    // Configuration error
    echo "Config Error: " . $e->getMessage() . "\n";
}

Common Pitfalls & Troubleshooting

⚠️ Critical: Handling Timeouts (Read Timeout)

LINE Pay Offline API interactions involve real-world network latency (connecting to POS, waiting for user confirmation).

The Problem: You might receive a ConnectTimeout or ReadTimeout (cURL error 28) if the response takes longer than your configured timeout settings.

The Solution: NEVER assume the payment failed just because of a timeout. The transaction might have succeeded on LINE Pay's server while your server gave up waiting.

  1. Catch the Error: Always catch LinePayTimeoutError.
  2. Double Check: Immediately call checkPaymentStatus($orderId).
  3. Reconcile: If checkPaymentStatus returns COMPLETE, treat the order as paid.
try {
    $response = $client->requestPayment(...);
} catch (LinePayTimeoutError $e) {
    // 1. Log the timeout
    // 2. Check actual status from LINE Pay
    $status = $client->checkPaymentStatus($orderId);
    
    if ($status['info']['status'] === 'COMPLETE') {
        // Handle as success
    }
}

🚫 OneTimeKey Reuse (Error 1172)

The oneTimeKey (barcode) provided by the customer is single-use only and expires quickly (usually 5 minutes).

  • Do not try to reuse a barcode for a retry if the first request failed with a logic error.
  • Do not use a hardcoded barcode for testing; you must regenerate it from the LINE App each time.

💰 Amount Mismatch (Error 1106)

When calling capturePayment(), the amount must match the authorized amount (unless you are performing a partial capture, if allowed).

  • Ensure your database stores the exact authorized amount.
  • Floating point precision errors can occur; consider storing amounts as integers (e.g., cents) or using bcmath.

Configuration Options

Option Type Required Description
channelId string LINE Pay Channel ID
channelSecret string LINE Pay Channel Secret
merchantDeviceProfileId string Your POS/terminal device ID
merchantDeviceType string Device type (default: "POS")
env string Environment: "sandbox" or "production"
timeout int Request timeout in seconds (default: 20)

Best Practices

1. Handle Timeouts Properly

As detailed in the Common Pitfalls & Troubleshooting section, never treat a timeout as a failure. Always verify the transaction status using checkPaymentStatus().

2. Verify Payment Amounts

Always verify the payment amount in the response:

$response = $client->requestPayment($request);
$totalPaid = array_sum(array_column($response['info']['payInfo'], 'amount'));

if ($totalPaid !== $requestedAmount) {
    error_log("Amount mismatch: requested $requestedAmount, paid $totalPaid");
}

3. Use Environment Variables

Never hardcode credentials:

$config = new LinePayOfflineConfig(
    channelId: getenv('LINE_PAY_CHANNEL_ID'),
    channelSecret: getenv('LINE_PAY_CHANNEL_SECRET'),
    merchantDeviceProfileId: getenv('MERCHANT_DEVICE_ID')
);

Testing

# Run tests
composer test

# Run static analysis
composer analyze

# Check code style
composer lint

Related Packages

License

MIT License - see LICENSE for details.

Resources

carllee/line-pay-offline-v4 适用场景与选型建议

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

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

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

围绕 carllee/line-pay-offline-v4 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-12