钉钉小程序通过my.request调用PHP后端需注意:使用POST+JSON、PHP手动解析php://input、严格校验timestamp和sign、JSAPI回调需AES解密后再验签。
钉钉小程序本身不直接调用 PHP 后端,但你可以在小程序里发起 my.request 请求到你的 PHP 接口,PHP 作为服务端接收并处理数据。关键不是“钉钉小程序对接 PHP”,而是「小程序如何发、PHP 如何收、怎么验签防伪造」——没做签名验证的接口,随时可能被恶意调
用。
钉钉小程序使用的是阿里系的 my.request(不是 wx.request 或 uni.request),它默认携带 Content-Type: application/json,且会自动序列化 data 字段为 JSON。
method 明确为 POST 或 GET,PHP 不会自动识别请求体里的 JSONdata: { key: 'val' },PHP 默认收不到 —— 因为 JSON 在请求体(php://input),不是 $_POST
POST + JSON,避免 URL 长度限制和编码问题不能依赖 $_POST,必须手动解析 php://input;同时要检查 Content-Type 头是否为 application/json,否则可能是表单或恶意请求。
if (isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) {
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
echo json_encode(['error' => 'Invalid JSON']);
exit;
}
} else {
http_response_code(400);
echo json_encode(['error' => 'Content-Type must be application/json']);
exit;
}
$data 就是你小程序里 my.request({ data: {...} }) 发的内容json_decode(..., true) 的第二个参数,否则返回对象,PHP 数组操作会报错charset=utf-8,但建议在响应头加上:header('Content-Type: application/json; charset=utf-8');
钉钉要求所有来自小程序的服务端回调(如打开小程序、JSAPI 调用结果)或你自定义的 API,都需校验时间戳 + 签名,否则攻击者可重放请求、伪造用户身份。
立即学习“PHP免费学习笔记(深入)”;
my.getAuthCode() 或 my.getOpenUserInfo() 获取临时授权码,但这些码必须由你的 PHP 后端用 appkey + appsecret 向钉钉服务端换用户信息 —— 这步不涉及 sign 校验my.request({ url: 'https://your.com/api/save' }),这个接口就该自己实现 sign 校验:前端生成 timestamp 和 sign(用 appsecret 对参数排序拼接后 SHA256),PHP 收到后重新算一遍比对sign 计算时没按字典序排序参数、没去掉空值、没转成小写、没用 UTF-8 编码拼接这类回调是钉钉服务器主动 POST 到你的 PHP 接口,不是小程序前端发的。钉钉会带 timestamp、sign、encrypt 三个关键字段,且整个 body 是加密的(AES-128-CBC),必须先解密再验签。
file_get_contents('php://input') 拿原始加密字符串encrypt 字段 + 你后台配置的 token + encodingAesKey 解密(注意:PHP 的 openssl_decrypt 要求 IV 为 16 字节,且 padding 补齐方式必须匹配)timestamp 有效性判断(5 分钟内)和 sign 校验success(无空格、无换行、无 JSON),否则认为失败并重试最常卡住的地方是:AES 解密失败(IV 错、key 长度不对)、解密后 JSON 格式异常(没用 json_decode 检查)、响应多了一个空格或换行 —— 钉钉就当没收到。