153 lines
5.8 KiB
PHP
153 lines
5.8 KiB
PHP
<?php
|
|
namespace App\Controllers;
|
|
|
|
use App\Models\Product;
|
|
use App\Models\Order;
|
|
use App\Models\Payment;
|
|
use Core\Payment\GatewayFactory;
|
|
use Core\Payment\OrderService;
|
|
use Core\Notify;
|
|
|
|
/** 前台:下单 → 支付 → 查询 */
|
|
class OrderController extends Controller
|
|
{
|
|
public function checkout($slug)
|
|
{
|
|
$product = (new Product())->where('slug', $slug);
|
|
if (!$product) { \Core\App::notFound(); return ''; }
|
|
$err = isset($_GET['err']) ? '请填写姓名与手机号' : '';
|
|
return $this->view('order/checkout', ['p' => $product, 'slug' => $slug, 'err' => $err]);
|
|
}
|
|
|
|
public function store()
|
|
{
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { $this->redirect('products'); }
|
|
if (!csrf_check()) { $this->redirect('products'); }
|
|
$slug = $this->post('slug', '');
|
|
$product = (new Product())->where('slug', $slug);
|
|
if (!$product) { $this->redirect('products'); }
|
|
$name = trim($this->post('name', ''));
|
|
$phone = trim($this->post('phone', ''));
|
|
$email = trim($this->post('email', ''));
|
|
$qty = max(1, (int) $this->post('qty', 1));
|
|
if ($name === '' || $phone === '') {
|
|
$this->redirect('order/checkout/' . $slug . '?err=1');
|
|
}
|
|
$amount = round((float) $product['price'] * $qty, 2);
|
|
$orderNo = $this->genNo();
|
|
$oid = (new Order())->insert([
|
|
'order_no' => $orderNo,
|
|
'product_id' => $product['id'],
|
|
'product_name' => $product['name'],
|
|
'customer_name' => $name,
|
|
'phone' => $phone,
|
|
'email' => $email,
|
|
'qty' => $qty,
|
|
'amount' => $amount,
|
|
'channel' => '',
|
|
'status' => 'pending',
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
]);
|
|
Notify::newCustomerOrder($orderNo, $name, $phone, $oid);
|
|
$this->redirect('order/pay/' . $orderNo);
|
|
}
|
|
|
|
public function pay($orderNo)
|
|
{
|
|
$order = (new Order())->where('order_no', $orderNo);
|
|
if (!$order) { \Core\App::notFound(); return ''; }
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$channel = $this->post('channel', '');
|
|
if ($channel === 'alipay' || $channel === 'wechat') {
|
|
if ($order['channel'] !== $channel) {
|
|
(new Order())->update($order['id'], ['channel' => $channel]);
|
|
$order['channel'] = $channel;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($order['status'] === 'paid') {
|
|
return $this->view('order/pay', ['order' => $order, 'paid' => true]);
|
|
}
|
|
if (empty($order['channel'])) {
|
|
return $this->view('order/pay', ['order' => $order, 'choose' => true]);
|
|
}
|
|
$gw = GatewayFactory::make($order['channel']);
|
|
$res = $gw->pay($order);
|
|
return $this->view('order/pay', ['order' => $order, 'gw' => $res]);
|
|
}
|
|
|
|
/** 演示支付:模拟支付成功(默认模式可用,便于走通全流程) */
|
|
public function demo($orderNo)
|
|
{
|
|
$o = (new Order())->where('order_no', $orderNo);
|
|
$channel = ($o && $o['channel'] === 'wechat') ? 'wechat' : 'alipay';
|
|
OrderService::markPaid($orderNo, 'DEMO' . time(), $channel);
|
|
$this->redirect('order/success/' . $orderNo);
|
|
}
|
|
|
|
public function success($orderNo)
|
|
{
|
|
$order = (new Order())->where('order_no', $orderNo);
|
|
if (!$order) { \Core\App::notFound(); return ''; }
|
|
$payments = (new Payment())->whereAll('order_no', $orderNo);
|
|
return $this->view('order/result', ['order' => $order, 'payments' => $payments]);
|
|
}
|
|
|
|
/**
|
|
* 客户查询订单:客户名 + 手机号 双重校验
|
|
* - 必填:客户名(下单时填写的姓名/单位)+ 手机号
|
|
* - 选填:订单号(精确查单笔)
|
|
*/
|
|
public function query()
|
|
{
|
|
$orders = []; $no = ''; $name = ''; $phone = ''; $err = '';
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && csrf_check()) {
|
|
$no = trim($this->post('order_no', ''));
|
|
$name = trim($this->post('name', ''));
|
|
$phone = trim($this->post('phone', ''));
|
|
|
|
if ($name === '' || $phone === '') {
|
|
$err = '请输入客户名与手机号以核验身份';
|
|
} else {
|
|
$om = new Order();
|
|
$pm = new Payment();
|
|
$nameKey = mb_strtolower($name, 'UTF-8');
|
|
// 客户名 + 手机号 同时匹配
|
|
$matched = array_filter($om->all(), function ($o) use ($nameKey, $phone) {
|
|
$oName = mb_strtolower(trim($o['customer_name'] ?? ''), 'UTF-8');
|
|
$oPhone = trim($o['phone'] ?? '');
|
|
return $oName === $nameKey && $oPhone === $phone;
|
|
});
|
|
|
|
if ($no !== '') {
|
|
$matched = array_values(array_filter($matched, fn($o) => ($o['order_no'] ?? '') === $no));
|
|
}
|
|
|
|
if (empty($matched)) {
|
|
$err = $no !== ''
|
|
? '未找到该订单号对应的订单,请核对客户名与手机号'
|
|
: '未找到匹配的客户名与手机号对应的订单';
|
|
} else {
|
|
$orders = array_map(function ($o) use ($pm) {
|
|
return ['order' => $o, 'payments' => $pm->whereAll('order_no', $o['order_no'])];
|
|
}, $matched);
|
|
}
|
|
}
|
|
}
|
|
return $this->view('order/query', [
|
|
'orders' => $orders,
|
|
'no' => $no,
|
|
'name' => $name,
|
|
'phone' => $phone,
|
|
'err' => $err,
|
|
]);
|
|
}
|
|
|
|
private function genNo(): string
|
|
{
|
|
return 'SQY' . date('YmdHis') . str_pad((int) ((microtime(true) * 1000) % 1000), 3, '0', STR_PAD_LEFT);
|
|
}
|
|
}
|