วิธีเข้าถึง Magento API จากไคลเอ็นต์ดั้งเดิมด้วย JavaScript


9

ฉันจำเป็นต้องเข้าถึง Magento API จากแอปพลิเคชันที่ใช้ JavaScript ในท้องถิ่น (Titanium Desktop) และสงสัยว่าจะทำอย่างไรดีที่สุด

สิ่งที่ฉันพบ:

  • กลไกการรับรองความถูกต้องเพียงอย่างเดียวคือ OAuth ดังนั้นผู้ใช้จะต้องป้อนข้อมูลประจำตัวของพวกเขาบนเว็บไซต์
  • มีห้องสมุดไคลเอนต์ JavaScript: https://code.google.com/p/oauth/source/browse/#svn%2Fcode%2Fjavascript
  • สำหรับแอปดั้งเดิมที่เป็นไคลเอนต์OAuthแนะนำให้ใช้ OAuth 2 User Agent Flow
  • URL การเปลี่ยนเส้นทางจะต้องชี้ไปที่หน้าเว็บท้องถิ่นซึ่งจะต้องแยกโทเค็นหรือคัดลอก & วาง

คำถาม:

  • เป็นไปได้ไหมที่จะแลกเปลี่ยนกลไกการพิสูจน์ตัวตนกับการรับรองความถูกต้องที่อิง HMAC ด้วยแอปพลิเคชันและความลับ แม้จะมีวิธีการแก้ปัญหาที่พิสูจน์แล้ว?
  • ถ้าไม่เป็นเช่นนั้น OAuth User Agent Flow นั้นสามารถใช้กับ Magento ได้หรือไม่? เอกสารไม่ได้กล่าวถึง
  • เป็นไปได้ไหมที่จะส่งข้อมูลรับรองผู้ใช้กับ AJAX (Cross-Origin-Policy ไม่ใช่ปัญหาที่นี่) เพื่อซ่อนขั้นตอนการอนุญาตส่วนใหญ่จากผู้ใช้ โทเค็นการเข้าถึงสามารถถูกดึงโดยตรงจากการตอบสนอง

ตกลงฉันพบว่าฉันให้ความสำคัญกับ REST เกินไป SOAP API ควรแก้ปัญหาของฉันได้แม้ว่า SOAP กับ JavaScript จะค่อนข้างยุ่งยาก มีห้องสมุดสำหรับ Titanium ( github.com/kwhinnery/Suds ) ฉันจะลองและโพสต์ผลลัพธ์ที่นี่
Fabian Schmengler

คำตอบ:


8

แก้ไข: พบวิธีที่ดีกว่าดูโซลูชัน 2 ด้านล่าง

ตามที่ระบุไว้ในความคิดเห็น SOAP API เป็นวิธีที่จะไป

โซลูชันที่ 1:

Sudsทำงานให้ฉันด้วยการปรับเปลี่ยนเล็กน้อย (การใช้งานTitanium.Network.HTTPClientแทนXMLHttpRequest) แต่มันไม่มากไปกว่าการสร้างซองจดหมาย SOAP สำหรับการโทรและการตอบกลับ XML ทั้งหมด

การนำ Proof-of-Concept ไปใช้โดยใช้ 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 ของตัวเองนั้นง่ายมาก ด้วยตัวอย่างของcore-hack นี้(ลิงค์ตาย) ฉันก็สามารถที่จะเขียนโมดูลสะอาดสำหรับอะแดปเตอร์ JSON-RPC Zend_Json_Serverอยู่บนพื้นฐานของ มันใช้การรับรองความถูกต้องและ ACL เช่นเดียวกับ SOAP และ XML-RPC API

ในการใช้จุดเริ่มต้น/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

ที่ฉันสามารถวางรหัสนี้ในวีโอไอพี
er.irfankhan11

มีคำแนะนำในการติดตั้ง: github.com/sgh-it/jsonrpc
Fabian Schmengler

และรหัส JavaScript เห็นได้ชัดว่าไม่ได้อยู่ใน Magento แต่ในไคลเอนต์ภายนอก
Fabian Schmengler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.