return FALSE; $r = well_tag_thread__update(array('id' => $id), $update); return $r; } function well_tag_thread_find($tagid, $page, $pagesize) { $arr = well_tag_thread__find(array('tagid' => $tagid), array('id' => -1), $page, $pagesize); return $arr; } function well_tag_thread_find_by_tid($tid, $page, $pagesize) { $arr = well_tag_thread__find(array('tid' => $tid), array(), $page, $pagesize); return $arr; } ?>php - Moodle External Web Services - Request parameters are not correctly received - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - Moodle External Web Services - Request parameters are not correctly received - Stack Overflow

programmeradmin2浏览0评论

Context

I am building an custom api to receive data from a salesforce platform in order to synchronise job openings on our moodle platform.

The idea is simply: salesforce has a manual request that will send the job data to moodle, which will handle the data.

The issue

When I try to test the request (using Postman) I am getting an error that seems to come from the parameter validation. According to the message, my data is not having the property "data" that has a single structure (associative array) as value.

My custom plugin:

db/services.php

<?php

/**
 * ...
 */

$functions = [
    'local_jobboard_receive_salesforce_data' => [
        'classname'   => 'local_jobboard_external',
        'methodname'  => 'receive_salesforce_data',
        'classpath'   => 'local/jobboard/externallib.php',
        'description' => 'Receives job data from Salesforce and saves it in the database.',
        'type'        => 'write',
        'ajax'        => false,
        'capabilities' => '',
    ]
];

$services = [
    'JobBoard API' => [
        'functions' => ['local_jobboard_receive_salesforce_data'],
        'restrictedusers' => 1,
        'enabled' => 1,
        'shortname' => 'jobboardapi'
    ]
];

externallib.php

<?php

/**
 * ...
 */

use core\exception\invalid_parameter_exception;
use stdClass;

defined('MOODLE_INTERNAL') || die();
require_once("$CFG->libdir/externallib.php");

class local_jobboard_external extends external_api
{
    public static function receive_salesforce_data_parameters()
    {
        return new external_function_parameters(
            array(
                'data' => new external_single_structure(
                    array(
                        'title'       => new external_value(PARAM_TEXT, 'Job title'),
                        'description' => new external_value(PARAM_RAW, 'Job description in markdown or HTML'),
                        'company'     => new external_value(PARAM_TEXT, 'Company name'),
                        'location'    => new external_value(PARAM_TEXT, 'Work location (Hybrid, Online, Office)', VALUE_OPTIONAL),
                        'deadline'    => new external_value(PARAM_INT, 'Application deadline (Unix timestamp)'),
                        'type'        => new external_value(PARAM_ALPHANUMEXT, 'Type (job or internship)'),
                        'note'        => new external_value(PARAM_TEXT, 'HR or Account manager notes', VALUE_OPTIONAL),
                        'tags'        => new external_value(PARAM_TEXT, 'Comma-separated skill tags'),
                        'targets'     => new external_multiple_structure(new external_value(PARAM_TEXT, 'Target categories'))
                    )
                )
            )
        );
    }

    public static function receive_salesforce_data($data)
    {
        global $DB;

        $rawInput = $data;
        error_log("[Salesforce API] Raw Input: " . $rawInput);

        $decoded_data = json_decode($rawInput, true);

        if (json_last_error() !== JSON_ERROR_NONE || !is_array($decoded_data)) {
            error_log("[Salesforce API] Invalid JSON format.");
            throw new invalid_parameter_exception('Invalid JSON format.');
        }

        if (!isset($decoded_data['data'])) {
            $decoded_data = ['data' => $decoded_data];
        }

        $params = self::validate_parameters(self::receive_salesforce_data_parameters(), $decoded_data);

        error_log("[Salesforce API] Parsed Params: " . json_encode($params));

        // .. rest of the logic
    }

    public static function receive_salesforce_data_returns()
    {
        return new external_single_structure(
            array(
                'status' => new external_value(PARAM_TEXT, 'Success status'),
                'message' => new external_value(PARAM_TEXT, 'Response message')
            )
        );
    }

    // other methods
}

My request header also has the content-type set to application/json.

Is there any reason for my request to fail? I am a bit at a loss here.

Thanks in advance!

Context

I am building an custom api to receive data from a salesforce platform in order to synchronise job openings on our moodle platform.

The idea is simply: salesforce has a manual request that will send the job data to moodle, which will handle the data.

The issue

When I try to test the request (using Postman) I am getting an error that seems to come from the parameter validation. According to the message, my data is not having the property "data" that has a single structure (associative array) as value.

My custom plugin:

db/services.php

<?php

/**
 * ...
 */

$functions = [
    'local_jobboard_receive_salesforce_data' => [
        'classname'   => 'local_jobboard_external',
        'methodname'  => 'receive_salesforce_data',
        'classpath'   => 'local/jobboard/externallib.php',
        'description' => 'Receives job data from Salesforce and saves it in the database.',
        'type'        => 'write',
        'ajax'        => false,
        'capabilities' => '',
    ]
];

$services = [
    'JobBoard API' => [
        'functions' => ['local_jobboard_receive_salesforce_data'],
        'restrictedusers' => 1,
        'enabled' => 1,
        'shortname' => 'jobboardapi'
    ]
];

externallib.php

<?php

/**
 * ...
 */

use core\exception\invalid_parameter_exception;
use stdClass;

defined('MOODLE_INTERNAL') || die();
require_once("$CFG->libdir/externallib.php");

class local_jobboard_external extends external_api
{
    public static function receive_salesforce_data_parameters()
    {
        return new external_function_parameters(
            array(
                'data' => new external_single_structure(
                    array(
                        'title'       => new external_value(PARAM_TEXT, 'Job title'),
                        'description' => new external_value(PARAM_RAW, 'Job description in markdown or HTML'),
                        'company'     => new external_value(PARAM_TEXT, 'Company name'),
                        'location'    => new external_value(PARAM_TEXT, 'Work location (Hybrid, Online, Office)', VALUE_OPTIONAL),
                        'deadline'    => new external_value(PARAM_INT, 'Application deadline (Unix timestamp)'),
                        'type'        => new external_value(PARAM_ALPHANUMEXT, 'Type (job or internship)'),
                        'note'        => new external_value(PARAM_TEXT, 'HR or Account manager notes', VALUE_OPTIONAL),
                        'tags'        => new external_value(PARAM_TEXT, 'Comma-separated skill tags'),
                        'targets'     => new external_multiple_structure(new external_value(PARAM_TEXT, 'Target categories'))
                    )
                )
            )
        );
    }

    public static function receive_salesforce_data($data)
    {
        global $DB;

        $rawInput = $data;
        error_log("[Salesforce API] Raw Input: " . $rawInput);

        $decoded_data = json_decode($rawInput, true);

        if (json_last_error() !== JSON_ERROR_NONE || !is_array($decoded_data)) {
            error_log("[Salesforce API] Invalid JSON format.");
            throw new invalid_parameter_exception('Invalid JSON format.');
        }

        if (!isset($decoded_data['data'])) {
            $decoded_data = ['data' => $decoded_data];
        }

        $params = self::validate_parameters(self::receive_salesforce_data_parameters(), $decoded_data);

        error_log("[Salesforce API] Parsed Params: " . json_encode($params));

        // .. rest of the logic
    }

    public static function receive_salesforce_data_returns()
    {
        return new external_single_structure(
            array(
                'status' => new external_value(PARAM_TEXT, 'Success status'),
                'message' => new external_value(PARAM_TEXT, 'Response message')
            )
        );
    }

    // other methods
}

My request header also has the content-type set to application/json.

Is there any reason for my request to fail? I am a bit at a loss here.

Thanks in advance!

Share Improve this question edited Mar 20 at 7:20 VLAZ 29.1k9 gold badges63 silver badges84 bronze badges asked Mar 19 at 16:12 BasileBasile 1721 silver badge14 bronze badges 2
  • I don't deal with Moodle a lot, so I'm just shooting in the dark a bit. You are sending an object with a single key called data. Have you tried wrapping that in one additional array: 3v4l./mOk52 – Chris Haas Commented Mar 19 at 17:49
  • @ChrisHaas That is what I also thought, so I added the json decoder with associative to true as a second argument to tranform the object in an associative array, and then I make a condition to make sure that it does have the format $decoded_data = ["data" => [...]]. but maybe i'm overlooking something? 3v4l./IbOX2 – Basile Commented Mar 19 at 21:45
Add a comment  | 

1 Answer 1

Reset to default 0

Moodle rest webservice calls usually expect all of the data to be passed as URL parameters, it doesn't look at the body of any request.

So, it would need to look something like:

http://localhost/webservice/rest/server.php?wstoken=xxx&wsfunction=local_jobsboard_recieve_salesforce_data&wsmoodlerestoformat=json&data['title']=Software%20Engineer&data['description']=We%20are%20looking%20for%20a

etc.

Note that wsmoodlerestformat is there to specify the response format, not the format of the data accepted.

There are a couple of 3rd-party plugins out there that add new webservice protocols that allow the content to be included as JSON in the body of the request:

  • https://moodle./plugins/webservice_restful - officially supports Moodle 4.4 (so not quite the latest Moodle 4.5, at the time of writing, but should still work)

  • https://moodle./plugins/webservice_restjson - only supports Moodle 2.9, has not been updated in 9 years (at the time of writing), so may have problems with recent versions of Moodle

发布评论

评论列表(0)

  1. 暂无评论