Cách truy cập API Magento từ máy khách gốc bằng JavaScript


9

Tôi cần truy cập API Magento từ một ứng dụng dựa trên JavaScript cục bộ (Titanium Desktop) và tự hỏi đâu là cách tốt nhất để làm điều đó.

Những gì tôi phát hiện ra cho đến nay:

Câu hỏi:

  • Có khả thi để trao đổi cơ chế xác thực thành một cái gì đó như xác thực dựa trên HMAC với khóa ứng dụng và bí mật không? Có những giải pháp đã được chứng minh?
  • Nếu không, luồng tác nhân người dùng OAuth có khả thi với Magento không? Các tài liệu không đề cập đến nó.
  • Có thể gửi thông tin đăng nhập của người dùng bằng AJAX (Chính sách chéo nguồn gốc không phải là vấn đề ở đây) để ẩn hầu hết quy trình ủy quyền khỏi người dùng? Mã thông báo truy cập sau đó có thể được trích xuất trực tiếp từ phản hồi.

OK, tôi phát hiện ra rằng tôi đã quá tập trung vào REST, API SOAP sẽ giải quyết vấn đề của tôi, mặc dù SOAP với JavaScript khá cồng kềnh. Có một thư viện cho Titanium ( github.com/kwhinnery/Suds ), tôi sẽ dùng thử và đăng kết quả tại đây.
Fabian Schmengler

Câu trả lời:


8

Chỉnh sửa: Tìm thấy một cách tốt hơn, xem Giải pháp 2 bên dưới

Như đã đề cập trong bình luận, API SOAP là con đường để đi.

Giải pháp 1:

Suds hoạt động với tôi với một chút sửa đổi (Cách sử dụng Titanium.Network.HTTPClientthay vì XMLHttpRequest), nhưng nó không khác gì tạo ra một phong bì SOAP cho cuộc gọi và trả về toàn bộ phản hồi XML.

Triển khai Proof-of-Concept, sử dụng jQuery Trì hoãn cho chuỗi yêu cầu:

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;
    };
};

Ví dụ sử dụng:

        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);
        });

Giải pháp 2:

Hóa ra việc viết một bộ điều hợp API riêng có thể thực sự dễ dàng. Với ví dụ vềlõi-hack này(liên kết chết) Tôi đã có thể viết một mô-đun sạch cho bộ điều hợp JSON-RPC dựa trên Zend_Json_Server. Nó sử dụng cùng một Xác thực và ACL như các API SOAP và XML-RPC.

Để sử dụng điểm vào /api/jsonrpc, bộ điều khiển mới phải được thêm vào apituyến đường:

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

Cập nhật 02/2015: Liên kết trên đã chết, vì vậy tôi đã mở nguồn bộ điều hợp JSON-RPC của mình dưới dạng tiện ích mở rộng hoàn chỉnh: https://github.com/sgh-it/jsonrpc

Máy khách JS của tôi bây giờ trông như thế này (một lần nữa với JQuery.Deferred, nhưng không có thư viện bên thứ 3 bổ sung nào cho 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;
    };
};

Lưu ý rằng tất cả các phương thức sau khi đăng nhập được chuyển qua call. Các methodtham số là một cái gì đó giống như sales_order.list, các argstham số một mảng hoặc đối tượng với các đối số phương pháp.

Ví dụ sử dụng:

        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);
                }
            );
        });

Làm cách nào để định cấu hình điểm cuối trong tập lệnh của bạn?
Mohamed

Bạn phải thay đổi định nghĩa bộ định tuyến lối vào config.xml(nếu bạn không muốn sử dụng apituyến đường, bạn cũng có thể sử dụng tuyến tùy chỉnh thay vào đó, xác định nó như trong bất kỳ mô-đun Magento nào khác
Fabian Schmengler

Nơi tôi có thể đặt mã này trong magento
er.irfankhan11

Hướng dẫn cài đặt là có: github.com/sgh-it/jsonrpc
Fabian Schmengler 18/2/2016

Và mã JavaScript rõ ràng không thuộc về Magento mà thuộc về máy khách bên ngoài
Fabian Schmengler
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.