Nachdem ich einige Zeit mit einem Paypal-Techniker verbracht habe, habe ich eine Lösung für Paypals Payflow Transparent Redirect ohne gehostete Seiten gefunden (eigene Zahlungsseite). Noch einmal, hier ist die Dokumentation, die für den Ingenieur ziemlich verwirrend ist: Payflow API Documentation. Außerdem ist der Code nicht optimiert, da es nur eine R & D App war, aber als Ganzes funktioniert es für mich. Nur ein Beispiel und eine Erklärung, und ich bin mir sicher, dass es bessere Möglichkeiten gibt, einzelne Schritte zu machen. Ich hoffe, dies hilft und ermöglicht es Ihnen, einige der Hindernisse zu umgehen, die Ihre Paypal Payflow-Integration verlangsamt haben.
JA, es ist PCI-konform, da keine sicheren Kundendaten Ihre eigenen Server treffen. Denken Sie daran, dass die PCI-Compliance ziemlich kompliziert und kompliziert ist, aber das ist ein großer Teil davon. Ok, ich werde erklären, was ich getan habe, um dies in einer MVC C# Umgebung zu ermöglichen. Ich werde die Schritte hier erklären und dann den Code unten einfügen.
- CLIENT: Der Client beendet das Hinzufügen von Artikeln zum Einkaufswagen und drückt die Taste KAUFEN. Javascript handhabt den Knopfklick, reicht nicht ein und bringt Sie zum nächsten Schritt.
- CLIENT -> SERVER: AJAX-Funktion POSTS zu Server-Methode, um Paypal für den Single-Use-Secure-Token zu kontaktieren. Diese Kommunikation identifiziert SIE (den Händler) mit Ihrer Authentifizierung, einer eindeutigen Transaktions-ID (einer GUID) und nicht sicheren Details über die Transaktion (Summe, Rechnungsinformationen, Versandinformationen, Rücksende-URL-Details). Auf diese Weise sind alle Ihre persönlichen Händleraccount Informationen sicher (Webserver zu Paypal).
- SERVER -> CLIENT: Von der Transaktion oben erhalten Sie eine Parameter-Zeichenfolge, die das sichere Token enthält (unter anderem, siehe Methode mit Beispiel). Mit diesem Teil der Informationen, ich dynamisch erstellen meine URL, die ich schließlich auf dem Client für die transparente Umleitung Teil benötigen, und senden Sie die URL-Zeichenfolge zurück an den Client.
- CLIENT: Unter Verwendung der URL, die in Schritt # 3 zurückgegeben wurde, vervollständige ich die URL, indem ich die benötigten Kreditkartenparameter mit jQuery hinzufüge.
- KUNDE -> PAYPAL: Hier habe ich nicht verstanden, was zu tun ist. Während Schritt 2 ein Post war, wird dieser Schritt ein REDIRECT sein. Sicher, das erscheint angemessen, da es "transparente Umleitung" genannt wird, aber dieser Teil ergab für mich keinen Sinn. Sobald Ihre gesamte URL vollständig ist, leiten Sie das Fenster zur Verarbeitung Ihrer Transaktion buchstäblich an Paypal um.
- PAYPAL -> SERVER: PayPal sendet zurück an eine der URLs, die Sie in Schritt 2 einbezogen haben (an eine öffentliche Methode auf einem meiner Controller), und ich lese das Antwortobjekt und parse die Parameter.
Einfach, oder? Vielleicht, aber für mich hat Schritt 5 große Probleme verursacht. Ich benutzte einen POST und konnte nicht verstehen, warum ich immer Fehler bei der Antwort bekam. Es war eine HTML-Seite mit etwas über einen ungültigen Händler oder eine Authentifizierung. Denken Sie daran, umzuleiten, nicht für Schritt # 5 zu posten.
CODE:
SCHRITT 1: Onclick-Attribut auf die Schaltfläche GetToken Funktion aufzurufen.
SCHRITT 2 und SCHRITT 3:
client-side:
function GetToken() {
$.ajax({
url: '@Url.Action("GetToken", "MyController")',
type: 'POST',
cache: 'false',
contentType: 'application/json; charset=utf-8',
dataType: 'text',
success: function (data) {
// data is already formatted in parameter string
SendCCDetailsToPaypal(data);
},
//error:
//TODO Handle the BAD stuff
});}
Server Side:
Ich habe verschiedene Methoden verwendet, um alle Parameterwerte benötigt bauen für die Token-Anfrage. Die ersten drei Builds: Authentifizierung, Transaktionsdetails, transparente Umleitung. Ich halte URLs und Payflow-Kontoinformationen in einer web.config-Datei. Die letzte Methode, ProcessTokenTransaction, führt alle schweren Aufgaben aus, um über WebRequest Kontakt mit Paypal aufzunehmen und es dann in die URL zu analysieren, die an den Client zurückgesendet wird. Diese Methode sollte für eine sauberere Lieferung überarbeitet werden, aber das überlasse ich Ihnen. ParseResponse ist eine Methode, die ein von mir erstelltes einfaches Modell auffüllt und dieses Modell zurückgibt.
URL für Token (Sandbox):https://pilot-payflowpro.paypal.com
DIES IST ALS DIE TOKEN URL DIFFERENT !! Wird im PaypalTranactionAPI-Konfigurationswert verwendet.
URL für Transaktion: (Sandbox)https://pilot-payflowlink.paypal.com
private string PrepareApiAuthenticationParams()
{
var paypalUser = ConfigurationManager.AppSettings["PaypalUser"];
var paypalVendor = ConfigurationManager.AppSettings["PaypalVendor"];
var paypalPartner = ConfigurationManager.AppSettings["PaypalPartner"];
var paypalPw = ConfigurationManager.AppSettings["PaypalPwd"];
//var amount = (decimal)19.53;
var apiParams = @"USER=" + paypalUser
+ "&VENDOR=" + paypalVendor
+ "&PARTNER=" + paypalPartner
+ "&PWD=" + paypalPw
+ "&TENDER=C"
+ "&TRXTYPE=A"
+ "&VERBOSITY=HIGH";
// find more appropriate place for this param
//+ "&VERBOSITY=HIGH";
return apiParams;
}
private string PrepareTransactionParams(CustomerDetail detail)
{
var currencyType = "USD";
var transactionParams = @"&BILLTOFIRSTNAME=" + detail.FirstName
+ "&BILLTOLASTNAME=" + detail.LastName
+ "&BILLTOSTREET=" + detail.Address1
+ "&BILLTOSTREET2=" + detail.Address2
+ "&BILLTOCITY=" + detail.City
+ "&BILLTOSTATE=" + detail.State
//+ "&BILLTOCOUNTRY=" + detail.Country + // NEEDS 3 digit country code
+ "&BILLTOZIP=" + detail.Zip
+ "&BILLTOPHONENUM=" + detail.PhoneNum
+ "&EMAIL=" + detail.Email
+ "&CURRENCY=" + currencyType
+ "&AMT=" + GET_VALUE_FROM_DB
+ "&ERRORURL= " + HostUrl + "/Checkout/Error"
+ "&CANCELURL=" + HostUrl + "/Checkout/Cancel"
+ "&RETURNURL=" + HostUrl + "/Checkout/Success";
// ADD SHIPTO info for address validation
return transactionParams;
}
private string PrepareTransparentParams(string requestId, string transType)
{
var transparentParams = @"&TRXTYPE=" + transType +
"&SILENTTRAN=TRUE" +
"&CREATESECURETOKEN=Y" +
"&SECURETOKENID=" + requestId;
return transparentParams;
}
// Method to build parameter string, and create webrequest object
public string ProcessTokenTransaction()
{
var result = "RESULT=0"; // default failure response
var transactionType = "A";
var secureToken = string.Empty;
var requestId = Guid.NewGuid().ToString().Replace("-", string.Empty);
var baseUrl = ConfigurationManager.AppSettings["PaypalGatewayAPI"];
var apiAuthenticationParams = PrepareApiAuthenticationParams();
// Create url parameter name/value parameter string
var apiTransactionParams = PrepareTransactionParams(detail);
// PCI compliance, Create url parameter name/value parameter string specific to TRANSAPARENT PROCESSING
var transparentParams = PrepareTransparentParams(requestId, transactionType);
var url = baseUrl;
var parameters = apiAuthenticationParams + apiTransactionParams + transparentParams;
// base api url + required
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "text/name"; // Payflow?
request.Headers.Add("X-VPS-REQUEST-ID", requestId);
byte[] bytes = Encoding.UTF8.GetBytes(parameters);
request.ContentLength = bytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
try
{
// sample successful response
// RESULT=0&RESPMSG=Approved&SECURETOKEN=9pOyyUMAwRUWmmv9nMn7zhQ0h&SECURETOKENID=5e3c50a4c3d54ef8b412e358d24c8915
result = reader.ReadToEnd();
var token = ParseResponse(result, requestId, transactionType);
var transactionUrl = ConfigurationManager.AppSettings["PaypalTransactionAPI"];
secureToken = transactionUrl + "?SECURETOKEN=" + token.SecureToken + "&SECURETOKENID=" + requestId;
//ameValueCollection parsedParams = HttpUtility.ParseQueryString(result);
stream.Dispose();
reader.Dispose();
}
catch (WebException ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
finally { request.Abort(); }
return secureToken;
}
private TokenResponse ParseResponse(string response, string requestId, string transactionType)
{
var nameValues = HttpUtility.ParseQueryString(response);
int result = -999; // invalid result to guarantee failure
int.TryParse(nameValues.Get(TokenResponse.ResponseParameters.RESULT.ToString()), out result);
// retrieving response message
var responseMessage = nameValues.Get(TokenResponse.ResponseParameters.RESPMSG.ToString());
// retrieving token value, if any
var secureToken = nameValues.Get(TokenResponse.ResponseParameters.SECURETOKEN.ToString());
var reference = nameValues.Get(TokenResponse.ResponseParameters.PNREF.ToString());
var authCode = nameValues.Get(TokenResponse.ResponseParameters.AUTHCODE.ToString());
var cscMatch = nameValues.Get(TokenResponse.ResponseParameters.CSCMATCH.ToString());
// populating model with values
var tokenResponse = new TokenResponse
{
Result = result,
ResponseMessage = responseMessage,
SecureToken = secureToken,
TransactionIdentifierToken = requestId,
TransactionType = transactionType,
ReferenceCode = reference,
AuthorizationCode = authCode,
CSCMatch = cscMatch
};
return tokenResponse;
}
Schritt 4 und Schritt 5:
Zurück zur Client-Seite:
Hier verwende ich die URL gebaut aus den vorherigen Schritten und fügen Sie die letzten benötigten Parameter (sichere Kreditkarteninformationen) mit jQuery und dann REDIRECT t hinzu o Paypal.
function SendCCDetailsToPaypal(secureParm) {
//alert('in SendCCDetailsToPaypal:' + secureParm);
var secureInfo = '&ACCT=' + $('#ccNumber').val() + '&EXPDATE=' + $("#expMonth").val() + $("#expYear").val() + "&CSC=" + $('#ccSecurityCode').val();
secureInfo = secureParm + secureInfo;
window.location.replace(secureInfo);
}
STEP 6:
Paypal wird auf eine der folgenden Methoden Post zurück: Abbrechen, Fehler oder Return (nennen Sie die Methoden alles, was Sie in der Token-Anfrage wollen). Parsen Sie die Antwort und schauen Sie sich die von Paypal zurückgegebenen Variablen an, insbesondere RESULT und RESPMSG. Lesen Sie die Dokumentation für Details, da Sie die Adressvalidierung und eine Reihe weiterer Funktionen integrieren können. Zeigen Sie anhand der Antwort an, was angemessen ist.
Server-Seite:
public ActionResult Cancel()
{
var result = ParseRequest(HttpUtility.UrlDecode(Request.Params.ToString()));
//return View("Return", result);
}
public ActionResult Error()
{
var result = ParseRequest(HttpUtility.UrlDecode(Request.Params.ToString()));
return View("Return", result);
}
public ActionResult Return()
{
var result = ParseRequest(HttpUtility.UrlDecode(Request.Params.ToString()));
return View("Return", result);
}
Hope this, und viel Glück hilft! Ich beantworte Klärungsfragen so wie ich kann. Vielen Dank für das Auschecken, und denken Sie daran, es zu bezahlen.
Blick auf das Dokument befindet sich hier: https: //developer.paypal.com/docs/classic/payflow/integration-guide/# about-the-secure-token "Der Gateway-Server verknüpft Ihre ID mit einem sicheren Token und gibt das Token als Zeichenfolge mit bis zu 32 alphanumerischen Zeichen zurück. To Übergeben Sie die Transaktionsdaten an die gehostete Checkout-Seite, übergeben Sie das sichere Token und die sichere Token-ID in einem HTTP-Formularpost. Das Token und die ID lösen den Gateway-Server aus, um Ihre Daten abzurufen und zur Kundengenehmigung anzuzeigen. Wir verwenden unseren eigenen Einkaufswagen, so dass ich keine HOSTED-Seiten verwende, vielleicht ist das mein Problem? – RichieMN
SCHEINT, dass Sie bei dieser Methode Authentifizierungsinformationen bei jeder Anfrage angeben müssen. Ein Blick in Paypals REST-API. Ich werde eine andere Frage/Kommentar mit was Iearn erstellen ... – RichieMN
Hmmm. Ich habe gerade versucht, dies zu implementieren und es funktioniert nicht. Wenn ich die Umleitung zur Payflowlink-URL durchführe, antwortet sie mit HTTP200 und ohne HTML-Body (und ohne Redirect). Ich habe mit dem technischen Support von PayPal gesprochen und sie sagen, dass diese Reihenfolge nicht möglich ist: Das Kreditkarten-Eingabeformular muss auf dem Paypal-Server gehostet werden, um Payflowlink zu verwenden (mit einem iFrame, um es auf unserer Website einzubetten). Ich wurde zur DoDirectPayment API weitergeleitet. Wird einige Zeit brauchen, um einen Test zu erstellen. – Owen