写本文章的目的是为了记录工作中遇到的问题,方便以后遇到可以迅速解决问题
paypal支付接口实现由几种方法,我使用的是REST API
所以在这里值介绍这种方法的使用
我们使用vs的Nuget下载Paypal的dll
首先需要配置Web.config文件
1.在configuration节点下配置configsections中的section节点
2.在configuration节点下配置paypal节点
"paypal" type="PayPal.SDKConfigHandler, PayPal" /> "log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
clientid,和clientSecret的值需要自己在沙箱中配置,才能得到
用户点击付款按钮时,调用这个方法
引用命名空间
using PayPal.Api;
public ActionResult PaypalPayment(string orderNo) { try { var config = ConfigManager.Instance.GetProperties();//读取配置文件 var accessToken = new OAuthTokenCredential(config).GetAccessToken(); var apiContext = new APIContext(accessToken); string payerId = Request.Params["PayerID"];//用户登录账号付款后,这个payerid才有值 if (string.IsNullOrEmpty(payerId))//还没有登陆付款 { PaypalTradeWayPayServer pay = new PaypalTradeWayPayServer(); var approvalUrl = pay.payment(orderNo, Request, Session, apiContext);//发送给paypal的参数方法 if (!string.IsNullOrEmpty(approvalUrl)) { return Redirect(approvalUrl); } else { return RedirectToAction("Error404", "MPublic", null); } } else {
var guid = Request.Params["guid"];//登陆付款后才进入这里 // Using the information from the redirect, setup the payment to execute. var paymentId = Session[guid] as string; var paymentExecution = new PaymentExecution() { payer_id = payerId }; var payment = new Payment() { id = paymentId }; // Execute the payment. var executedPayment = payment.Execute(apiContext, paymentExecution); ViewBag.result = "success"; } } catch (PayPal.PayPalException ex) { //插入错误日志 } return View("PayResult"); }
payment方法:
具体参数请自行查看
////// 得到ItemList /// /// /// public string payment(string orderNo, HttpRequest Request,HttpSessionStateBase Session, APIContext apiContext) { // ###Items // Items within a transaction. var order = Context.Data.Order.Where(x=>x.OrderNo== orderNo && x.Del==false &&x.PayType== Interface.Order.Eum.EumPayType.Paypal).ToEntity(); var orderDetail = Context.Data.OrderDetail.Where(x => x.OrderNo == orderNo).ToSelectList(x => new { Num = x.Num.ToString(), SkuPrice = x.SkuPrice, SkuName = x.SkuName,UnitName=x.UnitName }); if (order == null || orderDetail == null) { return ""; } var items = new List - (); string myCurrency = ChangeCurrency(order.CurrencyCode.Trim()); foreach (var detail in orderDetail) { var item = new Item { name = detail.SkuName, price = detail.SkuPrice.ToString(), quantity = detail.Num, currency=myCurrency,sku= detail.UnitName }; items.Add(item); } var itemList = new ItemList() { items = items }; var payer = new Payer() { payment_method = "paypal" }; // ###Redirect URLS // These URLs will determine how the user is redirected from PayPal once they have either approved or canceled the payment. string baseURI = Request.Url.Scheme + "://" + Request.Url.Authority + "/WebPay/PaypalPayment?";//支付完成后返回的地址 var guid = Convert.ToString((new Random()).Next(100000)); var redirUrls = new RedirectUrls() { cancel_url = baseURI + "guid=" + guid, return_url = baseURI + "guid=" + guid }; // ###Details // Let's you specify details of a payment amount. var details = new Details() { tax = "0.00", shipping = order.TotalFreight.Value.ToString(), subtotal = order.TotalAmount.Value.ToString() }; // ###Amount // Let's you specify a payment amount. var amount = new Amount() { currency = myCurrency, total = (order.TotalAmount.Value + order.TotalFreight.Value).ToString(), // Total must be equal to sum of shipping, tax and subtotal. details = details }; // ###Transaction // A transaction defines the contract of a // payment - what is the payment for and who // is fulfilling it. var transactionList = new List
(); // The Payment creation API requires a list of // Transaction; add the created `Transaction` // to a List string address = Request.Url.Scheme + "://" + Request.Url.Authority; transactionList.Add(new Transaction() { description = "Transaction description.", amount = amount, item_list = itemList, custom=order.OrderNo,//这个参数可以传递我们的需要的参数,这里我传的是订单号 notify_url= address+"/WebPay/Receive"//接收Paypal的IPN消息地址,必须需要外网可以访问 }); // ###Payment // A Payment Resource; create one using // the above types and intent as `sale` or `authorize` var payment = new Payment() { intent = "sale", payer = payer, transactions = transactionList, redirect_urls = redirUrls }; try { // Create a payment using a valid APIContext var createdPayment = payment.Create(apiContext); // Using the `links` provided by the `createdPayment` object, we can give the user the option to redirect to PayPal to approve the payment. var links = createdPayment.links.GetEnumerator(); string approvalUrl = ""; while (links.MoveNext()) { var link = links.Current; if (link.rel.ToLower().Trim().Equals("approval_url")) { approvalUrl = link.href; } } Session.Add(guid, createdPayment.id); Session.Add("orderNo", orderNo); return approvalUrl; } catch (PayPal.PayPalException ex) { //插入错误日志 } return ""; }
到这里支付请求就已经完成了,但修改订单状态和操作数据库的语句我们写到Paypal的IPN中执行
private string myEmail = "[email protected]"; //////接收Paypal的IPN消息 /// /// [HttpPost] public HttpStatusCodeResult Receive() {//Store the IPN received from PayPal LogRequest(Request); //Fire and forget verification task Task.Run(() => VerifyTask(Request)); //Reply back a 200 code return new HttpStatusCodeResult(HttpStatusCode.OK); } /// /// 验证是否是paypal发过来的消息 /// /// private void VerifyTask(HttpRequest ipnRequest) { var verificationResponse = string.Empty;try { System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; var verificationRequest = (HttpWebRequest)WebRequest.Create("https://www.sandbox.paypal.com/cgi-bin/webscr"); //Set values for the verification request verificationRequest.Method = "POST"; verificationRequest.ContentType = "application/x-www-form-urlencoded"; var param = Request.BinaryRead(ipnRequest.ContentLength); var strRequest = Encoding.ASCII.GetString(param); //Add cmd=_notify-validate to the payload strRequest = "cmd=_notify-validate&" + strRequest; verificationRequest.ContentLength = strRequest.Length; //Attach payload to the verification request var streamOut = new StreamWriter(verificationRequest.GetRequestStream(), Encoding.ASCII); streamOut.Write(strRequest); streamOut.Close(); //Send the request to PayPal and get the response var streamIn = new StreamReader(verificationRequest.GetResponse().GetResponseStream()); verificationResponse = streamIn.ReadToEnd(); streamIn.Close(); ProcessVerificationResponse(verificationResponse, ipnRequest); } catch (Exception exception) {//插入错误日志 ErrorLogPO errorLog = new ErrorLogPO(); errorLog.KID = Guid.NewGuid(); errorLog.ErrorMessage = exception.Message; errorLog.ErrorState = Interface.Offer.Eum.EumErrorLogType.Paypal; errorLog.OperaTime = DateTime.Now; errorLog.Del = false; OfferServer.ErrorLog.AddErrorLog(errorLog); } } /// /// 记录txn_id和状态验证重复 /// /// private void LogRequest(HttpRequest request) { //交易状态 string payment_status = request.Form["payment_status"].ToString();//交易号 string txn_id = request.Form["txn_id"].ToString(); // Persist the request values into a database or temporary data store PaypalTradeWayPayServer pay = new PaypalTradeWayPayServer(); pay.OneCreate(payment_status, txn_id); } /// /// 执行业务操作 /// /// /// private void ProcessVerificationResponse(string verificationResponse, HttpRequest request) { try { if (verificationResponse.Equals("VERIFIED")) { // check that Payment_status=Completed // check that Txn_id has not been previously processed // check that Receiver_email is your Primary PayPal email // check that Payment_amount/Payment_currency are correct // process payment //NameValueCollection coll; ////Load Form variables into NameValueCollection variable. //coll = Request.Form; //// Get names of all forms into a string array. //String[] requestItem = coll.AllKeys; //for (var i = 0; i < requestItem.Length; i++) //{ // WriteError(requestItem[i] + ":" + Request.Form[requestItem[i]]); //} //卖方邮箱 string receiver_email = request.Form["receiver_email"].ToString(); //交易状态 string payment_status = request.Form["payment_status"].ToString(); //交易号 string txn_id = request.Form["txn_id"].ToString(); string mc_gross = request.Form["mc_gross"].ToString();//金额 string mc_currency = request.Form["mc_currency"].ToString();//货币 // DateTime Payment_date = Convert.ToDateTime(request.Form["payment_date"].ToString());//交易时间 DateTime Payment_date = DateTime.Now; //订单号 string custom = request.Form["custom"].ToString();if (payment_status == "Completed") { PaypalWayPayPO model = PayWayServer.PaypalWayPay.Find(x => x.Txn_id == txn_id.Trim()); var order = OrderServer.Order.Find(x => x.OrderNo == custom.Trim()); PaypalTradeWayPayServer pay = new PaypalTradeWayPayServer(); bool verity = model.Payment_status == payment_status && receiver_email == myEmail && (order.TotalAmount.Value + order.TotalFreight.Value).ToString() == mc_gross && pay.ChangeCurrency(order.CurrencyCode.Trim()) == mc_currency;if (verity) { pay.UpdatePaypalData(Payment_date, custom, txn_id, payment_status); } } } else if (verificationResponse.Equals("INVALID")) { string custom1 = request.Form["custom"].ToString(); ErrorLogPO model = new ErrorLogPO(); model.KID = Guid.NewGuid(); model.ErrorState = EumErrorLogType.Paypal; model.ErrorMessage = "Paypal支付订单号为:" + custom1 + "状态无效"; model.OperaTime = DateTime.Now; model.Del = false; OfferServer.ErrorLog.AddErrorLog(model); } else { ErrorLogPO model = new ErrorLogPO(); model.KID = Guid.NewGuid(); model.ErrorState = EumErrorLogType.Paypal; model.ErrorMessage = "Palpal请求失败"; model.OperaTime = DateTime.Now; model.Del = false; OfferServer.ErrorLog.AddErrorLog(model); } } catch (Exception ex) { ErrorLogPO model = new ErrorLogPO(); model.KID = Guid.NewGuid(); model.ErrorState = EumErrorLogType.Paypal; model.ErrorMessage = ex.Message; model.OperaTime = DateTime.Now; model.Del = false; OfferServer.ErrorLog.AddErrorLog(model); } }