Sau khi dành nhiều thời gian với kỹ sư Paypal, tôi đã tìm ra giải pháp cho Payflow Transparent Redirect của Paypal mà không có trang được lưu trữ (có trang thanh toán riêng). Một lần nữa, đây là tài liệu mà, theo kỹ sư, là khá khó hiểu: Payflow API Documentation. Ngoài ra, mã không được tối ưu hóa vì nó chỉ là một ứng dụng R & D, nhưng nói chung, nó đang làm việc cho tôi. Chỉ là một ví dụ và giải thích, và tôi chắc chắn có những cách tốt hơn để thực hiện các bước riêng lẻ. Hy vọng điều này sẽ giúp và cho phép bạn bỏ qua một số rào chắn đã làm chậm quá trình tích hợp Paypal Payflow của bạn.
CÓ, PCI tuân thủ trong đó không có dữ liệu khách hàng an toàn nào sẽ tấn công vào máy chủ của riêng bạn. Hãy nhớ rằng sự tuân thủ PCI là khá phức tạp và có liên quan nhưng đây là một phần lớn của nó. Ok, vì vậy tôi sẽ giải thích những gì tôi đã làm để thực hiện công việc này trong môi trường MVC C#. Tôi sẽ giải thích các bước ở đây, sau đó bao gồm mã bên dưới.
- KHÁCH HÀNG: Khách hàng hoàn tất việc thêm mặt hàng vào giỏ hàng và nhấn nút MUA. Javascript xử lý nhấp chuột vào nút, không gửi và đưa bạn đến bước tiếp theo.
- KHÁCH HÀNG -> MÁY CHỦ: chức năng AJAX POSTS đến phương thức máy chủ để liên hệ với Paypal cho mã thông báo bảo mật dùng một lần. Giao tiếp này xác định BẠN (người bán) để paypal với xác thực của bạn, một id giao dịch duy nhất (một guid) và các chi tiết không an toàn về giao dịch (tổng cộng, thông tin thanh toán, thông tin giao hàng, chi tiết URL trả lại). Bằng cách này, tất cả thông tin acct cá nhân của người bán của bạn đều an toàn (máy chủ web đến Paypal).
- SERVER -> KHÁCH HÀNG: Từ giao dịch trên, bạn sẽ nhận được một chuỗi tham số có chứa mã bảo mật (trong số các công cụ khác, xem phương pháp có ví dụ). Sử dụng mẩu thông tin này, tôi tự động tạo url của mình mà cuối cùng tôi sẽ cần trên máy khách cho phần chuyển hướng trong suốt và gửi chuỗi url trở lại máy khách.
- KHÁCH HÀNG: Sử dụng url được trả lại ở bướC# 3, tôi hoàn thành URL bằng cách thêm các tham số thẻ tín dụng cần thiết bằng cách sử dụng jQuery.
- KHÁCH HÀNG -> PAYPAL: Đây là nơi tôi không hiểu phải làm gì. Trong khi bướC# 2 là một bài đăng, bước này sẽ là một REDIRECT. Chắc chắn, điều đó có vẻ thích hợp khi thấy nó được gọi là 'chuyển hướng trong suốt', nhưng phần đó không có ý nghĩa với tôi. Vì vậy, khi toàn bộ URL của bạn hoàn tất, bạn sẽ chuyển hướng cửa sổ đến Paypal để xử lý giao dịch của bạn theo nghĩa đen.
- PAYPAL -> SERVER: PayPal đăng lại một trong các URL bạn đã bao gồm trong bước 2 (đến phương thức công khai trên một trong các bộ điều khiển của tôi), và tôi đọc đối tượng phản hồi và phân tích cú pháp tham số.
Dễ dàng, phải không? Có lẽ, nhưng đối với tôi bước 5 gây ra cho tôi những vấn đề lớn. Tôi đã sử dụng POST và không hiểu tại sao tôi tiếp tục gặp lỗi về phản hồi. Đó là một trang html có thứ gì đó về một người bán hoặc xác thực không hợp lệ. Nhớ chuyển hướng, không đăng bài cho bướC# 5.
MÃ:
Bước 1: onclick thuộc tính trên nút để gọi GetToken chức năng.
Bước 2 và Bước 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:
Tôi đã phương pháp riêng biệt dùng để xây dựng tất cả các giá trị tham số cần thiết cho yêu cầu mã thông báo. Ba bản dựng đầu tiên: xác thực, chi tiết giao dịch, chuyển hướng trong suốt. Tôi giữ url và thông tin acct payflow trong một tập tin web.config. Phương thức cuối cùng, ProcessTokenTransaction, thực hiện tất cả việc nâng hạng nặng để liên hệ với Paypal thông qua WebRequest và sau đó phân tích nó thành URL sẽ được gửi lại cho máy khách. Phương pháp này nên được tái cấu trúc để phân phối sạch hơn, nhưng tôi sẽ để nguyên điều đó cho bạn. ParseResponse là một phương thức điền vào một mô hình đơn giản mà tôi đã tạo và trả về mô hình đó.
URL cho token (sandbox):https://pilot-payflowpro.paypal.com
NÀY khác với URL TOKEN !! Được sử dụng trong giá trị cấu hình PaypalTranactionAPI.
URL cho giao dịch: (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;
}
BƯỚC 4 và Bước 5:
Back to Client Side:
Ở đây tôi sử dụng URL được xây dựng từ các bước trước và thêm thông số cần thiết cuối cùng (thông tin thẻ tín dụng an toàn) bằng cách sử dụng jQuery và sau đó ĐỔI MỚI 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);
}
Bước 6:
Paypal sẽ gửi về một trong những phương pháp sau đây: Hủy bỏ, Lỗi, hoặc Return (đặt tên cho phương pháp bất cứ điều gì bạn muốn trong yêu cầu token). Phân tích cú pháp phản hồi và xem xét các biến được trả lại từ Paypal, đặc biệt là RESULT và RESPMSG. Đọc tài liệu để biết chi tiết cụ thể vì bạn có thể kết hợp xác thực địa chỉ và một loạt các tính năng khác. Dựa trên phản hồi, hiển thị những gì phù hợp. bên
server:
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 helps, và may mắn! Tôi sẽ trả lời các câu hỏi làm rõ khi tôi có thể. Cảm ơn bạn đã kiểm tra điều này, và nhớ trả nó về phía trước.
Xem tài liệu ở đây: https: //developer.paypal.com/docs/classic/payflow/hướng dẫn tích hợp/# about-the-secure-token "Máy chủ cổng liên kết ID của bạn với mã bảo mật và trả về mã thông báo dưới dạng chuỗi gồm 32 ký tự chữ và số. chuyển dữ liệu giao dịch đến trang thanh toán được lưu trữ, bạn chuyển mã thông báo bảo mật và ID mã thông báo an toàn trong bài đăng biểu mẫu HTTP. Mã thông báo và ID kích hoạt máy chủ Cổng để truy xuất dữ liệu của bạn và hiển thị nó để khách hàng chấp thuận. " Chúng tôi sử dụng giỏ hàng tự trồng của mình nên tôi không sử dụng các trang HOSTED, có lẽ đây là vấn đề của tôi? – RichieMN
SEEMS sử dụng phương pháp này bạn được yêu cầu bao gồm thông tin xác thực với mỗi yêu cầu. Nhìn vào REST API của Paypal. Tôi sẽ tạo một câu hỏi/nhận xét khác với những gì tôi đã học ... – RichieMN
Hmmm. Tôi chỉ cố gắng thực hiện điều này và nó không hoạt động. Khi tôi chuyển hướng đến URL payflowlink, nó phản hồi với HTTP200 và không có nội dung HTML (và không có chuyển hướng). Tôi đã nói chuyện với PayPal hỗ trợ kỹ thuật, và họ nói rằng trình tự này là không thể: các hình thức đầu vào thẻ tín dụng phải được lưu trữ trên máy chủ paypal để sử dụng payflowlink (sử dụng một iFrame để nhúng nó trên trang web của chúng tôi). Tôi được chuyển hướng đến API DoDirectPayment. Sẽ mất một thời gian để tạo ra một thử nghiệm. – Owen