快工助手跨境电商知识与商机助手

授权与鉴权

Shopee 官方资料 · Shopee Open Platform 开发者指南 · 适合开发者

stable本次发布有变化全部展示

来自 Shopee 官方资料快照 ·

打开官方原文 ↗
  1. 当前资料结构化阅读页
  2. 固定快照已留存,可追溯
  3. 官方原文可核对
查看技术与溯源信息
平台 / profile
Shopee / profile.shopee.developer_guide
语言
zh-Hans
发布版本
cn-20260909-2
标签
zhuge/sourceplatform/shopeeaudience/developercategory/api_doctopic/apitopic/developertopic/getting-started

资料正文

§1 授权与鉴权

授权是使用 Open API 的必要流程,卖家需将操作店铺的权限授予开发者。只有在获得卖家授权后,您的 App 才能调用除公共接口之外的接口。

Open API 会根据您传入的公共参数进行鉴权。若鉴权不通过,API 调用将失败并返回相应报错信息。

⚠️ 注意每次授权的有效期最长可设置为 365 天,卖家可在授权时自定义授权到期时间。授权到期后,您需要联系卖家重新授权您的 App。若CB SIP主店铺向应用授予授权,所有 SIP 关联店铺将自动获得该应用授权,但关联店铺的 API 调用权限有限,详情可见FAQ
#

§2 授权流程

授权流程包含 3个核心步骤:生成授权链接、获取店铺授权、获取及刷新访问令牌(access_token)。以下将详细说明授权前准备、流程细节及如何使用返回信息完成平台认证。

#

§3 生成授权链接

生成授权链接

为提升对接效率,平台提供了新的授权链接生成方式。授权链接由固定授权 URL 和授权参数拼接而成,所有类型的应用均可按以下规范生成授权链接。

注:对于卖家自研(Seller In House System) App,直接登陆开放平台> 进入App list>点击 “Authorize”>填写 redirect URL 生成授权链接

对于所有类型App,要实现v2店铺授权,开发者需要根据下列规范创建一个授权链接,授权链接是由固定授权url和其他所需参数拼接而成。

固定授权URL:

环境地区URL
生产环境全球(不含中国大陆及巴西)https://open.shopee.com/auth
中国大陆https://open.shopee.cn/auth
巴西https://open.shopee.com.br/auth
沙箱测试环境全球(不含中国大陆及巴西)https://open.sandbox.test-stable.shopee.com/auth
中国大陆https://open.sandbox.test-stable.shopee.cn/auth
巴西https://open.sandbox.test-stable.shopee.com.br/auth

其他所需参数:

参数名称类型是否必填描述
partner_idint应用的合作方 ID,由 Shopee 开放平台分配。
auth_typestring需授权的角色类型,枚举值如下:- seller:授权shop或merchant时选择;- supplier:授权供应商时选择(适用于 SCS 用户);- user:授权用户时选择(适用于直播类型应用,详见https://open.shopee.com/announcements/1190 )。
redirect_uristring卖家完成授权后接收授权码(code)的 URL。生产环境:若当前应用的生产环境回调 URL 域名为空,则不校验 redirect_uri 域名;若不为空,则需与应用的生产环境回调 URL 域名一致;沙箱测试环境:若当前应用的测试环境回调 URL 域名为空,则不校验 redirect_uri 域名;若不为空,则需与应用的测试环境回调 URL 域名一致。
response_typestring授权类型,固定值为 "code"。
statestring用于防范跨站请求伪造攻击的随机字符串(不可猜测),授权完成后原值将回调至 redirect_uri。
#

§4 域名校验要求

域名校验要求

为保障卖家数据安全,平台对授权链接中的回调地址(redirect URL)新增域名校验。所有开发者需在控制台(Console)为每个应用申报测试环境回调 URL 域名(Test Redirect URL Domain)和生产环境回调 URL 域名(Live Redirect URL Domain)。

上述参数中的redirect_uri为开发者在app信息中填写的回调地址,查看方式如下:

域名校验注意事项

  • 对于已创建但未申报回调 URL 域名的应用,开发者需尽快登录控制台,进入应用编辑页完成申报。申报完成前,平台暂不执行域名校验,不影响现有授权流程;
  • 若生成授权链接时传入的 redirect_uri(或旧链接中的 redirect)对应的域名与控制台申报域名不一致,将返回错误:"The domain of redirect_uri is not consistent with the Redirect URL Domain declared in console"(回调地址域名与控制台申报的回调 URL 域名不一致)。
#

§5 授权链接示例

#

§6 卖家登陆授权

卖家登陆授权

将授权链接分享给卖家后,卖家需登录账号完成授权流程。

账号类型:

  • 店铺账号授权单个店铺
  • 使用主账号授权多个商家 / 店铺 (子账号无法登录授权页面).
#

§7 Shop account授权

Shop account授权

1、卖家输入账号、密码,点击 “Log In”;

2、卖家输入手机接收的验证码,点击 “Verify”;

3、登录后,卖家在授权页面点击 “Confirm Authorization”;

4、系统将弹出授权期限选择器,卖家可选择预设期限(7 天、30 天、90 天、180 天、365 天),或选择 “自定义到期时间” 设置 365 天内的任意日期;

5、授权完成后,前端页面将跳转至授权链接中指定的 redirect_uri,并附带授权码(code)和店铺 ID(shop_id):https://open.shopee.com/?code=xxxxxxxxxx&shop_id=xxxxxx

#

§8 Main account授权

Main account授权

1、登录页面中,点击 “Switch to Sub Account” 以主账号登录;

2、输入主账号账号、密码,点击 “Log In”;

3、展开商家店铺列表,选择需授权的店铺。跨境卖家如需调用Merchant API,需提醒卖家勾选 “授权商家”(Auth Merchant)复选框;

4、若未勾选授权框,将弹出提醒窗口;

5、点击确认授权,完成操作。

6、授权完成后,前端页面将跳转至授权链接中指定的 redirect_uri,并附带授权码(code)和主账号 ID(main_account_id):https://open.shopee.com/?code=xxxxxx&main_account_id=xxxxxx

#

§9 获取及使用code

获取及使用code

卖家完成授权后,前端页面将跳转至授权链接中指定的 redirect_uri,并附带授权码(code)和shop_id/main_account_id,以main_account_id为例:https://open.shopee.com/?code=xxxxxx&main_account_id=xxxxxx

您可通过该 授权码(code) 获取首次访问令牌(access_token)。

#

§10 跳转 URL 中的返回参数

跳转 URL 中的返回参数

参数名称类型描述
codestring调用成功时返回,用于获取access_token和refresh_token。仅一次有效,10分钟后过期。
shop_idint本次授权给开发者的店铺shop_id。使用店铺账号授权后返回。
main_account_idint本次授权给开发者的主账号main_account_id。使用主账号授权后返回。

注:若生成授权链接时传入的 redirect_uri(或旧链接中的 redirect)对应的域名与控制台申报域名不一致,将返回错误:"The domain of redirect_uri is not consistent with the Redirect URL Domain declared in console"(回调地址域名与控制台申报的回调 URL 域名不一致)。

#

§11 获取与刷新access_token

获取与刷新access_token

access_token 是调用非公共 API 必需的动态令牌,有效期为 4 小时,有效期内可多次使用。需在过期前通过 refresh_token 调用刷新访问令牌 API(RefreshAccessToken)获取新的 access_token,refresh_token 有效期为 30 天。

⚠️ 注意事项

  • 每个 shop_id /merchant_id/user_id/supplier_id 对应的 access_token 和 refresh_token 需单独存储;
  • 新 access_token 生成后,旧 access_token 仍可有效 5 分钟;
  • 重新授权将触发 refresh_token 和 access_token 刷新;
  • 需在授权有效期内调用 RefreshAccessToken API。
  • 如果丢失了最新可用的refresh_token和access_token,请查看此FAQ
#

§12 GetAccesstoken

GetAccesstoken

授权成功后,使用跳转 URL 中的 code 及 shop_id(或 main_account_id)调用该 API,获取 shop_id、merchant_id、access_token 和 refresh_token。

路径:https://partner.shopeemobile.com/api/v2/auth/token/get

https://openplatform.sandbox.test-stable.shopee.sg/api/v2/auth/token/get (沙箱测试环境)

请求方式: Post

公共参数:

参数名称类型是否必填描述
signstring根据sign base string以partner key作为加密key通过HMAC-SHA256哈希得出的签名。
partner_idint从APP中获取到的partner_id,此partner_id放入query。
timestampint时间戳,有效期为5分钟。

业务参数:

参数名称类型是否必填描述
codestring授权后位于redirect URL中的code。仅一次性有效,10分钟后过期。
partner_idint从APP中获取到的partner_id,此partner_id放入body。
shop_idint条件必填授权给开发者的主账号shop_id,只能选shop_id或main_account_id中的一个作为入参。
main_account_idint条件必填授权给开发者的主账号main_account_id,只能选shop_id或main_account_id中的一个作为入参。

返回参数:

参数名称类型描述
request_idstring必返回,每个接口请求的ID,用于定位问题。
errorstring必返回,错误码,当调用成功时返回为空。
refresh_tokenstring调用成功时返回,使用refresh_token去获取新的access_token。针对每个shop_id和merchant_id分别有效,有效期为30天。
access_tokenstring调用成功时返回,动态令牌,可多次使用,4小时后过期。
expire_inint调用成功时返回,access_token有效时间,单位:秒。
messagestring必返回,详细报错信息。
merchant_id_listint[ ]当入参中有main_account_id时返回,包括main account下本次授权的所有merchant_id。
shop_id_listint[ ]当入参中有main_account_id时返回,包括main account下本次授权的所有shop_id。
supplier_id_listint[]auth_type=supplier时返回
user_id_listint[]auth_type=user时返回

计算sign

Sign是每次调用时用来鉴权的参数,此部分将会解释如何通过HMAC-SHA256生成作为公共参数用于鉴权的签名。

创建sign base string:

目前共有三类接口需要用不同的参数创建sign base string(与其公共参数一致):

按照先后次序, 将api path(不带host) 和下列公共参数拼接为单一字符串,即sign base string:

Shop APIs: partner_id, api path, timestamp, access_token, shop_id

Merchant APIs: partner_id, api path, timestamp, access_token, merchant_id

Public APIs: partner_id, api path, timestamp

鉴权签名计算:

使用HMAC-SHA256对sign base string进行哈希,partner key作为加密key,得出16进制全小写的哈希值即为鉴权签名。

Python Code Demo:

import hmac
import json
import time
import requests
import hashlib


def shop_auth():
    timest = int(time.time())
    host = "https://partner.shopeemobile.com"
    path = "/api/v2/shop/auth_partner"
    redirect_url = "https://www.baidu.com/"
    partner_id = 80001
    tmp = "test...."
    partner_key = tmp.encode()
    tmp_base_string = "%s%s%s" % (partner_id, path, timest)
    base_string = tmp_base_string.encode()
    sign = hmac.new(partner_key, base_string, hashlib.sha256).hexdigest()
    ##generate api
    url = host + path + "?partner_id=%s&timestamp=%s&sign=%s&redirect=%s" % (partner_id, timest, sign, redirect_url)
    print(url)

Go Code Demo:

func auth_shop(){
	timest := strconv.FormatInt(time.Now().Unix(),10)
	host := "https://partner.test.shopeemobile.com"
	path := "/api/v2/shop/auth_partner"
	redirectUrl := "https://www.baidu.com/"
	partnerId := strconv.Itoa(2006566)
	partnerKey := "1391fd986fe8ec7569bebed75b0c33ee35eb5a305bed7038657a5cd5f75b1c88"
	baseString := fmt.Sprintf("%s%s%s", partnerId,path,timest)
	h := hmac.New(sha256.New,[]byte(partnerKey))
	h.Write([]byte(baseString))
	sign := hex.EncodeToString(h.Sum(nil))
	url := fmt.Sprintf(host+path+"?partner_id=%s&timestamp=%s&sign=%s&redirect=%s", partnerId,timest,sign, redirectUrl)
	fmt.Println(url)
}

Java Code Demo:

    //generate auth url
    public static void shop_auth(){
        long timest = System.currentTimeMillis() / 1000L;
        String host = "https://partner.shopeemobile.com";
        String path = "/api/v2/shop/auth_partner";
        String redirect_url = "https://www.baidu.com/";
        long partner_id = 123456L;
        String tmp_partner_key = "...";
        String tmp_base_string = String.format("%s%s%s", partner_id, path, timest);
        byte[] partner_key;
        byte[] base_string;
        String sign = "";
        try {
            base_string = tmp_base_string.getBytes("UTF-8");
            partner_key = tmp_partner_key.getBytes("UTF-8");
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(partner_key, "HmacSHA256");
            mac.init(secret_key);
            sign = String.format("%064x",new BigInteger(1,mac.doFinal(base_string)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String url = host + path + String.format("?partner_id=%s&timestamp=%s&sign=%s&redirect=%s", partner_id,timest, sign, redirect_url);
        System.out.println(url);
    }

PHP Code Demo:

<?php 


function authShop($partnerId, $partnerKey) {   
    global $host;
    $path = "/api/v2/shop/auth_partner";
    $redirectUrl = "https://www.baidu.com/";

    $timest = time();
    $baseString = sprintf("%s%s%s", $partnerId, $path, $timest);
    $sign = hash_hmac('sha256', $baseString, $partnerKey);
    $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s&redirect=%s", $host, $path, $partnerId, $timest, $sign, $redirectUrl);
    return $url;
}

$host="https://partner.shopeemobile.com";

$partnerId = 847892;
$partnerKey = "57615053704d6470644f554a78656d50484143644964436a5568777544524579";

echo authShop($partnerId, $partnerKey);
?>

GetAccesstoken Demo

Python Code Demo:

print(shop_auth())
# first time request token
def get_token_shop_level(code, partner_id, tmp_partner_key, shop_id):
    timest = int(time.time())
    host = "https://partner.shopeemobile.com"
    path = "/api/v2/auth/token/get"
    body = {"code": code, "shop_id": shop_id, "partner_id": partner_id}
    tmp_base_string = "%s%s%s" % (partner_id, path, timest)
    base_string = tmp_base_string.encode()
    partner_key = tmp_partner_key.encode()
    sign = hmac.new(partner_key, base_string, hashlib.sha256).hexdigest()
    url = host + path + "?partner_id=%s&timestamp=%s&sign=%s" % (partner_id, timest, sign)
    # print(url)
    headers = {"Content-Type": "application/json"}
    resp = requests.post(url, json=body, headers=headers)
    ret = json.loads(resp.content)
    access_token = ret.get("access_token")
    new_refresh_token = ret.get("refresh_token")
    return access_token, new_refresh_token


def get_token_account_level(code, partner_id, tmp_partner_key, main_account_id):
    timest = int(time.time())
    host = "https://partner.test.shopeemobile.com"
    path = "/api/v2/auth/token/get"
    body = {"code": code, "main_account_id": main_account_id, "partner_id": partner_id}
    tmp_base_string = "%s%s%s" % (partner_id, path, timest)
    base_string = tmp_base_string.encode()
    partner_key = tmp_partner_key.encode()
    sign = hmac.new(partner_key, base_string, hashlib.sha256).hexdigest()
    url = host + path + "?partner_id=%s&timestamp=%s&sign=%s" % (partner_id, timest, sign)

    headers = {"Content-Type": "application/json"}
    resp = requests.post(url, json=body, headers=headers)
    ret = json.loads(resp.content)
    access_token = ret.get("access_token")
    new_refresh_token = ret.get("refresh_token")
    return access_token, new_refresh_token

Java Code Demo:

import com.alibaba.fastjson.JSONObject;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.HashMap;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import com.alibaba.fastjson.JSON;


public class shop_auth {
    public static void main(String[] args) throws ParseException, IOException {
        shop_auth();
        //get_token_shop_level(code,partner_id,partner_key,shop_id);
    }
    //generate auth url
    public static void shop_auth(){
        long timest = System.currentTimeMillis() / 1000L;
        String host = "https://partner.shopeemobile.com";
        String path = "/api/v2/shop/auth_partner";
        String redirect_url = "https://www.baidu.com/";
        long partner_id = 123456L;
        String tmp_partner_key = "...";
        String tmp_base_string = String.format("%s%s%s", partner_id, path, timest);
        byte[] partner_key;
        byte[] base_string;
        String sign = "";
        try {
            base_string = tmp_base_string.getBytes("UTF-8");
            partner_key = tmp_partner_key.getBytes("UTF-8");
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(partner_key, "HmacSHA256");
            mac.init(secret_key);
            sign = String.format("%064x",new BigInteger(1,mac.doFinal(base_string)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String url = host + path + String.format("?partner_id=%s&timestamp=%s&sign=%s&redirect=%s", partner_id,timest, sign, redirect_url);
        System.out.println(url);
    }

    //shop request for access token for the first time
    public static String[] get_token_shop_level(String code,long partner_id,String tmp_partner_key,long shop_id) throws ParseException,IOException{
        String[] res = new String[2];
        long timest = System.currentTimeMillis() / 1000L;
        String host = "https://partner.shopeemobile.com";
        String path = "/api/v2/auth/token/get";
        String tmp_base_string = String.format("%s%s%s", partner_id, path, timest);
        byte[] partner_key;
        byte[] base_string;
        BigInteger sign = null;
        String result = "";
        try {
            base_string = tmp_base_string.getBytes("UTF-8");
            partner_key = tmp_partner_key.getBytes("UTF-8");
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(partner_key, "HmacSHA256");
            mac.init(secret_key);
            sign = new BigInteger(1,mac.doFinal(base_string));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String tmp_url = host + path + String.format("?partner_id=%s&timestamp=%s&sign=%s", partner_id,timest, String.format("%032x",sign));
        URL url = new URL(tmp_url);
        HttpURLConnection conn = null;
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(10000);
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept", "application/json");
            Map<String,Object> map = new HashMap<>();
            map.put("code",code);
            map.put("shop_id",shop_id);
            map.put("partner_id",partner_id);
            String json = JSON.toJSONString(map);
            conn.connect();
            out = new PrintWriter(conn.getOutputStream());
            out.print(json);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = "";
            while((line=in.readLine())!=null){
                result +=line;
            }
            JSONObject jsonObject = JSONObject.parseObject(result);
            res[0] = (String) jsonObject.get("access_token");
            res[1] = (String) jsonObject.get("refresh_token");
        } catch(Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(out != null){
                    out.close();
                }
                if(in != null){
                    in.close();
                }
            }catch (IOException ioe){
                ioe.printStackTrace();
            }
        }
        return res;
    }

    //main account request for the access token for the first time
    public static String[] get_token_account_level(String code,long partner_id,String tmp_partner_key,long main_account_id) throws ParseException,IOException{
        String[] res = new String[2];
        long timest = System.currentTimeMillis() / 1000L;
        String host = "https://partner.test.shopeemobile.com";
        String path = "/api/v2/auth/token/get";
        String tmp_base_string = String.format("%s%s%s", partner_id, path, timest);
        byte[] partner_key;
        byte[] base_string;
        BigInteger sign = null;
        String result = "";
        try {
            base_string = tmp_base_string.getBytes("UTF-8");
            partner_key = tmp_partner_key.getBytes("UTF-8");
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(partner_key, "HmacSHA256");
            mac.init(secret_key);
            sign = new BigInteger(1,mac.doFinal(base_string));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String tmp_url = host + path + String.format("?partner_id=%s&timestamp=%s&sign=%s", partner_id,timest, String.format("%032x",sign));
        URL url = new URL(tmp_url);
        HttpURLConnection conn = null;
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(10000);
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept", "application/json");
            Map<String,Object> map = new HashMap<>();
            map.put("code",code);
            map.put("main_account_id",main_account_id);
            map.put("partner_id",partner_id);
            String json = JSON.toJSONString(map);
            conn.connect();
            out = new PrintWriter(conn.getOutputStream());
            out.print(json);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = "";
            while((line=in.readLine())!=null){
                result +=line;
            }
            JSONObject jsonObject = JSONObject.parseObject(result);
            res[0] = (String) jsonObject.get("access_token");
            res[1] = (String) jsonObject.get("refresh_token");
        } catch(Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(out != null){
                    out.close();
                }
                if(in != null){
                    in.close();
                }
            }catch (IOException ioe){
                ioe.printStackTrace();
            }
        }
        return res;
    }

PHP Code Demo:

<?php 

function getTokenShopLevel($code, $partnerId, $partnerKey, $shopId) {
    global $host;
    $path = "/api/v2/auth/token/get";
    
    $timest = time();
    $body = array("code" => $code,  "shop_id" => $shopId, "partner_id" => $partnerId);
    $baseString = sprintf("%s%s%s", $partnerId, $path, $timest);
    $sign = hash_hmac('sha256', $baseString, $partnerKey);
    $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s", $host, $path, $partnerId, $timest, $sign);
    

    $c = curl_init($url);
    curl_setopt($c, CURLOPT_POST, 1);
    curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($body));
    curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    $resp = curl_exec($c);
    echo "raw result: $resp";

    $ret = json_decode($resp, true);
    $accessToken = $ret["access_token"];
    $newRefreshToken = $ret["refresh_token"];
    echo "\naccess_token: $accessToken, refresh_token: $newRefreshToken raw: $ret"."\n";
    return $ret;
}


function getTokenAccountLevel($code, $partnerId, $partnerKey, $mainAccountId) {
    global $host;
    $path = "/api/v2/auth/token/get";
    
    $timest = time();
    $body = array("code" => $code,  "main_account_id" => $mainAccountId, "partner_id" => $partnerId);
    $baseString = sprintf("%s%s%s", $partnerId, $path, $timest);

    $sign = hash_hmac('sha256', $baseString, $partnerKey);
    $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s", $host, $path, $partnerId, $timest, $sign);

    $c = curl_init($url);
    curl_setopt($c, CURLOPT_POST, 1);
    curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($body));
    curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($c);
    echo "\nraw result ".$result."\n";

    $ret = json_decode($result, true);
    $accessToken = $ret["access_token"];
    $newRefreshToken = $ret["refresh_token"];
    echo "\naccess_token: ".$accessToken.", refresh_token: ".$newRefreshToken."\n";
    return $ret;
}

$host="https://partner.shopeemobile.com";

$partnerId = 847892;
$partnerKey = "57615053704d6470644f554a78656d50484143644964436a5568777544524579";

$code="494d7a4a4f5a66524556776f66425453";

// $shopId=200520705;
// getTokenShopLevel($code, $partnerId, $partnerKey, $shopId);

$accountId=19479;
getTokenAccountLevel($code, $partnerId, $partnerKey, $accountId)

?>
#

§13 RefreshAccessToken

RefreshAccessToken

接口描述: access_token过期前,使用refresh_token调用此接口刷新access_token。调用后会同时返回一个新refresh_token和access_token,需要在下一次调用此接口时使用新refresh_token。

路径: https://partner.shopeemobile.com/api/v2/auth/access_token/get(生产环境)

https:// https://openplatform.sandbox.test-stable.shopee.sg/api/v2/auth/access_token/get(沙箱测试环境)

请求方式: Post

注意⚠️: 对于同一个main_account_id,首次调用GetAccessToken时获取到的首个access_token和refresh_token相同。但是,通过首次调用RefreshAccessToken接口分别对每个shop_id和merchant_id调用刷新后,各个shop_id和merchant_id将会生成一套独立的新的access_token和refresh_token。

例如,在GetAccessToken获得首个access_token和refresh_token给7个shop_ids和3个merchant_ids。首个access_token过期后,使用首个refresh_token调用RefreshAccessToken,获得10组独立的access_token和refresh_token给每个shop_id和merchant_id。 此后,shop_id和merchant_id不再共享任何access_token或refresh_token。

公共参数:

与 GetAccessToken API 的公共参数一致。

参数名称类型是否必填描述
signstring根据sign base string以partner key作为加密key通过HMAC-SHA256哈希得出的签名。
partner_idint从APP中获取到的partner_id,此partner_id放入query。
timestampint时间戳,有效期为5分钟。

业务参数:

参数名称类型是否必填描述
refresh_tokenstring使用refresh_token去获取新的access_token。针对每个shop_id和merchant_id分别有效,有效期为30天。
partner_idint从APP中获取到的partner_id,此partner_id放入body。
shop_idint条件必填授权给开发者的主账号shop_id,只能选shop_id和merchant_id必须分开refresh,只能选其中一个作为入参。
merchant_idint条件必填授权给开发者的主账号merchant_id,每个merchant的身份标识。shop_id和merchant_id必须分开refresh,只能选其中一个作为入参。

返回参数:

参数名称类型描述
request_idstring必返回,每个接口请求的ID,用于定位问题。
errorstring必返回,错误码,当调用成功时返回为空。
refresh_tokenstring调用成功时返回,新的refresh_token,使用refresh_token去获取新的access_token。针对每个shop_id和merchant_id分别有效,有效期为30天。
access_tokenstring调用成功时返回,新的access_token,动态令牌,可多次使用,4小时后过期。
expire_inint调用成功时返回,access_token有效时间,单位:秒。
messagestring必返回,详细报错信息。
merchant_idint调用成功时返回,本次刷新的merchant_id,每个merchant的身份标识。
shop_idint调用成功时返回,本次刷新的shop_id。
partner_idint调用成功时返回,您本次刷新使用的partner_id
supplier_id_listint[]auth_type=supplier时返回
user_id_listint[]auth_type=user时返回

RefreshAccessToken Demo

Python Code Demo:

# refresh token


def get_access_token_shop_level(shop_id, partner_id, tmp_partner_key, refresh_token):
    timest = int(time.time())
    host = "https://partner.test.shopeemobile.com"
    path = "/api/v2/auth/access_token/get"
    body = {"shop_id": shop_id, "refresh_token": refresh_token,"partner_id":partner_id}
    tmp_base_string = "%s%s%s" % (partner_id, path, timest)
    base_string = tmp_base_string.encode()
    partner_key = tmp_partner_key.encode()
    sign = hmac.new(partner_key, base_string, hashlib.sha256).hexdigest()
    url = host + path + "?partner_id=%s&timestamp=%s&sign=%s" % (partner_id, timest, sign)
    # print(url)
    headers = {"Content-Type": "application/json"}
    resp = requests.post(url, json=body, headers=headers)
    ret = json.loads(resp.content)
    access_token = ret.get("access_token")
    new_refresh_token = ret.get("refresh_token")
    return access_token, new_refresh_token


def get_access_token_merchant_level(merchant_id, partner_id, tmp_partner_key, refresh_token):
    timest = int(time.time())
    host = "https://partner.test.shopeemobile.com"
    path = "/api/v2/auth/access_token/get"
    body = {"merchant_id": merchant_id, "refresh_token": refresh_token}
    tmp_base_string = "%s%s%s" % (partner_id, path, timest)
    base_string = tmp_base_string.encode()
    partner_key = tmp_partner_key.encode()
    sign = hmac.new(partner_key, base_string, hashlib.sha256).hexdigest()
    url = host + path + "?partner_id=%s&timestamp=%s&sign=%s" % (partner_id, timest, sign)

    headers = {"Content-Type": "application/json"}
    resp = requests.post(url, json=body, headers=headers)
    ret = json.loads(resp.content)
    access_token = ret.get("access_token")
    new_refresh_token = ret.get("refresh_token")
    return access_token, new_refresh_token

partner_id = 2006566
partner_key = "1a78dde5d6c3342f56ac939cbdd81607654c0e87725e118736ba5e3ae31c579c"
shop_id = 602226924
main_account_id = 31219
merchant_id = 45719
code = "c01204cada7b4cd0e4688154f5a256ca"
print(shop_auth())
# access_token,refresh_token = get_token_shop_level(code,partner_id,partner_key,602226924)
# print(access_token)
# print(refresh_token)
# print(get_access_token_shop_level(shop_id,partner_id,partner_key,refresh_token))


access_token,refresh_token = get_token_account_level(code,partner_id,partner_key,main_account_id)
print(access_token)
print(refresh_token)
print(get_access_token_merchant_level(merchant_id,partner_id,partner_key,refresh_token))
   

Java Code Demo:


    //shop refresh the access token
    public static String[] get_access_token_shop_level(String refresh_token,long partner_id,String tmp_partner_key,long shop_id) throws ParseException,IOException{
        String[] res = new String[2];
        long timest = System.currentTimeMillis() / 1000L;
        String host = "https://partner.shopeemobile.com";
        String path = "/api/v2/auth/access_token/get";
        String tmp_base_string = String.format("%s%s%s", partner_id, path, timest);
        byte[] partner_key;
        byte[] base_string;
        BigInteger sign = null;
        String result = "";
        try {
            base_string = tmp_base_string.getBytes("UTF-8");
            partner_key = tmp_partner_key.getBytes("UTF-8");
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(partner_key, "HmacSHA256");
            mac.init(secret_key);
            sign = new BigInteger(1,mac.doFinal(base_string));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String tmp_url = host + path + String.format("?partner_id=%s&timestamp=%s&sign=%s", partner_id,timest, String.format("%032x",sign));
        URL url = new URL(tmp_url);
        HttpURLConnection conn = null;
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(10000);
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept", "application/json");
            Map<String,Object> map = new HashMap<>();
            map.put("refresh_token",refresh_token);
            map.put("shop_id",shop_id);
            map.put("partner_id",partner_id);
            String json = JSON.toJSONString(map);
            conn.connect();
            out = new PrintWriter(conn.getOutputStream());
            out.print(json);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = "";
            while((line=in.readLine())!=null){
                result +=line;
            }
            JSONObject jsonObject = JSONObject.parseObject(result);
            res[0] = (String) jsonObject.get("access_token");
            res[1] = (String) jsonObject.get("refresh_token");
        } catch(Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(out != null){
                    out.close();
                }
                if(in != null){
                    in.close();
                }
            }catch (IOException ioe){
                ioe.printStackTrace();
            }
        }
        return res;
    }

    //merchant refresh the access token
    public static String[] get_access_token_merchant_level(String refresh_token,long partner_id,String tmp_partner_key,long merchant_id) throws ParseException,IOException{
        String[] res = new String[2];
        long timest = System.currentTimeMillis() / 1000L;
        String host = "https://partner.shopeemobile.com";
        String path = "/api/v2/auth/access_token/get";
        String tmp_base_string = String.format("%s%s%s", partner_id, path, timest);
        byte[] partner_key;
        byte[] base_string;
        BigInteger sign = null;
        String result = "";
        try {
            base_string = tmp_base_string.getBytes("UTF-8");
            partner_key = tmp_partner_key.getBytes("UTF-8");
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(partner_key, "HmacSHA256");
            mac.init(secret_key);
            sign = new BigInteger(1,mac.doFinal(base_string));
        } catch (Exception e) {
            e.printStackTrace();
        }
        String tmp_url = host + path + String.format("?partner_id=%s&timestamp=%s&sign=%s", partner_id,timest, String.format("%032x",sign));
        URL url = new URL(tmp_url);
        HttpURLConnection conn = null;
        PrintWriter out = null;
        BufferedReader in = null;
        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(10000);
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept", "application/json");
            Map<String,Object> map = new HashMap<>();
            map.put("refresh_token",refresh_token);
            map.put("merchant_id",merchant_id);
            map.put("partner_id",partner_id);
            String json = JSON.toJSONString(map);
            conn.connect();
            out = new PrintWriter(conn.getOutputStream());
            out.print(json);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = "";
            while((line=in.readLine())!=null){
                result +=line;
            }
            JSONObject jsonObject = JSONObject.parseObject(result);
            res[0] = (String) jsonObject.get("access_token");
            res[1] = (String) jsonObject.get("refresh_token");
        } catch(Exception e){
            e.printStackTrace();
        }finally {
            try{
                if(out != null){
                    out.close();
                }
                if(in != null){
                    in.close();
                }
            }catch (IOException ioe){
                ioe.printStackTrace();
            }
        }
        return res;
    }
}

PHP Code Demo:

<?php 

function getAccessTokenShopLevel($partnerId, $partnerKey, $shopId, $refreshToken) {
    global $host;
    $path = "/api/v2/auth/access_token/get";
    
    $timest = time();
    $body = array("partner_id" => $partnerId, "shop_id" => $shopId, "refresh_token" => $refreshToken);
    $baseString = sprintf("%s%s%s", $partnerId, $path, $timest);
    $sign = hash_hmac('sha256', $baseString, $partnerKey);
    $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s", $host, $path, $partnerId, $timest, $sign);


    $c = curl_init($url);
    curl_setopt($c, CURLOPT_POST, 1);
    curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($body));
    curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);

    $result = curl_exec($c);
    echo "\nraw result ".$result."\n";

    $ret = json_decode($result, true);

    $accessToken = $ret["access_token"];
    $newRefreshToken = $ret["refresh_token"];
    echo "\naccess_token: ".$accessToken.", refresh_token: ".$newRefreshToken."\n";
    return $ret;
}

function getAccessTokenMerchantLevel($partnerId, $partnerKey, $merchantId, $refreshToken) {
    global $host;
    $path = "/api/v2/auth/access_token/get";
    
    $timest = time();
    $body = array("partner_id" => $partnerId, "merchant_id" => $merchantId, "refresh_token" => $refreshToken);
    $baseString = sprintf("%s%s%s", $partnerId, $path, $timest);
    $sign = hash_hmac('sha256', $baseString, $partnerKey);
    $url = sprintf("%s%s?partner_id=%s&timestamp=%s&sign=%s", $host, $path, $partnerId, $timest, $sign);


    $c = curl_init($url);
    curl_setopt($c, CURLOPT_POST, 1);
    curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($body));
    curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($c);
    echo "\nraw result ".$result."\n";

    $ret = json_decode($result, true);
    $accessToken = $ret["access_token"];
    $newRefreshToken = $ret["refresh_token"];
    echo "\naccess_token: ".$accessToken.", refresh_token: ".$newRefreshToken."\n";
    return $ret;
}

$host="https://partner.shopeemobile.com";

$partnerId = 847892;
$partnerKey = "57615053704d6470644f554a78656d50484143644964436a5568777544524579";




// $shopId=200520705;
// $shopRefreshToken="71724c4e68746b546965424c70617244";
// getAccessTokenShopLevel($partnerId, $partnerKey, $shopId, $shopRefreshToken)

$merchantId=1018829;
$merchantRefreshToken="546e5064627042696756455277774f53";
getAccessTokenMerchantLevel($partnerId, $partnerKey, $merchantId, $merchantRefreshToken)

?>
#

§14 Shop account示例

Shop account示例

1、用redirect url:https://open.shopee.com/?code=7867624d4e76616648544f6e52625557&shop_id=54804中的code与shop_id调用GetAccesstoken接口获取第一对access_token与refresh_token.

https://partner.shopeemobile.com/api/v2/auth/token/get?partner_id=1000016&timestamp=1657263479&sign=9c685bc7e4a74e90f45fe1933f1d72b2d9705acda4093a9fb1ec7e2b57ccea2a

{"shop_id":54804,

"code":"7867624d4e76616648544f6e52625557",

"partner_id":1000016

}

2、保存返回的第一对access_token与refresh_token。

{

"refresh_token": "456e416149664b76745a6a794156794a",

"access_token": "6a55746e61546f707579627656637464",

"expire_in": 13859,

"request_id": "c040b886cfcabdfa5a23af51c595cd1b",

"error": "",

"message": ""

}

3、调用RefreshAccessToken接口刷新access_token与refresh_token。

https://partner.shopeemobile.com/api/v2/auth/access_token/get?partner_id=1000016×tamp=1657263479&sign=9c685bc7e4a74e90f45fe1933f1d72b2d9705acda4093a9fb1ec7e2b57ccea2a

{"shop_id":54804,

"refresh_token":"456e416149664b76745a6a794156794a",

"partner_id":1000016

}

4、保存新的access_token与refresh_token。

{

"partner_id": 1000016,

"refresh_token": "666478546b6c63464867685554477a57",

"access_token": "7a5970754768697552654a466f425573",

"expire_in": 14400,

"request_id": "6d79dd0ffe4e070e185c71ca5153cd51",

"error": "",

"message": "",

"shop_id": 54804

}

#

§15 Main account示例

Main account示例

1、用授权拿到的https://open.shopee.com/?code=644d4e48787873706c5a444c776d4b59&main_account_id=10208中的code与main_account_id调用GetAccesstoken接口获取第一对access_token与refresh_token.

https://partner.shopeemobile.com/api/v2/auth/token/get?partner_id=1000016&timestamp=1657263479&sign=9c685bc7e4a74e90f45fe1933f1d72b2d9705acda4093a9fb1ec7e2b57ccea2a

{"main_account_id":10208,

"code":"644d4e48787873706c5a444c776d4b59",

"partner_id":1000016

}

2、保存返回的第一对access_token与refresh_token。

{

"refresh_token": "684d42685667777868597a4477587455",

"access_token": "44776151594778486943647644745361",

"expire_in": 14344,

"request_id": "9199e13ee74b22411498209cb5516e24",

"merchant_id_list": [

1001705

],

"shop_id_list": [

33142,

46154

],

"error": "",

"message": ""

}

3、调用RefreshAccessToken接口分别刷新出shop_id与merchant_id的access_token与refresh_token

https://partner.shopeemobile.com/api/v2/auth/access_token/get?partner_id=1000016&timestamp=1657868745&sign=b78833ddcf533903cfae818bbfcf2b6b630e3bc0c941dd65453632f63bf7b495

{"shop_id":33142,

"refresh_token":"684d42685667777868597a4477587455",

"partner_id":1000016

}

https://partner.shopeemobile.com/api/v2/auth/access_token/get?partner_id=1000016&timestamp=1657868745&sign=b78833ddcf533903cfae818bbfcf2b6b630e3bc0c941dd65453632f63bf7b495

{"merchant_id":1001705,

"refresh_token":"684d42685667777868597a4477587455",

"partner_id":1000016

}

4、保存新的access_token与refresh_token。

{

"partner_id": 1000016,

"refresh_token": "417472546e73504949676279576c477a",

"access_token": "646d474965714a696177764963775743",

"expire_in": 14400,

"request_id": "78e64d11cb6dec6f6669282839fca916",

"error": "",

"message": "",

"shop_id": 33142

}

{

"partner_id": 1000016,

"refresh_token": "715075736d6c6570544364774f437369",

"access_token": "69634c664a7350696c6b466d5a53714a",

"expire_in": 14400,

"request_id": "51eacbc81bd6fa8fddddf1e0ef2dee16",

"error": "",

"message": "",

"merchant_id": 1001705

}

通过以上方式,您可以在四小时内调用RefreshAccessToken接口拿到新的access_token与refresh_token,保持循环调用将能在授权有效期内持续获得可用的access_token与refresh_token。如果丢失了返回的新的refresh_token和access_token,可以参考这篇 FAQ

#

§16 取消授权

可通过生成取消授权链接或在卖家中心操作取消授权。

#

§17 通过取消授权URL

通过取消授权URL

与授权的URL生成规则一致,但固定授权url需变为固定取消授权的url:

固定取消授权 URL

取消授权链接示例

- 生产环境:https://open.shopee.com/cancel_auth?partner_id=10090&auth_type=seller&redirect_uri=https://open.shopee.com&response_type=code

- 沙箱测试环境:https://open.test-stable.shopee.com/cancel_auth?partner_id=1000016&auth_type=seller&redirect_uri=https://open.test-stable.shopee.com&response_type=code

取消流程

1、按上述规范生成取消授权链接;

2、卖家通过取消授权链接登录账号;

3、卖家点击 “取消授权” 完成操作,取消后应用将不再有权访问卖家信息。

#

§18 Seller Center取消授权

Seller Center取消授权

Local卖家:

  • 卖家登录卖家中心,进入 “Home Page > Platform Partner;
  • 在Platform Partner页面,卖家可查看店铺 / 主账号授权的所有应用及授权到期时间;
  • 卖家点击操作列中的 “Separate”,取消对应应用的授权。

CNSC卖家

“首页 > 开放平台管理”:卖家可以去查看这主账号被授权给了哪些app,在授权管理页面,卖家可以在该界面直接解除merchant或shop的授权关系。

若授权过程中遇到错误,可参考官方常见问题(FAQ)排查。

如有其他疑问,可联系 Shopee 开放平台支持团队。

#