Ric*_*eMN 7 ajax paypal asp.net-ajax token payflowpro
我正在使用Payflow Pro(https://pilot-payflowpro.paypal.com)尝试成为PCI兼容的C#VS2012 Framework 4.5 MVC应用程序.我们多年来一直在使用PayflowPro,这就是我必须使用的.从我的阅读中看来,我似乎应该使用透明重定向,所以我不会向我的网络服务器发布任何私有内容,但我不知道我是否需要这个以及我希望如何处理这个问题.我也有几个问题......
我怎么认为这一切都有效: 我的理解是你需要一个安全的语言(与Paypal的通信,旅程1).然后您发布安全数据(CC,exp,安全代码),包括securetoken(与Paypal的通信,旅程2)并接收销售的授权和交易ID.
我希望如何做到这一点: 我打算拥有一个包含所有信息(用户详细信息,运送详细信息和CC信息)的表单,当用户按下购买按钮时,我将使用AJAX处理1到我的服务器(没有发送安全的用户信息).在这里,我将创建URL + params并发送paypal我的un/pw信息以检索令牌(全部来自我的服务器).响应将返回给客户端,如果成功,我将直接通过AJAX与Paypal的网关服务器进行通信,这次发送安全的CC信息+令牌(行程#2).根据对#2行程的响应,我会让用户知道他们的购买行为是什么.旅行2不应该需要我的Paypal UN/PW信息,因为它可以很容易地在客户端看到,我包括应该识别原始交易的SecureToken.根据我的解释,我认为不需要透明重定向.或者我在这里遗漏了什么?
另外,我想使用什么交易类型?为行程#1创建"授权",然后为行程#2创建"销售"?
所以这里是细节编码类型的东西: 对于我的研发测试,我正在建立自己的名称/值对参数字符串(见下文),并通过WebRequest通过他们的沙箱/测试网址(pilot-payflowpro.paypal)与网关服务器进行通信. COM).我得到了一个成功的回复和SECURETOKEN回来了.安全令牌的初始请求(如下所示)为TRXTYPE = A(授权),不发送卡信息.我想先授权吗?
以下是我的参数(也可能包括shipto信息,但未在下面列出):
USER=myAuthUserName
&VENDOR=myAuthUserName
&PARTNER=myPartner
&PWD=myPassword
&AMT=21.43
&BILLTOFIRSTNAME=FName
&BILLTOLASTNAME=LName
&BILLTOSTREET=123 Main Street
&BILLTOSTREET2=Apt 203B
&BILLTOCITY=MyCity
&BILLTOSTATE=CA
&BILLTOZIP=77777
&BILLTOPHONENUM=4444444444
&EMAIL=myemail@somedomain.com
&CURRENCY=USD
**&TRXTYPE=A**
&SILENTTRAN=TRUE
&CREATESECURETOKEN=Y
&SECURETOKENID=a99998afe2474b1b82c8214c0824df99
Run Code Online (Sandbox Code Playgroud)
正如我所说,我得到了一个成功的响应,并转到下一步发送安全数据(CC#,EXPDATE,安全代码).当我从params中删除我的UN/PW/VENDOR /合作伙伴信息时,由于无效的用户身份验证而出现错误.但是,看到我正在动态建立第二个电话,我不能在那里使用我的PayPal/pw.我错过了什么?有人提供上述此问题或其他问题的帮助吗?
如果我需要添加任何说明,请告诉我.在此先感谢您的时间!
在花了很多时间与Paypal工程师合作后,我成功找到了Paypal的Payflow透明重定向解决方案,没有托管页面(有自己的支付页面).同样,这里的文档对于工程师而言非常混乱: Payflow API文档.此外,代码没有优化,因为它只是一个研发应用程序,但总的来说,它对我有用.只是一个例子和解释,我相信有更好的方法来做个别的步骤.希望这会有所帮助,并允许您绕过一些减慢Paypal Payflow集成速度的障碍.
是的,它符合PCI标准,因为没有安全的客户数据会打到您自己的服务器上.请记住,PCI合规性非常复杂且涉及,但这是其中很重要的一部分.好的,所以我将解释我在MVC C#环境中做了哪些工作.我将解释这里的步骤,然后包括下面的代码.
容易,对吗?或许,但对我而言,第5步给我带来了很大的问题.我正在使用POST,但不明白为什么我一直在回复错误.这是一个关于无效商家或身份验证的HTML页面.请记住重定向,而不是发布第5步.
代码:
第1步:在按钮上单击onclick属性以调用GetToken函数.
第2步和第3步:
客户端:
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
});}
Run Code Online (Sandbox Code Playgroud)
服务器端:
我有单独的方法用于构建令牌请求所需的所有参数值.前三个构建:身份验证,事务详细信息,透明重定向.我在web.config文件中保留urls和payflow acct信息.最后一个方法ProcessTokenTransaction通过WebRequest完成与Paypal联系的所有繁重工作,然后将其解析为将发送回客户端的URL.这种方法应该重构为更清洁的交付,但我会留给你.ParseResponse是一种填充我创建的简单模型并返回该模型的方法.
令牌(沙盒)的URL: https ://pilot-payflowpro.paypal.com
这与TOKEN URL不同!! 用于PaypalTranactionAPI配置值.
交易网址:(沙箱) 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;
}
Run Code Online (Sandbox Code Playgroud)
第4步和第5步:
回到客户端:
在这里,我使用从前面的步骤构建的URL,并使用jQuery添加最终所需的参数(安全信用卡信息),然后REDIRECT到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);
}
Run Code Online (Sandbox Code Playgroud)
第6步:
Paypal将回发到以下方法之一:取消,错误或返回(在令牌请求中将方法命名为任何内容).解析响应并查看从Paypal返回的变量,特别是RESULT和RESPMSG.阅读文档了解具体细节,因为您可以合并地址验证和一系列其他功能.根据响应,显示适当的.
服务器端:
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);
}
Run Code Online (Sandbox Code Playgroud)
希望这有帮助,祝你好运!我会尽可能地回答澄清问题.感谢您查看此内容,并记得向前付款.
小智 5
我能够使用 RichieMN 的答案来实现透明重定向。但是,在SendCCDetailsToPaypal函数中使用window.location.replace进行重定向的问题是您在 GET 字符串上传递数据。
这适用于 PayFlow Gateway 端,但是当他们将客户的浏览器发送回您的 ResponseURL 时,您的 Apache 日志将显示整个payflowlink.paypal.com URL,包括 GET 字符串作为 Apache 访问日志中的引荐来源网址!该 GET 字符串包含信用卡号,现在您已经失去了 PCI 合规性!
为了缓解这个问题,您可以将 SecureToken 和 SecureTokenID 放入您的信用卡输入表单中,并将其直接 POST 到 payflowlink.paypal.com,或者您可以重写SendCCDetailsToPaypal构建表单并提交,如下所示:
function SendCCDetailsToPaypal() {
var parameters = {
"SECURETOKEN": secureToken,
"SECURETOKENID": secureTokenID,
"ACCT": $("#ccNumber").val(),
"EXPDATE": $("#expMonth").val() + $("#expYear").val(),
"CSC": $("#ccSecurityCode").val()
};
var form = $('<form></form>');
form.attr("method", "post");
form.attr("action", "https://pilot-payflowlink.paypal.com");
$.each(parameters, function(key, value) {
var field = $('<input></input>');
field.attr("type", "hidden");
field.attr("name", key);
field.attr("value", value);
form.append(field);
});
$(document.body).append(form);
form.submit();
}
Run Code Online (Sandbox Code Playgroud)
由于该表单通过 POST 传输数据,因此当您的服务器收到 POST 结果时,引荐来源网址不包含任何敏感数据,并且您的 PCI 合规性得以维持。
| 归档时间: |
|
| 查看次数: |
4301 次 |
| 最近记录: |