Yo con el tema de certificados, lo que hago es cargarlos desde el almacen de certificados sobre una lista que luego asigno a los items de un combobox para poder seleccionar el certificado que usaré en el envio:
Código Delphi
[-]
function Certificados(ListaCertificados: TStringList): Integer;
var
hStore: HCERTSTORE;
PrevContext, CurContext: PCERT_CONTEXT;
cbSize: DWORD;
sNombre: String;
begin
ListaCertificados.Clear;
hStore := CertOpenSystemStore(0, PChar('MY'));
if Assigned(hStore) then
begin
PrevContext := nil;
CurContext := CertEnumCertificatesInStore(hStore, PrevContext);
while Assigned(CurContext) do
begin
sNombre := '';
cbSize := CertGetNameString(CurContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
nil, nil, 0);
if cbSize > 0 then
begin
SetLength(sNombre, cbSize - 1);
CertGetNameString(CurContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil,
PChar(sNombre), cbSize);
ListaCertificados.Add(sNombre);
end;
PrevContext := CurContext;
CurContext := CertEnumCertificatesInStore(hStore, PrevContext);
end;
end;
Result := ListaCertificados.Count;
end;
para cargar los certificados en un combo (cmbCertificados:TComboBox; //en el form )
Código Delphi
[-]
var indice:integer; lisCert:TStringList;
begin
lisCert:=nil;
indice:=DMEnvioLAF.CargaCertificados(lisCert);
cmbcertificados.Clear;
cmbCertificados.Items.AddStrings(lisCert);
lisCert.free;
....
y cuando se selecciona un certificado del combo se deja en una variable infoCertificado:string; el contenido del combo, el elemento seleccionado
y es en el evento OnbeforePost del componente HTTPRIO donde asigno el certificado a partir de ese infocertificado.
Esto plantea un problema en delphi10 y en delphi11 porque la declaracion de tipos es distinta y en delphi11 se accede directamente para asignar los datos del certificado:
Código Delphi
[-]
procedure TDMEnvioLAF.HTTPRIOENVHTTPWebNode1BeforePost(
const HTTPReqResp: THTTPReqResp; Client: THTTPClient);
var Store : IStore;
Certs : ICertificates;
Cert : ICertificate2;
V : OleVariant;
{$REGION 'delphi10 var'}
{$ENDREGION 'delphi10 var'}
begin
V := infoCertificado;
Store := CoStore.Create;
Store.Open(CAPICOM_CURRENT_USER_STORE, 'MY',CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED );
Certs := Store.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME,V,False );
if Certs.Count > 0 then
begin
Cert:=IInterface(Certs.Item[1]) as ICertificate2;
{$REGION 'delphi10 code'}
{$ENDREGION 'delphi10 code'}
with HTTPRIOENV.HTTPWebNode.ClientCertificate do
begin
CertName:=V;
SerialNum:=cert.serialnumber;
end
end
else
showmessage('ERROR localizando certificado');
end;
no asigno la password, cojo el certificado directamente del almacen; no sé si al usarlo desde alli necesito informar la password. Pero a mi me funciona
ah, se necesita usar la libreria CAPICOM_TLB y tambien System.Net.HttpClient, System.Net.HttpClientComponent, Soap.Rio,
Soap.SOAPHTTPClient, Soap.SOAPHTTPTrans, soap.win.certhelper
puede que haya alguna de más, pero yo las tengo todas ellas puestas