I am trying to make a paypal handler. You type a money amount into an input, than you press donate button, you will be forwarded to the paypal page, you can login and than press continue button... The problem after I press the continue button its forward me back to the https://www.example.org/Account/PayPalHandler/ page, and thats it all. What is missing from my code to complete the paypal transaction?
[HttpPost]
public ActionResult DoPaymentPaypall(UserModel User_)
{
ResultModel<ManageAccountListModel> res_ = new ResultModel<ManageAccountListModel>();
res_.DataSelect = new ManageAccountListModel();
if (SessionManagement.LoginnedUser != null)
{
var config = ConfigManager.Instance.GetProperties();
var accessToken = new OAuthTokenCredential(config).GetAccessToken();
var apiContext = new APIContext(accessToken);
string moneyCount_ = User_.moneycount.ToString();
var payment = Payment.Create(apiContext, new Payment
{
intent = "sale",
payer = new Payer
{
payment_method = "paypal"
},
transactions = new List<Transaction>
{
new Transaction
{
description = "Donation",
invoice_number = "001",
amount = new Amount
{
currency = "USD",
total = moneyCount_,
details = new Details
{
tax = "0",
shipping = "0",
subtotal = moneyCount_
}
},
item_list = new ItemList
{
items = new List<Item>
{
new Item
{
name = "Donation",
currency = "USD",
price = moneyCount_,
quantity = "1",
sku = "Custom Package"
}
}
}
}
},
redirect_urls = new RedirectUrls
{
return_url = "https://www.example.org/Account/PayPalHandler/",
cancel_url = "https://www.example.org/"
}
});
res_.SuccessMessage = payment.links.ToList()[1].href;
}
res_.Success = true;
return new JsonResult { Data = res_, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Your code above seems to only show the initial/start of the process...so assuming you mean after the user has approved your request to use Paypal for payment (don't confuse this as "the payment" - this step only indicates that the user as agreed to use Paypal for payment) you'll need to Execute the payment.
The link shows the full flow
Create payment (this is what your code above maps to) - you'll get a payment id in this step
redirect user to Paypal approval_url for approval (of the details in the Create above) using the id you recieved
Paypal sends user back to your site with info on how to Execute payment (if user approves)
Execute payment (this is done at your site/app)
Hth
Related
public ActionResult Index()
{
StripeConfiguration.ApiKey = "secretKey";
var options = new SessionCreateOptions
{
PaymentMethodTypes = new List<string> {
"card",
},
LineItems = new List<SessionLineItemOptions> {
new SessionLineItemOptions {
Name = "Basic Plan",
Description = "Up to 1 Featured Product",
Amount = 1000,
Currency = "usd",
Quantity = 1,
},
},
SuccessUrl = "https://localhost:44390/payment/successful",
CancelUrl = "https://localhost:44390/payment/fail",
PaymentIntentData = new SessionPaymentIntentDataOptions
{
Metadata = new Dictionary<string, string>
{
{"Order_ID", "123456" },
{"Description", "Basic Plan" }
}
}
};
var service = new SessionService();
Session session = service.Create(options);
return PartialView("_PaymentIndex", session);
}
Is there any way of checking the status of the payment, because I wanna call another action if the payment is confirmed. Like the same as adding a successful url, but for an action. I'm kinda new to this so :/
Edit:
I added a webhook to https://xxxx.eu.ngrok.io/payment/UpdatePaymentStatus for this action:
[HttpPost]
public ActionResult UpdatePaymentStatus()
{
try
{
StripeConfiguration.ApiKey = "key";
Stream req = Request.InputStream;
req.Seek(0, System.IO.SeekOrigin.Begin);
string json = new StreamReader(req).ReadToEnd();
myLogger.GetInstance().Warning(User.Identity.Name, "| Check |", "Payment/UpdatePaymentStatus");
// Get all Stripe events.
var stripeEvent = EventUtility.ParseEvent(json);
string stripeJson = stripeEvent.Data.RawObject + string.Empty;
var childData = Charge.FromJson(stripeJson);
var metadata = childData.Metadata;
int orderID = -1;
string strOrderID = string.Empty;
if (metadata.TryGetValue("Order_ID", out strOrderID))
{
int.TryParse(strOrderID, out orderID);
// Find your order from database.
// For example:
// Order order = db.Order.FirstOrDefault(x=>x.ID == orderID);
}
switch (stripeEvent.Type)
{
case Events.ChargeCaptured:
case Events.ChargeFailed:
case Events.ChargePending:
case Events.ChargeRefunded:
case Events.ChargeSucceeded:
case Events.ChargeUpdated:
var charge = Charge.FromJson(stripeJson);
string amountBuyer = ((double)childData.Amount / 100.0).ToString();
if (childData.BalanceTransactionId != null)
{
long transactionAmount = 0;
long transactionFee = 0;
if (childData.BalanceTransactionId != null)
{
// Get transaction fee.
var balanceService = new BalanceTransactionService();
BalanceTransaction transaction = balanceService.Get(childData.BalanceTransactionId);
transactionAmount = transaction.Amount;
transactionFee = transaction.Fee;
}
// My status, it is defined in my system.
int status = 0; // Wait
double transactionRefund = 0;
// Set order status.
if (stripeEvent.Type == Events.ChargeFailed)
{
status = -1; // Failed
myLogger.GetInstance().Warning(User.Identity.Name, "| Purchase of basic plan failed |", "Payment/UpdatePaymentStatus");
}
if (stripeEvent.Type == Events.ChargePending)
{
status = -2; // Pending
myLogger.GetInstance().Warning(User.Identity.Name, "| Purchase of basic plan pending |", "Payment/UpdatePaymentStatus");
}
if (stripeEvent.Type == Events.ChargeRefunded)
{
status = -3; // Refunded
transactionRefund = ((double)childData.AmountRefunded / 100.0);
myLogger.GetInstance().Warning(User.Identity.Name, "| Purchase of basic plan refunded |", "Payment/UpdatePaymentStatus");
}
if (stripeEvent.Type == Events.ChargeSucceeded)
{
status = 1; // Completed
myLogger.GetInstance().Info(User.Identity.Name, "Bought Basic Plan", "Payment/UpdatePaymentStatus");
}
// Update data
// For example: database
// order.Status = status;
// db.SaveChanges();
}
break;
default:
//log.Warn("");
break;
}
return Json(new
{
Code = -1,
Message = "Update failed."
});
}
catch (Exception e)
{
//log.Error("UpdatePaymentStatus: " + e.Message);
return Json(new
{
Code = -100,
Message = "Error."
});
}
}
public ActionResult Successful()
{
return View();
}
public ActionResult Fail()
{
return View();
}
}
Still not working though. I'm not getting any logs(using nLog) and the webhook is failing(in stripe dashboard).
Your code is creating a Checkout Session via the API. This is associated with Stripe's Checkout product. Stripe controls the UI to collect all the payment method details which means you're going to redirect your customer directly to Stripe's hosted page.
Once a customer pays, they will be redirected to your payment page configured in SuccessUrl in your code. You need to write code that detects the customer hitting that URL and map it to the session they were paying.
Additionally, it's possible for a customer to close their browser too before hitting your page. For that reason, Stripe also sends the checkout.session.completed event to your webhook handler. You can write code to handle that event and look at the status of their payment and all relevant information.
Stripe covers all possible fulfillment approaches in their documentation: https://stripe.com/docs/payments/checkout/fulfill-orders
I want to integrate Stripe into my ASP.NET MVC application.
So, As the first step, I'm trying to do it with simple code.
This is my simple code below,
var customers = new CustomerService();
var charges = new ChargeService();
var publishableKey = "pk_test_51KseuBH1Mw1tyjglBiJls20038FcgbHr";
StripeConfiguration.SetApiKey(publishableKey);
StripeConfiguration.ApiKey = "sk_test_51KseuRqoYQ6YGD7TNzPp0051boOPvQ";
var customer = customers.Create(new CustomerCreateOptions
{
Email = "isanka.ad#gmail.com",
Source = publishableKey
});
var charge = charges.Create(new ChargeCreateOptions
{
Amount = 500,
Description = "Sample Charge",
Currency = "usd",
Customer = customer.Id
});
I have tried different codes on forams. But it always returns the same error below,
No such token: 'pk_test_51KseuBHaMw1tyjglBiJls20038FcgbHr'
This is my Stripe keys,
Did I define secret key and publishable key incorrectly?
The publishable key must not be used in your backend code. It is for your client-side code, as described in the documentation: https://stripe.com/docs/keys. Moreover, the Source property on the customer describes the payment method: https://stripe.com/docs/api/customers/create?lang=dotnet. I can recommend getting started with Stripe with the quick start guide: https://stripe.com/docs/payments/quickstart.
It seems you copied only the first line of the API Key.
Please make sure that you are using the complete API Key in your application, and you don't need to use publishable key in your backend integration.
The source value only accepts payment source created via the Token or Sources APIs.
When creating a customer in your sample code, the Source was assigned with publishableKey which is invalid and that's probably why "No such token" was returned.
If you do not have any source created upfront, then Source should be removed from your customer creation request.
I was missing creating the card and token
generate. Above I have assigned the publishable token as the source value, not generated token.
Here is the full working code.
public async Task<ProcessPaymentResult> ProcessPaymentAsync(ProcessPaymentRequest processPaymentRequest)
{
var processPaymentResult = new ProcessPaymentResult();
try
{
var customers = new CustomerService();
var charges = new ChargeService();
var options = new RequestOptions
{
ApiKey = // your Secret Key
};
#region Card payment checkout
var creditCardType = processPaymentRequest.CreditCardType.ToString();
var optionToken = new TokenCreateOptions
{
Card = new TokenCardOptions
{
Number = processPaymentRequest.CreditCardNumber,
ExpMonth = processPaymentRequest.CreditCardExpireMonth,
ExpYear = processPaymentRequest.CreditCardExpireYear,
Cvc = processPaymentRequest.CreditCardCvv2,
Name = processPaymentRequest.CreditCardName,
Currency = _workContext.WorkingCurrency.CurrencyCode
},
};
var tokenService = new TokenService();
Token paymentToken = await tokenService.CreateAsync(optionToken, options);
#endregion
#region Stripe Customer
var customer = new Customer();
var customerEmail = processPaymentRequest.CustomValues["CustomerEmail"].ToString();
// Search customer in Stripe
var stripeCustomer = await customers.ListAsync(new CustomerListOptions
{
Email = customerEmail,
Limit = 1
}, options);
if (stripeCustomer.Data.Count==0)
{
// create new customer
customer = await customers.CreateAsync(new CustomerCreateOptions
{
Source = paymentToken.Id,
Phone = processPaymentRequest.CustomValues["Phone"].ToString(),
Name = processPaymentRequest.CustomValues["CustomerName"].ToString(),
Email = customerEmail,
Description = $" { processPaymentRequest.CustomValues["RegisteredEmail"]};{ processPaymentRequest.CustomValues["CustomerName"] }",
}, options);
}
else
{
// use existing customer
customer = stripeCustomer.FirstOrDefault();
}
#endregion
#region Stripe charges
var charge = await charges.CreateAsync(new ChargeCreateOptions
{
Source = paymentToken.Id,//Customer = customer.Id,
Amount = (int)(Math.Round(processPaymentRequest.OrderTotal, 2) * 100),
Currency = _workContext.WorkingCurrency.CurrencyCode,
ReceiptEmail = customer.Email,
Description = $" { processPaymentRequest.CustomValues["RegisteredEmail"]};{ processPaymentRequest.CustomValues["CustomerName"] }",
}, options);
if (charge.Status.ToLower().Equals("succeeded"))
{
processPaymentResult.NewPaymentStatus = PaymentStatus.Paid;
processPaymentResult.CaptureTransactionId = charge.Id;
}
else
{
processPaymentResult.AddError("Error processing payment." + charge.FailureMessage);
}
#endregion
}
catch (Exception ex)
{
processPaymentResult.AddError(ex.Message);
}
return processPaymentResult;
}
You need to add secretKey in the setapikey function.
// StripeConfiguration.SetApiKey(publishableKey);
StripeConfiguration.SetApiKey(secretKey);
Hi im working on stripe subscription based session. I have created a Product on Stripe Dashboard and on session creating im passing hardcoded priceid and connected account id in the session but i m receiving bad request exception on creating the same session.
Here is my sample code as directed by this link https://stripe.com/docs/payments/checkout/migration in connect plateform and marketplaces After Section
StripeConfiguration.ApiKey = "{ApiKey}";
var options = new SessionCreateOptions
{
PaymentMethodTypes = new List<string>
{
"card",
},
LineItems = new List<SessionLineItemOptions>
{
new SessionLineItemOptions
{
Price = "{price_...}", //pricing id copied from dashboard
},
},
Mode = "subscription",
PaymentIntentData = new SessionPaymentIntentDataOptions
{
ApplicationFeeAmount = 20,
},
SuccessUrl = "https://example.com/success",
CancelUrl = "https://example.com/cancel",
};
var requestOptions = new RequestOptions
{
StripeAccount = "acct_...", // activated connected account id copied from dashboard
};
var service = new SessionService();
Session session = service.Create(options, requestOptions); // exception no such price found bad request
I use PayPal-NET-SDK for interact with PayPal system (sanbox). I have next code:
static void Main(string[] args)
{
try
{
var config = ConfigManager.Instance.GetProperties();
var accessToken = new OAuthTokenCredential(config).GetAccessToken();
var apiContext = new APIContext(accessToken);
var payment = Payment.Create(apiContext, new Payment
{
intent = "order",
payer = new Payer
{
payment_method = "paypal"
},
transactions = new List<Transaction>
{
new Transaction
{
description = "Transaction description.",
invoice_number = "002",
amount = new Amount
{
currency = "USD",
total = "15.00",
},
payee = new Payee
{
email = "test1#gmail.com"
}
}
},
redirect_urls = new RedirectUrls
{
return_url = "site for redirect", // in my code there is normal url
cancel_url = "site for redirect""
}
});
var approval = payment.GetTokenFromApprovalUrl();
var url = payment.GetApprovalUrl();
payment.token = approval;
var response = payment.Execute(apiContext, new PaymentExecution {payer_id = "C598R54Q6P39G" });
}
catch (PaymentsException e)
{
Console.WriteLine(e.Response);
}
}
After executing this code i receive bad request error from PayPal ("Payer has not approved payment"). If go to link in url in debug, i get to PayPal confirm page, and after push continue button, payment executing withoue exceptions (but funds still same, money is not sending). How i can send money to other paypal wallet without redirect to PayPal aproving page?
Resolved by using payout (as i uderstand, payments use for client to merchant transfer).
static void Main(string[] args)
{
try
{
// Authenticate with PayPal
var config = ConfigManager.Instance.GetProperties();
var accessToken = new OAuthTokenCredential(config).GetAccessToken();
var apiContext = new APIContext(accessToken);
var payout = Payout.Create(apiContext, new Payout
{
sender_batch_header = new PayoutSenderBatchHeader
{
email_subject = "Hello payout",
sender_batch_id = "ilab_Payout002",
recipient_type = PayoutRecipientType.EMAIL
},
items = new List<PayoutItem>
{
new PayoutItem
{
amount = new Currency
{
currency = "USD",
value = "17.5"
},
note = "Exchange is done!",
receiver = "ilab-test1#gmail.com",
recipient_type = PayoutRecipientType.EMAIL,
sender_item_id = "121341"
}
},
});
}
catch (PaymentsException e)
{
Console.WriteLine(e.Response);
}
}
}
In Sandbox Mass paypal payment
I am getting Transaction_status = Failed
var payout = new Payout
{
sender_batch_header = new PayoutSenderBatchHeader
{
sender_batch_id = "batch_" + System.Guid.NewGuid().ToString().Substring(0, 8),
email_subject = "You have a payment"
},
items = new List<PayoutItem>
{
new PayoutItem
{
recipient_type = PayoutRecipientType.EMAIL,
amount = new Currency
{
value = dblAmount.ToString(),
currency = paypalSettings.currency_code
},
receiver = paypalSettings.strReceiverEmail,
note = "Thank you.",
sender_item_id = paypalSettings.strReservationID
}
}
};
var apiContext = GetAPIContext(paypalSettings);
var createdPayout = payout.Create(apiContext, true);
return createdPayout.items[0].transaction_status.ToString();
in return I am getting "Failed".
Thanks in advance.
To use the mass payment or payout you need to make sure that sender has enough PayPal balance . It won't take the money from credit/debit or bank account . You must have sufficient PayPal balance .
If this is not the case , you can share the complete response you got from the PayPal .