Files
2026-09-15 10:35:56 +08:00

162 lines
6.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun\Oceanpayment\Model\Gateway;
use Esun\Oceanpayment\Model\Config;
use Esun\Oceanpayment\Model\Signature;
use Magento\Framework\UrlInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Address;
class RequestBuilder
{
public function __construct(
private readonly Config $config,
private readonly Signature $signature,
private readonly UrlInterface $urlBuilder
) {
}
public function build(Order $order): array
{
$method = (string)$order->getPayment()->getMethod();
if ($method !== Config::METHOD_CODE && $method !== Config::LEGACY_METHOD_CODE) {
throw new \InvalidArgumentException('The order does not use Oceanpayment Hosted.');
}
$data = $this->buildBase($order, $method);
$data['backUrl'] = $this->urlBuilder->getUrl(
'oceanpayment/payment/back',
['_secure' => true, '_nosid' => true]
);
$data['signValue'] = $this->signature->createRequest(
$data,
$this->config->getSecret('secure_code', (int)$order->getStoreId(), $method)
);
return array_filter($data, static fn ($value): bool => $value !== '');
}
public function buildEmbedded(Order $order): array
{
$method = (string)$order->getPayment()->getMethod();
if ($method !== Config::ONEPAGE_METHOD_CODE) {
throw new \InvalidArgumentException('The order does not use Oceanpayment OnePage.');
}
$data = $this->buildBase($order, $method);
$data['backUrl'] = $this->urlBuilder->getUrl(
'oceanpayment/payment/back',
['_secure' => true, '_nosid' => true]
);
$data['signValue'] = $this->signature->createEmbeddedRequest(
$data,
$this->config->getSecret('secure_code', (int)$order->getStoreId(), $method)
);
return array_filter($data, static fn ($value): bool => $value !== '');
}
private function buildBase(Order $order, string $method): array
{
$storeId = (int)$order->getStoreId();
$billing = $order->getBillingAddress();
if (!$billing) {
throw new \InvalidArgumentException('The order has no billing address.');
}
$shipping = $order->getShippingAddress() ?: $billing;
$data = [
'account' => $this->config->getSecret('account', $storeId, $method),
'terminal' => $this->config->getSecret('terminal', $storeId, $method),
'noticeUrl' => $this->urlBuilder->getUrl(
'oceanpayment/payment/notify',
['_secure' => true, '_nosid' => true]
),
'methods' => $this->clean($this->config->getValue('methods', $storeId, $method), 50),
'order_number' => $this->clean((string)$order->getIncrementId(), 50),
'order_currency' => strtoupper($this->clean((string)$order->getOrderCurrencyCode(), 3)),
'order_amount' => number_format((float)$order->getGrandTotal(), 2, '.', ''),
'billing_firstName' => $this->clean((string)$billing->getFirstname(), 50),
'billing_lastName' => $this->clean((string)$billing->getLastname(), 50),
'billing_email' => $this->clean((string)$billing->getEmail(), 50),
'billing_phone' => $this->clean((string)$billing->getTelephone(), 50),
'billing_country' => strtoupper($this->clean((string)$billing->getCountryId(), 100)),
'billing_state' => $this->clean($this->getRegion($billing), 100),
'billing_city' => $this->clean((string)$billing->getCity(), 500),
'billing_address' => $this->clean(implode(' ', $billing->getStreet()), 500),
'billing_zip' => $this->clean((string)$billing->getPostcode(), 50),
'billing_ip' => $this->clean((string)$order->getRemoteIp(), 50),
'ship_firstName' => $this->clean((string)$shipping->getFirstname(), 50),
'ship_lastName' => $this->clean((string)$shipping->getLastname(), 50),
'ship_email' => $this->clean((string)$shipping->getEmail(), 50),
'ship_phone' => $this->clean((string)$shipping->getTelephone(), 50),
'ship_country' => strtoupper($this->clean((string)$shipping->getCountryId(), 100)),
'ship_state' => $this->clean($this->getRegion($shipping), 100),
'ship_city' => $this->clean((string)$shipping->getCity(), 500),
'ship_addr' => $this->clean(implode(' ', $shipping->getStreet()), 500),
'ship_zip' => $this->clean((string)$shipping->getPostcode(), 50),
'order_notes' => '',
];
$data += $this->getProductData($order);
$language = $this->clean($this->config->getValue('language', $storeId, $method), 50);
if ($language !== '') {
$data['language'] = $language;
}
$key = $this->config->getSecret('public_key', $storeId, $method);
if ($key !== '') {
$data['key'] = $key;
}
return $data;
}
private function getProductData(Order $order): array
{
$names = [];
$quantities = [];
$skus = [];
$prices = [];
foreach ($order->getAllVisibleItems() as $item) {
$names[] = $this->cleanListValue((string)$item->getName(), 120);
$quantities[] = $this->cleanListValue((string)(float)$item->getQtyOrdered(), 20);
$skus[] = $this->cleanListValue((string)$item->getSku(), 120);
$prices[] = number_format((float)$item->getPrice(), 2, '.', '');
}
if ($names === []) {
$names[] = 'Magento Order';
$quantities[] = '1';
$skus[] = (string)$order->getIncrementId();
$prices[] = number_format((float)$order->getGrandTotal(), 2, '.', '');
}
return [
'productName' => mb_substr(implode(',', $names), 0, 500),
'productNum' => mb_substr(implode(',', $quantities), 0, 50),
'productSku' => mb_substr(implode(',', $skus), 0, 500),
'productPrice' => mb_substr(implode(',', $prices), 0, 500),
];
}
private function getRegion(Address $address): string
{
return (string)($address->getRegionCode() ?: $address->getRegion() ?: '-');
}
private function cleanListValue(string $value, int $length): string
{
return str_replace(',', ' ', $this->clean($value, $length));
}
private function clean(string $value, int $length): string
{
return mb_substr($this->signature->sanitize($value), 0, $length);
}
}