16,748
社区成员
支付宝支付:
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_content=' + 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_content=' + 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;