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

Delphi 字节数组固定长度补前导00 适配智能卡APDU指令

问题根因

你代码中先执行SetLength(taxPayerId, 20)申请了20字节的数组,后续直接将TEncoding.UTF8.GetBytes的返回值赋值给taxPayerId,这会直接覆盖之前申请的数组,替换为长度和字符串转码结果一致的短数组,长度设置完全失效。

修正方案

直接修正逻辑

直接修改你现有税号处理部分的代码即可达到目标效果:

var
  dateAndTimeOfIssue, taxPayerId: TArray<Byte>;
  dateOfIssueMS, DOIReversed: Int64;
  // 新增临时变量存储转码后的税号字节
  tempTaxIdBytes: TArray<Byte>;
  i, contentOffset: Integer;
begin
  // 原有日期处理逻辑无需修改,本身是正确的
  dateOfIssueMS := StrToInt64(MilliSecondsBetween(f.InvoiceRequest.dateAndTimeOfIssue, 
                   UnixDateDelta).ToString);
  ReverseBytes(@(dateofIssueMS), @(DOIReversed), SizeOf(dateofIssueMS));
  SetLength(dateAndTimeOfIssue, 8);
  Move(DOIReversed, dateAndTimeOfIssue[0], SizeOf(DOIReversed));

  // 修正后的税号字节处理
  tempTaxIdBytes := TEncoding.UTF8.GetBytes(F.MyCompany.taxpayerId);
  // 初始化20字节的目标数组,全部填充00
  SetLength(taxPayerId, 20);
  for i := Low(taxPayerId) to High(taxPayerId) do
    taxPayerId[i] := $00;
  // 计算内容偏移量:内容放在数组尾部,前序补0
  contentOffset := Length(taxPayerId) - Length(tempTaxIdBytes);
  if contentOffset >= 0 then
    Move(tempTaxIdBytes[0], taxPayerId[contentOffset], Length(tempTaxIdBytes));
end;

通用封装(推荐)

你后续需要处理多个字节数组、还要合并为最终APDU包,可以封装两个通用函数复用逻辑:

  1. 固定长度字节数组生成函数
/// <summary>生成固定长度的字节数组,空缺位置默认补00</summary>
/// <param name="srcBytes">源内容字节</param>
/// <param name="targetLen">目标数组长度</param>
/// <param name="fillByte">填充用字节,默认$00</param>
/// <param name="fillBefore">是否在内容前填充,True=前补,False=后补</param>
function GetFixedLenBytes(const srcBytes: TArray<Byte>; targetLen: Integer; 
  fillByte: Byte = $00; fillBefore: Boolean = True): TArray<Byte>;
var
  i, copyOffset, copyLen: Integer;
begin
  SetLength(Result, targetLen);
  // 先全量填充指定字节
  for i := Low(Result) to High(Result) do
    Result[i] := fillByte;
  if Length(srcBytes) = 0 then Exit;
  // 计算复制偏移和长度,超出目标长度则截断
  copyLen := Min(Length(srcBytes), targetLen);
  if fillBefore then
    copyOffset := targetLen - copyLen
  else
    copyOffset := 0;
  Move(srcBytes[0], Result[copyOffset], copyLen);
end;
  1. 多字节数组合并函数
/// <summary>合并多个字节数组为一个数组</summary>
function MergeByteArray(const arrList: array of TArray<Byte>): TArray<Byte>;
var
  i, totalLen, currPos: Integer;
begin
  totalLen := 0;
  for i := Low(arrList) to High(arrList) do
    Inc(totalLen, Length(arrList[i]));
  SetLength(Result, totalLen);
  currPos := 0;
  for i := Low(arrList) to High(arrList) do
  begin
    if Length(arrList[i]) = 0 then Continue;
    Move(arrList[i][0], Result[currPos], Length(arrList[i]));
    Inc(currPos, Length(arrList[i]));
  end;
end;

后续处理其他字段、合并数组时直接调用即可:

// 处理税号
tempTaxIdBytes := TEncoding.UTF8.GetBytes(F.MyCompany.taxpayerId);
taxPayerId := GetFixedLenBytes(tempTaxIdBytes, 20);
// 处理其他字段同理,比如某字段需要后补0
// otherField := GetFixedLenBytes(otherBytes, 10, $00, False);
// 合并为最终APDU字节数组
finalAPDU := MergeByteArray([dateAndTimeOfIssue, taxPayerId, otherField1, otherField2]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 08:15:01