'', // 小程序路径 * 'url' => '', // 网页路径 * 'openid' => '', // 可选,优先使用 * ] * @return array [bool, string] */ public function sendTemplateMessage(string $templateKey, array $dataData, array $options = []): array { try { $config = config("wx_msg.template_map.$templateKey"); if (!$config) return [false, "微信消息模板键值不存在: {$templateKey}"]; $openid = $options['openid'] ?? ""; if (empty($openid)) return [false, "openid 不能为空"]; list($tokenOk, $token) = $this->getTokenSTABLE(); if (! $tokenOk) return [false, $token]; $jumpType = $config['jump_type'] ?? ''; $payload = [ 'touser' => $openid, 'template_id' => $config['tmp_id'], 'data' => $this->buildTemplateData($config, $dataData, $options), ]; // 动态跳转处理 if ($jumpType === 'h5') { $payload['url'] = $options['url'] ?? ''; } elseif ($jumpType === 'mp') { if(empty($options['pagepath'])){ $payload['url'] = ''; }else{ $payload['miniprogram'] = [ 'appid' => config('wx_msg.appid'), 'pagepath' => $options['pagepath'] ?? '', ]; } } $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$token}"; $res = $this->curlOpen($url, ['post' => json_encode($payload, JSON_UNESCAPED_UNICODE)]); $res = json_decode($res, true); if (isset($res['errcode']) && $res['errcode'] === 0) return [true, '']; return [false , $res['errmsg']]; } catch (Exception $e) { return [false, $e->getMessage()]; } } /** * 构建模板数据结构 */ protected function buildTemplateData(array $config, array $dataData, array $options = []): array { $result = []; foreach ($config['params'] as $key => $field) { $value = $dataData[$key] ?? ''; $maxLen = $this->getWxFieldMaxLength($field); $value_f = $this->safeWxValue((string)$value, $maxLen); $result[$field] = ['value' => $value_f, 'color' => '#173177']; } return $result; } /** * 微信字段类型最大长度映射 */ protected function getWxFieldMaxLength(string $type): int { $map = [ 'thing' => 20, 'thing1' => 20, 'thing2' => 20, 'thing3' => 20, 'thing4' => 20, 'thing5' => 20, 'character_string' => 32, 'character_string1' => 32, 'character_string2' => 32, 'character_string3' => 32, 'number' => 10, 'amount' => 10, 'time' => 20, 'date' => 20, 'phone_number' => 11, 'car_number' => 10, ]; // 截取字段类型前缀(比如 thing5 → thing) $prefix = preg_replace('/\d+$/', '', $type); return $map[$type] ?? $map[$prefix] ?? 30; } /** * 安全处理微信模板值(截断 + 清理) */ protected function safeWxValue(string $value, int $maxLen): string { $value = trim(strip_tags($value)); // 去除HTML标签 $value = preg_replace('/\s+/', ' ', $value); // 合并空白字符 // 多字节安全截断(支持中文) if (mb_strlen($value, 'UTF-8') > $maxLen) { $value = mb_substr($value, 0, $maxLen - 1, 'UTF-8') . '…'; } return $value; } }