当前位置: 首页 > news >正文

苹果认证Apple Store Connenct api的使用

苹果认证工具类Apple Store Connenct api

苹果应用商店支持下载财务报告和销售报告,官方有提供两种下载方式
方式一:Reporter.jar
方式二:Api(Http)

先定个结论,推荐使用Api的方式去调用。下文会介绍原因

文章目录

  • 苹果认证工具类Apple Store Connenct api
  • Reporter.jar调用
    • 1. 下载reporter工具
    • 2. 生成访问令牌
    • 3. 下载财务/销售报告
      • 获取供应商编码和地区编码
      • 获取财务汇总报告
      • 获取财务详情报告
  • Api调用
    • 1.密钥和私钥
    • 2.生成JWT令牌
    • 3.工具类(已实现,可以拿来即用)

Reporter.jar调用

官方链接:https://help.apple.com/itc/contentreporterguide/#/apda86f89da5

1. 下载reporter工具

如Reporter2.2,你将会得到两个文件:

  • Reporter.jar
  • Reporter.properties

2. 生成访问令牌

参考地址:https://help.apple.com/itc/contentreporterguide/#/apd2f1f1cfa3

  • 语法
$ java -jar Reporter.jar p=[properties file name] [application name].generateToken

[application name]——请替换为“Sales”或“Finance”
注:您只需生成一个访问令牌即可访问销售和财务数据。无须为二者生成单独的访问令牌。

  • 示例
$ java -jar Reporter.jar p=Reporter.properties Sales.generateToken
Please type in your username: ********
Please type in your password: ********
Once you generate an access token, you won't be able to log in to Reporter with your username and password. Do you still want to continue? (y/n):
如果输入“y”:
Your access token has been generated.
AccessToken:12abc345-de6f-7ghi-89jk123lmno
Expiration Date:2017-06-07
(过期日期格式:YYYY-MM-DD)

如果用户已有令牌:
$ java -jar Reporter.jar p=Reporter.properties Sales.generateToken
Please type in your username: ********
Please type in your password: ********
If you generate a new access token, your existing token will be deleted. Do you still want to continue? (y/n):
  • 令牌回填到属性文件的AccessToken中
    Reporter.properties
AccessToken=xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxxx

Mode=Normal

SalesUrl=https://reportingitc-reporter.apple.com/reportservice/sales/v1
FinanceUrl=https://reportingitc-reporter.apple.com/reportservice/finance/v1

3. 下载财务/销售报告

参考地址:https://help.apple.com/itc/contentreporterguide/#/itc21263284f

获取供应商编码和地区编码

java -jar Reporter.jar p=Reporter.properties Finance.getVendorsAndRegions

return:
The following reports are available for vendor 00000000:
AE:Financial
AU:Financial
BG:Financial
BR:Financial
CA:Financial
CH:Financial
CL:Financial
CN:Financial
Z1:FinancialDetail

PS:特别备注,Z1表示多个国家的报告,且只有详情报告FinancialDetail。 其他国家代码均为汇总报告Financial

获取财务汇总报告

【语法】

java -jar Reporter.jar p=Reporter.properties m=Robot.XML Finance.getReport [供应商编码],[地区代码], [报告类型], [苹果日历-年], [苹果日历-月]

【示例】

java -jar Reporter.jar p=Reporter.properties m=Robot.XML Finance.getReport 00000000, US, Financial, 2022, 9

得到国家US的汇总报告,返回一个.gz压缩文件

获取财务详情报告

java -jar Reporter.jar p=Reporter.properties m=Robot.XML Finance.getReport 00000000, Z1, FinanceDetail, 2022, 9

得到多个国家详情报告,返回一个.gz压缩文件

Api调用

简述调用逻辑:
1、苹果应用商店下载密钥私钥
2、生成JWT令牌
3、携带JWT访问API接口(如访问财务报告)

这一看清晰多了,通用逻辑就两个,一个是密钥、私钥,另一个是令牌。

1.密钥和私钥

参考地址:https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api

每个开发者账号都会对应一个密钥和私钥,请各自保管好

示例:

密钥kid私钥private key
12345678-----BEGIN PRIVATE KEY-----12345678省略一大堆-----END PRIVATE KEY-----

2.生成JWT令牌

参考地址:https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests

按照JWT生成规则三要素:
1、标头header
2、负载payload
3、私钥

  1. 组装header
Header FieldValue
alg - Encryption AlgorithmES256 All JWTs for App Store Connect API must be signed with ES256 encryption.
kid - Key IdentifierYour private key ID from App Store Connect; for example 2X9R4HXF34.
typ - Token TypeJWT

简化一下:

{
    "alg" : "ES256", //固定
    "kid" : {密钥},
    "typ" : "JWT" // 固定
}
  1. 组装payload
Payload FieldValue
iss - Issuer IDYour issuer ID from the API Keys page in App Store Connect; for example, 57246542-96fe-1a63-e053-0824d011072a.
iat - Issued At TimeThe token’s creation time, in UNIX epoch time; for example, 1528407600.
exp - Expiration TimeThe token’s expiration time in Unix epoch time. Tokens that expire more than 20 minutes into the future are not valid except for resources listed in Determine the Appropriate Token Lifetime.
aud - Audienceappstoreconnect-v1
scope - Token ScopeA list of operations you want App Store Connect to allow for this token; for example, GET /v1/apps/123. (Optional)

简化下:

{
    "iss" : {用户ID},
    "iat" : 1528407600, // 令牌起始时间,单位秒
    "exp" : 1528408800, // 令牌失效时间,注意最长不超过20分钟
    "aud" : "appstoreconnect-v1" // 固定
    "scope" : [ // [可选值]用来限制权限
        "GET /v1/apps?filter[platform]=IOS"
    ]
}
  1. 签名私钥认证,得到jwt

参考下面工具类,或者全文检索一下createToken关键字,读一下你就懂了

3.工具类(已实现,可以拿来即用)

package com.whale.data.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.whale.common.core.constant.TokenConstants;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yanyq
 * @desc apple store connect 苹果认证工具类
 * @date 2022/10/18
 */
public class AppleKitUtils {

    /**
     * 创建令牌
     *
     * @param userId     用户ID
     * @param kid        密钥 如:2X9R4HXF34
     * @param privateKey 私钥 如:djhdkajshdky12dy1hd12hd98h129d8h192d8h198dh1982dh198dh918hd92d总之很长就对了
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static String createToken(String userId, String kid, String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        // 1.设置标头
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "ES256");
        header.put("kid", kid);
        header.put("typ", "JWT");

        // 2.设置负载
        Map<String, Object> claims = new HashMap<>();
        // 发行人ID
        claims.put("iss", userId);
        // 按时发行(单位秒)
        long currentTimeSeconds = DateUtil.currentSeconds();
        claims.put("iat", currentTimeSeconds);
        // 到期时间
        claims.put("exp", currentTimeSeconds + 60 * 20);
        // 观众(固定值)
        claims.put("aud", "appstoreconnect-v1");

        // 3.创建私钥对象
        // 私钥多余数据过滤
        String privateKeyPEM = privateKey.replaceAll("\\-*BEGIN.*KEY\\-*", "")
                .replaceAll("\\-*END.*KEY\\-*", "")
                .replaceAll("\r", "")
                .replaceAll("\n", "");
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyPEM));
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        PrivateKey pk = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

        // 4.生成token
        String token = Jwts.builder()
                .setHeader(header)
                .setClaims(claims)
                .signWith(SignatureAlgorithm.ES256, pk)
                .compact();
        return token;
    }

    /**
     * 下载苹果财务详细报告
     *
     * @param token        令牌
     * @param vendorNumber 供应商编码
     * @param reportDate   报告日期,参考苹果日历
     * @param downloadPath 文件下载路径
     */
    private static void downloadAppleFinanceReportDetail(String token, String vendorNumber, String reportDate, String downloadPath) throws IOException {
        String url = "https://api.appstoreconnect.apple.com/v1/financeReports";
        String reportType = "FINANCE_DETAIL";
        String regionCode = "Z1";
        // 创建客户端
        HttpRequest post = HttpUtil.createGet(url);
        // 创建请求头
        post.header(TokenConstants.AUTHENTICATION, TokenConstants.PREFIX + token);
        post.header("Accept", "application/a-gzip");
        post.form("filter[regionCode]", regionCode);
        post.form("filter[reportDate]", reportDate);
        post.form("filter[reportType]", reportType);
        post.form("filter[vendorNumber]", vendorNumber);
        // 执行
        HttpResponse execute = post.execute();
        if (execute.isOk()) {
            // 请求成功
            byte[] retBytes = execute.bodyBytes();
            File file = FileUtil.file(downloadPath);
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            FileOutputStream fos = new FileOutputStream(file);
            // 数据写到本地
            IoUtil.write(fos, true, retBytes);
        } else {
            // 请求失败
            String retBody = execute.body();
            System.out.println(retBody);
        }
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
        // 账号信息
        String kid = "xxxxxxxx";
        String userId = "xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx";
        String privateKey = "xxxxxxxxxx/xxxxxxxx/xxxxxxxxx/xxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx";
        String token = createToken(userId, kid, privateKey);

        // 请求财务报告明细数据
        // 请求信息
        String vendorNumber = "80000000";
        String reportDate = "2022-09";
        String downloadPath = "/Users/admin/Downloads/bb.gz";
        downloadAppleFinanceReportDetail(token, vendorNumber, reportDate, downloadPath);

    }
}


相关文章:

  • wordpress萨龙怎么使用/成人计算机速成培训班
  • 模板网站建设源码/百度大搜
  • 网站流量一直下降/互联网+营销策略怎么写
  • 芜湖做网站都有哪些/长春seo排名优化
  • 政协网站法治建设/类似火脉的推广平台
  • 邵阳市 网站建设/网络推广赚钱平台有哪些
  • HashMap和Hashtable(全网最详细)
  • Linux10 -- 相关习题
  • 公司招人:34岁以上两年一跳的不要,开出工资以为看错了
  • JVM之对象的内存模型、创建过程、对象引用、生命周期
  • docker安装和优化
  • 【机器学习】Ensemble Learning 集成学习 + Python代码实战
  • 巷子里的酒
  • 【C语言案例】——三子棋
  • 云上mysql 简易安装
  • 【手写的从前】解析参考:Numpy手写的多层神经网络
  • Speech recognition模型:RNN Transducer(RNN-T)
  • 【Leetcode】二分法求解问题