You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:33:03