init('douyin', $config); // 按照抖音支付API要求构建订单参数 $orderData = [ 'out_order_no' => $order['out_order_no'] ?? $order['out_trade_no'], 'total_amount' => intval(bcmul((string)$order['total_amount'], '100')), // 抖音支付金额单位为分 'subject' => $order['subject'] ?? '商品支付', 'body' => $order['body'] ?? '商品支付', 'valid_time' => $config['valid_time'] ?? 600, // 默认10分钟 ]; // 添加可选参数 if (isset($order['cp_extra'])) { $orderData['cp_extra'] = $order['cp_extra']; } if (isset($config['disable_msg'])) { $orderData['disable_msg'] = $config['disable_msg']; } if (isset($config['msg_page'])) { $orderData['msg_page'] = $config['msg_page']; } // 获取支付方法 $method = $this->getMethod('douyin'); // 调用 Yansongda\Pay 进行支付 $result = Pay::douyin()->$method($orderData); Log::write('抖音支付预下单响应:' . json_encode($result->toArray(), JSON_UNESCAPED_UNICODE)); return $result; } /** * 转账功能(抖音支付暂不支持) * @param array $payload * @param array $config * @return array */ public function transfer($payload, $config = []) { throw new Exception('抖音支付暂不支持转账功能'); } /** * 支付回调处理 * @param callable $callback * @param array $config * @return string */ public function notify($callback, $config = []) { $this->init('douyin', $config); try { // 使用 Yansongda\Pay 处理回调验签 $data = Pay::douyin()->callback(); Log::write('抖音支付回调原始数据:' . json_encode($data, JSON_UNESCAPED_UNICODE)); // 处理支付成功回调 if ($data['type'] === 'payment') { // 格式化数据为统一格式 $arrMsg = json_decode($data['msg'], true); $callbackData = [ 'out_trade_no' => $arrMsg['cp_orderno'] ?? '', 'transaction_id' => $arrMsg['order_id'] ?? '', 'total_amount' => $arrMsg['total_amount'] ?? 0, 'pay_fee' => $arrMsg['total_amount'] ?? 0, // 抖音支付金额单位为分,这里保持原样 'notify_time' => date('Y-m-d H:i:s'), // 'buyer_info' => $data['buyer_info'] ?? '', // 'cp_extra' => $data['cp_extra'] ?? '' ]; $result = $callback($callbackData, $data); return $result; } Log::error('抖音支付回调类型不支持: ' . ($data['type'] ?? 'unknown')); return 'fail'; } catch (HttpResponseException $e) { $data = $e->getResponse()->getData(); $message = $data ? ($data['msg'] ?? '') : $e->getMessage(); $this->logPayment('抖音支付回调HttpResponseException', ['error' => $message], 'error'); return 'fail'; } catch (\Exception $e) { $this->logPayment('抖音支付回调异常', ['error' => $e->getMessage()], 'error'); return 'fail'; } } /** * 退款 * @param array $order_data * @param array $config * @return array */ public function refund($order_data, $config = []) { $this->init('douyin', $config); // 构建退款参数 $refundData = [ 'out_order_no' => $order_data['out_trade_no'], 'out_refund_no' => $order_data['out_refund_no'], 'refund_amount' => intval($order_data['refund_amount']), // 抖音退款金额单位为分 'reason' => $order_data['reason'] ?? '用户申请退款', ]; // 如果有回调地址配置 if (isset($config['notify_url'])) { $refundData['notify_url'] = $config['notify_url']; } // 调用 Yansongda\Pay 进行退款 $result = Pay::douyin()->refund($refundData); Log::write('抖音退款响应:' . json_encode($result->toArray(), JSON_UNESCAPED_UNICODE)); return $result; } /** * 退款回调处理 * @param callable $callback * @param array $config * @return string */ public function notifyRefund($callback, $config = []) { $this->init('douyin', $config); try { // 使用 Yansongda\Pay 处理退款回调验签 $data = Pay::douyin()->callback(); Log::write('抖音退款回调原始数据:' . json_encode($data, JSON_UNESCAPED_UNICODE)); // 处理退款成功回调 if ($data['type'] === 'refund' && $data['msg'] === 'success') { $result = $callback($data, $data); return $result; } Log::error('抖音退款回调类型不支持: ' . ($data['type'] ?? 'unknown')); return 'fail'; } catch (HttpResponseException $e) { $data = $e->getResponse()->getData(); $message = $data ? ($data['msg'] ?? '') : $e->getMessage(); $this->logPayment('抖音退款回调HttpResponseException', ['error' => $message], 'error'); return 'fail'; } catch (\Exception $e) { $this->logPayment('抖音退款回调异常', ['error' => $e->getMessage()], 'error'); return 'fail'; } } /** * 格式化支付参数 * @param array $config * @param array $data * @param string $type * @return array */ protected function formatConfig($config, $data = [], $type = 'normal') { // 设置抖音支付的基本配置 $config['app_id'] = $data['app_id'] ?? ''; $config['secret'] = $data['secret'] ?? $data['salt'] ?? ''; // 设置回调URL $platform = $this->platform ?? 'DouyinMiniProgram'; $config['notify_url'] = request()->domain() . '/api/pay/notify/payment/douyin/platform/' . $platform; // 设置抖音支付网关(沙盒和生产环境) if (isset($config['sandbox']) && $config['sandbox']) { $config['mode'] = Pay::MODE_SANDBOX; } else { $config['mode'] = Pay::MODE_NORMAL; } return $config; } }