钉钉小程序通过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 不会自动识别请求体里的 JSON - 若传参用
data: { key: 'val' },PHP 默认收不到 —— 因为 JSON 在请求体(php://input),不是$_POST - 建议统一用
POST + JSON,避免 URL 长度限制和编码问题
PHP 怎么正确读取钉钉小程序发来的 JSON 数据
不能依赖 $_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');
为什么必须校验 timestamp 和 sign?
钉钉要求所有来自小程序的服务端回调(如打开小程序、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 编码拼接
PHP 接收钉钉 JSAPI 回调(比如扫码、支付完成)的特殊处理
这类回调是钉钉服务器主动 POST 到你的 PHP 接口,不是小程序前端发的。钉钉会带 timestamp、sign、encrypt 三个关键字段,且整个 body 是加密的(AES-128-CBC),必须先解密再验签。
- 先用
file_get_contents('php://input')拿原始加密字符串 - 用钉钉提供的
encrypt字段 + 你后台配置的token+encodingAesKey解密(注意:PHP 的openssl_decrypt要求 IV 为 16 字节,且 padding 补齐方式必须匹配) - 解密后才是标准 JSON,再做
timestamp有效性判断(5 分钟内)和sign校验 - 钉钉要求响应必须是纯文本
success(无空格、无换行、无 JSON),否则认为失败并重试
最常卡住的地方是:AES 解密失败(IV 错、key 长度不对)、解密后 JSON 格式异常(没用 json_decode 检查)、响应多了一个空格或换行 —— 钉钉就当没收到。











