Android对接Magento 2 REST API:OAuth 1.0a授权POST请求技术问询
嘿,恭喜你已经通过Postman验证了Magento API的可用性!在Android里实现OAuth 1.0a签名其实没那么棘手,我给你分享两种实用方案——一种是用成熟的第三方库省事儿,另一种是手动实现核心逻辑帮你搞懂原理,你可以根据自己的需求选:
方案一:用第三方OAuth库快速实现(推荐)
手动写签名容易踩编码、排序的坑,用现成的库能省不少时间。这里推荐Signpost,它是专门处理OAuth 1.0a的Java库,Android上也能完美适配。
步骤1:引入依赖
在你的app/build.gradle(Module级别)里添加依赖:
// 核心库 implementation 'oauth.signpost:signpost-core:1.2.1.2' // 如果用HttpURLConnection,加这个 implementation 'oauth.signpost:signpost-commonshttp4:1.2.1.2' // 如果用OkHttp,也有对应的适配包 // implementation 'com.github.openintents:signpost-okhttp:1.2.1.2'
步骤2:初始化OAuth凭证
用你从Magento拿到的Consumer Key、Consumer Secret、Access Token、Access Token Secret初始化消费者:
OAuthConsumer consumer = new CommonsHttpOAuthConsumer( "你的Consumer Key", "你的Consumer Secret" ); // 设置访问令牌 consumer.setTokenWithSecret( "你的Access Token", "你的Access Token Secret" );
步骤3:签名并发送POST请求
这里以HttpURLConnection为例,发送一个创建产品的请求:
try { URL apiUrl = new URL("https://你的Magento域名/rest/V1/products"); HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection(); // 配置请求 connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/json"); connection.setDoOutput(true); // 关键:对请求进行OAuth签名 consumer.sign(connection); // 写入POST请求体(Magento要求的JSON格式) String requestBody = "{\"product\": {\"sku\": \"test-android-sku\", \"name\": \"Android测试产品\", \"price\": 29.99}}"; try (OutputStream os = connection.getOutputStream()) { byte[] input = requestBody.getBytes(StandardCharsets.UTF_8); os.write(input, 0, input.length); } // 处理响应 int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { try (BufferedReader br = new BufferedReader( new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { StringBuilder response = new StringBuilder(); String responseLine; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } Log.d("MagentoAPI", "请求成功:" + response.toString()); } } else { Log.e("MagentoAPI", "请求失败,响应码:" + responseCode); } } catch (Exception e) { e.printStackTrace(); }
方案二:手动实现OAuth 1.0a签名(理解原理)
如果你想搞清楚OAuth 1.0a的签名逻辑,可以手动实现核心步骤。OAuth 1.0a签名的核心是HMAC-SHA1加密签名基字符串,步骤如下:
核心代码实现
import android.util.Base64; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.TreeMap; import java.util.UUID; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; // 生成OAuth Authorization头的方法 private String generateOAuthHeader(String apiUrl, String requestMethod, String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret) throws Exception { // 1. 生成随机Nonce和秒级时间戳 String nonce = UUID.randomUUID().toString().replace("-", ""); long timestamp = System.currentTimeMillis() / 1000; // 2. 收集所有需要签名的参数(按字典序排序) Map<String, String> oauthParams = new TreeMap<>(); oauthParams.put("oauth_consumer_key", consumerKey); oauthParams.put("oauth_nonce", nonce); oauthParams.put("oauth_signature_method", "HMAC-SHA1"); oauthParams.put("oauth_timestamp", String.valueOf(timestamp)); oauthParams.put("oauth_token", accessToken); oauthParams.put("oauth_version", "1.0"); // 3. 构建签名基字符串 String baseString = requestMethod.toUpperCase() + "&" + URLEncoder.encode(apiUrl, "UTF-8") + "&" + URLEncoder.encode(buildParamString(oauthParams), "UTF-8"); // 4. 生成签名密钥 String signingKey = URLEncoder.encode(consumerSecret, "UTF-8") + "&" + URLEncoder.encode(accessTokenSecret, "UTF-8"); // 5. HMAC-SHA1加密生成签名 SecretKeySpec keySpec = new SecretKeySpec(signingKey.getBytes("UTF-8"), "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(keySpec); byte[] signatureBytes = mac.doFinal(baseString.getBytes("UTF-8")); String signature = Base64.encodeToString(signatureBytes, Base64.NO_WRAP); // 6. 拼接Authorization头 StringBuilder headerBuilder = new StringBuilder("OAuth "); for (Map.Entry<String, String> entry : oauthParams.entrySet()) { if (headerBuilder.length() > 6) headerBuilder.append(", "); headerBuilder.append(entry.getKey()).append("=\"") .append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("\""); } headerBuilder.append(", oauth_signature=\"").append(URLEncoder.encode(signature, "UTF-8")).append("\""); return headerBuilder.toString(); } // 拼接参数为URL编码的字符串 private String buildParamString(Map<String, String> params) throws UnsupportedEncodingException { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (sb.length() > 0) sb.append("&"); sb.append(URLEncoder.encode(entry.getKey(), "UTF-8")) .append("=") .append(URLEncoder.encode(entry.getValue(), "UTF-8")); } return sb.toString(); }
使用示例(搭配OkHttp)
try { String apiUrl = "https://你的Magento域名/rest/V1/products"; String oAuthHeader = generateOAuthHeader(apiUrl, "POST", "你的Consumer Key", "你的Consumer Secret", "你的Access Token", "你的Access Token Secret"); OkHttpClient client = new OkHttpClient(); MediaType jsonMediaType = MediaType.parse("application/json; charset=utf-8"); RequestBody requestBody = RequestBody.create(jsonMediaType, "{\"product\": {\"sku\": \"test-manual-sku\", \"name\": \"手动签名测试产品\", \"price\": 39.99}}"); Request request = new Request.Builder() .url(apiUrl) .post(requestBody) .addHeader("Authorization", oAuthHeader) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { Log.d("MagentoAPI", "手动签名请求成功:" + response.body().string()); } else { Log.e("MagentoAPI", "手动签名请求失败,响应码:" + response.code()); } } }); } catch (Exception e) { e.printStackTrace(); }
关键注意事项
- URL编码必须正确:所有参数和签名基字符串都要用UTF-8编码,否则Magento会拒绝请求。
- 时间戳是秒级:必须用当前时间的秒数,不能用毫秒,否则签名会无效。
- Nonce必须唯一:每次请求都要生成新的随机字符串,不能重复使用。
- JSON请求体无需加入签名:Magento的REST API接受JSON格式的POST体,OAuth 1.0a默认只对URL参数和OAuth参数签名,不需要把JSON内容加入签名逻辑。
内容的提问来源于stack exchange,提问作者vmp
相关产品推荐
相关产品推荐

