导航:
论坛 -> 开源项目
斑竹:joki,ralf_jones
作者:
2020/11/26 11:14:59
标题:
用delphi开发微信支付和支付宝支付
浏览:5719
加入我的收藏
楼主:
不管是微信支付还是支付宝支付, 3个最棘手的问题是: 1,如何生成签名 2,支付请求如何提交 3, 如何验证签名 下面就围绕这三个问题来讲。 我使用的是XE3. 先看微信支付: 1,微信支付的签名生成 uses IdHashMessageDigest, NatvieXml; //我使用的是NativeXml4.07 function TMicroPayParamBuilder.GetSign: string; var Digest: TIdHashMessageDigest5; utf8: UTF8String; begin utf8 := ''; Assert(FAppId <> '', '公众账号ID 不能为空!'); utf8 := utf8 + 'appid=' + FAppId; if FAttach <> '' then utf8 := utf8 + '&attach=' + FAttach; Assert(FAuthCode <> '', '授权码 不能为空!'); utf8 := utf8 + '&auth_code=' + FAuthCode; Assert(FBody <> '', '商品描述 不能为空!'); utf8 := utf8 + '&body=' + FBody; if FDetail <> '' then utf8 := utf8 + '&detail=' + BuildDetail(); Assert(FMchId <> '', '商户号 不能为空!'); utf8 := utf8 + '&mch_id=' + FMchId; utf8 := utf8 + '&non_ce_str=' + FNonceStr; Assert(FOutTradeNo <> '', '商户订单号 不能为空!'); utf8 := utf8 + '&out_trade_no=' + FOutTradeNo; Assert(FSpbillCreateIp <> '', '终端IP 不能为空!'); utf8 := utf8 + '&spbill_create_ip=' + FSpbillCreateIp; Assert(FTotalFee > 0, '订单金额 必须大于0!'); utf8 := utf8 + '&total_fee=' + IntToStr(FTotalFee); Assert(Fkey <> '', '密钥 不能为空!'); utf8 := utf8 + '&key=' + Fkey; //计算签名 try Digest:= TIdHashMessageDigest5.Create; Result := Digest.HashBytesAsHex(BytesOf(utf8)); finally Digest.Free; end; end; //生成Http Post请求的数据 function TMicroPayParamBuilder.BuildParam: string; var xml : TNativeXml; Node: TXmlNode; begin xml := TNativeXml.CreateEx(nil, False, False, True, 'xml'); try Node:= xml.NodeNewTextType('appid', FAppId , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewTextType('mch_id', FMchId , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewTextType('nonce_str', FNonceStr , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewTextType('sign', Sign , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewTextType('body', FBody , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewTextType('out_trade_no', FOutTradeNo , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewIntType('total_fee', FTotalFee , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewTextType('spbill_create_ip', FSpbillCreateIp , xeElement); xml.Root.NodeAdd(Node); Node:= xml.NodeNewTextType('auth_code', FAuthCode , xeElement); xml.Root.NodeAdd(Node); if FAttach <> '' then begin Node:= xml.NodeNewTextType('attach', FAttach , xeElement); xml.Root.NodeAdd(Node); end; if FDetail <> '' then begin Node:= xml.NodeNewTextType('detail', BuildDetail() , xeElement); xml.Root.NodeAdd(Node); end; Result := xml.WriteToString; finally xml.Free; end; end; 2, 微信支付请求如何提交 class function TTencentSSLHttpPost.Post(URL: string; Builder: TBaseParamBuilder): string; var ssl:TIdSSLIOHandlerSocketOpenSSL; http: TIdHttp; inStrm, outStrm: TStringStream; begin http:= TIdHttp.Create(nil); ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil); ssl.SSLOptions.Method := sslvSSLv23; http.IOHandler := ssl; inStrm:= TStringStream.Create(Builder.BuildParam, TEncoding.UTF8); outStrm:= TStringStream.Create('', TEncoding.UTF8); try try http.Post(URL, inStrm, outStrm); Result := outStrm.DataString; except Result := ''; end; finally ssl.Free; http.Free; outStrm.Free; inStrm.Free; end; end; const URL_MicroPay = 'https://api.mch.weixin.qq.com/pay/micropay& #39;; class function TMicroPayHttpUtils.PostRequest( Builder: TMicroPayParamBuilder): string; begin Result := TTencentSSLHttpPost.Post(URL_MicroPay, Builder); end; 微信如何验证签名: TStringsHelper = class helper for TStrings function Join(const Splitter: string): string; end; { TMyStrings} function TStringsHelper.Join(const Splitter: string): string; var I : Integer; begin Result := ''; for I := 0 to Self.Count - 1 do Result := Result + Splitter + Self.Names[I] + '=' + Self.ValueFromIndex[I]; if Result <> '' then System.Delete(result, 1, Length(Splitter)); end; function MyStringListSort(List: TStringList; Index1, Index2: Integer): Integer; begin Result := CompareStr(List.Names[Index1], List.Names[Index2]); end; function VerifyResponseSign(xml: TNativeXml; Key: string): Boolean; overload; var sign: string; I : Integer; List : TStringList; utf8: UTF8String; Digest: TIdHashMessageDigest5; begin Result := False; if xml.Root.FindNode('sign') = nil then Exit; sign := xml.Root.FindNode('sign').ValueUnicode; List := TStringList.Create; try for I := 0 to xml.Root.NodeCount - 1 do begin if (xml.Root.Nodes[I].NameUnicode <> 'sign') and (xml.Root.Nodes[I].NameUnicode <> 'WhiteSpace') and (xml.Root.Nodes[I].ValueUnicode <> '') then List.Add(xml.Root.Nodes[I].NameUnicode + '=' + xml.Root.Nodes[I].ValueUnicode); end; List.CustomSort(MyStringListSort); utf8 := List.Join('&') + '&key=' + key; try Digest:= TIdHashMessageDigest5.Create; Result := SameText(Digest.HashBytesAsHex(BytesOf(utf8)), sign); finally Digest.Free; end; finally List.Free; end; end; function VerifyResponseSign(xml: TNativeXml): Boolean; overload; begin Result := VerifyResponseSign(xml, GetKey()); end; function VerifyResponseSign(Response: string; Key: string): Boolean; overload; var xml: TNativeXml; begin Result := False; xml := TNativeXml.Create(nil); try try xml.ReadFromString(Response); except Exit; end; Result := VerifyResponseSign(xml, Key); finally xml.Free; end; end; 那么如何发送一个刷卡支付请求呢? procedure TForm4.btn4Click(Sender: TObject); var Param: TMicroPayParamBuilder; Response: string; begin Param:= TMicroPayParamBuilder.Create; try if edBody.Text <> '' then Param.Body := edBody.Text; Param.OutTradeNo:= edTradeNo.Text; Param.SpbillCreateIp:=idpwtch1.LocalIP; param.AuthCode:= edAuthCode.Text; Param.Attach := edAttach.Text; Param.TotalFee := 10; param.AppId := edAppId.Text; Param.MchId := edMch_id.Text; Param.Key := edKey.Text; mmo1.Lines.Append(Param.BuildParam); mmo1.Lines.Append('----------'); Response := TMicroPayHttpUtils.PostRequest(Param); if Response = '' then begin ShowMessage('请求出错! 可能是网络不通!'); Exit; end; mmo1.Lines.Append(Response); if not VerifyResponseSign(Response, GetKey()) then showmessage('签名验证不通过!'); finally Param.Free; end; end; 支付宝支付: 1,支付宝支付的签名生成 uses IdSSLOpenSSL, IdSSLOpenSSLHeaders; //生成RSA签名 //参数: //PrivateKey:私钥 //Content: 要签名的内容 function GenerateRSASign(const PrivateKey:AnsiString; const Content: AnsiString): AnsiString; var rsaPrivate:PRSA; rsa_out_len: Cardinal; bio:PBIO; hIdCrypto:HMODULE; hash:array[0..SHA_DIGEST_LENGTH - 1] of AnsiChar; type TRSA_sign = function (_type : LongInt; const m : PAnsiChar; m_length : LongWord; sigret : PAnsiChar; var siglen : Cardinal; const rsa : PRSA) : LongInt; cdecl; TSHA1 = function (d: PAnsiChar; n:Cardinal; md:PAnsiChar):PAnsiChar; cdecl; function LoadFunctionCLib(const FceName: string; const ACritical : Boolean = True): Pointer; begin Result := GetProcAddress(hIdCrypto, PChar(FceName)); end; var RSA_sign : TRSA_sign; SHA1: TSHA1; bytes: TBytes; begin LoadOpenSSLLibrary; hIdCrypto := LoadLibrary('libeay32.dll'); Assert(hIdCrypto <> 0, '无法加载libeay32.dll'); try bio := BIO_new_mem_buf(@PrivateKey[1], Length(PrivateKey)); rsaPrivate :=PEM_read_bio_RSAPrivateKey(bio, nil, nil, nil) ; Assert(rsaPrivate <> nil, GetErrorMssage()); FillChar(hash[0], SHA_DIGEST_LENGTH, 0); SHA1:= LoadFunctionCLib('SHA1'); Assert(@SHA1 <> nil, 'SHA1加载失败'); SHA1(@Content[1], Length(Content), @hash[0]); RSA_sign:= LoadFunctionCLib('RSA_sign'); Assert(@RSA_sign <> nil, 'RSA_sign加载失败'); SetLength(bytes, 1024); RSA_sign(EVP_sha1()._type, @hash[0], SHA_DIGEST_LENGTH, @bytes[0], rsa_out_len, rsaPrivate); SetLength(bytes, rsa_out_len); Result := TIdEncoderMIME.EncodeBytes(bytes); BIO_free(bio); RSA_free(rsaPrivate); finally UnLoadOpenSSLLibrary FreeLibrary(hIdCrypto); end; end; //生成条码支付的签名 //TAliPayRequestParamBuilder继承自TBaseAliPayParamBuilder function TAliPayRequestParamBuilder.GetSign: string; var utf8: UTF8String; ansi: AnsiString; List: TStringList; begin List := TStringList.Create; try Assert(AppId <> '' , '开发者的应用ID 不能为空!'); List.Add('app_id=' + AppId); List.Add('biz_con_tent=' + BizContent.AsString); //BizContent: ISuperObject Assert(Charset <> '' , '编码格式 不能为空!'); List.Add('charset=' + Charset); Assert(Method <> '' , '接口名称 不能为空!'); List.Add('method=' + Method); if NotifyUrl <> '' then List.Add('notify_url=' + NotifyUrl); Assert(SignType <> '' , '签名算法类型 不能为空!'); List.Add('sign_type=' + SignType); Assert(Timestamp <> '' , '发送请求时间 不能为空!'); List.Add('timestamp=' + Timestamp); Assert(Version <> '' , '接口版本 不能为空!'); List.Add('version=' + Version); List.CustomSort(MyStringListSort); utf8 := List.Join('&'); TLogger.Instance.Warn('TTradePayParamBuilder.GetSign:' + utf8); ansi := Utf8ToAnsi(utf8); Assert(PrivateKey <> '', '私钥 不能为空!'); Result := GenerateRSASign(PrivateKey, ansi);//生成签名 finally List.Free; end; end; //生成条码支付的请求参数 procedure TAliPayRequestParamBuilder.BuildParamList(Params: TStrings); begin Params.Add('app_id=' + AppId); Params.Add('biz_con_tent=' + BizContent.AsString); Params.Add('charset=' + Charset); Params.Add('method=' + Method); if NotifyUrl <> '' then Params.Add('notify_url=' + NotifyUrl); Params.Add('sign_type=' + SignType); Params.Add('timestamp=' + Timestamp); Params.Add('version=' + Version); Params.Add('sign=' + GetSign()); end; 2,支付宝如何提交请求 class function TAliPaySSLHttpPost.Post(const URL: string; Builder: TBaseAliPayParamBuilder): string; var ssl:TIdSSLIOHandlerSocketOpenSSL; http: TIdHttp; List: TStrings; begin http:= TIdHttp.Create(nil); http.Request.Accept := 'text/xml,text/javascript,text/html,text/plain'; http.Request.UserAgent := 'aop-sdk-java'; http.HTTPOptions := [hoKeepOrigProtocol, hoForceEncodeParams]; ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil); ssl.SSLOptions.Method := sslvTLSv1_2; http.IOHandler := ssl; List:= TStringList.Create; Builder.BuildParamList(List); //把请求参数放到List里 TLogger.Instance.Warn('TAliPaySSLHttpPost.Post Params:' + List.Join('&')); try try Result := http.Post(URL, List, TEncoding.ANSI); except on e: Exception do begin Result := ''; end; end; finally ssl.Free; http.Free; List.Free; end; end; 3,支付宝支付如何验证签名 /验证RSA签名 //参数: //PublicKey:支付宝公钥 //Content: 要签名的内容 //Sign: 签名 function VerifyRSASign(const PublicKey,Sign: AnsiString; const Content:AnsiString ): Boolean; var rsaPub:PRSA; bioPub:PBIO; hIdCrypto:HMODULE; hash:array[0..SHA_DIGEST_LENGTH - 1] of AnsiChar; type TSHA1 = function (d: PAnsiChar; n:Cardinal; md:PAnsiChar):PAnsiChar; cdecl; TRSA_verify = function (dtype : LongInt; const m : PAnsiChar; m_length : LongWord; sigret : PAnsiChar; siglen : Cardinal; const rsa : PRSA) : LongInt; cdecl; TPEM_read_bio_RSA_PUBKEY =function (bp:PBIO; x:PPRSA; cb: Ppem_password_cb; u:Pointer):PRSA; cdecl; function LoadFunctionCLib(const FceName: string; const ACritical : Boolean = True): Pointer; begin Result := GetProcAddress(hIdCrypto, PChar(FceName)); end; var SHA1: TSHA1; RSA_verify:TRSA_verify; bytes: TBytes; PEM_read_bio_RSA_PUBKEY : TPEM_read_bio_RSA_PUBKEY; begin hIdCrypto := LoadLibrary('libeay32.dll'); Assert(hIdCrypto <> 0, '无法加载libeay32.dll'); try bioPub := BIO_new_mem_buf(@PublicKey[1], Length(PublicKey)); PEM_read_bio_RSA_PUBKEY := LoadFunctionCLib('PEM_read_bio_RSA_PUBKEY'); Assert(@PEM_read_bio_RSA_PUBKEY <> nil , 'PEM_read_bio_RSA_PUBKEY加载失败'); rsaPub := PEM_read_bio_RSA_PUBKEY(bioPub, nil, nil, nil) ; Assert(rsaPub <> nil, GetErrorMssage()); FillChar(hash[0], SHA_DIGEST_LENGTH, 0); SHA1:= LoadFunctionCLib('SHA1'); Assert(@SHA1 <> nil, 'SHA1加载失败'); SHA1(@Content[1], Length(Content), @hash[0]); bytes := TIdDecoderMIME.DecodeBytes(Sign); RSA_verify:= LoadFunctionCLib('RSA_verify'); Assert(@RSA_verify <> nil, 'RSA_sign加载失败'); Result := RSA_verify(EVP_sha1()._type, @hash[0], SHA_DIGEST_LENGTH, @bytes[0], Length(bytes), rsaPub)>0; BIO_free(bioPub); RSA_free(rsaPub); finally FreeLibrary(hIdCrypto); end; end;
----------------------------------------------
no
作者:
2020/11/26 13:01:26
1楼:
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
2020/11/26 13:08:59
1楼:
这个需要顶。
----------------------------------------------
山外青山楼外楼,能人背后有能人弄..
作者:
wntee (wntee)
▲▲▲▲△
-
普通会员
2020/11/26 13:15:22
2楼:
MARK
----------------------------------------------
当前后左右都没有路时,命运一定是鼓励你向上飞了...
作者:
2020/11/26 13:56:21
3楼:
感谢分享!
----------------------------------------------
虽千万人吾往矣!
作者:
2020/11/26 15:41:39
4楼:
先项一下! 有人测试过可行吗?
----------------------------------------------
-delphi大富翁论坛http://www.delphibbs.com
作者:
2020/11/26 19:19:10
5楼:
d(ŐдŐ๑)
----------------------------------------------
-
作者:
vga (vga)
★☆☆☆☆
-
盒子活跃会员
2020/11/27 8:32:59
6楼:
标记一下
----------------------------------------------
-
作者:
wfymqj (wfymqj)
★☆☆☆☆
-
盒子活跃会员
2020/11/27 8:39:32
7楼:
收藏学习,感谢分享!
----------------------------------------------
-
作者:
2020/11/27 9:15:20
8楼:
这个必须顶上去。
----------------------------------------------
-
作者:
2020/11/27 10:04:08
9楼:
标记学习,上个DEMO能测试下就更完美了。
----------------------------------------------
简单做人,认真做事。
作者:
yxsoft (yxsoft)
★☆☆☆☆
-
盒子活跃会员
2020/11/27 13:34:07
10楼:
牛,有空试下,还没搞过这块,不过很有用
----------------------------------------------
Great!
作者:
hbug (hbug)
★☆☆☆☆
-
普通会员
2020/11/27 14:45:35
11楼:
收藏起来。
----------------------------------------------
专业提供人力资源软件、指纹考勤软件、POS进销存软件、酒店餐饮软件 http://www.winsoftcn.com
作者:
2020/11/27 20:24:18
12楼:
标记下,谢谢楼主的付出!
----------------------------------------------
-
作者:
abea (abea)
★☆☆☆☆
-
盒子活跃会员
2020/11/29 11:28:18
13楼:
感谢分享,顶上去。
----------------------------------------------
-
作者:
2020/11/29 13:11:33
14楼:
感谢分享
----------------------------------------------
-
作者:
xjia (xjia)
★☆☆☆☆
-
盒子活跃会员
2020/11/29 15:32:34
15楼:
感谢楼主分享~~
----------------------------------------------
-
作者:
star5 (星五)
★☆☆☆☆
-
盒子活跃会员
2020/11/29 20:24:43
16楼:
感谢楼主分享,我也在论坛里分享了微信的; 而支付宝和钉钉的,我是用其它语言实现,给DELPHI调用,因为我个人不太喜欢用DLL,而DEPLHI在算法这块资源太少了。
----------------------------------------------
博客 - http://offeu.com 脚本模型 - http://webpascal.com 需要短信接口的请联系我,可发行业与营销内容。
作者:
2020/11/30 10:09:33
17楼:
如果用于手机开发,建议用FMX结合html5/javacscript或android studio,可以更好地实现支付功能。
----------------------------------------------
-
作者:
abencat (远离delphi的人)
★☆☆☆☆
-
盒子活跃会员
2020/11/30 15:10:10
18楼:
markdown
----------------------------------------------
delphi爱好者
作者:
janker (janker)
★☆☆☆☆
-
盒子活跃会员
2020/11/30 19:40:41
19楼:
感谢楼主分享~~
----------------------------------------------
-
作者:
2020/12/1 12:56:02
20楼:
收藏。。感谢
----------------------------------------------
SQL SERVER DBA QQ:315054403 曾经的Delphier 缘在上海
作者:
yagzh (心不了情)
★☆☆☆☆
-
盒子活跃会员
2020/12/3 9:00:32
21楼:
感謝
----------------------------------------------
-
作者:
hean (hean)
★☆☆☆☆
-
普通会员
2021/2/3 17:19:18
22楼:
感谢楼主的分享。
----------------------------------------------
-
作者:
2021/2/4 13:12:07
23楼:
支持感谢分享
----------------------------------------------
-
作者:
2021/2/5 11:52:42
24楼:
支持感谢分享
----------------------------------------------
-
作者:
2021/6/18 14:30:36
25楼:
最重要的内容,微信退款需要加载证书怎么弄
----------------------------------------------
-
作者:
2021/6/21 21:39:40
26楼:
Windows操作系统下,直接安装证书就行了 使用TNetHTTPClient组件,注意研究一下TNetHTTPClient.OnNeedClientCertificate这个方法
----------------------------------------------
-
作者:
2021/6/21 21:44:26
27楼:
无DLL的1024位Alipay签名,需要使用 CryptoBlackBox 组件 ---------- unit Alipay.Signature; interface uses System.SysUtils, System.Classes, SBPublicKeyCrypto, SBConstants; /// <summary> /// 支付宝签名 /// </summary> function Sign(AParams, APrivateKey: string): string; /// <summary> /// 支付宝验签 /// </summary> function CheckSign(AParams, APublicKey, ASign: string): Boolean; implementation function Sign(AParams, APrivateKey: string): string; var Pvkey: string; Crypto: TElRSAPublicKeyCrypto; KeyMaterial: TELRSAKeyMaterial; PrivateKeyStream: TStringStream; InputBuffer, SignBuffer: TMemoryStream; strIn, strSign: Ansistring; begin Pvkey:= '-----BEGIN RSA PRIVATE KEY-----' + #13#10 + Trim(APrivateKey) + #13#10 + '-----END RSA PRIVATE KEY-----'; PrivateKeyStream := TStringStream.Create(Pvkey.Trim, TEncoding.ASCII); Crypto := TElRSAPublicKeyCrypto.Create(); KeyMaterial := TELRSAKeyMaterial.Create; InputBuffer := TMemoryStream.Create; SignBuffer := TMemoryStream.Create; try Crypto.InputEncoding := pkeBinary; // 指定需要签字的内容的编码格式:pkeBinary或pkeBase64 Crypto.OutputEncoding := pkeBase64; // 指定输出结果的编码格式 Crypto.HashAlgorithm := SB_ALGORITHM_DGST_SHA256; // 签字的HASH格式:这里选择SHA256 KeyMaterial.LoadSecret(PrivateKeyStream); // 装载私钥 Crypto.KeyMaterial := KeyMaterial; // 关联 strIn := Ansistring(AParams); // 需要签字的内容 strIn := AnsiToUtf8(strIn); // 使用UTF8模式 InputBuffer.Write(strIn[1], Length(strIn)); InputBuffer.Position := 0; Crypto.SignDetached(InputBuffer, SignBuffer); // 签字 SignBuffer.Position := 0; SetLength(strSign, SignBuffer.Size); SignBuffer.Read(strSign[1], SignBuffer.Size); Result:= String(strSign); finally FreeAndNil(PrivateKeyStream); FreeAndNil(Crypto); FreeAndNil(KeyMaterial); FreeAndNil(InputBuffer); FreeAndNil(SignBuffer); end; end; function CheckSign(AParams, APublicKey, ASign: string): Boolean; var Pbkey: string; Crypto: TElRSAPublicKeyCrypto; KeyMaterial: TELRSAKeyMaterial; PublicKeyStream: TStringStream; InputBuffer, SignBuffer: TMemoryStream; strIn, strSign: Ansistring; R: TSBPublicKeyVerificationResult; begin Pbkey:= '-----BEGIN RSA PUBLIC KEY-----' + #13#10 + Trim(APublicKey) + #13#10 + '-----END RSA PUBLIC KEY-----'; PublicKeyStream := TStringStream.Create(Pbkey.Trim, TEncoding.ASCII); Crypto := TElRSAPublicKeyCrypto.Create(); KeyMaterial := TELRSAKeyMaterial.Create; InputBuffer := TMemoryStream.Create; SignBuffer := TMemoryStream.Create; try Crypto.InputEncoding := pkeBase64; // 指定需要签字的内容的编码格式:pkeBinary或pkeBase64 Crypto.HashAlgorithm := SB_ALGORITHM_DGST_SHA256; // 签字的HASH格式:这里选择SHA256 // if KeyMaterial is TELRSAKeyMaterial then TELRSAKeyMaterial(KeyMaterial).Passphrase := ''; KeyMaterial.LoadPublic(PublicKeyStream); // 装载公钥 Crypto.KeyMaterial := KeyMaterial; // 关联 strIn := AnsiString(AParams); // 需要签字的内容 strIn := AnsiToUtf8(strIn); // 使用UTF8模式 InputBuffer.Write(strIn[1], Length(strIn)); InputBuffer.Position := 0; strSign:= AnsiString(ASign); strSign := AnsiToUtf8(strSign); SignBuffer.Write(strSign[1], Length(strSign)); SignBuffer.Position := 0; R:= Crypto.VerifyDetached(InputBuffer, SignBuffer); // 验证 Result:= R = pkvrSuccess; finally FreeAndNil(PublicKeyStream); FreeAndNil(Crypto); FreeAndNil(KeyMaterial); FreeAndNil(InputBuffer); FreeAndNil(SignBuffer); end; end; end.
----------------------------------------------
-
作者:
2021/6/22 12:32:05
28楼:
好
----------------------------------------------
-
作者:
lsuper (lsuper)
★☆☆☆☆
-
盒子活跃会员
2021/6/22 13:38:28
29楼:
大赞!一直基于 SBB SecureBlackbox,也支持跨平台 ~
----------------------------------------------
-
作者:
2021/6/22 17:11:51
30楼:
学习学习
----------------------------------------------
-
作者:
2021/7/7 15:11:35
33楼:
这个要能封装成一个控件就好了,学习了,谢谢楼主。
----------------------------------------------
-
作者:
2021/7/8 13:52:05
34楼:
支持
----------------------------------------------
-
作者:
2022/5/12 22:48:23
35楼:
…… 被禁用帐号,帖子内容自动屏蔽! ……
----------------------------------------------
SPAM