寫本文章的目的是為了記錄工作中遇到的問題,方便以後遇到可以迅速解決問題 paypal支付介面實現由幾種方法,我使用的是REST API 所以在這裡值介紹這種方法的使用 我們使用vs的Nuget下載Paypal的dll 首先需要配置Web.config文件 1.在configuration節點下配置c ...
寫本文章的目的是為了記錄工作中遇到的問題,方便以後遇到可以迅速解決問題
paypal支付介面實現由幾種方法,我使用的是REST API
所以在這裡值介紹這種方法的使用
我們使用vs的Nuget下載Paypal的dll
首先需要配置Web.config文件
1.在configuration節點下配置configsections中的section節點
2.在configuration節點下配置paypal節點
<configuration>
<configSections> <!--IMPORTANT: Make sure you add the configSections node to your config file so that the rest of the config file is picked by the application--> <section name="paypal" type="PayPal.SDKConfigHandler, PayPal" /> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections>
<paypal>
<settings>
<!-- Replace the mode to `security-test-sandbox` to test if your server supports TLSv1.2. For more information follow README instructions.-->
<add name="mode" value="sandbox" />
<add name="connectionTimeout" value="360000" />
<add name="requestRetries" value="1" />
<add name="clientId" value="ATnMWGSD5FAe8_kd5eA83ZN5V5jiRY57CCqYUG6We3uDrIfZNSolS_CZ0DK2I74yf03IEcN8HgMIl3Md" />
<add name="clientSecret" value="ENW9z0srkaWrowK5BQif52xHJoDoTaqZU38bz-y0mAz37sHDD9okHubjPcr0gmkZtlR9MbVuMshl_hyX" />
</settings>
</paypal>
</configuration>
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方法:
具體參數請自行查看
/// <summary> /// 得到ItemList /// </summary> /// <param name="order"></param> /// <returns></returns> 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<Item>(); 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<Transaction>(); // 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]"; /// <summary> ///接收Paypal的IPN消息 /// </summary> /// <returns></returns> [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); } /// <summary> /// 驗證是否是paypal發過來的消息 /// </summary> /// <param name="ipnRequest"></param> 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); } } /// <summary> /// 記錄txn_id和狀態驗證重覆 /// </summary> /// <param name="request"></param> 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); } /// <summary> /// 執行業務操作 /// </summary> /// <param name="verificationResponse"></param> /// <param name="request"></param> 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); } }