I'm trying to set up PayPal to accept payment from my site which calculate fees based on the number of photos they uploaded. Followed a tutorial, but I wanted to pass the price which I calculated in my other controller.
My PayPal controller:
public ActionResult PaymentWithPaypal()
{
APIContext apiContext = PayPalConfig.GetAPIContext();
try
{
string payerId = Request.Params["PayerID"];
if (string.IsNullOrEmpty(payerId))
{
string baseURI = Request.Url.Scheme + "://" + Request.Url.Authority + "/Paypal/PaymentWithPayPal?";
var guid = Convert.ToString((new Random()).Next(100000));
var createdPayment = this.CreatePayment(apiContext, baseURI + "guid=" + guid);
var links = createdPayment.links.GetEnumerator();
string paypalRedirectUrl = null;
while (links.MoveNext())
{
Links lnk = links.Current;
if (lnk.rel.ToLower().Trim().Equals("approval_url"))
{
paypalRedirectUrl = lnk.href;
}
}
Session.Add(guid, createdPayment.id);
return Redirect(paypalRedirectUrl);
}
else
{
var guid = Request.Params["guid"];
var executedPayment = ExecutePayment(apiContext, payerId, Session[guid] as string);
if (executedPayment.state.ToLower() != "approved")
{
return View("FailureView");
}
}
}
catch (Exception ex)
{
Logger.Log("Error" + ex.Message);
return View("FailureView");
}
return View("SuccessView");
}
private PayPal.Api.Payment payment;
private PayPal.Api.Payment ExecutePayment(APIContext apiContext, string payerId, string paymentId)
{
var paymentExecution = new PaymentExecution() { payer_id = payerId };
this.payment = new PayPal.Api.Payment() { id = paymentId };
return this.payment.Execute(apiContext, paymentExecution);
}
private PayPal.Api.Payment CreatePayment(APIContext apiContext, string redirectUrl)
{
var itemList = new ItemList() { items = new List<Item>() };
itemList.items.Add(new Item()
{
name = "Participation Fee",
currency = "USD",
price = "5",
quantity = "1",
sku = "sku"
});
var payer = new Payer() { payment_method = "paypal" };
var redirUrls = new RedirectUrls()
{
cancel_url = redirectUrl,
return_url = redirectUrl
};
var details = new Details()
{
tax = "1",
shipping = "1",
subtotal = "5"
};
var amount = new Amount()
{
currency = "USD",
total = "7",
details = details
};
var transactionList = new List<Transaction>();
transactionList.Add(new Transaction()
{
description = "Transaction description.",
invoice_number = "your invoice number",
amount = amount,
item_list = itemList
});
this.payment = new PayPal.Api.Payment()
{
intent = "sale",
payer = payer,
transactions = transactionList,
redirect_urls = redirUrls
};
return this.payment.Create(apiContext);
}
Controller where my price is calculated:
int Asection;
int Bsection;
int Csection;
int Dsection;
if (viewPhotos.GetA1.Any() || viewPhotos.GetA2.Any() || viewPhotos.GetA3.Any() || viewPhotos.GetA4.Any())
{
Asection = 1;
}
else
{
Asection = 0;
}
if (viewPhotos.GetB1.Any() || viewPhotos.GetB2.Any() || viewPhotos.GetB3.Any() || viewPhotos.GetB4.Any())
{
Bsection = 1;
}
else
{
Bsection = 0;
}
if (viewPhotos.GetC1.Any() || viewPhotos.GetC2.Any() || viewPhotos.GetC3.Any() || viewPhotos.GetC4.Any())
{
Csection = 1;
}
else
{
Csection = 0;
}
if (viewPhotos.GetD1.Any() || viewPhotos.GetD2.Any() || viewPhotos.GetD3.Any() || viewPhotos.GetD4.Any())
{
Dsection = 1;
}
else
{
Dsection = 0;
}
int TotalSection = Asection + Bsection + Csection + Dsection;
viewPhotos.MoneyValue = TotalSection;
int RequiredMoney;
if (TotalSection == 1)
{
RequiredMoney = 20;
}
else if (TotalSection == 2)
{
RequiredMoney = 25;
}
else if (TotalSection == 3)
{
RequiredMoney = 30;
}
else
{
RequiredMoney = 36;
}
viewPhotos.RequiredMoney = RequiredMoney;
return View(viewPhotos);
My view where price was shown to user:
<p>You will need to pay participation fees USD #Model.RequiredMoney.</p>
<h3>Total: USD #Model.RequiredMoney</h3>
#Html.ActionLink("Make Payment with PayPal", "PaymentWithPaypal", "Paypal")
So far the above codes work with the default testing item price and detail on the site. Would appreciate if anyone could help to show how do I set the amount to be collected by PayPal to my calculated price, without any shipping or tax. Thanks in advance.
After searching and reviewing the log for a while, here's how I solved my problem:
At the controller where I calculated my price, I used TempData to store my price:
TempData["ParticipationFee"] = RequiredMoney;
Then at the PaypalController, under CreatePayment function,
var itemList = new ItemList() { items = new List<Item>() };
string FeeAmount = TempData["ParticipationFee"].ToString();
itemList.items.Add(new Item()
{
name = "Participation Fee",
currency = "USD",
price = FeeAmount,
quantity = "1",
sku = "sku"
});
Hit F5 and got a successful response from Paypal Sandbox. Woot!
Related
I try to return the stock of the items and I can not get it. Could someone guide me and tell me what I'm doing wrong?
This is my code, quantityAvailable is always 0 and location is null. This is an excerpt from my source code:
var recordRefs = new List<RecordRef>();
var ExternalIds = new List<string>();
ExternalIds.Add("REV0001");
ExternalIds.Add("REV0002");
foreach (string externalId in ExternalIds)
{
recordRefs.Add(new RecordRef
{
externalId = externalId,
type = RecordType.InventoryItem,
typeSpecified = true
});
}
var request1 = new ItemSearchBasic
{
externalId = new SearchMultiSelectField
{
#operator = SearchMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = recordRefs.ToArray()
}
};
SearchResult response = Client.Service.search(request1);
if (response.status.isSuccess)
{
if (response.totalRecords > 1)
{
Record[] records;
records = response.recordList;
for (int lcv = 0; lcv <= records.Length - 1; lcv++)
{
if (records[lcv].GetType().Name == "InventoryItem")
{
Console.WriteLine(((InventoryItem)records[lcv]).itemId);
Console.WriteLine(((InventoryItem)records[lcv]).internalId);
Console.WriteLine(((InventoryItem)records[lcv]).quantityAvailable);
Console.WriteLine(((InventoryItem)records[lcv]).averageCost);
}
}
}
}
I want to insert text from c# textbox1 to google docs template body namedrange "BoddyTitle" and from textbox2 to body namedrange "BoddyContent" .
Because indexes of created namedrange is modifying for every update, I need to get value of that indexes before update with new text.
Pls help get that indexes.
List <Request> requests = new List<Request>
{
};
requests.Add(new Request()
{
ReplaceNamedRangeContent = new ReplaceNamedRangeContentRequest()
{
Text = textBox1.Text, NamedRangeName = "BoddyTitle"
}
}); // Index = 5-50,
requests.Add(new Request()
{
ReplaceNamedRangeContent = new ReplaceNamedRangeContentRequest()
{
Text = textBox2.Text, NamedRangeName = "BoddyContent"
}
}); // Index = 55-10000,
BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest { Requests = requests };
dservice.Documents.BatchUpdate(body, docid).Execute();
resolved, here the code
List<Request> requests = new List<Request> { };
DocumentsResource.GetRequest req = dservice.Documents.Get(docid);
Document doc = req.Execute();
int max = 0;
for (int i = 0; i < doc.Body.Content.Count; i++)
{
if (doc.Body.Content[i].EndIndex.Value > max)
{
max = doc.Body.Content[i].EndIndex.Value;
}
}
if (max < 3)
{
// requests.Add(new Request() { DeleteNamedRange = new DeleteNamedRangeRequest() { Name = "BoddyTitle" } });
// requests.Add(new Request() { DeleteNamedRange = new DeleteNamedRangeRequest() { Name = "BoddyContent", } });
requests.Add(new Request() { InsertText = new InsertTextRequest() { Text = "\n\nx", Location = new Location { Index = 1 } } });
requests.Add(new Request() { InsertText = new InsertTextRequest() { Text = "\n\nx", Location = new Location() { SegmentId = "", Index = 4 } } });
requests.Add(new Request() { CreateNamedRange = new CreateNamedRangeRequest() { Name = "BoddyTitle", Range = new Range() { SegmentId = "", StartIndex = 3, EndIndex = 4 } } });
requests.Add(new Request() { CreateNamedRange = new CreateNamedRangeRequest() { Name = "BoddyContent", Range = new Range() { SegmentId = "", StartIndex = 6, EndIndex = 7 } } });
}
// requests.Add(new Request() { DeleteContentRange = new DeleteContentRangeRequest() { Range = new Range { StartIndex = 1, EndIndex = max - 1 } } });
if (textBox1.Text != "" && textBox2.Text != "")
{
requests.Add(new Request() { ReplaceNamedRangeContent = new ReplaceNamedRangeContentRequest() { Text = textBox1.Text.Replace("\r\n", "\n"), NamedRangeName = "BoddyTitle" } });
requests.Add(new Request() { ReplaceNamedRangeContent = new ReplaceNamedRangeContentRequest() { Text = textBox2.Text.Replace("\r\n", "\n"), NamedRangeName = "BoddyContent" } });
}
else { MessageBox.Show("Textbox Empty" ); }
if (requests.Count >0)
{
BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest { Requests = requests };
dservice.Documents.BatchUpdate(body, docid).Execute();Process.Start("https://docs.google.com/document/d/doc_id/edit?usp=sharing");
}
I'm currently having an error(as mentioned in the title). I don't know what's wrong or which line I'm having problems with. I'm sure all the values mentioned in the error are the same but it still pops up the same error.
My aim is to make the all the values the same to solve the error.
Here's the full description of my error:
{
"name": "https://stackoverflow.com/VALIDATION_ERROR",
"details": [
{
"field": "transactions[0]",
"issue": "Item amount must add up to specified amount subtotal (or total if amount details not specified)"
}
],
"message": "Invalid request - see details",
"information_link": "https://developer.paypal.com/docs/api/payments/#errors",
"debug_id": "67a354f1a8fc7"
}
Please help!
Here are my codes for reference:
// scList has 2 values inside.
List<UserShoppingCartDAO> scList = UserShoppingCartDAO.GetCartOfUser(uID);
List<Item> itms = new List<Item>();
ItemList itemList = new ItemList();
decimal deliveryCharges = 0;
string deliveryChargesStr = "";
decimal postagePackingCost = 0;
decimal examPaperPrice = 0;
int quantityOfExamPapers = 0;
decimal subtotal = 0;
decimal total = 0;
var transactionDetails = new Details();
var transactionAmount = new Amount();
Transaction tran = new Transaction();
for (int iCounter = 0; iCounter < scList.Count; iCounter++)
{
Product p = Product.getProduct(scList[iCounter].ProductID.ToString());
deliveryCharges = p.price * 0.05m;
deliveryChargesStr = deliveryCharges.ToString();
postagePackingCost = 10m;
examPaperPrice = p.price;
quantityOfExamPapers = scList[iCounter].ProductQuantity;
subtotal = (quantityOfExamPapers * examPaperPrice);
total = subtotal + postagePackingCost;
var examPaperItem = new Item();
examPaperItem.name = p.productName;
examPaperItem.currency = "SGD";
examPaperItem.price = total.ToString();
examPaperItem.sku = p.productID.ToString();
examPaperItem.description = p.productDesc;
examPaperItem.quantity = quantityOfExamPapers.ToString();
itms.Add(examPaperItem);
itemList.items = itms;
// var transactionDetails = new Detail
transactionDetails.tax = "0";
if (transactionDetails.shipping == null)
{
transactionDetails.shipping = postagePackingCost.ToString();
}
else
{
decimal total2 = decimal.Parse(transactionDetails.shipping) + postagePackingCost;
transactionDetails.shipping = total2.ToString();
}
if (transactionDetails.subtotal == null)
{
transactionDetails.subtotal = subtotal.ToString();
}
else
{
decimal total2 = decimal.Parse(transactionDetails.subtotal) + subtotal;
transactionDetails.subtotal = total2.ToString();
}
//transactionDetails.shipping = postagePackingCost.ToString();
//transactionDetails.subtotal = subtotal.ToString("0.00");
// var transactionAmount = new Amount();
transactionAmount.currency = "SGD";
if (transactionAmount.total == null)
{
transactionAmount.total = total.ToString();
}
else
{
decimal total2 = decimal.Parse(transactionAmount.total) + total;
transactionAmount.total = total2.ToString();
}
transactionAmount.details = transactionDetails;
// Transaction tran = new Transaction();
tran.description = scList[0].ProductDescription;
tran.invoice_number = Guid.NewGuid().ToString();
tran.amount = transactionAmount;
// transaction.item_list = new List<Item>();
tran.item_list = itemList;
transactionList.Add(tran);
}
transactionList.Remove(transactionList[1]);
//Authenticate with paypal
var config = ConfigManager.Instance.GetProperties();
var accessToken = new OAuthTokenCredential(config).GetAccessToken();
//Get APIContent Object
var apiContext = new APIContext(accessToken);
var payer = new Payer();
payer.payment_method = "paypal";
var redirectUrls = new RedirectUrls();
redirectUrls.cancel_url = "http://localhost60681/Cancel.aspx";
redirectUrls.return_url = "http://localhost:60681/CompletePurchase.aspx";
var payment = Payment.Create(apiContext, new Payment
{
intent = "sale",
payer = payer,
transactions = transactionList,
redirect_urls = redirectUrls
});
Session["paymentId"] = payment.id;
foreach (var link in payment.links)
{
if (link.rel.ToLower().Trim().Equals("approval_url"))
{
Response.Redirect(link.href);
}
}
I am getting the list of Invoice details by Invoice Id.
Now i want to update AmountDue by respective Invoice Id.
i tried by below code:
ByInvoiceId.AmountDue = Convert.ToDecimal(100.00);
public_app_api.Invoices.Update(ByInvoiceId);
but..Error as
"A validation exception occurred"
What's the reason behind and How to solve this?
There are a number of ways to change the amount due on an invoice, however changing the value of the property directly is not one of them.
The amount due on an invoice is driven by the totals of the line items on the invoice minus the total of payments and allocated credit. One way to change the amount due is to change the values of your line items or add/remove some line items. You won't be able to change the invoice if it has been paid/partially paid.
Another way you could change the amount due on an invoice is to add a payment against the invoice or allocate credit from a credit note, prepayment, or overpayment to the invoice
In addition to MJMortimer's answer.
You can't change the line amounts on an AUTHORISED invoice via the c# API. You have to VOID the invoice and create a new one. You can however update DRAFT and SUBMITTED ones by updating the line items.
EDIT: Here is some code to help you. This is create invoice code, but amending one is essentially the same.
public XeroTransferResult CreateInvoices(IEnumerable<InvoiceModel> invoices, string user, string status)
{
_user = XeroApiHelper.User(user);
var invoicestatus = InvoiceStatus.Draft;
if (status == "SUBMITTED")
{
invoicestatus = InvoiceStatus.Submitted;
}
else if (status == "AUTHORISED")
{
invoicestatus = InvoiceStatus.Authorised;
}
var api = XeroApiHelper.CoreApi();
var xinvs = new List<Invoice>();
foreach (var inv in invoices)
{
var items = new List<LineItem>();
foreach (var line in inv.Lines)
{
decimal discount = 0;
if (line.PriceBeforeDiscount != line.Price)
{
discount = (decimal)(1 - line.Price / line.PriceBeforeDiscount) * 100;
}
items.Add(new LineItem
{
AccountCode = line.AccountCode,
Description = line.PublicationName != "N/A" ? line.PublicationName + " - " + line.Description : line.Description,
TaxAmount = (decimal)line.TaxAmount,
Quantity = 1,
UnitAmount = (decimal)line.PriceBeforeDiscount,
DiscountRate = discount,
TaxType = line.XeroCode,
ItemCode = line.ItemCode
});
}
var person = inv.Company.People.FirstOrDefault(p => p.IsAccountContact);
if (person == null)
{
person = inv.Company.People.FirstOrDefault(p => p.IsPrimaryContact);
}
var ninv = new Invoice
{
Number = inv.ClientInvoiceId,
Type = InvoiceType.AccountsReceivable,
Status = invoicestatus,
Reference = inv.Reference,
Contact = new Contact
{
Name = inv.Company.OrganisationName,
//ContactNumber = "MM" + inv.Company.CompanyId.ToString(),
FirstName = person.FirstName,
LastName = person.LastName,
EmailAddress = person.Email,
Phones = new List<Phone>()
{
new Phone {PhoneNumber = person.Telephone, PhoneType = PhoneType.Default},
new Phone {PhoneNumber = person.Mobile, PhoneType = PhoneType.Mobile}
},
Addresses = new List<Address>
{ new Address
{
//AttentionTo = inv.Company.People.FirstOrDefault(p => p.IsAccountContact) == null
//? inv.Company.People.FirstOrDefault(p=> p.IsPrimaryContact).FullName
//: inv.Company.People.FirstOrDefault(p => p.IsAccountContact).FullName,
//AddressLine1 = inv.Company.OrganisationName,
AddressLine1 = inv.Company.Address.Address1,
AddressLine2 = inv.Company.Address.Address2 ?? "",
AddressLine3 = inv.Company.Address.Address3 ?? "",
Region = inv.Company.Address.CountyState,
City = inv.Company.Address.TownCity,
PostalCode = inv.Company.Address.PostCode,
}
}
},
AmountDue = (decimal)inv.TotalAmount,
Date = inv.InvoiceDate,
DueDate = inv.DueDate,
LineItems = items,
LineAmountTypes = LineAmountType.Exclusive
};
if (SessionContext.TransferContactDetailsToXero == false)
{
ninv.Contact = new Contact
{
Id = inv.Company.XeroId ?? Guid.Empty,
Name = inv.Company.OrganisationName
};
}
xinvs.Add(ninv);
}
var success = true;
var xinvresult = new List<Invoice>();
try
{
api.SummarizeErrors(false);
xinvresult = api.Invoices.Create(xinvs).ToList();
}
catch (ValidationException ex)
{
// Something's gone wrong
}
foreach (var inv in xinvresult)
{
var mminvoice = invoices.FirstOrDefault(i => i.ClientInvoiceId == inv.Number);
if (inv.Errors != null && inv.Errors.Count > 0)
{
success = false;
if (mminvoice != null)
{
var errors = new List<XeroError>();
foreach (var err in inv.Errors)
{
errors.Add(new XeroError { ErrorDescription = err.Message });
}
mminvoice.XeroErrors = errors;
}
}
else
{
mminvoice.XeroTransferDate = DateTime.Now;
mminvoice.XeroId = inv.Id;
mminvoice.XeroErrors = new List<XeroError>();
}
}
return new XeroTransferResult
{
Invoices = invoices,
Success = success
};
}
Trying to follow the PayPal .NET tutorial on GitHub.
I've fixed it the best I can but still getting a lot of errors related to missing functions etc. Here is what I have so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PayPal.Api;
using System.Configuration;
using PayPal.Sample.Utilities;
using System.Web.Providers.Entities;
/// <summary>
/// Summary description for OAuthTokenCredential
/// </summary>
public class CredentialManager
{
Dictionary<string, string> _Config = null;
string _AccessToken = string.Empty;
APIContext _APIConText = null;
public CredentialManager()
{
// Get a reference to the config
var config = ConfigManager.Instance.GetProperties();
_Config = config;
// Use OAuthTokenCredential to request an access token from PayPal
var accessToken = new OAuthTokenCredential(config).GetAccessToken();
_AccessToken = accessToken;
//API Context
var apiContext = new APIContext(accessToken);
_APIConText = apiContext;
// Initialize the apiContext's configuration with the default configuration for this application.
apiContext.Config = ConfigManager.Instance.GetProperties();
// Define any custom configuration settings for calls that will use this object.
apiContext.Config["connectionTimeout"] = "1000"; // Quick timeout for testing purposes
// Define any HTTP headers to be used in HTTP requests made with this APIContext object
//if (apiContext.HTTPHeaders == null)
//{
// apiContext.HTTPHeaders = new Dictionary<string, string>();
//}
//apiContext.HTTPHeaders["some-header-name"] = "some-value";
}
public Payment GetPAyment(APIContext apiContext, string paymentid)
{
var payment = Payment.Get(apiContext, paymentid);
return payment;
}
public bool CreatePayment()
{
try
{
bool Success = false;
//var apiContext = Configuration.GetAPIContext();
string payerId = Request.Params["PayerID"];
if (string.IsNullOrEmpty(payerId))
{
var itemList = new ItemList()
{
items = new List<Item>()
{
new Item()
{
name = "Item Name",
currency = "USD",
price = "15",
quantity = "5",
sku = "sku"
}
}
};
var payer = new Payer() { payment_method = "paypal" };
var baseURI = Request.Url.Scheme + "://" + Request.Url.Authority + "/PaymentWithPayPal.aspx?";
var guid = Convert.ToString((new Random()).Next(100000));
var redirectUrl = baseURI + "guid=" + guid;
var redirUrls = new RedirectUrls()
{
cancel_url = redirectUrl + "&cancel=true",
return_url = redirectUrl
};
var details = new Details()
{
tax = "15",
shipping = "10",
subtotal = "75"
};
var amount = new Amount()
{
currency = "USD",
total = "100.00", // Total must be equal to sum of shipping, tax and subtotal.
details = details
};
var transactionList = new List<Transaction>();
transactionList.Add(new Transaction()
{
description = "Transaction description.",
invoice_number = Common.GetRandomInvoiceNumber(),
amount = amount,
item_list = itemList
});
var payment = new Payment()
{
intent = "sale",
payer = payer,
transactions = transactionList,
redirect_urls = redirUrls
};
var createdPayment = payment.Create(_APIConText);
var links = createdPayment.links.GetEnumerator();
while (links.MoveNext())
{
var link = links.Current;
if (link.rel.ToLower().Trim().Equals("approval_url"))
{
this.flow.RecordRedirectUrl("Redirect to PayPal to approve the payment...", link.href);
}
}
Session.Add(guid, createdPayment.id);
Session.Add("flow-" + guid, this.flow);
}
else
{
var guid = Request.Params["guid"];
var paymentId = Session[guid] as string;
var paymentExecution = new PaymentExecution() { payer_id = payerId };
var payment = new Payment() { id = paymentId };
var executedPayment = payment.Execute(apiContext, paymentExecution);
}
return Success;
}
catch(Exception ex)
{
return false;
}
}
}
I'm getting random errors on the following:
using PayPal.Sample.Utilities;
string payerId = Request.Params["PayerID"];
var baseURI = Request.Url.Scheme + "://" + Request.Url.Authority + "/PaymentWithPayPal.aspx?";
invoice_number = Common.GetRandomInvoiceNumber(),
Session.Add(guid, createdPayment.id);
Session.Add("flow-" + guid, this.flow);
var guid = Request.Params["guid"];
var paymentId = Session[guid] as string;
var executedPayment = payment.Execute(_APIConText, paymentExecution);
Errors:
"Request" does not exist
"Common" does not exist
"flow" does not exist
"session" is not valid in its current type
I think I'm just missing a reference or something. I'm trying to do it for C# ASP .Net (not MVC)
You'll find the "Common" class here
Common.GetRandomInvoiceNumber() is just generating a random number. I think you would just replace that with your own generated invoice number.