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.HTTPClient
thay 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 api
tuyế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 method
tham số là một cái gì đó giống như sales_order.list
, các args
tham 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);
}
);
});