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

怎么知道公司网站是哪家做的郑州竞价托管代运营

怎么知道公司网站是哪家做的,郑州竞价托管代运营,哪个语言做动态网站好用,网站建设要什么软件公证方式 Mac 公证方式有三种 公证方法 优点 缺点 阐述 Xcode Xcode携带的图形界面,使用方便 无法进行自动化公证 单个App应用上架使用较多 altool(旧版) 支持pkg,dmg,脚本自动化 2023/11/01 将会过期 已经…

公证方式

Mac 公证方式有三种

公证方法

优点

缺点

阐述

Xcode

Xcode携带的图形界面,使用方便

无法进行自动化公证

单个App应用上架使用较多

altool(旧版)

支持pkg,dmg,脚本自动化

2023/11/01 将会过期

已经是弃用,不建议使用 Mac开发-公证流程记录Notarization-附带脚本_xcrun altool --notarize-app --primary-bundle-id-CSDN博客

notarytool(新版)

支持pkg,dmg,脚本自动化

必须依赖macos环境

必须要依赖macos环境,并且更新Xcode版本和mac版本,有一定的环境限制

Notary API

支持pkg,dmg,脚本自动化

无需依赖macos环境

使用的是苹果官方提供的Web API进行公证,不受运行环境限制

这里 Notary API 有较大的优势,之前 altool 脚本公证的方式我们已经做过,由于 2023/11/01 将被弃用,考虑后续跨平台的需要,使用 notary API 进行脚本自动化公证

https://developer.apple.com/documentation/notaryapi/submitting_software_for_notarization_over_the_web

流程

具体的流程大概如下:

  1. 获取 API密钥 (Private Key)
  2. 使用 API密钥 (Private Key) 生成 JSON Web Token (JWT) , 相当于授权令牌 token
  3. 请求 Notary API 并在 HTTP 请求头中,携带 JWT 内容
  4. 得到请求结果

1. 获取 API密钥

https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api

官方文档阐述

  1. 登录App Store Connect
  2. 选择 [用户和访问] 这栏 ,然后选择API Keys选项卡
  3. 单击生成API密钥或添加(+)按钮。
  4. 输入密钥的名称。
  5. 在Access下,为密钥选择角色
  6. 点击生成
  7. 点击下载秘钥 (注意下载后苹果不再保存,你只能下载一次)

根据上述流程获取你的 API 秘钥

2. 生成令牌 Token

https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests

2.1. 环境安装
  1. 根据 https://jwt.io/libraries 所述,安装 pyjwt 库
  2. 由于本地环境 python3, 使用 pip3 install pyjwt 安装, 并参考官网使用说明 https://pyjwt.readthedocs.io/en/stable/usage.html#encoding-decoding-tokens-with-hs256
  3. pyjwt 依赖 cryptography 库,需要额外安装 pip3 install cryptography
  4. 文件上传依赖 boto3 库,pip3 install boto3

2.2. JWT Encode/Decode

参考 https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests 所述进行设置,值得注意的是,苹果会拒绝大多数设置过期时间为 20 分钟以上的 JWT 票据,所以我们需要间隔生成 JWT

  1. header
{"alg": "ES256","kid": "2X9R4HXF34","typ": "JWT"
}
  1. body
{"iss": "57246542-96fe-1a63-e053-0824d011072a","iat": 1528407600,"exp": 1528408800,"aud": "appstoreconnect-v1","scope": ["GET /notary/v2/submissions","POST /notary/v2/submissions",]
}
  1. API 秘钥

对应的生成逻辑如下

def get_jwt_token():# 读取私钥文件内容with open('./AuthKey_xxxxx.p8', 'rb') as f:jwt_secret_key = f.read()# 获取当前时间now = datetime.datetime.now()# 计算过期时间(当前时间往后 20 分钟)expires = now + datetime.timedelta(minutes=20)# 设置 JWT 的 headerjwt_header = {"alg": "ES256","kid": "2X9R4HXF34","typ": "JWT"}# 检查文件是否存在if os.path.exists("./jwt_token"):# 读取with open('./jwt_token', 'rb') as f:jwt_pre_token = f.read()print('[info]','jwt token %s' % (jwt_pre_token))try:decoded = jwt.decode(jwt_pre_token,jwt_secret_key,algorithms="ES256",audience="appstoreconnect-v1")except Exception as e:print('[error]', 'decode exception %s' % (e))else:exp = datetime.datetime.fromtimestamp(decoded["exp"])if exp - datetime.timedelta(seconds=60) < now:print("jwt token 已过期,重新生成")else:print("jwt token 有效,使用之前token")return jwt_pre_token# 设置 JWT 的 payloadjwt_payload = {"iss": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","iat": int(now.timestamp()),"exp": int(expires.timestamp()),"aud": "appstoreconnect-v1","scope": ["GET /notary/v2/submissions","POST /notary/v2/submissions",]}print('[info]', 'jwt_header %s' % (jwt_header), 'jwt_payload %s' % jwt_payload)token = jwt.encode(jwt_payload,jwt_secret_key,algorithm="ES256",headers=jwt_header,)# 打开文件,如果文件不存在则创建文件with open("./jwt_token", "w") as f:# 将 token 写入文件f.write(token)print('[info]', 'jwt token is %s' % (token))return token

3. 公证上传

公证处理的流程如下

  1. POST https://appstoreconnect.apple.com/notary/v2/submissions 请求submission s3 上传凭证
  2. 使用 boto3 框架根据获取的凭证信息,查询一次公证状态,如果非 Accepted 状态,进行上传文件。(阻塞式)
file_md5=None
def post_submissison(filepath): global file_md5body = get_body(filepath)token = get_jwt_token()file_md5 = get_md5(filepath)# 指定文件夹路径folder_path = './output'# 缓存路径cache_path = f"{folder_path}/{file_md5}"# 检查文件夹是否存在if not os.path.exists(folder_path):# 如果文件夹不存在,则创建文件夹os.makedirs(folder_path)else:# 如果文件夹已经存在,则进行相应的处理print("[info]", '%s 已经存在' % folder_path)# 检查文件是否存在if os.path.exists(cache_path):# 读取with open(cache_path, 'rb') as f:string = f.read().decode()output = json.loads(string)print('[info]', '使用上次 submission s3 上传凭证 = %s' % (output))else:resp = requests.post("https://appstoreconnect.apple.com/notary/v2/submissions", json=body, headers={"Authorization": "Bearer " + token})resp.raise_for_status()output = resp.json()print('[info]', '获取 submission s3上传凭证 = %s' % (output))# 打开文件,如果文件不存在则创建文件with open(cache_path, "w") as f:# 将 resp 写入文件f.write(resp.content.decode())# 读取 output 中的内容aws_info = output["data"]["attributes"]bucket = aws_info["bucket"]key = aws_info["object"]# sub_id = output["data"]["id"]# 如果已经完成了公证state = get_submission_state(filepath, True)if state == True:print('[info]', 'file %s alreay finished notarization' % (filepath))staple_pkg(filepath)exit(0)s3 = boto3.client("s3",aws_access_key_id=aws_info["awsAccessKeyId"],aws_secret_access_key=aws_info["awsSecretAccessKey"],aws_session_token=aws_info["awsSessionToken"],config=Config(s3={"use_accelerate_endpoint": True}))print('[info]', 'start upload files ...... please wait 2-15 mins')# 上传文件s3.upload_file(filepath, bucket, key)print('[info]', 'upload file complete ...')
  1. 查询公证状态,Accepted 、In Progress、Invalid 目前探测到这三种状态
def get_submission_state(filepath, once=False):print('[info]', 'get_submission_state %s %s ' % (filepath, once))global file_md5if not file_md5:file_md5 = get_md5(filepath)# 指定文件夹路径folder_path = './output'# 缓存路径cache_path = f"{folder_path}/{file_md5}"# 检查文件是否存在if os.path.exists(cache_path):# 获取文件大小file_size = os.path.getsize(cache_path)if file_size == 0:# 文件内容为空print('[info]', ' %s 内容为空,未获取到submission信息' % (filepath))return Falseelse:# 读取缓存内容with open(cache_path, 'rb') as f:string = f.read().decode()output = json.loads(string)else:return Falsesub_id = output["data"]["id"]url = f"https://appstoreconnect.apple.com/notary/v2/submissions/{sub_id}"ret = Falsewhile True:try:# 获取submissiontoken = get_jwt_token()resp = requests.get(url, headers={"Authorization": "Bearer " + token})resp.raise_for_status()except Exception as e:# 异常处理print("[Error]", ' %s get status failed, code = %s ' % filepath % resp.status_code)return Falseelse:# 200 正常返回处理# 检查 statusresp_json = resp.json()print('[info]', 'GET %s resp is %s , header is %s' % (url,resp_json,resp.headers))status = resp_json["data"]["attributes"]["status"]if status == "Accepted":print("[info]", ' %s notarization succesfull' % filepath)ret = Truebreakif status == "Invalid":print("[info]", ' %s notarization failed' % filepath)ret = Falsebreakif once == False:# 暂停 30 秒time.sleep(30)else:print("[info]", 'get_submission_state run once')breakif once == False:print_submission_logs(sub_id)return ret
  1. 获取日志内容
def print_submission_logs(identifier):try:url = f"https://appstoreconnect.apple.com/notary/v2/submissions/{identifier}/logs"token = get_jwt_token()resp = requests.get(url, headers={"Authorization": "Bearer " + token})resp.raise_for_status()except Exception as e:print("[Error]", '/notary/v2/submissions/%s/logs failed, code = %s ' % (identifier, resp.status_code))else:resp_json = resp.json()print('[info]', 'notarization %s logs is %s' % (identifier, resp_json))
  1. 如果 步骤3 查询到结果为 Accepted,则使用 stapler 工具打上票据,进行分发
def staple_pkg(filepath):global file_md5if not file_md5:file_md5 = get_md5(filepath)# 完成公证subprocess.run(["xcrun", "stapler", "staple", filepath])now = datetime.datetime.now()# 验证公证结果temp_output_file = f"./temp_file_{file_md5}"with open(temp_output_file, "w") as f:subprocess.run(["xcrun", "stapler", "validate", filepath], stdout=f, stderr=subprocess.STDOUT)# 读取验证结果with open(temp_output_file, "r") as f:validate_result = f.read()os.remove(temp_output_file)# 检查验证结果if "The validate action worked!" not in validate_result:print('[error]',"\033[31m[error] stapler validate invalid, may be notarization failed!\033[0m")return Falseelse:print('[info]','staple_pkg succesfull')return True

4. 脚本使用方式

脚本文件  https://github.com/CaicaiNo/Apple-Mac-Notarized-script/blob/master/notarize-web/notarize.py

在执行下列步骤前,请先阅读 Generating Tokens for API Requests | Apple Developer Documentation

  1. 替换你的秘钥文件 (例如 AuthKey_2X9R4HXF34.p8)
private_key = f"./../../res/AuthKey_2X9R4HXF34.p8"
  1. 设置你的 kid
 # 设置 JWT 的 headerjwt_header = {"alg": "ES256","kid": "2X9R4HXF34","typ": "JWT"}
  1. 设置你的 iss
# 设置 JWT 的 payloadjwt_payload = {"iss": "57246542-96fe-1a63-e053-0824d011072a","iat": int(now.timestamp()),"exp": int(expires.timestamp()),"aud": "appstoreconnect-v1","scope": ["GET /notary/v2/submissions","POST /notary/v2/submissions",]}
  1. 调用脚本
python3 -u ./notarize.py --pkg "./Output/${PACKAGE_NAME}_$TIME_INDEX.pkg" --private-key "./../../res/AuthKey_2X9R4HXF34.p8"if [ $? -eq 0 ]; thenecho "./Output/aTrustInstaller_$TIME_INDEX.pkg notarization successful"// 公证成功
else// 公证失败echo "./Output/aTrustInstaller_$TIME_INDEX.pkg notarization failed"exit 1
fi


文章转载自:
http://dinncohaydn.tqpr.cn
http://dinncoquaestorship.tqpr.cn
http://dinncogermaine.tqpr.cn
http://dinncoraff.tqpr.cn
http://dinncodecauville.tqpr.cn
http://dinncomismark.tqpr.cn
http://dinncomilitiaman.tqpr.cn
http://dinncoperchloric.tqpr.cn
http://dinncosaratov.tqpr.cn
http://dinncotowerless.tqpr.cn
http://dinncoviol.tqpr.cn
http://dinncorotorcraft.tqpr.cn
http://dinncoscorepad.tqpr.cn
http://dinncofasciolet.tqpr.cn
http://dinncocommonality.tqpr.cn
http://dinncoinstructional.tqpr.cn
http://dinncotheorist.tqpr.cn
http://dinncoparisyllabic.tqpr.cn
http://dinncocoleopterous.tqpr.cn
http://dinncotrailside.tqpr.cn
http://dinncogerman.tqpr.cn
http://dinncoherbary.tqpr.cn
http://dinncoseaborne.tqpr.cn
http://dinncoulva.tqpr.cn
http://dinncoverdant.tqpr.cn
http://dinncoperpetration.tqpr.cn
http://dinncoservia.tqpr.cn
http://dinncogrowler.tqpr.cn
http://dinncoencomiastic.tqpr.cn
http://dinncotable.tqpr.cn
http://dinncofavourer.tqpr.cn
http://dinncopolemically.tqpr.cn
http://dinncohippocampus.tqpr.cn
http://dinncononperiodic.tqpr.cn
http://dinncounsnarl.tqpr.cn
http://dinncoamblyopia.tqpr.cn
http://dinncogangmaster.tqpr.cn
http://dinncosteve.tqpr.cn
http://dinncojul.tqpr.cn
http://dinncodownhold.tqpr.cn
http://dinncoidioplasmic.tqpr.cn
http://dinncononbeing.tqpr.cn
http://dinncoargyll.tqpr.cn
http://dinncokif.tqpr.cn
http://dinncospermatic.tqpr.cn
http://dinncocosmographic.tqpr.cn
http://dinncounimpressible.tqpr.cn
http://dinncoshea.tqpr.cn
http://dinncocellarer.tqpr.cn
http://dinncoabnegator.tqpr.cn
http://dinncoattainability.tqpr.cn
http://dinncoattractor.tqpr.cn
http://dinncoinconsiderate.tqpr.cn
http://dinncotracheary.tqpr.cn
http://dinncoredout.tqpr.cn
http://dinncoanglicanism.tqpr.cn
http://dinncohexameter.tqpr.cn
http://dinncomucic.tqpr.cn
http://dinncomissouri.tqpr.cn
http://dinncointerrogation.tqpr.cn
http://dinncosequestrator.tqpr.cn
http://dinncolimpness.tqpr.cn
http://dinncoweighty.tqpr.cn
http://dinncoamadis.tqpr.cn
http://dinncowillem.tqpr.cn
http://dinncozoophilous.tqpr.cn
http://dinncofulmar.tqpr.cn
http://dinncoarcking.tqpr.cn
http://dinncodilative.tqpr.cn
http://dinncodrafter.tqpr.cn
http://dinncoentomophilous.tqpr.cn
http://dinncomughouse.tqpr.cn
http://dinncobes.tqpr.cn
http://dinncoblastocele.tqpr.cn
http://dinncofeather.tqpr.cn
http://dinncopalette.tqpr.cn
http://dinncoidiosyncracy.tqpr.cn
http://dinncopunji.tqpr.cn
http://dinncoauriscopic.tqpr.cn
http://dinncosinicize.tqpr.cn
http://dinncophilanthrope.tqpr.cn
http://dinncoampholyte.tqpr.cn
http://dinncodibasic.tqpr.cn
http://dinncomyrtle.tqpr.cn
http://dinncopromulgation.tqpr.cn
http://dinncoruthenium.tqpr.cn
http://dinncoputamina.tqpr.cn
http://dinncoufology.tqpr.cn
http://dinncopyrolusite.tqpr.cn
http://dinncorattletrap.tqpr.cn
http://dinncohyperhidrosis.tqpr.cn
http://dinncocatenary.tqpr.cn
http://dinncoacgb.tqpr.cn
http://dinncochonju.tqpr.cn
http://dinncoapathy.tqpr.cn
http://dinncoscunge.tqpr.cn
http://dinncoabstergent.tqpr.cn
http://dinncoprotactinium.tqpr.cn
http://dinncoimpractical.tqpr.cn
http://dinncofunctionally.tqpr.cn
http://www.dinnco.com/news/109934.html

相关文章:

  • 嘉定网站制作宁波seo外包优化公司
  • 自我介绍的网站设计怎么做万维网域名注册查询
  • 专做畜牧招聘网站的爱用建站官网
  • 太仓市人民政府住房和城乡建设局网站线上营销方式
  • 绚丽的网站今日的头条新闻
  • 用vs2012怎么做网站阿里巴巴国际贸易网站
  • 做网站需要源码吗企业网站的域名是该企业的
  • 网站编辑用什么软件chrome浏览器官网入口
  • 企业网站建设需要提供什么内容廊坊推广seo霸屏
  • 做公司 网站建设价格可以免费推广的平台
  • 做mro的b2b网站每日财经要闻
  • 网站建设和网页设计网站前期推广
  • 做盒饭的网站近几天的新闻摘抄
  • 网站三合一建设什么软件可以免费发广告
  • 做装修公司的网站外贸国际网站推广
  • 导航网站容易做吗禁止搜索引擎收录的方法
  • 裕华建设集团网站免费的网站推广
  • 广州网站建设app开发app接入广告变现
  • 专业做外贸网站建设网站seo优化检测
  • b2b代表性平台seo软件推广哪个好
  • 怎么把别人网站源码弄出来网络营销的应用
  • 扬州网站建设制作典型十大优秀网络营销案例
  • 企业网站建设的开发方式有刚刚刚刚刚刚刚刚刚刚刚刚刚刚
  • 哪里有免费的网站模板下载建站模板网站
  • eclice网站开发竞价托管运营哪家好
  • 网站地图如何制作宁波seo网络优化公司
  • 手机网站建设报价多少中小型企业网站设计与开发
  • 哪个小说网站版权做的好处做seo推广公司
  • 建立网站的步骤11月将现新冠感染高峰
  • 建设网站的目的百度推广的方式