!107 Order Payment

* wip
* add exceptions
* order->orderPayments ui
* add order payments
* paypal 和 stripe 保存支付数据
* add order payment.
This commit is contained in:
Edward Yang 2023-05-25 09:53:49 +00:00
parent 5b83f02098
commit d6f518dff6
12 changed files with 244 additions and 6 deletions

View File

@ -71,7 +71,7 @@ class OrderController extends Controller
*/
public function show(Request $request, Order $order)
{
$order->load(['orderTotals', 'orderHistories', 'orderShipments']);
$order->load(['orderTotals', 'orderHistories', 'orderShipments', 'orderPayments']);
$data = hook_filter('admin.order.show.data', ['order' => $order, 'html_items' => []]);
$data['statuses'] = StateMachineService::getInstance($order)->nextBackendStatuses();
$data = hook_filter('admin.order.show.data', $data);

View File

@ -0,0 +1,17 @@
<?php
/**
* InvalidException.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @created 2023-05-25 14:48:12
* @modified 2023-05-25 14:48:12
*/
namespace Beike\Exceptions;
class InvalidException extends \Exception
{
}

View File

@ -59,6 +59,11 @@ class Order extends Base
return $this->hasMany(OrderShipment::class);
}
public function orderPayments(): HasMany
{
return $this->hasMany(OrderPayment::class);
}
public function subTotal()
{
$totals = $this->orderTotals;

View File

@ -0,0 +1,21 @@
<?php
/**
* OrderPayment.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @created 2023-05-25 10:02:52
* @modified 2023-05-25 10:02:52
*/
namespace Beike\Models;
class OrderPayment extends Base
{
protected $table = 'order_payments';
protected $fillable = [
'order_id', 'transaction_id', 'request', 'response', 'callback', 'receipt',
];
}

View File

@ -0,0 +1,61 @@
<?php
/**
* OrderPaymentRepo.php
*
* @copyright 2023 beikeshop.com - All Rights Reserved
* @link https://beikeshop.com
* @author Edward Yang <yangjin@guangda.work>
* @created 2023-05-25 10:02:39
* @modified 2023-05-25 10:02:39
*/
namespace Beike\Repositories;
use Beike\Models\OrderPayment;
class OrderPaymentRepo
{
/**
* @param $orderId
* @param $data
* @return mixed
* @throws \Throwable
*/
public static function createOrUpdatePayment($orderId, $data): mixed
{
$orderId = (int) $orderId;
if (empty($orderId) || empty($data)) {
return null;
}
$orderPayment = OrderPayment::query()->where('order_id', $orderId)->first();
if (empty($orderPayment)) {
$orderPayment = new OrderPayment();
}
$paymentData = [
'order_id' => $orderId,
];
if (isset($data['transaction_id'])) {
$paymentData['transaction_id'] = $data['transaction_id'];
}
if (isset($data['request'])) {
$paymentData['request'] = json_encode($data['request'] ?? []);
}
if (isset($data['response'])) {
$paymentData['response'] = json_encode($data['response'] ?? []);
}
if (isset($data['callback'])) {
$paymentData['callback'] = json_encode($data['callback'] ?? []);
}
if (isset($data['receipt'])) {
$paymentData['receipt'] = $data['receipt'];
}
$orderPayment->fill($paymentData);
$orderPayment->saveOrFail();
return $orderPayment;
}
}

View File

@ -15,6 +15,7 @@ use Beike\Models\Order;
use Beike\Models\OrderHistory;
use Beike\Models\OrderShipment;
use Beike\Models\Product;
use Beike\Repositories\OrderPaymentRepo;
use Throwable;
class StateMachineService
@ -29,6 +30,8 @@ class StateMachineService
private array $shipment;
private array $payment;
public const CREATED = 'created'; // 已创建
public const UNPAID = 'unpaid'; // 待支付
@ -116,6 +119,19 @@ class StateMachineService
return $this;
}
/**
* 设置支付信息
*
* @param array $payment
* @return $this
*/
public function setPayment(array $payment = []): self
{
$this->payment = $payment;
return $this;
}
/**
* 获取所有订单状态列表
*
@ -340,6 +356,18 @@ class StateMachineService
}
}
/**
* 添加发货单号
* @throws Throwable
*/
private function addPayment($oldCode, $newCode)
{
if (empty($this->payment)) {
return;
}
OrderPaymentRepo::createOrUpdatePayment($this->orderId, $this->payment);
}
/**
* 发送新订单通知
*/

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('order_payments', function (Blueprint $table) {
$table->id();
$table->integer('order_id');
$table->string('transaction_id')->nullable();
$table->string('request')->nullable();
$table->string('response')->nullable();
$table->string('callback')->nullable();
$table->string('receipt')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('order_payments');
}
};

View File

@ -15,6 +15,7 @@
namespace Plugin\Paypal\Controllers;
use Beike\Repositories\OrderPaymentRepo;
use Beike\Repositories\OrderRepo;
use Beike\Services\StateMachineService;
use Illuminate\Http\JsonResponse;
@ -96,8 +97,10 @@ class PaypalController
$customer = current_customer();
$order = OrderRepo::getOrderByNumber($orderNumber, $customer);
OrderPaymentRepo::createOrUpdatePayment($order->id, ['request' => $data]);
$paypalOrderId = $data['paypalOrderId'];
$result = $this->paypalClient->capturePaymentOrder($paypalOrderId);
OrderPaymentRepo::createOrUpdatePayment($order->id, ['response' => $result]);
try {
DB::beginTransaction();

View File

@ -11,6 +11,7 @@
namespace Plugin\Stripe\Controllers;
use Beike\Repositories\OrderPaymentRepo;
use Beike\Repositories\OrderRepo;
use Beike\Services\StateMachineService;
use Beike\Shop\Http\Controllers\Controller;
@ -24,6 +25,7 @@ class StripeController extends Controller
*
* @param Request $request
* @return array
* @throws \Throwable
*/
public function capture(Request $request): array
{
@ -32,14 +34,18 @@ class StripeController extends Controller
$customer = current_customer();
$order = OrderRepo::getOrderByNumber($number, $customer);
$creditCardData = $request->all();
$result = (new StripePaymentService($order))->capture($creditCardData);
OrderPaymentRepo::createOrUpdatePayment($order->id, ['request' => $creditCardData]);
$result = (new StripePaymentService($order))->capture($creditCardData);
OrderPaymentRepo::createOrUpdatePayment($order->id, ['response' => $result]);
if ($result) {
StateMachineService::getInstance($order)->changeStatus(StateMachineService::PAID);
StateMachineService::getInstance($order)->setShipment()->changeStatus(StateMachineService::PAID);
return json_success(trans('Stripe::common.capture_success'));
}
return json_success(trans('Stripe::common.capture_fail'));
return json_success(trans('Stripe::common.capture_fail'));
} catch (\Exception $e) {
return json_fail($e->getMessage());

View File

@ -208,6 +208,50 @@
</div>
@endhookwrapper
@if ($order->orderPayments)
@hookwrapper('admin.order.form.payments')
<div class="card mb-4">
<div class="card-header"><h6 class="card-title">{{ __('admin/order.payments_history') }}</h6></div>
<div class="card-body">
<div class="table-push">
<table class="table ">
<thead class="">
<tr>
<th>{{ __('admin/order.order_id') }}</th>
<th>{{ __('admin/order.text_transaction_id') }}</th>
<th>{{ __('admin/order.text_request') }}</th>
<th>{{ __('admin/order.text_response') }}</th>
<th>{{ __('admin/order.text_callback') }}</th>
<th>{{ __('admin/order.text_receipt') }}</th>
<th>{{ __('order.created_at') }}</th>
<th>{{ __('order.updated_at') }}</th>
</tr>
</thead>
<tbody>
@foreach ($order->orderPayments as $payment)
<tr>
<td>{{ $payment->order_id }}</td>
<td>{{ $payment->transaction_id }}</td>
<td>{{ $payment->request }}</td>
<td>{{ $payment->response }}</td>
<td>{{ $payment->callback }}</td>
<td>
@if ($payment->receipt)
<a href="{{ image_origin($payment->receipt) }}" target="_blank">{{ __('admin/order.text_click_view') }}</a>
@endif
</td>
<td>{{ $payment->created_at }}</td>
<td>{{ $payment->updated_at }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
@endhookwrapper
@endif
@if ($order->orderShipments)
@hookwrapper('admin.order.form.shipments')
<div class="card mb-4">
@ -219,7 +263,7 @@
<tr>
<th>{{ __('order.express_company') }}</th>
<th>{{ __('order.express_number') }}</th>
<th>{{ __('order.history_created_at') }}</th>
<th>{{ __('order.updated_at') }}</th>
</tr>
</thead>
<tbody>
@ -265,7 +309,7 @@
<tr>
<th>{{ __('order.history_status') }}</th>
<th>{{ __('order.history_comment') }}</th>
<th>{{ __('order.history_created_at') }}</th>
<th>{{ __('order.updated_at') }}</th>
</tr>
</thead>
<tbody>

View File

@ -23,4 +23,13 @@ return [
'notify' => 'Whether to remind',
'orders_update_status' => 'Update Status',
'error_status' => 'Please select a status',
'payments_history' => 'Payment History',
'text_response' => 'Pesponse',
'text_request' => 'Pequest',
'text_callback' => 'Callback',
'text_callback' => 'Callback',
'text_receipt' => 'Receipt',
'order_id' => 'Order Id',
'text_transaction_id' => 'Transaction Id',
'text_click_view' => 'Click To View',
];

View File

@ -23,4 +23,12 @@ return [
'notify' => '是否提醒',
'orders_update_status' => '更新状态',
'error_status' => '请选择状态',
'payments_history' => '支付记录',
'text_response' => '返回数据',
'text_request' => '请求参数',
'text_callback' => '回调',
'text_receipt' => '凭据',
'order_id' => '订单ID',
'text_transaction_id' => '交易ID',
'text_click_view' => '点击查看',
];