/// <summary> /// Tests that use this method must be ignored when run in an automated environment because executing an order /// will require approval via the executed payment's approval_url. /// </summary> /// <returns></returns> private Order GetExecutedPaymentOrder(PayPal.APIContext apiContext) { var pay = PaymentTest.CreatePaymentOrder(); var paymentExecution = PaymentExecutionTest.GetPaymentExecution(); paymentExecution.payer_id = pay.id; paymentExecution.transactions[0].amount.details = null; var executedPayment = pay.Execute(apiContext, paymentExecution); var orderId = executedPayment.transactions[0].related_resources[0].order.id; return(Order.Get(apiContext, orderId)); }
} // End of the payex_confirmation method #endregion #region PayPal payment /// <summary> /// Create a paypal payment /// </summary> public ActionResult CreatePayPalPayment(Order order, List<OrderRow> orderRows, Domain domain, KeyStringList tt) { // Create the string to return string error_message = ""; // Get the currency Currency currency = Currency.GetOneById(order.currency_code); // Get the webshop settings KeyStringList webshopSettings = WebshopSetting.GetAllFromCache(); // Get credentials string paypalClientId = webshopSettings.Get("PAYPAL-CLIENT-ID"); string paypalClientSecret = webshopSettings.Get("PAYPAL-CLIENT-SECRET"); string paypalMode = webshopSettings.Get("PAYPAL-MODE"); Dictionary<string, string> config = new Dictionary<string, string> { { "mode", paypalMode } }; // Create a payment variable PayPal.Api.Payments.Payment createdPayment = null; try { // Create the credential token PayPal.OAuthTokenCredential tokenCredential = new PayPal.OAuthTokenCredential(paypalClientId, paypalClientSecret, config); // Create the api context PayPal.APIContext paypalContext = new PayPal.APIContext(tokenCredential.GetAccessToken()); paypalContext.Config = config; // Create the amount details decimal subTotal = order.net_sum + order.rounding_sum - order.gift_cards_amount; PayPal.Api.Payments.Details amountDetails = new PayPal.Api.Payments.Details(); amountDetails.subtotal = subTotal.ToString("F2", CultureInfo.InvariantCulture); amountDetails.tax = order.vat_sum.ToString("F2", CultureInfo.InvariantCulture); // Create the amount decimal totalAmount = order.total_sum - order.gift_cards_amount; PayPal.Api.Payments.Amount amount = new PayPal.Api.Payments.Amount(); amount.total = totalAmount.ToString("F2", CultureInfo.InvariantCulture); amount.currency = order.currency_code; amount.details = amountDetails; // Create a transaction PayPal.Api.Payments.Transaction transaction = new PayPal.Api.Payments.Transaction(); transaction.item_list = new PayPal.Api.Payments.ItemList(); transaction.item_list.items = new List<PayPal.Api.Payments.Item>(10); // Add order rows to the transaction for (int i = 0; i < orderRows.Count; i++) { // Create a new item PayPal.Api.Payments.Item item = new PayPal.Api.Payments.Item(); item.sku = orderRows[i].product_code.Length > 50 ? orderRows[i].product_code.Substring(0, 50) : orderRows[i].product_code; item.name = orderRows[i].product_name.Length > 100 ? orderRows[i].product_name.Substring(0, 50) : orderRows[i].product_name; item.price = orderRows[i].unit_price.ToString("F2", CultureInfo.InvariantCulture); item.quantity = Convert.ToInt32(orderRows[i].quantity).ToString(); item.currency = order.currency_code; // Add the item to the list transaction.item_list.items.Add(item); } // Add the rounding if(order.rounding_sum != 0) { PayPal.Api.Payments.Item roundingItem = new PayPal.Api.Payments.Item(); roundingItem.sku = "rd"; roundingItem.name = tt.Get("rounding"); roundingItem.price = order.rounding_sum.ToString("F2", CultureInfo.InvariantCulture); roundingItem.quantity = "1"; roundingItem.currency = order.currency_code; transaction.item_list.items.Add(roundingItem); } // Add the gift cards amount if (order.gift_cards_amount > 0) { decimal giftCardAmount = order.gift_cards_amount * -1; PayPal.Api.Payments.Item giftCardsItem = new PayPal.Api.Payments.Item(); giftCardsItem.sku = "gc"; giftCardsItem.name = tt.Get("gift_cards"); giftCardsItem.price = giftCardAmount.ToString("F2", CultureInfo.InvariantCulture); giftCardsItem.quantity = "1"; giftCardsItem.currency = order.currency_code; transaction.item_list.items.Add(giftCardsItem); } // Set the transaction amount transaction.amount = amount; List<PayPal.Api.Payments.Transaction> transactions = new List<PayPal.Api.Payments.Transaction>(); transactions.Add(transaction); // Create the payer PayPal.Api.Payments.Payer payer = new PayPal.Api.Payments.Payer(); payer.payment_method = "paypal"; // Create redirect urls string hostUrl = Request.Url.Host; PayPal.Api.Payments.RedirectUrls redirectUrls = new PayPal.Api.Payments.RedirectUrls(); redirectUrls.return_url = domain.web_address + "/order/paypal_confirmation/" + order.id; redirectUrls.cancel_url = domain.web_address + "/order/confirmation/" + order.id; // Create the payment PayPal.Api.Payments.Payment payment = new PayPal.Api.Payments.Payment(); payment.intent = "sale"; payment.payer = payer; payment.redirect_urls = redirectUrls; payment.transactions = transactions; // Create the payment createdPayment = payment.Create(paypalContext); } catch (Exception ex) { error_message = ex.Message; } // Check if there is any errors in the payment if (createdPayment != null) { // Save the paypal payment id Order.SetPaymentToken(order.id, createdPayment.id); // Get the link string link = ""; foreach(PayPal.Api.Payments.Links url in createdPayment.links) { if (url.rel == "approval_url") { link = url.href; break; } } // Redirect the user to the paypal page return Redirect(link); } else { // Redirect the user to the order confirmation page return RedirectToAction("confirmation", "order", new { id = order.id }); } } // End of the CreatePayPalPayment method
public ActionResult paypal_confirmation(Int32 id = 0) { // Get the payer id string payerId = ""; if (Request.Params["PayerID"] != null) { payerId = Server.UrlDecode(Request.Params["PayerID"]); } // Get the order Order order = Order.GetOneById(id); // Make sure that the order not is null if(order == null) { // Redirect the user to the order confirmation page return RedirectToAction("index", "home"); } // Get the webshop settings KeyStringList webshopSettings = WebshopSetting.GetAllFromCache(); // Get credentials string paypalClientId = webshopSettings.Get("PAYPAL-CLIENT-ID"); string paypalClientSecret = webshopSettings.Get("PAYPAL-CLIENT-SECRET"); string paypalMode = webshopSettings.Get("PAYPAL-MODE"); Dictionary<string, string> config = new Dictionary<string, string> { { "mode", paypalMode } }; // Create a error message string error_message = ""; // Create a payment variable PayPal.Api.Payments.Payment createdPayment = null; try { // Create the credential token PayPal.OAuthTokenCredential tokenCredential = new PayPal.OAuthTokenCredential(paypalClientId, paypalClientSecret, config); // Create the api context PayPal.APIContext paypalContext = new PayPal.APIContext(tokenCredential.GetAccessToken()); paypalContext.Config = config; // Get the payment PayPal.Api.Payments.Payment payment = PayPal.Api.Payments.Payment.Get(paypalContext, order.payment_token); // Create the payment excecution PayPal.Api.Payments.PaymentExecution paymentExecution = new PayPal.Api.Payments.PaymentExecution(); paymentExecution.payer_id = payerId; paypalContext.HTTPHeaders = null; // Excecute the payment createdPayment = payment.Execute(paypalContext, paymentExecution); } catch (Exception ex) { error_message = ex.Message; } // Check if the created payment is different from null if (createdPayment != null && createdPayment.state == "approved") { // Get the sale id List<PayPal.Api.Payments.RelatedResources> resources = createdPayment.transactions[0].related_resources; // Save the paypal sale id Order.SetPaymentToken(order.id, resources[0].sale.id); // Update the order status Order.UpdatePaymentStatus(order.id, "payment_status_paid"); // Add customer files CustomerFile.AddCustomerFiles(order); } // Redirect the user to the order confirmation page return RedirectToAction("confirmation", "order", new { id = id }); } // End of the paypal_confirmation method
} // End of the UpdatePaymentStatus method /// <summary> /// Respond to an updated order status /// </summary> /// <param name="order"></param> /// <param name="paymentOption"></param> /// <param name="orderStatus"></param> /// <returns></returns> private string UpdateOrderStatus(Order order, PaymentOption paymentOption, string orderStatus) { // Create the string to return string error_message = ""; // Get the current domain Domain domain = Tools.GetCurrentDomain(); // Get webshop settings KeyStringList webshopSettings = WebshopSetting.GetAllFromCache(); // Check the order status if (orderStatus == "order_status_delivered") { if(paymentOption.connection == 102) // Payson invoice { // Get credentials string paysonEmail = webshopSettings.Get("PAYSON-EMAIL"); string userId = webshopSettings.Get("PAYSON-AGENT-ID"); string md5Key = webshopSettings.Get("PAYSON-MD5-KEY"); bool paysonTest = false; bool.TryParse(webshopSettings.Get("PAYSON-TEST"), out paysonTest); // Create the api PaysonIntegration.PaysonApi paysonApi = new PaysonIntegration.PaysonApi(userId, md5Key, null, paysonTest); // Update the order PaysonIntegration.Data.PaymentUpdateData paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.ShipOrder); PaysonIntegration.Response.PaymentUpdateResponse paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData); // Check if the response is successful if (paymentUpdateResponse != null && paymentUpdateResponse.Success == false) { // Set error messages foreach (string key in paymentUpdateResponse.ErrorMessages) { error_message += "• " + "Payson: " + paymentUpdateResponse.ErrorMessages[key] + "<br/>"; } } } else if(paymentOption.connection == 301) // Svea invoice { // Get the order rows List<OrderRow> orderRows = OrderRow.GetByOrderId(order.id); // Create the payment configuration SveaSettings sveaConfiguration = new SveaSettings(); // Create the order builder Webpay.Integration.CSharp.Order.Handle.DeliverOrderBuilder inoviceBuilder = Webpay.Integration.CSharp.WebpayConnection.DeliverOrder(sveaConfiguration); // Add order rows for (int i = 0; i < orderRows.Count; i++) { // Get the unit Unit unit = Unit.GetOneById(orderRows[i].unit_id, domain.back_end_language); // Create an order item Webpay.Integration.CSharp.Order.Row.OrderRowBuilder orderItem = new Webpay.Integration.CSharp.Order.Row.OrderRowBuilder(); orderItem.SetArticleNumber(orderRows[i].product_code); orderItem.SetName(orderRows[i].product_name); orderItem.SetQuantity(orderRows[i].quantity); orderItem.SetUnit(unit.unit_code); orderItem.SetAmountExVat(orderRows[i].unit_price); orderItem.SetVatPercent(orderRows[i].vat_percent * 100); // Add the order item inoviceBuilder.AddOrderRow(orderItem); } // Get the order id Int64 sveaOrderId = 0; Int64.TryParse(order.payment_token, out sveaOrderId); // Set invoice values inoviceBuilder.SetOrderId(sveaOrderId); inoviceBuilder.SetNumberOfCreditDays(15); inoviceBuilder.SetInvoiceDistributionType(Webpay.Integration.CSharp.Util.Constant.InvoiceDistributionType.POST); inoviceBuilder.SetCountryCode(SveaSettings.GetSveaCountryCode(order.country_code)); // Make the request to send the invoice Webpay.Integration.CSharp.WebpayWS.DeliverOrderEuResponse deliverOrderResponse = inoviceBuilder.DeliverInvoiceOrder().DoRequest(); // Check if the response is successful if (deliverOrderResponse.Accepted == false) { // Set error messages error_message += "• " + "Svea code: " + deliverOrderResponse.ResultCode.ToString() + "<br/>"; error_message += "• " + "Svea message: " + deliverOrderResponse.ErrorMessage + "<br/>"; } } else if (paymentOption.connection >= 400 && paymentOption.connection <= 499) // Payex { // Check the transaction Dictionary<string, string> payexResponse = PayExManager.CheckTransaction(order, webshopSettings); // Get response variables string error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : ""; string description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : ""; string parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : ""; string transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : ""; string transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : ""; // Check if the response was successful if (error_code.ToUpper() == "OK") { if(transaction_status == "3") // Authorize { // Capture the transaction payexResponse = PayExManager.CaptureTransaction(order); // Get response variables error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : ""; description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : ""; parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : ""; transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : ""; transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : ""; string transaction_number_original = payexResponse.ContainsKey("transaction_number_original") == true ? payexResponse["transaction_number_original"] : ""; if(error_code.ToUpper() != "OK" || transaction_status != "6") { // Set error messages error_message += "• " + "Payex code: " + error_code + "<br/>"; error_message += "• " + "Payex message: " + description + "<br/>"; error_message += "• " + "Payex parameter: " + parameter_name + "<br/>"; error_message += "• " + "Payex status: " + transaction_status + "<br/>"; error_message += "• " + "Payex number (original): " + transaction_number + "<br/>"; } else { // Update the transaction number for the order Order.SetPaymentToken(order.id, transaction_number); } } } else { // Set error messages error_message += "• " + "Payex code: " + error_code + "<br/>"; error_message += "• " + "Payex message: " + description + "<br/>"; error_message += "• " + "Payex parameter: " + parameter_name + "<br/>"; error_message += "• " + "Payex status: " + transaction_status + "<br/>"; error_message += "• " + "Payex number: " + transaction_number + "<br/>"; } } } else if (orderStatus == "order_status_cancelled") { if(paymentOption.connection >= 100 && paymentOption.connection <= 199) // Payson { // Get credentials string paysonEmail = webshopSettings.Get("PAYSON-EMAIL"); string userId = webshopSettings.Get("PAYSON-AGENT-ID"); string md5Key = webshopSettings.Get("PAYSON-MD5-KEY"); bool paysonTest = false; bool.TryParse(webshopSettings.Get("PAYSON-TEST"), out paysonTest); // Create the api PaysonIntegration.PaysonApi paysonApi = new PaysonIntegration.PaysonApi(userId, md5Key, null, paysonTest); // Get details about the payment status PaysonIntegration.Response.PaymentDetailsResponse paysonResponse = paysonApi.MakePaymentDetailsRequest(new PaysonIntegration.Data.PaymentDetailsData(order.payment_token)); // Get the type and status of the payment PaysonIntegration.Utils.PaymentType? paymentType = paysonResponse.PaymentDetails.PaymentType; PaysonIntegration.Utils.PaymentStatus? paymentStatus = paysonResponse.PaymentDetails.PaymentStatus; PaysonIntegration.Utils.InvoiceStatus? invoiceStatus = paysonResponse.PaymentDetails.InvoiceStatus; // Payment update PaysonIntegration.Data.PaymentUpdateData paymentUpdateData = null; PaysonIntegration.Response.PaymentUpdateResponse paymentUpdateResponse = null; if (paymentType == PaysonIntegration.Utils.PaymentType.Direct && paymentStatus == PaysonIntegration.Utils.PaymentStatus.Completed) { // Refund the payment paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.Refund); paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData); } else if (paymentType == PaysonIntegration.Utils.PaymentType.Invoice && invoiceStatus == PaysonIntegration.Utils.InvoiceStatus.OrderCreated) { // Cancel the order paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.CancelOrder); paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData); } else if (paymentType == PaysonIntegration.Utils.PaymentType.Invoice && (invoiceStatus == PaysonIntegration.Utils.InvoiceStatus.Shipped || invoiceStatus == PaysonIntegration.Utils.InvoiceStatus.Done)) { // Credit the order paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.CreditOrder); paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData); } // Check if there was any errors if (paymentUpdateResponse != null && paymentUpdateResponse.Success == false) { // Set error messages foreach (string key in paymentUpdateResponse.ErrorMessages) { error_message += "• " + "Payson: " + paymentUpdateResponse.ErrorMessages[key] + "<br/>"; } } } else if(paymentOption.connection == 201) // PayPal { // Get credentials string paypalClientId = webshopSettings.Get("PAYPAL-CLIENT-ID"); string paypalClientSecret = webshopSettings.Get("PAYPAL-CLIENT-SECRET"); string paypalMode = webshopSettings.Get("PAYPAL-MODE"); Dictionary<string, string> config = new Dictionary<string, string> { { "mode", paypalMode } }; try { // Create the credential token PayPal.OAuthTokenCredential tokenCredential = new PayPal.OAuthTokenCredential(paypalClientId, paypalClientSecret, config); // Create the api context PayPal.APIContext paypalContext = new PayPal.APIContext(tokenCredential.GetAccessToken()); paypalContext.Config = config; // Look up the sale PayPal.Api.Payments.Sale sale = PayPal.Api.Payments.Sale.Get(paypalContext, order.payment_token); if (sale.state == "completed") { // Refund the payment paypalContext.HTTPHeaders = null; PayPal.Api.Payments.Refund refund = sale.Refund(paypalContext, new PayPal.Api.Payments.Refund()); if(refund.state != "completed") { error_message += "• " + "PayPal: " + refund.state; } } else { error_message += "• " + "PayPal: " + sale.state; } } catch (Exception ex) { error_message += "• PayPal: " + ex.Message; } } else if(paymentOption.connection == 301) // Svea invoice { // Create the payment configuration SveaSettings sveaConfiguration = new SveaSettings(); // Get the order id Int64 sveaOrderId = 0; Int64.TryParse(order.payment_token, out sveaOrderId); // Cancel the order Webpay.Integration.CSharp.Order.Handle.CloseOrderBuilder closeOrder = Webpay.Integration.CSharp.WebpayConnection.CloseOrder(sveaConfiguration); closeOrder.SetOrderId(sveaOrderId); closeOrder.SetCountryCode(SveaSettings.GetSveaCountryCode(order.country_code)); Webpay.Integration.CSharp.WebpayWS.CloseOrderEuResponse closeOrderResponse = closeOrder.CloseInvoiceOrder().DoRequest(); // Check if the response is successful if (closeOrderResponse.Accepted == false) { // Set error messages error_message += "• " + "Svea code: " + closeOrderResponse.ResultCode.ToString() + "<br/>"; error_message += "• " + "Svea message: " + closeOrderResponse.ErrorMessage + "<br/>"; } } else if(paymentOption.connection >= 400 && paymentOption.connection <= 499) // Payex { // Check the transaction Dictionary<string, string> payexResponse = PayExManager.CheckTransaction(order, webshopSettings); // Get response variables string error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : ""; string description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : ""; string parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : ""; string transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : ""; string transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : ""; // Check if the response was successful if(error_code.ToUpper() == "OK") { // Check if we should cancel or credit the order if(transaction_status == "3") // Authorize { // Cancel the transaction payexResponse = PayExManager.CancelTransaction(order, webshopSettings); // Get response variables error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : ""; description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : ""; parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : ""; transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : ""; transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : ""; if(error_code.ToUpper() != "OK" || transaction_status != "4") { // Set error messages error_message += "• " + "Payex code: " + error_code + "<br/>"; error_message += "• " + "Payex message: " + description + "<br/>"; error_message += "• " + "Payex parameter: " + parameter_name + "<br/>"; error_message += "• " + "Payex status: " + transaction_status + "<br/>"; error_message += "• " + "Payex number: " + transaction_number + "<br/>"; } } else if(transaction_status == "0" || transaction_status == "6") // Sale or capture { // Get the order rows List<OrderRow> orderRows = OrderRow.GetByOrderId(order.id); // Credit the transaction payexResponse = PayExManager.CreditTransaction(order, orderRows, webshopSettings); // Get response variables error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : ""; description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : ""; parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : ""; transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : ""; transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : ""; if (error_code.ToUpper() != "OK" || transaction_status != "2") { // Set error messages error_message += "• " + "Payex code: " + error_code + "<br/>"; error_message += "• " + "Payex message: " + description + "<br/>"; error_message += "• " + "Payex parameter: " + parameter_name + "<br/>"; error_message += "• " + "Payex status: " + transaction_status + "<br/>"; error_message += "• " + "Payex number: " + transaction_number + "<br/>"; } } } else { // Set error messages error_message += "• " + "Payex code: " + error_code + "<br/>"; error_message += "• " + "Payex message: " + description + "<br/>"; error_message += "• " + "Payex parameter: " + parameter_name + "<br/>"; error_message += "• " + "Payex status: " + transaction_status + "<br/>"; error_message += "• " + "Payex number: " + transaction_number + "<br/>"; } } } // Return the error message return error_message; } // End of the UpdateOrderStatus method
private Int32 AndNowItIsTimeToTalkToPayPal(Int32 productCost, String productDescription, String yourname, out String redirect_approvalUrlFromCreatedPayment) { // ................................ // Miscellaneous Error Messages from PayPal ... ***** "debug_id" is NOT a constant, examples: "67f86e19d300d", "36f998b61c785" String response_VALIDATION_ERROR = "{\"name\":\"VALIDATION_ERROR\",\"details\":[{\"field\":\"transactions[0].amount\",\"issue\":\"Required field missing\"}],\"message\":\"Invalid request - see details\",\"information_link\":\"https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR\",\"debug_id\":\""; Int32 response_VALIDATION_ERROR_Length = response_VALIDATION_ERROR.Length; // https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR // VALIDATION_ERROR // Invalid request - see details // There was a validation issue with your request - see details // ==> https://developer.paypal.com/webapps/developer/docs/api/#validation-issues // ................................ String response_INTERNAL_SERVICE_ERROR = "{\"name\":\"INTERNAL_SERVICE_ERROR\",\"message\":\"An internal service error has occurred\",\"information_link\":\"https://developer.paypal.com/webapps/developer/docs/api/#INTERNAL_SERVICE_ERROR\",\"debug_id\":\""; Int32 response_INTERNAL_SERVICE_ERROR_Length = response_INTERNAL_SERVICE_ERROR.Length; // https://developer.paypal.com/webapps/developer/docs/api/#INTERNAL_SERVICE_ERROR // INTERNAL_SERVICE_ERROR // An internal service error has occurred // Resend the request at another time. If this error continues, // contact PayPal Merchant Technical Support. // https://developer.paypal.com/webapps/developer/support // ................................ Int32 payPalSuccessLevel = 999; // 999 =. unknown redirect_approvalUrlFromCreatedPayment = String.Empty; // THINGS WE NEED TO USE THE PAYPAL REST API String argumentsPlusPayPalClentID = "AU ... 6G"; // todo ... your PayPal REST API SDK user ID String argumentsPlusPayPalSecret = "EA ... -f"; // todo ... your PayPal REST API SDK PASSWORD // String payPalRestApiEndpoint = "api.sandbox.paypal.com"; // For TESTING !!! // = "api.paypal.com"; // For LIVE !!! // ................................ Dictionary<String, String> sdkConfig = new Dictionary<String, String>(); sdkConfig.Add("mode", "sandbox"); // ................................ // POTENTIAL POINT OF FAILURE // example: "Exception in HttpConnection Execute: Invalid HTTP response The operation has timed out" String oAuthAccessTokenForPayPal = String.Empty; // scope outside of try/catch try { oAuthAccessTokenForPayPal = new PayPal .OAuthTokenCredential(argumentsPlusPayPalClentID, argumentsPlusPayPalSecret, sdkConfig).GetAccessToken(); } // .GetAccessToken takes us over to PayPal catch (Exception) { throw; // todo ... make this code more robust } // ................................ // We're back from PayPal with our access token. PayPal.APIContext apiContext // use the "Bearer" token from PayPal = new PayPal.APIContext(oAuthAccessTokenForPayPal); apiContext.Config = sdkConfig; // ................................ PayPal.Api.Payments.Amount argumentsPlusPayPalPaymentAmount = new PayPal.Api.Payments.Amount(); // https://developer.paypal.com/docs/classic/api/currency_codes/ argumentsPlusPayPalPaymentAmount.currency = "GBP"; // UK Pound Sterling; "USD" for US$ argumentsPlusPayPalPaymentAmount.total = productCost.ToString(); // ................................ String description = String.Empty; // 127 character maximum length description = productDescription + " " + DateTime.Now.ToLongDateString() + " -- " + DateTime.Now.ToLongTimeString() + " -- " + productCost + " U.K. pounds" + " -- Thank you " + yourname + " for your purchase."; // ................................ // borrowed code from: http://msdn.microsoft.com/en-us/library/xwewhkd1(v=vs.110).aspx // Regex.Replace Method (String, String) // ... match ALL one or more white-space characters in our description text, // replace EACH instance found with just one space. System.Text.RegularExpressions.Regex regexPattern = new System.Text.RegularExpressions.Regex(@"\s+"); description = regexPattern.Replace(description, " "); // PayPal's HTML will drop extra whilespace, so we do not send any extra whitespace. // ................................ PayPal.Api.Payments.Transaction argumentsSale = new PayPal.Api.Payments.Transaction(); if (description.Length > 127) description = description.Substring(0, 127); // allow no more that 127 characters (PayPal's Limit) argumentsSale.description = description; argumentsSale.amount = argumentsPlusPayPalPaymentAmount; // ................................ List<PayPal.Api.Payments.Transaction> transactionList = new List<PayPal.Api.Payments.Transaction>(); transactionList.Add(argumentsSale); // ................................ PayPal.Api.Payments.Payer argumentBuyer = new PayPal.Api.Payments.Payer(); // The payment method "paypal" lets the customer choose // whether to pay us using a PayPal account // or to pay us with their credit card as a PayPal guest. argumentBuyer.payment_method = "paypal"; // ................................ // Note: we need some way to connect PayPal's response // back to our customer ... TIMTOWTDI Guid reconnectToOurBuyer = Guid.NewGuid(); PayPal.Api.Payments.RedirectUrls redirUrls = new PayPal.Api.Payments.RedirectUrls(); String cancelURL = "http://localhost:53326/home/argumentsnotsold/" + reconnectToOurBuyer.ToString("N"); // customer changes her/his mind String returnURL = "http://localhost:53326/home/argumentssold/" + reconnectToOurBuyer.ToString("N"); // Hurrah! A sale! redirUrls.cancel_url = cancelURL; redirUrls.return_url = returnURL; // ................................ // Next, we create a Payment object to send to PayPal PayPal.Api.Payments.Payment getInvoiceFromPayPal = new PayPal.Api.Payments.Payment(); getInvoiceFromPayPal.intent = "sale"; getInvoiceFromPayPal.payer = argumentBuyer; getInvoiceFromPayPal.transactions = transactionList; getInvoiceFromPayPal.redirect_urls = redirUrls; // ................................ PayPal.Api.Payments.Payment createdInvoice = null; // scope outside of try/catch try { // the next line can fail, for example: http://paradigmmentors.net//files/code/argumentsPlus/500_internal_Server_Error_catch.txt createdInvoice = getInvoiceFromPayPal.Create(apiContext); // <== // SUCCESSFUL CREATION // we must persist createdInvoice.id (the Payment.id value) payPalSuccessLevel = 100; // successful SavePayPalInvoice(reconnectToOurBuyer, createdInvoice); } catch (PayPal.Exception.ConnectionException connectionExceptionPayPal) { payPalSuccessLevel = 111; if(String.Compare(connectionExceptionPayPal.Message, "Invalid HTTP response The remote server returned an error: (400) Bad Request.") == 0) { payPalSuccessLevel += 10000; if(String.Compare(connectionExceptionPayPal.Response.Substring(0, response_VALIDATION_ERROR_Length), response_VALIDATION_ERROR) == 0) { // todo Take appropriate action } else { payPalSuccessLevel += 20000; // todo Take appropriate action } } else if(String.Compare(connectionExceptionPayPal.Message, "Invalid HTTP response The remote server returned an error: (500) Internal Server Error.") == 0) { payPalSuccessLevel = 500; if (String.Compare(connectionExceptionPayPal.Response.Substring(0, response_INTERNAL_SERVICE_ERROR_Length), response_INTERNAL_SERVICE_ERROR) == 0) { payPalSuccessLevel += 30000; // todo Take appropriate action } else { payPalSuccessLevel += 40000; // todo Take appropriate action } } else { payPalSuccessLevel = 666; // todo Take appropriate action } // throw; // todo complete } catch (PayPal.Exception.PayPalException paypalException) { if (String.Compare(paypalException.Message, "Exception in HttpConnection Execute: Invalid HTTP response The remote server returned an error: (500) Internal Server Error.") == 0) { // the "may" be an inner exception payPalSuccessLevel = 777; if (paypalException.InnerException != null) // we take a chance that the InnerException is PayPal.Exception.ConnectionException { try { PayPal.Exception.ConnectionException payPalInnerException = (PayPal.Exception.ConnectionException)paypalException.InnerException; if (String.Compare(payPalInnerException.Response.Substring(0, response_INTERNAL_SERVICE_ERROR_Length), response_INTERNAL_SERVICE_ERROR) == 0) { payPalSuccessLevel = 30777; // fine tune our error code // todo Take appropriate action } else { payPalSuccessLevel = 40777; // fine tune our error code // todo Take appropriate action } } catch (Exception) { payPalSuccessLevel = 50777; // fine tune our error code // we probably guessed wrong // todo ........... handle appropriately } } } else { payPalSuccessLevel = 888; // todo Take appropriate action } // throw; // todo complete } catch (Exception genericException) // todo complete { // example causes: // (a) "No connection string named 'ArgumentPlusContext' // could be found in the application config file." // (b) "Directory lookup for the file // c:\argumentsPlus\argumentClinic.mdf\" failed // with the operating system error // The system cannot find the file specified. // CREATE DATABASE failed. payPalSuccessLevel = 2222; // todo Take appropriate action } // ................................ Boolean approval_url_found = false; if(payPalSuccessLevel == 100) { List<PayPal.Api.Payments.Links> linksFromCreatedPayment = createdInvoice.links; foreach (PayPal.Api.Payments.Links rel_approval in linksFromCreatedPayment) { if (rel_approval.rel.ToLower().Equals("approval_url")) { redirect_approvalUrlFromCreatedPayment = Server.UrlDecode(rel_approval.href); approval_url_found = true; break; } } if (!approval_url_found) payPalSuccessLevel = 69; } return payPalSuccessLevel; }
public ActionResult ArgumentsSold(String id, // your ID String token, // PayPal token String PayerID) { String payment_id = String.Empty; String executeUrlFromCreatedPayment = String.Empty; // ................................ // ======> // THINGS WE NEED TO USE THE PAYPAL REST API // ======> String argumentsPlusPayPalClentID = " ... your user ID for Arguments Plus ..."; // ======> String argumentsPlusPayPalSecret = " ... this is YOUR PASSWORD ..."; String argumentsPlusPayPalClentID = "AU ... 6G"; // todo ... your PayPal REST API SDK user ID String argumentsPlusPayPalSecret = "EA ... -f"; // todo ... your PayPal REST API SDK PASSWORD // ======> String payPalRestApiEndpoint = "api.sandbox.paypal.com"; // For TESTING !!! // ======> // = "api.paypal.com"; // For LIVE !!! Dictionary<String, String> sdkConfig = new Dictionary<String, String>(); sdkConfig.Add("mode", "sandbox"); // ................................ // POTENTIAL POINT OF FAILURE // example: "Exception in HttpConnection Execute: Invalid HTTP response The operation has timed out" String oAuthAccessTokenForPayPal = String.Empty; // scope outside of try/catch try { oAuthAccessTokenForPayPal = new PayPal.OAuthTokenCredential(argumentsPlusPayPalClentID, argumentsPlusPayPalSecret, sdkConfig).GetAccessToken(); } // .GetAccessToken takes us over to PayPal catch (Exception) { throw; // todo ... make this code more robust } // ................................ PayPal.APIContext apiContext = new PayPal.APIContext(oAuthAccessTokenForPayPal); apiContext.Config = sdkConfig; // ................................ // id is our Guid for reconnecting to our customer's invoice PayPal.Api.Payments.Payment createdInvoice = GetSavedPayPalInvoice(id); // ................................ // now we convert the approved invoice into an actual payment PayPal.Api.Payments.Payment payment = new PayPal.Api.Payments.Payment(); payment.id = createdInvoice.id; // use the previously returned "invoice" identifier PayPal.Api.Payments.PaymentExecution askPayPalForMoney = new PayPal.Api.Payments.PaymentExecution(); askPayPalForMoney.payer_id = PayerID; // from Query string ==> ?token=EC-3LN850372M719842K&PayerID=JJT6YSAZSFJTC PayPal.Api.Payments.Payment paidInvoice = null; // scope outside of try/catch try { // an APPROVED PAYMENT morphs into a SALE !!!!!!!!!!!!!!!!!!!!! paidInvoice = payment.Execute(apiContext, askPayPalForMoney); // off to PayPal // Here, if all has gone well, we're just right back from PayPal // and the money for the above invoice is now in our PayPal Merchant Account. ViewBag.PaidInvoice = paidInvoice; } catch (PayPal.Exception.ConnectionException connectionExceptionPayPal) { if (String.Compare(connectionExceptionPayPal.Message, "Invalid HTTP response The remote server returned an error: (400) Bad Request.") == 0) { String response_PAYMENT_STATE_INVALID = "{\"name\":\"PAYMENT_STATE_INVALID\",\"message\":\"This request is invalid due to the current state of the payment\",\"information_link\":\"https://developer.paypal.com/webapps/developer/docs/api/#PAYMENT_STATE_INVALID\",\"debug_id\":\""; Int32 response_PAYMENT_STATE_INVALID_Length = response_PAYMENT_STATE_INVALID.Length; if (String.Compare(connectionExceptionPayPal.Response.Substring(0,response_PAYMENT_STATE_INVALID_Length), response_PAYMENT_STATE_INVALID) == 0) { // todo Take appropriate action } else { // todo Take appropriate action } } else { // todo Take appropriate action } throw; // todo complete this code ... for PRODUCTION, more robustness is a must! } catch (Exception generalExceptionGettingMoney) { throw; // todo ... deal with this error appropriately ("throw" is not appropriate) } // ................................ // PayPal has provided data -- we capture as much or as little as when require. // We can save the PayPal data and/or display it on our web page, et cetera. // Remember: respect your customers' privacy. Protect their data. String payment_state = String.Empty; // N.B.: this is NOT the province/state/region payment_state = paidInvoice.state; // Possible Values: pending, approved ViewBag.Payment_State = payment_state; String payment_intent = String.Empty; payment_intent = paidInvoice.intent; // Expected Value: "sale" ViewBag.Payment_Intent = payment_intent; String payment_method = String.Empty; payment_method = paidInvoice.payer.payment_method; // Expected Value: "paypal" ViewBag.Payment_Method = payment_method; String parent_payment = String.Empty; parent_payment = paidInvoice.transactions[0].related_resources[0].sale.parent_payment; ViewBag.Parent_Payment = parent_payment; String update_time = String.Empty; update_time = paidInvoice.update_time; // "2014-02-05T04:06:39Z" string ViewBag.Update_Time = update_time; String create_time = String.Empty; create_time = paidInvoice.create_time; // "2014-02-05T04:06:39Z" string ViewBag.Create_Time = create_time; // ................................ String payPal_email_address = String.Empty; // paidInvoice::email "*****@*****.**" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.email)) payPal_email_address = paidInvoice.payer.payer_info.email; ViewBag.PayPal_Email_Address = payPal_email_address; String payPal_first_name = String.Empty; // paidInvoice::first_name "gerry" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.first_name)) payPal_first_name = paidInvoice.payer.payer_info.first_name; ViewBag.PayPal_First_Name = payPal_first_name; String payPal_last_name = String.Empty; // paidInvoice::last_name "lowry" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.last_name)) payPal_last_name = paidInvoice.payer.payer_info.last_name; ViewBag.PayPal_Last_Name = payPal_last_name; String payPal_phone = String.Empty; // paidInvoice::phone null string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.phone)) payPal_phone = paidInvoice.payer.payer_info.phone; ViewBag.PayPal_Phone = payPal_phone; String payPal_city = String.Empty; // paidInvoice::city "SAN Jose" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.city)) payPal_city = paidInvoice.payer.payer_info.shipping_address.city; ViewBag.City = payPal_city; String payPal_country_code = String.Empty; // paidInvoice::country_code "US" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.country_code)) payPal_country_code = paidInvoice.payer.payer_info.shipping_address.country_code; ViewBag.PayPal_Country_Code = payPal_country_code; String payPal_address_line1 = String.Empty; // paidInvoice::line1 "1 Main St" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.line1)) payPal_address_line1 = paidInvoice.payer.payer_info.shipping_address.line1; ViewBag.PayPal_Address_Line1 = payPal_address_line1; String payPal_address_line2 = String.Empty; // paidInvoice::line2 null string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.line2)) payPal_address_line2 = paidInvoice.payer.payer_info.shipping_address.line2; ViewBag.PayPal_Address_Line2 = payPal_address_line2; String payPal_postal_code = String.Empty; // paidInvoice::postal_code "95131" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.postal_code)) payPal_postal_code = paidInvoice.payer.payer_info.shipping_address.postal_code; ViewBag.PayPal_Postal_Code = payPal_postal_code; String payPal_address_state = String.Empty; // paidInvoice::state "CA" string if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.state)) payPal_address_state = paidInvoice.payer.payer_info.shipping_address.state; ViewBag.PayPal_Address_State = payPal_address_state; // ................................ String payPal_transaction_amount_total = String.Empty; // paidInvoice::transation[0].amount" string if (!String.IsNullOrWhiteSpace(paidInvoice.transactions[0].amount.total)) payPal_transaction_amount_total = paidInvoice.transactions[0].amount.total; ViewBag.PayPal_Transaction_Amount_Total = payPal_transaction_amount_total; String payPal_transaction_amount_currency = String.Empty; // paidInvoice::transation[0].amount" string if (!String.IsNullOrWhiteSpace(paidInvoice.transactions[0].amount.total)) payPal_transaction_amount_currency = paidInvoice.transactions[0].amount.currency; ViewBag.PayPal_Transaction_Amount_Currency = payPal_transaction_amount_currency; String payPal_transaction_descripition = String.Empty; // paidInvoice::transation[0].amount" string if (!String.IsNullOrWhiteSpace(paidInvoice.transactions[0].amount.total)) payPal_transaction_descripition = paidInvoice.transactions[0].description; ViewBag.PayPal_Transaction_Description = payPal_transaction_descripition; // ................................ return View(); }