فهرست منبع

repay 支付方式

chengwl 16 ساعت پیش
والد
کامیت
1042af2a5f

+ 33 - 0
packages/Webkul/BagistoApi/src/Models/RepayOrderPaymentMethods.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace Webkul\BagistoApi\Models;
+
+use ApiPlatform\Metadata\ApiResource;
+use ApiPlatform\Metadata\GraphQl\QueryCollection;
+use Webkul\BagistoApi\Dto\PaymentMethodOutput;
+use Webkul\BagistoApi\State\RepayOrderPaymentMethodsProvider;
+
+/**
+ * RepayOrderPaymentMethods - GraphQL API Resource for repay-order payment methods.
+ */
+#[ApiResource(
+    routePrefix: '/api/shop',
+    shortName: 'RepayOrderPaymentMethods',
+    operations: [],
+    graphQlOperations: [
+        new QueryCollection(
+            name: 'collection',
+            args: [
+                'orderId' => [
+                    'type'        => 'Int!',
+                    'description' => 'Bagisto order id to fetch repay-available payment methods for',
+                ],
+            ],
+            output: PaymentMethodOutput::class,
+            provider: RepayOrderPaymentMethodsProvider::class,
+            paginationEnabled: false,
+            description: 'Get available payment methods for replaying payment on a pending order',
+        ),
+    ]
+)]
+class RepayOrderPaymentMethods {}

+ 2 - 0
packages/Webkul/BagistoApi/src/Providers/BagistoApiServiceProvider.php

@@ -44,6 +44,7 @@ use Webkul\BagistoApi\State\PageProvider;
 use Webkul\BagistoApi\State\AttributeCollectionProvider;
 use Webkul\BagistoApi\State\AttributeOptionCollectionProvider;
 use Webkul\BagistoApi\State\AttributeOptionQueryProvider;
+use Webkul\BagistoApi\State\RepayOrderPaymentMethodsProvider;
 use Webkul\BagistoApi\State\AttributeValueProcessor;
 use Webkul\BagistoApi\State\AuthenticatedCustomerProvider;
 use Webkul\BagistoApi\State\BundleOptionProductsProvider;
@@ -312,6 +313,7 @@ class BagistoApiServiceProvider extends ServiceProvider
         $this->app->tag(CustomerAddressProvider::class, ProviderInterface::class);
         $this->app->tag(GetCheckoutAddressCollectionProvider::class, ProviderInterface::class);
         $this->app->tag(PaymentMethodsProvider::class, ProviderInterface::class);
+        $this->app->tag(RepayOrderPaymentMethodsProvider::class, ProviderInterface::class);
         $this->app->tag(ShippingRatesProvider::class, ProviderInterface::class);
         $this->app->tag(AuthenticatedCustomerProvider::class, ProviderInterface::class);
         $this->app->tag(CartTokenMutationProvider::class, ProviderInterface::class);

+ 115 - 0
packages/Webkul/BagistoApi/src/State/RepayOrderPaymentMethodsProvider.php

@@ -0,0 +1,115 @@
+<?php
+
+namespace Webkul\BagistoApi\State;
+
+use ApiPlatform\Metadata\Operation;
+use ApiPlatform\State\ProviderInterface;
+use Illuminate\Support\Facades\Auth;
+use Webkul\BagistoApi\Dto\PaymentMethodOutput;
+use Webkul\BagistoApi\Exception\AuthorizationException;
+use Webkul\BagistoApi\Exception\OperationFailedException;
+use Webkul\BagistoApi\Exception\ResourceNotFoundException;
+use Webkul\Payment\Facades\Payment;
+use Webkul\Sales\Models\Order;
+use Webkul\Sales\Repositories\OrderRepository;
+
+/**
+ * Provides available payment methods for repaying an existing order.
+ */
+class RepayOrderPaymentMethodsProvider implements ProviderInterface
+{
+    public function __construct(
+        protected OrderRepository $orderRepository,
+    ) {}
+
+    /**
+     * Provide payment methods for replaying payment on an order.
+     */
+    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
+    {
+        $args = $context['args'] ?? [];
+        $orderId = $args['orderId'] ?? null;
+
+        if (! $orderId || ! is_numeric($orderId)) {
+            throw new ResourceNotFoundException(__('bagistoapi::app.graphql.customer-order.id-required'));
+        }
+
+        $customer = Auth::guard('sanctum')->user();
+
+        if (! $customer) {
+            throw new AuthorizationException(__('bagistoapi::app.graphql.logout.unauthenticated'));
+        }
+
+        $order = $this->orderRepository->find((int) $orderId);
+
+        if (! $order) {
+            throw new ResourceNotFoundException(__('bagistoapi::app.graphql.payment.order-not-found', ['id' => $orderId]));
+        }
+
+        if ((int) $order->customer_id !== (int) $customer->id) {
+            throw new OperationFailedException(__('bagistoapi::app.graphql.payment.replay-not-allowed'));
+        }
+
+        if (! in_array($order->status, [Order::STATUS_PENDING, Order::STATUS_PENDING_PAYMENT], true)) {
+            throw new OperationFailedException(__('bagistoapi::app.graphql.payment.not-pending', ['status' => $order->status]));
+        }
+
+        $methods = Payment::getSupportedPaymentMethods();
+
+        if ($methods && is_array($methods) && isset($methods['payment_methods'])) {
+            $methodsArray = $methods['payment_methods'];
+        } elseif ($methods && is_object($methods) && property_exists($methods, 'payment_methods')) {
+            $methodsArray = (array) $methods->payment_methods;
+        } else {
+            $methodsArray = [];
+        }
+
+        if (! $methodsArray || ! is_array($methodsArray)) {
+            return [];
+        }
+
+        $outputs = [];
+        $currentMethod = (string) ($order->payment?->method ?? '');
+
+        foreach ($methodsArray as $key => $method) {
+            $methodData = is_object($method) ? (array) $method : $method;
+            $methodCode = (string) ($methodData['method'] ?? $key);
+            $isValid = $this->isValidPaymentMethod($methodCode,$order);
+            //TODO 逻辑判断支付是否符合要求
+            if (!$isValid) {
+                continue;
+            }
+
+            $output = new PaymentMethodOutput;
+            $output->id = $methodCode;
+            $output->method = $methodData['method'] ?? null;
+            $output->title = $methodData['method_title'] ?? null;
+            $output->description = $methodData['description'] ?? null;
+            $output->icon = $methodData['image'] ?? null;
+            // $output->isAllowed = $isAllowed;
+            $output->additionalData = $methodData['additional_data'] ?? null;
+            $outputs[] = $output;
+        }
+
+        return $outputs;
+    }
+
+    /**
+     * Replay support parity with PaymentService::createGatewayOrderForOrder:
+     * - paypal_smart_button is natively supported
+     * - custom gateways must provide a handler class with createGatewayOrder()
+     */
+    private function isValidPaymentMethod(string $methodCode,Order $order): bool
+    {
+        if ($methodCode === 'paypal_smart_button') {
+            return true;
+        }
+
+        $config = config('payment_methods.'.$methodCode);
+
+        if (! is_array($config) || empty($config['class'])) {
+            return false;
+        }
+        return true;
+    }
+}