unit YSL_ConsumeIntf;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdHTTP, IdHashMessageDigest, superobject;
type
TConsume = record
cardSnr: string; //卡序列号
clientTradeCode: string; //随机码
consumeMoney: Double; //消费金额
consumeBusinessSourceType: Integer; //传9
placeId: Integer; //场所编号(配置一下,测试环境随便)
placeName: string; //场所名称(配置一下,测试环境随便)
sourceUser: string; //操作员(配置一下,测试环境使用gzy)
sign: string; //签名
end;
type
TRetConsume = record
corpCode: string;
cardInfoId: string; //卡ID
clientTradeCode: string; //客户端交易号
consumeMoney: Double; //消费金额
leftMoney: Double; //剩余金额
cardSnr: string; //卡序列号
end;
function Post_YSLConsume(cardSnr: string; consumeMoney: Double; var leftMoney: Double): Boolean;
implementation
function MyReadIniItem(const Section, Item, IniFileName, DefaultValue: string): string;
var
Value: string;
begin
SetLength(Value, 3001 * sizeof(Char));
GetPrivateProfileString(PChar(Section), PChar(Item), '', PChar(Value), 3000, PChar(ExtractFilePath(Paramstr(0)) + IniFileName));
SetLength(Value, StrLen(PChar(Value)));
if Trim(Value) <> '' then
Result := Value
else
Result := DefaultValue;
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('"YSLConsumeIntf"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;
function ret_mymd5(const sVaule: string): string;
var
mymd5: TIdHashMessageDigest5;
begin
try
mymd5 := TIdHashMessageDigest5.Create;
Result := LowerCase(mymd5.AsHex(mymd5.HashValue(sVaule)));
finally
mymd5.Free;
end;
end;
function getContent(AConsume: TConsume; privateKey: string): string;
var
i: Integer;
lv_sTmp: string;
lv_List: TStringList;
begin
Result := '';
try
lv_List := TStringList.Create;
try
if Trim(AConsume.cardSnr) <> '' then
lv_List.Add('cardSnr=' + AConsume.cardSnr);
if Trim(AConsume.clientTradeCode) <> '' then
lv_List.Add('clientTradeCode=' + AConsume.clientTradeCode);
if Length(FloatToStr(AConsume.consumeMoney)) > 0 then
lv_List.Add('consumeMoney=' + FloatToStr(AConsume.consumeMoney));
if Length(IntToStr(AConsume.consumeBusinessSourceType)) > 0 then
lv_List.Add('consumeBusinessSourceType=' + IntToStr(AConsume.consumeBusinessSourceType));
if Length(IntToStr(AConsume.placeId)) > 0 then
lv_List.Add('placeId=' + IntToStr(AConsume.placeId));
if Trim(AConsume.placeName) <> '' then
lv_List.Add('placeName=' + AConsume.placeName);
if Trim(AConsume.sourceUser) <> '' then
lv_List.Add('sourceUser=' + AConsume.sourceUser);
lv_List.Sorted := False;
lv_List.CaseSensitive := True; //此句设置排序大小写敏感
lv_List.Sort; //最后进行sort排序
//累加字符串
for i := 0 to lv_List.Count - 1 do
lv_sTmp := lv_sTmp + lv_List.Strings[i] + '&';
lv_sTmp := Copy(lv_sTmp, 1, Length(lv_sTmp) - 1) + privateKey;
MyWriteLog('[组合签名字符串]' + lv_sTmp);
Result := lv_sTmp;
finally
FreeAndNil(lv_List);
end;
except
on e: Exception do
begin
MyWriteLog('[组合签名字符串]异常:' + e.Message);
Exit;
end;
end;
end;
function getSing(AConsume: TConsume; privateKey: string): string;
var
lv_sTmp: string;
begin
try
lv_sTmp := ret_mymd5(getContent(AConsume, privateKey));
MyWriteLog('[生成签名结果]' + lv_sTmp);
Result := lv_sTmp;
except
on e: Exception do
begin
MyWriteLog('[获取签名]异常:' + e.Message);
Exit;
end;
end;
end;
function doHttpPost(const aUrl, aJson: string): string;
var
IDHttp: TIdHTTP;
requestBody: TStringStream;
begin
Result := EmptyStr;
try
try
IDHttp := TIdHTTP.Create(nil);
IDHttp.Request.ContentType := 'application/json';
IDHttp.HTTPOptions := IDHttp.HTTPOptions + [hoKeepOrigProtocol]; //必须有这行才使设置协议版本生效
IDHttp.ProtocolVersion := pv1_1;
requestBody := TStringStream.Create(aJson);
Result := AnsiLowerCase(Utf8ToAnsi(IDHttp.Post(aUrl, requestBody)));
except
on e: Exception do
begin
MyWriteLog('[POST]接口请求异常!' + e.Message);
Exit;
end;
end;
finally
freeandnil(IDHttp);
freeandnil(requestBody);
end;
end;
function Record2Json_TConsume(AConsume: TConsume): string;
var
lv_sTmp: string;
begin
try
lv_sTmp := '{';
lv_sTmp := lv_sTmp + '"cardSnr":"' + AConsume.cardSnr + '",';
lv_sTmp := lv_sTmp + '"clientTradeCode":"' + AConsume.clientTradeCode + '",';
lv_sTmp := lv_sTmp + '"consumeMoney":"' + FloatToStr(AConsume.consumeMoney) + '",';
lv_sTmp := lv_sTmp + '"consumeBusinessSourceType":"' + IntToStr(AConsume.consumeBusinessSourceType) + '",';
lv_sTmp := lv_sTmp + '"placeId":"' + IntToStr(AConsume.placeId) + '",';
lv_sTmp := lv_sTmp + '"placeName":"' + AConsume.placeName + '",';
lv_sTmp := lv_sTmp + '"sourceUser":"' + AConsume.sourceUser + '",';
lv_sTmp := lv_sTmp + '"sign":"' + AConsume.sign + '"}';
Result := lv_sTmp;
except
on e: Exception do
begin
MyWriteLog('[组合消费Json字符串]异常:' + e.Message);
Exit;
end;
end;
end;
function getGUID(): string;
var
lv_sTmp: string;
AGUID: TGUID;
begin
try
CreateGUID(AGUID);
lv_sTmp := StringReplace(GUIDToString(AGUID),'-','',[rfReplaceAll]);
lv_sTmp := StringReplace(lv_sTmp,'{','',[rfReplaceAll]);
lv_sTmp := StringReplace(lv_sTmp,'}','',[rfReplaceAll]);
Result := lv_sTmp;
except
on e: Exception do
begin
MyWriteLog('[生成GUID随机码]异常:' + e.Message);
Exit;
end;
end;
end;
function AnalysisRetString(sRetJsonString: string; var ARetConsume: TRetConsume; var leftMoney: Double): Boolean;
var
JSO: ISuperObject;
begin
Result := False;
try
if sRetJsonString = '' then
begin
MyWriteLog('[解析返回信息]字符串为空,退出!');
Exit;
end;
JSO := SO(sRetJsonString);
if JSO.O['status'] = nil then
begin
MyWriteLog('[解析返回信息]status为空,退出!');
Result := False;
Exit;
end
else
begin
if JSO.O['status'].AsInteger <> 200 then
begin
MyWriteLog('[解析返回信息]status非成功200标识,退出!');
Result := False;
Exit;
end;
if JSO.O['data'].O['corpcode'] <> nil then
ARetConsume.corpCode := JSO.O['data'].O['corpcode'].AsString;
if JSO.O['data'].O['cardinfoid'] <> nil then
ARetConsume.cardInfoId := JSO.O['data'].O['cardinfoid'].AsString;
if JSO.O['data'].O['clienttradecode'] <> nil then
ARetConsume.clientTradeCode := JSO.O['data'].O['clienttradecode'].AsString;
if JSO.O['data'].O['consumemoney'] <> nil then
ARetConsume.consumeMoney := JSO.O['data'].O['consumemoney'].AsDouble;
if JSO.O['data'].O['leftmoney'] <> nil then
ARetConsume.leftMoney := JSO.O['data'].O['leftmoney'].AsDouble;
if JSO.O['data'].O['cardsnr'] <> nil then
ARetConsume.cardSnr := JSO.O['data'].O['cardsnr'].AsString;
leftMoney := ARetConsume.leftMoney;
Result := True;
end;
except
on e: Exception do
begin
MyWriteLog('[解析返回信息]异常:' + e.Message);
Exit;
end;
end;
end;
function Post_YSLConsume(cardSnr: string; consumeMoney: Double; var leftMoney: Double): Boolean;
var
AConsume: TConsume;
ARetConsume: TRetConsume;
lv_sUrl,lv_sRetString,lv_sTmp: string;
begin
Result := False;
leftMoney := 0;
try
MyWriteLog('-------------------[消费]--------------------');
MyWriteLog('传入参数:cardSnr=' + cardSnr + ',consumeMoney=' + FloatToStr(consumeMoney));
FillMemory(@AConsume, SizeOf(TConsume), Byte(#0));
FillMemory(@ARetConsume, SizeOf(TRetConsume), Byte(#0));
AConsume.cardSnr := cardSnr;
AConsume.clientTradeCode := getGUID();
AConsume.consumeMoney := consumeMoney;
AConsume.consumeBusinessSourceType := 9;
AConsume.placeId := StrToIntDef(MyReadIniItem('Location','LocationCode','YSLConsume.Ini',''),0);
AConsume.placeName := MyReadIniItem('Location','LocationName','YSLConsume.Ini','');
AConsume.sourceUser := MyReadIniItem('User','OperatorCode','YSLConsume.Ini','');
AConsume.sign := getSing(AConsume, MyReadIniItem('Key','PrivateKey','YSLConsume.Ini',''));
lv_sUrl := MyReadIniItem('Url','Url_Consume','YSLConsume.Ini','');
lv_sTmp := Record2Json_TConsume(AConsume);
MyWriteLog('提交Url:' + lv_sUrl+ ', 参数:' + lv_sTmp);
lv_sRetString := doHttpPost(lv_sUrl,lv_sTmp);
MyWriteLog('返回信息:' + lv_sRetString);
Result := AnalysisRetString(lv_sRetString,ARetConsume,leftMoney);
MyWriteLog('-------------------[消费]--是否成功:' + BoolToStr(Result,True) + ',剩余金额:' + FloatToStr(leftMoney) + '元------------------');
except
on e: Exception do
begin
MyWriteLog('[消费接口]异常:' + e.Message);
Exit;
end
end;
end;
end.
delphi_postjson
最新推荐文章于 2024-04-15 12:29:18 发布