如何区分Mailchimp API 3.0中两类返回400错误的订阅场景
问题描述
尝试订阅已处于订阅状态的用户时,Mailchimp API返回400错误;但用户退订后再次尝试订阅,同样返回400错误。我需要区分这两种情况,但查看Mailchimp错误文档后发现,400错误对应多种原因(请求错误、无效资源、无效操作、JSON解析异常),无法获取更具体的信息判断是用户已订阅还是已退订。请问如何获取更有用的错误信息?
以下是测试代码:
<?php $statusMsg = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['subscribe'])) { if (!empty($_POST['email']) && !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) === false) { // input sanitation array_walk_recursive($_POST, function(&$value) { $value = htmlspecialchars(stripslashes(trim($value))); }); $fname = $_POST['fname']; $lname = $_POST['lname']; $email = $_POST['email']; // MailChimp API credentials $apiKey = '<my test API key>'; $listId = '<my list id>'; // MailChimp API URL $dataCenter = substr($apiKey,strpos($apiKey,'-') + 1); $url = 'https://' . $dataCenter . '.api.mailchimp.com/3.0/lists/' . $listId . '/members/'; // member information $json = json_encode([ 'email_address' => $email, 'status' => 'subscribed', 'merge_fields' => [ 'FNAME' => $fname, 'LNAME' => $lname ] ]); // send a HTTP POST request with curl $ch = curl_init($url); curl_setopt($ch, CURLOPT_USERPWD, 'user:' . $apiKey); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // store the status message based on response code if ($httpCode == 200) { $statusMsg = '<p style="color: #34A853">You have successfully subscribed.</p>'; } else { switch ($httpCode) { case 400: // problem: this also happens when user is unsubscribed $msg = 'You are already subscribed.'; break; default: $msg = 'Some problem occurred, please try again. Error code ' . $httpCode . '.'; break; } $statusMsg = '<p style="color: red;">'.$msg.'</p>'; } } else { $statusMsg = '<p style="color: red;">Please enter valid email address.</p>'; } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mailchimp API Test</title> <link rel="stylesheet" href="style.css"> </head> <body> <main> <div id="container"> <h1>Subscribe to our Newsletter</h1> <?php echo $statusMsg; ?> <form method="post"> <input type="text" name="subscribe" value="subscribe" aria-hidden="true" readonly hidden> <p><label for="fname"> First Name:</label><br> <input id="fname" type="text" name="fname" /></p> <p><label for="lname"> Last Name:</label><br> <input id="lname" type="text" name="lname" /></p> <p><label for="email"> Email address:</label><br> <input id="email" type="text" name="email" /></p> <input type="submit" value="Submit" /> </form> </div> </main> </body> </html>
解决方案
1. 解析API返回的详细错误响应
Mailchimp的400错误并非只返回状态码,还会在响应体中包含具体错误细节的JSON数据。你的代码目前忽略了$result变量的内容,只需将其解码为数组,即可提取error_code和detail字段来区分不同场景。
修改错误处理逻辑如下:
else { // 解析API返回的错误JSON $errorData = json_decode($result, true); switch ($httpCode) { case 400: $msg = '请求错误,请稍后重试'; // 提取具体错误码和详情 if (isset($errorData['errors'][0])) { $errorCode = $errorData['errors'][0]['error_code']; $errorDetail = $errorData['errors'][0]['detail']; switch ($errorCode) { case 'ERROR_CONTACT_EXISTS': $msg = '您已处于订阅状态'; break; case 'ERROR_CONTACT_UNSUBSCRIBED': $msg = '您已退订,无法通过此方式直接重新订阅,请通过官方渠道手动恢复'; break; default: $msg = "请求错误:{$errorDetail}"; break; } } break; default: $msg = "发生未知问题,错误码:{$httpCode}"; if (isset($errorData['detail'])) { $msg .= ",详情:{$errorData['detail']}"; } break; } $statusMsg = '<p style="color: red;">' . $msg . '</p>'; }
2. 提前查询用户状态(优化方案)
在发起订阅请求前,先调用Mailchimp的会员查询接口,提前获取用户当前状态,避免触发模糊的400错误。接口需要使用邮箱地址的MD5哈希值作为参数:
// 生成邮箱的MD5哈希(需转小写后计算) $emailHash = md5(strtolower($email)); $checkUrl = "https://{$dataCenter}.api.mailchimp.com/3.0/lists/{$listId}/members/{$emailHash}"; $chCheck = curl_init($checkUrl); curl_setopt($chCheck, CURLOPT_USERPWD, "user:{$apiKey}"); curl_setopt($chCheck, CURLOPT_RETURNTRANSFER, true); $checkResult = curl_exec($chCheck); $checkHttpCode = curl_getinfo($chCheck, CURLINFO_HTTP_CODE); curl_close($chCheck); // 根据查询结果处理 if ($checkHttpCode == 200) { $memberData = json_decode($checkResult, true); switch ($memberData['status']) { case 'subscribed': $statusMsg = '<p style="color: red;">您已处于订阅状态</p>'; // 跳过订阅请求 goto endFormProcessing; case 'unsubscribed': $statusMsg = '<p style="color: red;">您已退订,请通过官方渠道手动恢复订阅</p>'; // 跳过订阅请求 goto endFormProcessing; // 可处理其他状态如pending、cleaned等 } } elseif ($checkHttpCode != 404) { // 查询接口出错,提示用户 $statusMsg = '<p style="color: red;">查询用户状态失败,请稍后重试</p>'; goto endFormProcessing; } // 原有订阅请求逻辑... endFormProcessing: // 后续代码
注意事项
- 务必处理
curl_exec返回false的情况,避免解析空数据导致报错 - Mailchimp的错误码可能会更新,需以官方最新文档为准
- 退订用户无法通过API直接恢复订阅,必须由用户手动确认,提示信息需准确
内容的提问来源于stack exchange,提问作者chillywilly
相关产品推荐
相关产品推荐

