# Kylin Payment 安装配置

## 1. 安装

### 1.1 Composer 安装

使用 Composer 安装 Kylin Payment：

```bash
composer require kylin/payment
```

### 1.2 发布配置文件

发布支付配置文件：

```bash
php artisan vendor:publish --provider="Kylin\Payment\Providers\PaymentServiceProvider"
```

### 1.3 数据库迁移

运行数据库迁移：

```bash
php artisan migrate
```

## 2. 配置

### 2.1 配置文件

在 `config/payment.php` 文件中配置支付相关参数：

```php
return [
    /*
    |--------------------------------------------------------------------------
    | 默认支付方式
    |--------------------------------------------------------------------------
    |
    | 默认使用的支付方式
    |
    */
    'default' => env('PAYMENT_DEFAULT', 'wechat'),

    /*
    |--------------------------------------------------------------------------
    | 支付方式配置
    |--------------------------------------------------------------------------
    |
    | 各种支付方式的配置信息
    |
    */
    'methods' => [
        /*
        |--------------------------------------------------------------------------
        | 微信支付配置
        |--------------------------------------------------------------------------
        |
        | 微信支付的配置信息
        |
        */
        'wechat' => [
            'app_id' => env('WECHAT_PAYMENT_APPID', ''),
            'mch_id' => env('WECHAT_PAYMENT_MCH_ID', ''),
            'key' => env('WECHAT_PAYMENT_KEY', ''),
            'cert_path' => env('WECHAT_PAYMENT_CERT_PATH', ''),
            'key_path' => env('WECHAT_PAYMENT_KEY_PATH', ''),
            'notify_url' => env('WECHAT_PAYMENT_NOTIFY_URL', ''),
            'refund_notify_url' => env('WECHAT_PAYMENT_REFUND_NOTIFY_URL', ''),
        ],

        /*
        |--------------------------------------------------------------------------
        | 支付宝支付配置
        |--------------------------------------------------------------------------
        |
        | 支付宝支付的配置信息
        |
        */
        'alipay' => [
            'app_id' => env('ALIPAY_APPID', ''),
            'private_key' => env('ALIPAY_PRIVATE_KEY', ''),
            'public_key' => env('ALIPAY_PUBLIC_KEY', ''),
            'notify_url' => env('ALIPAY_NOTIFY_URL', ''),
            'return_url' => env('ALIPAY_RETURN_URL', ''),
            'sandbox' => env('ALIPAY_SANDBOX', false),
        ],

        /*
        |--------------------------------------------------------------------------
        | 银联支付配置
        |--------------------------------------------------------------------------
        |
        | 银联支付的配置信息
        |
        */
        'unionpay' => [
            'mer_id' => env('UNIONPAY_MER_ID', ''),
            'cert_path' => env('UNIONPAY_CERT_PATH', ''),
            'cert_pwd' => env('UNIONPAY_CERT_PWD', ''),
            'notify_url' => env('UNIONPAY_NOTIFY_URL', ''),
            'return_url' => env('UNIONPAY_RETURN_URL', ''),
            'sandbox' => env('UNIONPAY_SANDBOX', false),
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | 支付订单配置
    |--------------------------------------------------------------------------
    |
    | 支付订单的配置信息
    |
    */
    'order' => [
        'table' => 'payment_orders',
        'expire' => 30, // 订单过期时间（分钟）
    ],

    /*
    |--------------------------------------------------------------------------
    | 支付退款配置
    |--------------------------------------------------------------------------
    |
    | 支付退款的配置信息
    |
    */
    'refund' => [
        'table' => 'payment_refunds',
    ],

    /*
    |--------------------------------------------------------------------------
    | 支付记录配置
    |--------------------------------------------------------------------------
    |
    | 支付记录的配置信息
    |
    */
    'record' => [
        'table' => 'payment_records',
    ],
];
```

### 2.2 环境变量

在 `.env` 文件中配置支付相关环境变量：

```env
# 支付配置
PAYMENT_DEFAULT=wechat

# 微信支付配置
WECHAT_PAYMENT_APPID=your_wechat_appid
WECHAT_PAYMENT_MCH_ID=your_wechat_mch_id
WECHAT_PAYMENT_KEY=your_wechat_key
WECHAT_PAYMENT_CERT_PATH=path/to/cert.pem
WECHAT_PAYMENT_KEY_PATH=path/to/key.pem
WECHAT_PAYMENT_NOTIFY_URL=http://your-domain.com/payment/wechat/notify
WECHAT_PAYMENT_REFUND_NOTIFY_URL=http://your-domain.com/payment/wechat/refund-notify

# 支付宝支付配置
ALIPAY_APPID=your_alipay_appid
ALIPAY_PRIVATE_KEY=your_alipay_private_key
ALIPAY_PUBLIC_KEY=your_alipay_public_key
ALIPAY_NOTIFY_URL=http://your-domain.com/payment/alipay/notify
ALIPAY_RETURN_URL=http://your-domain.com/payment/alipay/return
ALIPAY_SANDBOX=false

# 银联支付配置
UNIONPAY_MER_ID=your_unionpay_mer_id
UNIONPAY_CERT_PATH=path/to/cert.pfx
UNIONPAY_CERT_PWD=your_cert_password
UNIONPAY_NOTIFY_URL=http://your-domain.com/payment/unionpay/notify
UNIONPAY_RETURN_URL=http://your-domain.com/payment/unionpay/return
UNIONPAY_SANDBOX=false
```

## 3. 数据库结构

### 3.1 支付订单表

```sql
CREATE TABLE `payment_orders` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(32) NOT NULL COMMENT '订单号',
  `amount` decimal(10,2) NOT NULL COMMENT '订单金额',
  `subject` varchar(255) NOT NULL COMMENT '订单主题',
  `body` text NOT NULL COMMENT '订单描述',
  `method` varchar(32) NOT NULL COMMENT '支付方式',
  `status` varchar(32) NOT NULL DEFAULT 'pending' COMMENT '订单状态',
  `transaction_id` varchar(64) DEFAULT NULL COMMENT '支付平台交易号',
  `extra` text COMMENT '额外信息',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `expired_at` timestamp NULL DEFAULT NULL COMMENT '过期时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付订单表';
```

### 3.2 支付退款表

```sql
CREATE TABLE `payment_refunds` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `refund_no` varchar(32) NOT NULL COMMENT '退款单号',
  `order_no` varchar(32) NOT NULL COMMENT '订单号',
  `amount` decimal(10,2) NOT NULL COMMENT '退款金额',
  `status` varchar(32) NOT NULL DEFAULT 'pending' COMMENT '退款状态',
  `refund_transaction_id` varchar(64) DEFAULT NULL COMMENT '退款交易号',
  `reason` text COMMENT '退款原因',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `refund_no` (`refund_no`),
  KEY `order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付退款表';
```

### 3.3 支付记录表

```sql
CREATE TABLE `payment_records` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(32) NOT NULL COMMENT '订单号',
  `action` varchar(32) NOT NULL COMMENT '操作类型',
  `amount` decimal(10,2) NOT NULL COMMENT '金额',
  `status` varchar(32) NOT NULL COMMENT '操作状态',
  `message` text COMMENT '操作信息',
  `data` text COMMENT '操作数据',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付记录表';
```

## 4. 服务提供者

### 4.1 支付服务提供者

```php
<?php

namespace Kylin\Payment\Providers;

use Illuminate\Support\ServiceProvider;
use Kylin\Payment\Services\PaymentService;
use Kylin\Payment\Services\WechatPaymentService;
use Kylin\Payment\Services\AlipayPaymentService;
use Kylin\Payment\Services\UnionPayPaymentService;
use Kylin\Payment\Services\PaymentRecordService;

class PaymentServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        // 注册支付服务
        $this->app->singleton('payment', function ($app) {
            return new PaymentService($app);
        });

        // 注册微信支付服务
        $this->app->singleton('payment.wechat', function ($app) {
            return new WechatPaymentService($app);
        });

        // 注册支付宝支付服务
        $this->app->singleton('payment.alipay', function ($app) {
            return new AlipayPaymentService($app);
        });

        // 注册银联支付服务
        $this->app->singleton('payment.unionpay', function ($app) {
            return new UnionPayPaymentService($app);
        });

        // 注册支付记录服务
        $this->app->singleton('payment.record', function ($app) {
            return new PaymentRecordService($app);
        });
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        // 发布配置文件
        $this->publishes([
            __DIR__.'/../config/payment.php' => config_path('payment.php'),
        ], 'payment-config');

        // 发布迁移文件
        $this->publishes([
            __DIR__.'/../database/migrations/' => database_path('migrations'),
        ], 'payment-migrations');
    }
}
```

## 5. 常见问题

### 5.1 配置文件不存在

**问题**：配置文件不存在
**解决方案**：运行 `php artisan vendor:publish --provider="Kylin\Payment\Providers\PaymentServiceProvider"` 发布配置文件

### 5.2 数据库表不存在

**问题**：数据库表不存在
**解决方案**：运行 `php artisan migrate` 运行数据库迁移

### 5.3 支付方式配置错误

**问题**：支付方式配置错误
**解决方案**：检查支付方式的配置信息是否正确，特别是 app_id、mch_id、key 等敏感信息

### 5.4 支付通知地址错误

**问题**：支付通知地址错误
**解决方案**：检查支付通知地址是否正确，确保地址可以被支付平台访问

### 5.5 证书文件不存在

**问题**：证书文件不存在
**解决方案**：检查证书文件路径是否正确，确保证书文件存在且可读

## 6. 最佳实践

1. **配置管理**：使用环境变量管理敏感配置，避免硬编码
2. **证书管理**：妥善保管支付证书，避免泄露
3. **日志记录**：记录支付相关的操作，便于排查问题
4. **错误处理**：捕获支付相关的异常，确保服务稳定
5. **安全验证**：验证支付通知的签名，确保通知的真实性
6. **订单管理**：定期清理过期订单，避免数据冗余
7. **退款管理**：妥善处理退款请求，确保资金安全

## 7. 总结

Kylin Payment 提供了灵活的安装和配置选项，可以根据项目的需要进行自定义。通过正确的安装和配置，可以充分发挥支付模块的优势，提高支付的安全性和可靠性。
