如何使用JavaScript从本机客户端访问Magento API


9

我需要从基于本地JavaScript的应用程序(Titanium Desktop)访问Magento API,并想知道这样做的最佳方法是什么。

到目前为止,我发现了什么:

问题:

  • 将身份验证机制交换为带有应用程序密钥和机密的基于HMAC的身份验证是否可行?是否有经过验证的解决方案?
  • 如果没有,Magento是否可以执行OAuth用户代理流程?该文档没有提及它。
  • 是否可以使用AJAX提交用户凭据(此处不是跨域策略),以便向用户隐藏大部分授权过程?然后可以直接从响应中提取访问令牌。

好的,我发现我太关注REST了,尽管带JavaScript的SOAP有点麻烦,但是SOAP API应该可以解决我的问题。有一个Titanium库(github.com/kwhinnery/Suds),我将尝试一下并将结果发布在这里。
Fabian Schmengler,

Answers:


8

编辑:找到了更好的方法,请参阅下面的解决方案2

如评论中所述,SOAP API是必经之路。

解决方案1:

Suds为我工作时做了一些修改(使用Titanium.Network.HTTPClient代替XMLHttpRequest),但它只不过是为调用创建SOAP信封并返回整个XML响应而已。

概念验证实现,使用jQuery Deferred进行请求链接:

Service.MagentoClient = function()
{
    var self = this;
    var suds = new SudsClient({
        endpoint : "http://the-magento-host/api/v2_soap/",
        targetNamespace : "urn:Magento",
    });

    self.login = function() {
        var deferred = new $.Deferred();
        var args = {
            username : 'the-username',
            apiKey: 'the-api-key'
        };
        suds.invoke("login", args, function(xmlDoc) {
            self.sessionId = $(xmlDoc).find("loginReturn").text();
            deferred.resolve({});
            //TODO reject if no sessionid returned
        });
        return deferred;
    };

    self.setStatus = function(orderId, status, comment, notify) {
        var deferred = new $.Deferred();
        if (!self.sessionId) {
            deferred.reject({ error: 'Login not successful.' });
            return;
        }
        var args = {
            sessionId        : self.sessionId,
            orderIncrementId : orderId,
            status           : status,
            comment          : comment,
            notify           : notify
        }
        suds.invoke("salesOrderAddComment", args, function(xmlDoc) {
            var success = $(xmlDoc).find("salesOrderAddCommentResponse").text();
            if (success) {
                deferred.resolve({});
            } else {
                deferred.reject({ error: 'Update not successful.' });
            }

        });
        return deferred;
    };
};

用法示例:

        var magento = new Service.MagentoClient();
        magento.login().then(function() {
            magento.setStatus('100000029', 'complete', 'soap test');
        }).then(function() {
            alert('Update successful');
        }, function(reject) {
            alert('Update failed: ' + reject.error);
        });

解决方案2:

事实证明,编写自己的API适配器非常容易。举个例子这个核心hack(无效链接)我能够为基于的JSON-RPC适配器编写一个干净的模块Zend_Json_Server。它使用与SOAP和XML-RPC API相同的身份验证和ACL。

要使用入口点/api/jsonrpc,必须将新控制器添加到api路线:

<config>
    <frontend>
        <routers>
            <api>
                <args>
                    <modules>
                        <my_jsonrpc before="Mage_Api">My_JsonRpc_Api</my_jsonrpc>
                    </modules>
                </args>
            </api>
        </routers>
    </frontend>
</config>

更新02/2015:上面的链接现在不可用了,因此我将JSON-RPC适配器作为完整的扩展程序开源:https : //github.com/sgh-it/jsonrpc

我的JS客户端现在看起来像这样(再次使用JQuery.Deferred,但没有用于API的其他第三方库):

/**
 * Client for the Magento API
 */
Service.MagentoClient = function()
{
    var self = this;

    /**
     * @param string   method    the remote procedure to call
     * @param object   params    parameters for the RPC
     * @param callback onSuccess callback for successful request. Expects one parameter (decoded response object)
     * @param callback onError   callback for failed request. Expects one parameter (error message)
     * 
     * @return void
     */
    self.jsonRpc = function(method, params, onSuccess, onError) {
        var request = {
            method : method,
            params : params,
            jsonrpc : "2.0",
            id : 1
        };

        var options = {
            entryPoint : config.magentoClient.entryPoint,
            method: 'post',
            timeout: config.magentoClient.timeout
        };

        var httpClient = Titanium.Network.createHTTPClient();
        httpClient.onload = function(e) {
            try {
                var response = JSON.parse(this.responseText);
            } catch (jsonError) {
                return onError(jsonError);
            }
            if (response.error) {
                if (response.error.code == 5) { // session expired
                    self.sessionId = null;
                }
                return onError(response.error.message);
            }
            onSuccess(response);
        };
        httpClient.onerror = function(e) {
            onError(e.error + '; Response:' + this.responseText);
        };
        httpClient.setTimeout(options.timeout);

        if (httpClient.open(options.method, options.entryPoint)) {
            httpClient.setRequestHeader("Content-type", "application/json");
            httpClient.send(JSON.stringify(request));
        } else {
            onError('cannot open connection');
        }

    }
    /**
     * Retrieve session id for API
     * 
     * @return JQuery.Deferred deferred object for asynchronous chaining
     */
    self.login = function() {
        var deferred = new $.Deferred();
        if (self.sessionId) {
            deferred.resolve();
            return deferred;
        }
        var loginParams = config.magentoClient.login;
        try {
            self.jsonRpc('login', loginParams, function(response) {
                if (response && response.result) {
                    self.sessionId = response.result;
                    deferred.resolve();
                } else {
                    deferred.reject('Login failed.');
                }
            }, function(error) {
                deferred.reject(error);
            });
        } catch (rpcError) {
            deferred.reject(rpcError);
        }
        return deferred;
    };
    /**
     * Updates order states in Magento
     *
     * @param string method   name of the remote method
     * @param object args     arguments for the remote method
     * 
     * @return JQuery.Deferred deferred object for asynchronous chaining
     */
    self.call = function(method, args) {
        var deferred = new $.Deferred();
        if (!self.sessionId) {
            deferred.reject('No session.');
            return;
        }
        var callParams = {
            sessionId : self.sessionId,
            apiPath   : method,
            args      : args
        };
        try {
            self.jsonRpc('call', callParams, function(response) {
                deferred.resolve(response.result);
            }, function(error) {
                deferred.reject(error);
            });
        } catch (rpcError) {
            deferred.reject(rpcError);
        }

        return deferred;
    };
};

请注意,登录后的所有方法均通过路由call。的method参数是一样的东西sales_order.list,所述args参数阵列或物体与所述方法的参数。

用法示例:

        var filters = [];
        var magento = new Service.MagentoClient();
        magento.login().then(function() {
            magento.call('sales_order.list', [filters]).then(
                function(orders) {
                    // do something with the response
                }, function(error) {
                    alert('Magento API error: ' + error);
                }
            );
        });

如何在脚本中配置端点?
阿克拉莫(Akrramo)

您必须在中更改前端路由器的定义config.xml(如果您不想使用该api路由,也可以使用自定义路由,就像在任何其他Magento模块中那样定义它
Fabian Schmengler

我可以在magento中放置此代码的位置
er.irfankhan11 '16


而且JavaScript代码显然不属于Magento,而是属于外部客户端
Fabian Schmengler,2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.