atomjoy/payu

Laravel payu 库

v3.0.0 2023-02-08 17:38 UTC

This package is auto-updated.

Last update: 2024-08-30 14:53:26 UTC


README

在 Laravel 中使用 PayU 支付。如何在 payu api 中创建订单支付链接。

Payu 文档,沙盒

https://developers.payu.com/pl/overview.html#sandbox

安装 Laravel 包

https://getcomposer.org/download安装php composer

composer require atomjoy/payu "^3.0.0"
composer update
composer dump-autoload -o

配置 Laravel

添加数据库

mysql -u root

CREATE DATABASE IF NOT EXISTS laravel CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON laravel.* TO root@localhost IDENTIFIED BY 'toor' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON laravel.* TO root@127.0.0.1 IDENTIFIED BY 'toor' WITH GRANT OPTION;
FLUSH PRIVILEGES;

# Clear or change password
SET PASSWORD FOR root@localhost=PASSWORD('');

# Change password
ALTER USER 'testing'@'localhost' IDENTIFIED BY 'toor';
FLUSH PRIVILEGES;

配置 .env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=toor

创建订单模型

php artisan make:model Order -a

迁移订单类表格

在表格中添加列。

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
  public function up()
  {
    Schema::create('orders', function (Blueprint $table) {
      $table->id();
      $table->decimal('cost', 15, 2)->nullable()->default(0.00);
      $table->enum('payment_method', ['money', 'card', 'online', 'cashback'])->nullable()->default('money');
      $table->enum('payment_gateway', ['payu'])->nullable(true);
      $table->string('firstname');
      $table->string('lastname');
      $table->string('phone');
      $table->string('email');
      $table->timestamps();
      $table->softDeletes();
      $table->unsignedBigInteger('user_id')->nullable(true);
      $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
    });
  }

  public function down()
  {
    Schema::dropIfExists('orders');
  }
};

订单模型类

为订单类添加接口并填写所需方法。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Payu\Interfaces\PayuOrderInterface;
use Payu\Models\Payment;

class Order extends Model implements PayuOrderInterface
{
  use HasFactory, SoftDeletes;

  protected $guarded = [];

  public function payments()
  {
    return $this->hasMany(Payment::class)->withTrashed();
  }

  public function paid_payment()
  {
    return $this->hasOne(Payment::class)->where('status', 'COMPLETED')->withTrashed()->latest();
  }

  // Wymagane metody poniżej
  function orderId()
  {
    return $this->id;
  }

  function orderCost()
  {
    return $this->cost;
  }

  function orderFirstname()
  {
    return $this->firstname;
  }

  function orderLastname()
  {
    return $this->lastname;
  }

  function orderPhone()
  {
    return $this->phone;
  }

  function orderEmail()
  {
    return $this->email;
  }
}

在数据库中创建表格

# Aktualizuj tabelki
php artisan migrate
php artisan migrate --env=testing

创建和编辑 Payu Api 配置文件

config/payu.php

php artisan vendor:publish --tag=payu-config

更新 cache dir linux (如果出现错误)

sudo mkdir -p storage/framework/cache/payu
sudo chown -R www-data:www-data storage/framework/cache/payu
sudo chmod -R 770 storage/framework/cache/payu

编辑支付确认页面(可选)

resources/views/vendor/payu

php artisan vendor:publish --tag=payu-pages

添加 Payu logo 文件夹(可选)

public/vendor/payu

php artisan vendor:publish --tag=payu-public --force

测试

在 phpunit.xml 中添加

<testsuite name="Payu">
  <directory suffix="Test.php">./vendor/atomjoy/payu/tests/Payu</directory>
</testsuite>

仅针对 sandbox 配置(['payu.env' => 'sandbox'])的测试

在数据库 payments 表格中创建支付链接(用于将客户重定向到商店)。

php artisan test --testsuite=Payu --stop-on-failure

Laravel PayU Api

在 PayU 管理面板中禁用自动接收支付,如果希望手动确认 WAITING_FOR_CONFIRMATION 状态的 COMPLETED 或 CANCELED。

为订单创建支付链接(沙盒)

订单编号 {orders.id} => 1, 2, 3, ...

# Utwórz zamowienie i link do płatności
https://{your.domain.here}/web/payment/create

# Lub utwórz link do płatności z id zamówienia
https://{your.domain.here}/web/payment/url/payu/{orders.id}

# Pobierz dane płatności
https://{your.domain.here}/web/payment/retrive/payu/{orders.id}

# Aktualizuj dane płatności
https://{your.domain.here}/web/payment/refresh/payu/{orders.id}

# Przyjmij płatność
https://{your.domain.here}/web/payment/confirm/payu/{orders.id}

# Odrzuć płatność
https://{your.domain.here}/web/payment/cancel/payu/{orders.id}

支付处理路由列表(沙盒)

atomjoy/payu/routes/sandbox.php

Laravel 中 Payu Api 示例

为订单创建支付链接(生产)

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {

  // Create order here or get from db with id
  $id = 'orders.id';

  // Create payment url
  $url = Payu::pay(Order::findOrFail($id));

  // Redirect client to payment page
  return redirect($url);

} catch (QueryException | PDOException $e) {
  report($e);
  return response('Database Error.', 422);
} catch (Exception $e) {
  report($e);
  return response($e->getMessage(), 422);
}

确认支付(waiting_for_confirmation)

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {
  $id = 'orders.id';
  $status = Payu::confirm(Order::findOrFail($id));

} catch (\Exception $e) {
  return $e->getMessage();
}

拒绝支付(waiting_for_confirmation)

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {
  $id = 'orders.id';
  $status = Payu::cancel(Order::findOrFail($id));

} catch (\Exception $e) {
  return $e->getMessage();
}

更新支付

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {
  $id = 'orders.id';
  $status = Payu::refresh(Order::findOrFail($id));

} catch (\Exception $e) {
  return $e->getMessage();
}

支付详情

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {
  $id = 'orders.id';
  $payment = Payu::retrive(Order::findOrFail($id));

} catch (\Exception $e) {
  return $e->getMessage();
}

交易详情

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {
  $id = 'orders.id';
  $transaction = Payu::transaction(Order::findOrFail($id));

} catch (\Exception $e) {
  return $e->getMessage();
}

全额退款

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {
  $id = 'orders.id';
  $status = Payu::refund(Order::findOrFail($id));

} catch (\Exception $e) {
  return $e->getMessage();
}

退款详情

<?php
use App\Models\Order;
use Payu\Facades\Payu;

try {
  $id = 'orders.id';
  $status = Payu::refunds(Order::findOrFail($id));

} catch (\Exception $e) {
  return $e->getMessage();
}

支付方式列表

<?php
use Payu\Facades\Payu;

try {
  $pay_methods = Payu::payments('pl');

} catch (\Exception $e) {
  return $e->getMessage();
}

Payu 事件(events)

<?php

use Payu\Events\PayuPaymentCreated;
use Payu\Events\PayuPaymentCanceled;
use Payu\Events\PayuPaymentConfirmed;
use Payu\Events\PayuPaymentRefunded;
use Payu\Events\PayuPaymentNotified;

捕获事件(listeners)

php artisan make:listener PaymentCreatedNotification --event=PayuPaymentCreated

为模型创建类

php artisan make:model Order -a
php artisan make:resource OrderResource
php artisan make:resource OrderCollection

获取订单列表(管理员面板)

<?php

use Illuminate\Support\Facades\Route;
use App\Models\Order;

// Przykład
Route::get('/orders', function () {
  // Zamówienia z płatnościami
  return Order::with('payment')->orderBy('created_at', 'desc')->get();

  // Zamówienia z płatnościami i danymi klienta
  return Order::with('payment','client')->orderBy('created_at', 'desc')->get();

  // Filtruj kolumny
  return Order::with(['payment' => function($query) {
    $query->select('id','id','total','status','status_refund','created_at')->orderBy('created_at', 'desc');
  }])->orderBy('created_at', 'desc')->get();
});

授权协议

本项目的授权协议是 GNU GPLv3 许可协议。