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

如何用JavaScript从ASN.1解析Apple收据的bundle_id等信息?

Node.js 解析Apple App Store收据ASN.1格式提取核心字段

核心思路

Apple App Store收据在PKCS#7容器的EncapsulatedContentInfo中以OCTET STRING存储,解析需两步:先提取该OCTET STRING作为收据的ASN.1 payload,再解析payload内部结构——它是一个包含多组属性的序列,每组属性由类型码、版本、值组成,bundle_id、receipt_creation_date等字段对应固定类型码(比如bundle_id对应2,receipt_creation_date对应12)。

具体实现步骤(基于node-forge + asn1js)

  1. 解析PKCS#7容器,提取收据ASN.1 payload
    用node-forge加载PKCS#7数据,定位并提取目标OCTET STRING:

    const forge = require('node-forge');
    const asn1js = require('asn1js');
    
    // receiptData为base64编码的收据字符串
    function extractReceiptPayload(receiptData) {
      const derBuffer = forge.util.decode64(receiptData);
      const asnStructure = forge.asn1.fromDer(derBuffer);
      // 定位PKCS#7中的EncapsulatedContentInfo -> eContent
      const signedData = asnStructure.value[0].value[1];
      const encapContentInfo = signedData.value[2];
      const eContent = encapContentInfo.value[1].value[0];
      // 转换为Uint8Array供asn1js解析
      return new Uint8Array(forge.util.createBuffer(eContent.value).bytes());
    }
    
  2. 解析收据ASN.1 payload,提取目标字段
    用asn1js解析payload,遍历属性序列匹配类型码提取字段:

    function parseReceiptFields(payload) {
      const asn1Result = asn1js.fromBER(payload);
      const receiptSequence = asn1Result.result.valueBlock.value;
      const receiptFields = {};
    
      receiptSequence.forEach(attribute => {
        const typeId = attribute.valueBlock.value[0].valueBlock.valueDec;
        const value = attribute.valueBlock.value[2].valueBlock.value;
    
        switch (typeId) {
          case 2: // bundle_id
            receiptFields.bundle_id = value;
            break;
          case 12: // receipt_creation_date
            receiptFields.receipt_creation_date = new Date(value);
            break;
          // 可扩展其他字段:比如交易ID(17)、产品ID(19)、原始购买日期(14)等
        }
      });
    
      return receiptFields;
    }
    
  3. 整合调用示例

    const receiptData = '你的base64格式收据字符串';
    const payload = extractReceiptPayload(receiptData);
    const parsedFields = parseReceiptFields(payload);
    console.log('Bundle ID:', parsedFields.bundle_id);
    console.log('收据创建时间:', parsedFields.receipt_creation_date);
    

关键说明

  • 类型码对应关系:Apple官方定义了所有收据字段的类型码,可参考官方文档的「Receipt Attributes」部分。
  • 日期处理:收据中的日期字段是IA5STRING格式的ISO 8601字符串,直接用new Date()即可转换为JavaScript日期对象。
  • 简化方案:若不想手动实现,可使用第三方封装库(如app-store-receipt-parser),内部已完成PKCS#7解析和字段映射逻辑。

内容的提问来源于stack exchange,提问作者Juraj Zovinec

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:56:27