Delphi_调用DLL方法[调用对象下面的方法]

Stella981
• 阅读 666
unit PayIntf_MisDll;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  { /* 交易类型: '00'消费'01'撤销'02'退货'03'查余
                  '04'重打印'05'签到'06'结算'08'小费'09'预授权
                  '10'预授权追加'11'预授权完成'12'预授权撤销
                  '13'预授权完成撤销'14'商场分期'15'专用分期
                  '16'分期撤销'18'分期额度查询'19'汽车卡洗车
                  '20'快速支付'21'指定账户圈存'22'电子现金退货
                  '23'电子现金查余'24'积分兑换消费'25'积分兑换撤销
                  '26'积分查询'28'权益积分查询'29'权益积分消费
                  '30'权益积分撤销'32'卡转出转账'33'财务报销'34'财务还款
                  ‘60’-聚合支付被扫
                  ‘61’-聚合支付主扫
                  ‘62’-聚合支付退货
                  ‘63’-获取 POS 扫码枪二维码数据
                  ‘64’-单笔聚合支付异常订单查询
                  '72'-聚合支付异常订单查询
                  ‘90’-惠兜圈优惠立减银行卡
                  ‘94’-惠兜圈立减优惠银联二维码
                  ‘95’-云闪付优惠立减交易
                  ‘96’-商场分期优惠立减
                  */  }
  TInputData = record
    posid: array[0..7] of char;         // /* 收银机号(8 字节,左对齐,不足部分补空格)*/
    operid: array[0..7] of char;        // /* 操作员号(8 字节,左对齐,不足部分补空格)*/
    trans: array[0..1] of char;         //交易类型 见上面
    amount: array[0..11] of char;       //  /* 金额(12 字节,无小数点,左补 0,单位:分)*/
    old_date: array[0..7] of char;      //  /* 原交易日期(8 字节,yyyymmdd 格式,隔日退货时用)*/
    old_reference: array[0..11] of char;  // /* 原交易参考号*/
    old_trace: array[0..5] of char;     // /* 流水号(6 字节,右对齐,左补 0,退货或重打印等用)*/
    old_batch: array[0..5] of char;     // /*57~62 位  原批次号*/
    old_auth: array[0..5] of char;      //  /*63~68 位  原授权码*/
    old_terno: array[0..7] of char;     // /*69~76 位  原交易终端号*/
    szFenqiNum: array[0..1] of char;    // /*77~78 位 分期数 03,06,09,12,18,24,36,42,48,60*/
    szServiceNum: array[0..1] of char;  //  /*79~80 位 享受服务人数*/
    szGoodsNo: array[0..11] of char;    //  /*81~92 位  商品项目编码*/
    trk2: array[0..36] of char;         // /*  二磁道数据(37 字节,左对齐,不足部分补空格)*/
    trk3: array[0..103] of char;        // /* 三磁道数据(104 字节, 左对齐,不足部分补空格)*/
    lrc: array[0..2] of char;           //  /* 交易校验数据(3 位从 0~9 的随机字符)*/
    szOrderTrace: array[0..19] of char; // 6/16/2015 新增 收银流水(订单)号 左对齐 不足补空格
    szPrefer: array[0..49] of char;     // 优惠券左对齐 不足补空格
    szRsv: array[0..299] of char;       // 保留字段 在此输入二维码的条码数据 左对齐 不足补空格
  end;

  TOutPutData = record
    resp_code: array[0..1] of char;    //  /*1~2 位  返回码 (2 字节,"00"交易成功,其他失败)*/
    bank_code: array[0..3] of char;    //  /*3~6 位  银行行号(4 字节)*/
    card_no: array[0..29] of char;     //  /*7~36 位  卡号:622280*********4860 */
    expr: array[0..3] of char;         //  /*37~40 位 有效期 (4 字节) */
    amount: array[0..11] of char;      //  /*141~52 位 金额(12 字节,无小数点,左补 0,单位:分)*/
    trace: array[0..5] of char;        //  /*53~58 位 流水号 (6 字节,左对齐)*/
    refer: array[0..11] of char;       //  /*59~70 位 交易参考号*/
    auth: array[0..5] of char;         //  /*71~76 位 授权号*/
    batch: array[0..5] of char;        //  /*77~82 位 批次号*/
    date: array[0..13] of char;        //  /*83~96 位 交易日期(8 字节,yyyymmddhhmmss 格式)*/
    userno: array[0..14] of char;      //  /*97~111 位 商户号*/
    terno: array[0..7] of char;        //  /*112~119 位 终端号*/
    old_terno: array[0..7] of char;    //  /*120~127 位  原终端号*/
    resp_chin: array[0..49] of char;   //  /* 错误说明(左对齐,不足部分补空格)*/
    OrderNo: array[0..49] of char;     //  /* 二维码交易订单订单号 */
    trans: array[0..1] of char;        //  /* 交易类型 */
    ChannelType: array[0..1] of char;  //  /* '0'银联二维码 '1'微信 '2' 支付宝 '3'龙支付 */
    lrc: array[0..2] of char;          //  /* 交易数据校验码(3 字节)*/
  end;

function PayIntf_Trans(ParkCode, OptorCode, Trans, Money, OldTrandID: string; var OrderNo: string): Boolean;

function GetInputStr(ParkCode, OptorCode, Trans, Money, OldTrandID: string; var InStr: string): Boolean;

procedure GetOutputData(OutStr: string);

procedure FillArrayChar(FillType, ParamVaule: string; var ArrVaule: array of char);

function GetOldTradeInfo(OldTrandID: string; var old_date, old_reference, old_trace: string): boolean;

function CheckDataValid(ParkCode, OptorCode, Trans, Money, OldTrandID: string): boolean;

function Obj2Json_InputData(InputData: TInputData): string;

function Obj2Json_OutputData(OutputData: TOutputData): string;

procedure MyWriteLog(const mStr: string);

function BankTrans(PInStr: Pchar; POutStr: Pchar): integer; stdcall; external 'C:\landiccbmispos\MisPos.dll';   //0- 成功 , 其他-失败

implementation

function CheckDataValid(ParkCode, OptorCode, Trans, Money, OldTrandID: string): boolean;
var
  sMsg,sFileDLL: string;
begin
  Result := False;
  sFileDLL := 'C:\landiccbmispos\MisPos.dll';
  if not FileExists(sFileDLL) then
  begin
    sMsg := '调用支付接口文件不存在!';
    MyWriteLog(sMsg + '[' + sFileDLL + ']');
    Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
    Exit;
  end;

  if (Trans <> '00') and (Trans <> '01') and (Trans <> '02')
  and (Trans <> '05') and (Trans <> '06') then    //'00'消费'01'撤销'02'退货'03'查余 '05'签到'06'结算
  begin
    sMsg := '非法的交易类型!';
    MyWriteLog(sMsg);
    Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
    Exit;
  end;
  if (Trans = '01') or (Trans = '02') then
  begin
    if OldTrandID = '' then
    begin
      sMsg := '撤销和退货时,请传入原交易单号!';
      MyWriteLog(sMsg);
      Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
      Exit;
    end;
  end;
  if StrToCurrDef(Money,0) <= 0 then
  begin
    sMsg := '金额不允许为负数或零!';
    MyWriteLog(sMsg);
    Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
    Exit;
  end;

  Result := True;
end;

function PayIntf_Trans(ParkCode, OptorCode, Trans, Money, OldTrandID: string; var OrderNo: string): Boolean;
var
  lv_nRet: integer;
  InStr: string;
  OutStr: string;
  sMsg: string;
  resp_code: string;
begin
  {*  1、检查传入参数:根据文档规则
   *  2、参数组合成定长字符串
   *  3、调用DLL方法
   *  4、解析返回定长字符串:判断结果
   *  5、记录日志
   *}
   
  //检查传入参数
  if not CheckDataValid(ParkCode, OptorCode, Trans, Money, OldTrandID) then
  begin
    Exit;
  end;

  //组合传入参数,形成定长字符串InStr
  if not GetInputStr(ParkCode, OptorCode, Trans, Money, OldTrandID, InStr) then
  begin
    Exit;
  end;

  MyWriteLog('发送定长字符串:[' + InStr + ']');
  SetLength(OutStr, SizeOf(TOutPutData));
  Application.ProcessMessages;
  lv_nRet := BankTrans(Pchar(InStr), Pchar(OutStr));   //调用DLL中的BankTrans方法
  Application.ProcessMessages;
  MyWriteLog('返回定长字符串:[' + OutStr + ']');
  GetOutputData(OutStr);

  if (lv_nRet <> 0) or (Copy(OutStr, 1, 2) <> '00') then
  begin
    sMsg := '交易失败!';
    MyWriteLog(sMsg);
    Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
    Exit;
  end;

  OrderNo := Trim(Copy(OrderNo, 158, 50));
  if Copy(OrderNo, 1, 8) <> 'EEEEEEEE' then   // 特殊,当退货出现异常情况, 如网络异常时, 返回头的输出参数头2个字节为00其余字符会以大写字母EE填充,
  begin                                       //同时DLL会弹出对话框。请商户及时和银行核实是否退货成功!!!
    sMsg := '交易成功!';
    MyWriteLog(sMsg + '[' + OrderNo + ']');
    Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
  end else
  begin
    sMsg := '交易成功,单需要手工核对!';
    MyWriteLog(sMsg + '[' + OrderNo + ']');
    Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
  end;
  
end;

function GetInputStr(ParkCode, OptorCode, Trans, Money, OldTrandID: string; var InStr: string): Boolean;
var
  old_date, old_reference, old_trace, sMsg: string;
  InputData: TInputData;
begin
  {交易说明:
            消费 :传入必要信息为 (交易类型,金额)
            退货 :传入必要信息为 (交易类型,金额,原交易参考号,原交易日期)
            撤销 : 传入必要信息为 (交易类型,金额,原流水号)
            查余 : 传入必要信息为 (交易类型)
            注: 查询金额 操作 卡内余额显示在 密码键盘。并且不会返回对应的余额.
            重打印 : 传入必要信息为 (交易类型,原流水号)
            注: 重打印上一笔交易 原流水号:”000000”
            签到 : 传入必要信息为 (交易类型)
            结算 : 传入必要信息为 (交易类型)  }
  Result := False;
  try
    FillChar(InputData,SizeOf(TInputData),' ');
    FillArrayChar('RN', ParkCode, InputData.posid);
    FillArrayChar('RN', OptorCode, InputData.operid);
    FillArrayChar('R0', Trans, InputData.trans);
    FillArrayChar('L0', IntToStr(Trunc(StrToCurrDef(Money, 0) * 100)), InputData.amount);

    if (Trans = '01') or (Trans = '02') then    //'00'消费'01'撤销'02'退货'03'查余
    begin
      //获取原交易信息
      if not GetOldTradeInfo(OldTrandID, old_date, old_reference, old_trace) then
      begin
        Exit;
      end;

      if Trans = '01' then
      begin
        FillArrayChar('L0', old_trace, InputData.old_trace);           // /* 原流水号(6 字节,右对齐,左补 0,退货或重打印等用)*/
        FillArrayChar('RN', '', InputData.old_date);
        FillArrayChar('RN', '', InputData.old_reference);
      end;
      if Trans = '02' then
      begin
        FillArrayChar('L0', '', InputData.old_trace);
        FillArrayChar('RN', old_date, InputData.old_date);             // /* 原交易日期(8 字节,yyyymmdd 格式,隔日退货时用)*/
        FillArrayChar('RN', old_reference, InputData.old_reference);   // /* 原交易参考号*/
      end;
    end
    else        //非撤销和退货
    begin
      FillArrayChar('L0', '', InputData.old_trace);
      FillArrayChar('RN', '', InputData.old_date);
      FillArrayChar('RN', '', InputData.old_reference);
    end;

    //以下为默认填充
    FillArrayChar('RN', '', InputData.old_batch);    // /*57~62 位  原批次号*/
    FillArrayChar('RN', '', InputData.old_auth);     //  /*63~68 位  原授权码*/
    FillArrayChar('RN', '', InputData.old_terno);    // /*69~76 位  原交易终端号*/
    FillArrayChar('RN', '', InputData.szFenqiNum);   // /*77~78 位 分期数 03,06,09,12,18,24,36,42,48,60*/
    FillArrayChar('RN', '', InputData.szServiceNum); //  /*79~80 位 享受服务人数*/
    FillArrayChar('RN', '', InputData.szGoodsNo);    //  /*81~92 位  商品项目编码*/
    FillArrayChar('RN', '', InputData.trk2);         // /*  二磁道数据(37 字节,左对齐,不足部分补空格)*/
    FillArrayChar('RN', '', InputData.trk3);         // /* 三磁道数据(104 字节, 左对齐,不足部分补空格)*/
    FillArrayChar('RN', '', InputData.lrc);          //  /* 交易校验数据(3 位从 0~9 的随机字符)*/
    FillArrayChar('RN', '', InputData.szOrderTrace); // 6/16/2015 新增 收银流水(订单)号 左对齐 不足补空格
    FillArrayChar('RN', '', InputData.szPrefer);     // 优惠券左对齐 不足补空格
    FillArrayChar('RN', '', InputData.szRsv);        // 保留字段 在此输入二维码的条码数据 左对齐 不足补空格

    //取传参的累加的定长字符串
    SetLength(InStr,SizeOf(TInputData));
    StrLCopy(Pchar(InStr), @InputData, SizeOf(TInputData));
    sMsg := '发送信息[转换为JSON]:' + Obj2Json_InputData(InputData);
    MyWriteLog(sMsg);
    Result := True;
  except
    on e: exception do
    begin
      sMsg := '获取传入参数字符串异常:' + e.message;
      MyWriteLog(sMsg);
      Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
      Exit;
    end;
  end;
end;

procedure GetOutputData(OutStr: string);
var
  sMsg, sTemp: string;
  OutputData: TOutPutData;
begin
  try
    if OutStr = '' then
    begin
      sMsg := '交易返回参数为空!';
      MyWriteLog(sMsg);
      Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
      Exit;
    end;

    //字符串赋值给记录
    FillChar(OutputData,SizeOf(TOutputData),' ');
    StrLCopy(@OutputData, Pchar(OutStr), SizeOf(TOutputData));

    //记录返回的信息
    sTemp := '返回信息[转换为JSON]:' + Obj2Json_OutputData(OutputData);
    MyWriteLog(sTemp);
  except
    on e: exception do
    begin
      sMsg := '转换返回参数异常:' + e.message;
      MyWriteLog(sMsg);
      Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
      Exit;
    end;
  end;
end;

function Obj2Json_InputData(InputData: TInputData): string;
begin
  Result := '{';
  Result := Result + '"posid":"' + Trim(InputData.posid) + '",';
  Result := Result + '"operid":"' + Trim(InputData.operid) + '",';
  Result := Result + '"trans":"' + Trim(InputData.trans) + '",';
  Result := Result + '"amount":"' + Trim(InputData.amount) + '",';
  Result := Result + '"old_date":"' + Trim(InputData.old_date) + '",';
  Result := Result + '"old_reference":"' + Trim(InputData.old_reference) + '",';
  Result := Result + '"old_trace":"' + Trim(InputData.old_trace) + '",';
  Result := Result + '"old_batch":"' + Trim(InputData.old_batch) + '",';
  Result := Result + '"old_auth":"' + Trim(InputData.old_auth) + '",';
  Result := Result + '"old_terno":"' + Trim(InputData.old_terno) + '",';
  Result := Result + '"szFenqiNum":"' + Trim(InputData.szFenqiNum) + '",';
  Result := Result + '"szServiceNum":"' + Trim(InputData.szServiceNum) + '",';
  Result := Result + '"szGoodsNo":"' + Trim(InputData.szGoodsNo) + '",';
  Result := Result + '"trk2":"' + Trim(InputData.trk2) + '",';
  Result := Result + '"trk3":"' + Trim(InputData.trk3) + '",';
  Result := Result + '"lrc":"' + Trim(InputData.lrc) + '",';
  Result := Result + '"szOrderTrace":"' + Trim(InputData.szOrderTrace) + '",';
  Result := Result + '"szPrefer":"' + Trim(InputData.szPrefer) + '",';
  Result := Result + '"szRsv":"' + Trim(InputData.szRsv) + '"';
  Result := Result + '}';
end;

function Obj2Json_OutputData(OutputData: TOutputData): string;
begin
  Result := '{';
  Result := Result + '"resp_code":"' + Trim(OutputData.resp_code) + '",';
  Result := Result + '"bank_code":"' + Trim(OutputData.bank_code) + '",';
  Result := Result + '"card_no":"' + Trim(OutputData.card_no) + '",';
  Result := Result + '"expr":"' + Trim(OutputData.expr) + '",';
  Result := Result + '"amount":"' + Trim(OutputData.amount) + '",';
  Result := Result + '"trace":"' + Trim(OutputData.trace) + '",';
  Result := Result + '"refer":"' + Trim(OutputData.refer) + '",';
  Result := Result + '"auth":"' + Trim(OutputData.auth) + '",';
  Result := Result + '"batch":"' + Trim(OutputData.batch) + '",';
  Result := Result + '"date":"' + Trim(OutputData.date) + '",';
  Result := Result + '"userno":"' + Trim(OutputData.userno) + '",';
  Result := Result + '"terno":"' + Trim(OutputData.terno) + '",';
  Result := Result + '"old_terno":"' + Trim(OutputData.old_terno) + '",';
  Result := Result + '"resp_chin":"' + Trim(OutputData.resp_chin) + '",';
  Result := Result + '"OrderNo":"' + Trim(OutputData.OrderNo) + '",';
  Result := Result + '"trans":"' + Trim(OutputData.trans) + '",';
  Result := Result + '"ChannelType":"' + Trim(OutputData.ChannelType) + '",';
  Result := Result + '"lrc":"' + Trim(OutputData.lrc) + '"';
  Result := Result + '}';
end;

function GetOldTradeInfo(OldTrandID: string; var old_date, old_reference, old_trace: string): boolean;
var
  sMsg: string;
begin
  Result := False;
  try
    old_date := '20190805';
    old_reference := '123456789987456';
    old_trace := '123456';

    Result := True;
  except
    on e: exception do
    begin
      sMsg := '获取原交易支付信息异常[原交易号:' + OldTrandID + ']:' + e.message;
      MyWriteLog(sMsg);
      Application.MessageBox(Pchar(sMsg), '提示', MB_OK);
      Exit;
    end;
  end;
end;

procedure FillArrayChar(FillType, ParamVaule: string; var ArrVaule: array of char);
var
  I, Len, Diff: integer;
  sTemp: string;
begin
  Len := Length(ArrVaule);
  if Length(ParamVaule) < Len then
  begin
    Diff := Len - Length(ParamVaule);
    for I := 1 to Diff do
    begin
      if Copy(FillType, 2, 1) = '0' then    //填充"0"
      begin
        sTemp := sTemp + '0';
      end
      else
      begin
        sTemp := sTemp + ' ';             //填充空格
      end;
    end;

    if Copy(FillType, 1, 1) = 'L' then  //左填充
    begin
      sTemp := sTemp + ParamVaule;
    end
    else if Copy(FillType, 1, 1) = 'R' then   //右填充
    begin
      sTemp := ParamVaule + sTemp;
    end;
  end else
  begin
    sTemp := ParamVaule;
  end;

  for I := 1 to Len do
  begin
    ArrVaule[I - 1] := sTemp[I];
  end;
end;

procedure MyWriteLog(const mStr: string);
var
  f: textfile;
  myDir, myFileName: string;
  FileHandle: Integer;
  LogType, LogDate, ModuleID: string;
begin
  LogType := 'INFO';
  LogDate := FormatDateTime('YYYY-MM-DD hh:nn:ss zzz', Now);
  ModuleID := '';
//  if not (CanLogFile in FLogFlags) then exit;
  //------写入文件部分的实现--开始
  myDir := ExtractFilePath(Paramstr(0));
  //确定文件名称
  myFileName := FormatDateTime('"PayIntf"yyyymmdd".log"', Date);
  //如果可执行目录下不存在log目录创建之
  if not DirectoryExists(myDir + '\log') then
    CreateDir(myDir + '\log');
  //如果当日日志文件不存在,则创建文件并释放句柄
  if not FileExists(myDir + '\log\' + myFileName) then
  begin
    FileHandle := FileCreate(myDir + '\log\' + myFileName); //创建文件
    FileClose(FileHandle); //释放句柄
  end;
  try//try...except...statements
    AssignFile(f, myDir + '\log\' + myFileName);
    Append(f);
    Writeln(f, '$$' + Format('%6s', [LogType]) + '$$ ' + Format('%12s', [ModuleID]) + '$$' + LogDate + chr(9) + mStr);
    Flush(f);
    CloseFile(f);
    //-----写入文件部分的实现--结束
  except//try...except...statements
  end; //try...except...statements
end;

end.
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
SysUtils.StrByteType
unitUnit1;interfaceusesWindows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls;typeTForm
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这