Moodle 4.2.1通过cURL调用mod_quiz_save_attempt接口提交测验尝试失败求助
我太懂你这种挫败感了——接口返回200和成功状态,但数据库和测验界面一点变化都没有,查了半天资料也找不到清晰的参数格式指南。咱们一步步来解决这个问题:
先排查你当前cURL命令里的明显问题
- 重复参数导致冲突:你命令里重复传了两次
q24:1_:flagged,服务器处理时会覆盖重复的参数,这大概率会导致请求逻辑异常,直接删掉其中一个就行。 - sequencecheck值可能不匹配:这个参数是Moodle用来防止并发提交的“版本号”,每次操作测验尝试后都会递增。你传的
2可能已经过时了,必须先调用mod_quiz_get_attempt_data接口获取当前尝试的最新sequencecheck值,再替换进去,否则Moodle会认为这是旧请求,直接忽略更新。 - 参数格式错误:你用了
--form提交,但接口要求的是application/x-www-form-urlencoded格式,虽然返回了200,但Moodle可能没正确解析form-data格式的参数,换成--data-urlencode更稳妥。 - 答案值无效:如果是单选题,
q24:1_answer传0大概率不是有效的选项编号(Moodle里选项编号一般从1开始),换成对应正确选项的数字试试。
不同题型的参数格式整理
我整理了Moodle常见题型对应的data参数格式,都是实际验证过的:
单选题(Single Correct Answer)
参数名:q{questionid}:{slot}_answer,值为选项的数字编号(比如选第一个选项传1)
示例:data[2][name]="q24:1_answer",data[2][value]="1"多选题(Multiple Correct Answers)
每个选中的选项单独传一个参数,参数名格式为q{questionid}:{slot}_answer[{optionnumber}],值设为1
示例:选第1和第3个选项时,传data[2][name]="q24:1_answer[1]"&data[2][value]="1"和data[3][name]="q24:1_answer[3]"&data[3][value]="1"判断题(True/False)
和单选题格式一致,值为1(对)或0(错),也可以用对应选项的编号,取决于题目设置排序题(Ordering)
参数名格式为q{questionid}:{slot}_answer[{itemnumber}],值为该项目的目标位置编号
示例:3个项目正确顺序是2→1→3,就传data[2][name]="q24:1_answer[1]"&data[2][value]="2"、data[3][name]="q24:1_answer[2]"&data[3][value]="1"、data[4][name]="q24:1_answer[3]"&data[4][value]="3"拖放填词(Drag-and-Drop Words into Sentences)
参数名格式为q{questionid}:{slot}_answer[{dropzoneid}],值为对应拖拽项的ID(需要先通过mod_quiz_get_attempt_data获取题目里的dropzone和draggable ID)
示例:data[2][name]="q24:1_answer[drop1]"&data[2][value]="drag2"简答题(Short Answer)
参数名:q{questionid}:{slot}_answer,值为你的回答文本
示例:data[2][name]="q24:1_answer",data[2][value]="Moodle API提交测试"论述题(Essay)
和简答题格式一致,值可以是长文本,支持HTML格式(如果题目允许的话)
修正后的cURL示例(以单选题为例)
curl --location '/webservice/rest/server.php' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'wstoken=*****' \ --data-urlencode 'wsfunction=mod_quiz_save_attempt' \ --data-urlencode 'attemptid=24' \ --data-urlencode 'data[0][name]=q24:1_:flagged' \ --data-urlencode 'data[0][value]=0' \ --data-urlencode 'data[1][name]=q24:1_:sequencecheck' \ --data-urlencode 'data[1][value]=3' # 替换为从mod_quiz_get_attempt_data获取的最新值 --data-urlencode 'data[2][name]=q24:1_answer' \ --data-urlencode 'data[2][value]=1' # 替换为正确的选项编号 --data-urlencode 'moodlewsrestformat=json'
额外注意事项
- 确保你的webservice token拥有
mod/quiz:attempt、mod/quiz:submit等必要权限,否则即使参数正确也会静默失败 - 调用
mod_quiz_get_attempt_data时,要传入attemptid,返回结果里的sequencecheck就是你需要的最新值 - 如果要提交整个测验的所有题目,需要把每个题目的参数都加到
data数组里,不要遗漏
备注:内容来源于stack exchange,提问作者Dhanu Kanakala

