paymentService = new CcbPaymentService(); $this->orderService = new CcbOrderService(); } /** * 生成支付串 * * @return void */ public function createPayment() { try { // 1. 获取订单ID $orderId = $this->request->post('order_id', 0); if (empty($orderId)) { $this->error('订单ID不能为空'); } // 2. 查询订单 $order = OrderModel::where('id', $orderId) ->where('user_id', $this->auth->id) ->find(); if (!$order) { $this->error('订单不存在'); } // 3. 检查订单状态 if ($order['status'] != 'unpaid') { $this->error('订单已支付或已关闭'); } // 4. 生成支付串 $result = $this->paymentService->generatePaymentString($orderId); if (!$result['status']) { $this->error('支付串生成失败: ' . $result['message']); } // 5. 保存支付流水号到订单 $order->ccb_pay_flow_id = $result['data']['order_sn']; // 使用订单号作为流水号 $order->save(); // 6. 记录支付日志 $this->savePaymentLog($order, $result['data']['payment_string'], $result['data']['order_sn']); // 7. 返回支付串 $this->success('支付串生成成功', [ 'payment_string' => $result['data']['payment_string'], 'payment_url' => $result['data']['payment_url'], 'mac' => $result['data']['mac'], 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'pay_flow_id' => $result['data']['order_sn'], 'amount' => $result['data']['amount'], ]); } catch (Exception $e) { Log::error('[建行支付] 生成支付串失败 order_id:' . ($orderId ?? 0) . ' error:' . $e->getMessage()); $this->error('生成支付串失败: ' . $e->getMessage()); } } /** * 支付回调 (前端调用) * * 说明: * 前端调起支付后,建行App会跳转回H5页面 * H5页面需要调用此接口通知后端支付成功 * * @return void */ public function callback() { try { // 1. 获取参数 $orderId = $this->request->post('order_id', 0); $transId = $this->request->post('trans_id', ''); $payTime = $this->request->post('pay_time', ''); if (empty($orderId)) { $this->error('订单ID不能为空'); } // 2. 查询订单 $order = OrderModel::where('id', $orderId)->find(); if (!$order) { $this->error('订单不存在'); } // 3. 检查订单状态 if ($order['status'] == 'paid' || $order['status'] == 'completed') { $this->success('订单已支付', [ 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'status' => $order['status'], ]); return; } // 4. 验证支付结果 (调用建行查询接口) $verifyResult = $this->paymentService->verifyPayment($order->order_sn); if (!$verifyResult) { $this->error('支付验证失败,请稍后再试'); } // 5. 更新订单状态 Db::startTrans(); try { $order->status = 'paid'; $order->paid_time = time() * 1000; // Shopro使用毫秒时间戳 $order->save(); // 6. 推送订单状态到建行 $this->pushOrderToCcb($order); // 7. 更新支付日志 $this->updatePaymentLog($order->ccb_pay_flow_id, [ 'status' => 1, 'pay_time' => time(), 'trans_id' => $transId, ]); Db::commit(); Log::info('[建行支付] 支付成功 order_id:' . $order->id . ' order_sn:' . $order->order_sn . ' trans_id:' . $transId); $this->success('支付成功', [ 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'status' => 'paid', ]); } catch (Exception $e) { Db::rollback(); throw $e; } } catch (Exception $e) { Log::error('[建行支付] 支付回调失败 order_id:' . ($orderId ?? 0) . ' error:' . $e->getMessage()); $this->error('支付处理失败: ' . $e->getMessage()); } } /** * 建行支付通知 (建行服务器回调) * * 说明: * 建行支付成功后,会向notify_url发送支付通知 * 这是服务器到服务器的回调,需要验签 * * @return void */ public function notify() { try { // TODO: 实现建行支付通知处理逻辑 // 1. 接收建行推送的支付结果 // 2. 验签 // 3. 更新订单状态 // 4. 返回success给建行 $this->success('SUCCESS'); } catch (Exception $e) { Log::error('[建行通知] 处理失败 error:' . $e->getMessage()); $this->error('FAIL'); } } /** * 推送订单到建行 * * @param object $order 订单对象 * @return void */ private function pushOrderToCcb($order) { // 获取订单商品列表 $orderItems = Db::name('shopro_order_item') ->where('order_id', $order->id) ->field('goods_id, goods_sku_text, goods_title, goods_price, goods_num, discount_fee') ->select(); $goodsList = []; foreach ($orderItems as $item) { $goodsList[] = [ 'goods_id' => $item['goods_id'], 'goods_name' => $item['goods_title'], 'goods_sku' => $item['goods_sku_text'], 'goods_price' => $item['goods_price'], 'goods_num' => $item['goods_num'], 'discount_amount' => $item['discount_fee'] ?? 0 ]; } // 获取用户的建行用户ID $user = Db::name('user')->where('id', $order->user_id)->field('ccb_user_id')->find(); // 构造订单数据 (使用Shopro实际字段名) $orderData = [ 'id' => $order->id, 'order_sn' => $order->order_sn, 'ccb_user_id' => $user['ccb_user_id'] ?? '', 'total_amount' => $order->total_amount, // 订单总金额 'pay_amount' => $order->total_fee, // 实际支付金额 'discount_amount' => $order->discount_fee, // 优惠金额 'status' => $order->status, // Shopro使用status枚举 'refund_status' => $order->aftersale_status ?? 0, // 售后状态 'create_time' => $order->createtime, // Shopro使用秒级时间戳 'paid_time' => $order->paid_time, // 支付时间 'ccb_pay_flow_id' => $order->ccb_pay_flow_id, 'goods_list' => $goodsList, ]; // 推送到建行 $result = $this->orderService->pushOrder($order->id); if (!$result['status']) { Log::warning('[建行推送] 订单推送失败 order_id:' . $order->id . ' error:' . ($result['message'] ?? '')); } else { // 更新同步状态 $order->ccb_sync_status = 1; $order->ccb_sync_time = time(); $order->save(); Log::info('[建行推送] 订单推送成功 order_id:' . $order->id . ' order_sn:' . $order->order_sn); } } /** * 保存支付日志 * * @param object $order 订单对象 * @param string $paymentString 支付串 * @param string $payFlowId 支付流水号 * @return void */ private function savePaymentLog($order, $paymentString, $payFlowId) { Db::name('ccb_payment_log')->insert([ 'order_id' => $order->id, 'order_sn' => $order->order_sn, 'pay_flow_id' => $payFlowId, 'payment_string' => $paymentString, 'user_id' => $order->user_id, 'ccb_user_id' => $order->ccb_user_id, 'amount' => $order->pay_amount, 'status' => 0, // 待支付 'create_time' => time(), ]); } /** * 更新支付日志 * * @param string $payFlowId 支付流水号 * @param array $data 更新数据 * @return void */ private function updatePaymentLog($payFlowId, $data) { Db::name('ccb_payment_log') ->where('pay_flow_id', $payFlowId) ->update($data); } }