PayPal: After Check whether subscriber is paid for subscription - c#

I'm creating website using reactjs for frontend and for backend I'm using c# asp .net mvc. I have already integrated paypal subscription in whichevery month fixed amount deducted form his account(which I have already done) by following this link https://medium.com/analytics-vidhya/paypal-subscription-in-react-1121c39b26be. and here is my code.
window.paypal.Buttons({
style: {
shape: 'rect',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'my-plan-id'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID);
console.log(data)
},
onError: (err) => {
console.log(err)
}
}).render(paypal.current)
but my requirement is when user login first time user must provide his paypal account details and after providing paypal account info check user has sufficient amount in his account proceed to dashboard. But my problem is how to handle if user has no balance in his account or unpaid and in this case after login user redirected to specific page not dashboard.
In short: how to check user is paid or unpaid if paid proceed to dashboard else redirect to specific page.

how to check user is paid or unpaid if paid proceed to dashboard else redirect to specific page.
The answer to this is to consult your database, which should have this information stored (whether a payment has been made, or whether the subscription is current) and allow you to determine what to do based on the information you have.
So your real question must be how to receive notifications from PayPal that a subscription payment has been made. For that, I will refer you to the answer in here: How do you know if a user has paid for a subscription
As for how to match subscription payments to users -- when a subscription is created, you can store its ID associated with your user, which is easiest to do if you activate the subscription from the server as discussed above. You can also pass a custom_id field during subscription creation, which can contain your own user ID for reconciliation.

Related

How to get the teams user details without accessing the bot

Is there any method or new features available in teams to get new user details without accessing the particular bot?
There is a possibility of implementing roaster to grab the user details like user ID and object ID based on the azure active directory. We can get the information based on the number of entries per page minimum to 50 count users. The type of information we can get is like when the user log in into the system and what are the operations done by the user based on the name ID.
Python:
async def _show_members(
self, turn_context: TurnContext
):
members = await TeamsInfo.get_team_members(turn_context)
}
Credit: surbhigupta

How do you attach a Payment Method to a Payment Intent using the Stripe API

I've read a lot of documentation on "why" my Stripe payment intents are left in a status of "The Customer has not entered a payment method" and that "We recommend that you explicitly provide the payment_method going forward" however I can't tell how do that (provide the payment_method).
When I initialise the Payment Intent object I have "AutomaticPaymentMethods" enabled. I only have 1 payment method enabled in my Stripe Dashboard (cards).
(Also, I'm using Blazor with JS interop for this - if that is relevant...)
string customerId = await getCustomer(); // fetch existing customer from Stripe API based on current user or create a new one
Stripe.PaymentMethodService pms = new PaymentMethodService();
Stripe.PaymentIntentCreateOptions options = new PaymentIntentCreateOptions
{
Amount = p.UnitAmount,
Currency = p.Currency,
Customer = customerId,
ReceiptEmail = "test#malinator.com",
Description = "Test Purchase",
StatementDescriptor = "Test Purchase",
AutomaticPaymentMethods = new PaymentIntentAutomaticPaymentMethodsOptions
{
Enabled = true,
},
};
Stripe.PaymentIntentService pis = new Stripe.PaymentIntentService();
Stripe.PaymentIntent pi = pis.Create(options);
return pi;
The Payment Method is null on the resulting Payment Intent object.
It is still null after the payment details have been completed in the "payment-element" on my HTML form.
Is the payment_method something I can set up as the Payment Intent object is created (as I only wish to use "cards" at the moment anyway), or is it something I need to set in the confirm_payment JS call? (Either way, how to I obtain that Payment Method?)
Your code creates a PaymentIntent server-side for say $10 USD. This represents the "state machine" of an overall payment for the customer. They might never pay, or they might try to pay once and get a decline or a success, or they might get declined, try another card and see a success. Each "payment attempt" is represented in the API as a Charge object and the corresponding payment method details associated with that are represented as a PaymentMethod.
Now all of that "payment attempt" happens client-side where you collect payment method details and you use those to "confirm the PaymentIntent".
You mentioned you are using PaymentElement which is Stripe's newer UI library component to collect payment method details and accept a payment client-side. Since you only accept card payments, the PaymentElement would get initialized with your PaymentIntent's client_secret and render the card form to collect those card details.
What you need to do here is have a button to "pay" and when it's clicked, your Javascript code should call the confirmPayment() method from Stripe.js. Doing that will use the card details entered by the customer and attempt to confirm the PaymentIntent that is for a specific amount and currency. This payment might succeed, in which case the customer is redirected to your return_url, or it might be declined in which case the promise completes with error details you can handle to surface an error.
What you need to do here is look into your client-side code, ensure that you call confirmPayment() as expected and debug the response you get back to help narrow it down.
After the PaymentIntent is confirmed successfully and has status: 'succeeded' then it will have payment_method: 'pm_123' that is the id of the PaymentMethod object associated with the successful confirmation. All the information about that card would be on the successful Charge object associated with it inside payment_method_details.

Secure way to Delete a record in ASP.Net MVC

I want to delete a product from my ASP.Net MVC 5 website. I want to know if adding [AntiForgeryToken] and [Authorize] is enough to secure the Delete operation?
View
<p>Delete: #Model.Name</p>
#using (Html.BeginForm("Delete", "ProductController", FormMethod.Post, new { ProductId = Model.ProductId }))
{
#Html.AntiForgeryToken()
<button type="submit">Delete</button>
}
Controller
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Delete(long ProductId)
{
/* Do I need to check if the logged in User has permission to delete the product?
var product = ProductRepository.Get(Id);
if (product.Creator == User.Identity.GetUserId<long>())
{
ProductRepository.Delete(ProductId);
}
*/
// or, can I avoid the trip to DB and just delete the record?
ProductRepository.Delete(ProductId);
}
Scenario: A hacker registers on my website and create a valid account. Now the hacker views his own product and obviously he has an AntiForgeryToken. Can he now just change the ProductId in the browser and Post a request to delete someone else's Product?
Short answer. That is not enough.
Antiforgery tokens just say that the person making the original page request is the person making the update.
The base authorize attribute just verifies that the user is logged in.
What you are looking for is data security. There's an example of this on microsoft's own site.
What you've stated in your last paragraph, a hacker can sign up for an account create their own list of products and given what you show them in the url could guess legitimate other records to edit
Say you have a url
https://example.com/product/edit/13
what is preventing the user/hacker from guessing at
https://example.com/product/edit/12
or
https://example.com/product/edit/14
Without security at the data level that says what records a user can or can't access/update, you run into a situation where a malicious user could see or edit all kinds of information.
This is the exact scenario that FISERV found to expose other client information
from the article
Hermansen had signed up to get email alerts any time a new transaction
posted to his account, and he noticed the site assigned his alert a
specific “event number.” Working on a hunch that these event numbers
might be assigned sequentially and that other records might be
available if requested directly, Hermansen requested the same page
again but first edited the site’s code in his browser so that his
event number was decremented by one digit.

Detecting paypal subscription cancel on login asp.net

I am building an asp.net web app that involves paypal subscriptions. I need to check if the user has cancelled on login is this possible and if so how? I have seen other posts on this subject but my situation is different since I'll be checking on login. I was thinking maybe I can do a batch dump of data from paypal nightly and check against that to set a flag on the users that cancelled. Not sure what the best way to do this is..
If you want to check whether the user has accepted or cancelled the agreement after logging to the PayPal then yes you can check this by using the Express Checkout Token . You need to call GetExpressCheckoutDetails API on the Token after the buyer log in to the PayPal account and look for the variable BILLINGAGREEMENTACCEPTEDSTATUS in the response .
BILLINGAGREEMENTACCEPTEDSTATUS=0 means buyer has not accepted the agreement or clicked on cancel after logging to the PayPal account .
BILLINGAGREEMENTACCEPTEDSTATUS=1 , means by has clicked on the "agree and continue" after logging to the PayPal .
I have included some sample response .
For rejection after log in :
NVP Response:
TOKEN=EC-0RC04801KU663840M
**BILLINGAGREEMENTACCEPTEDSTATUS=0**
CHECKOUTSTATUS=PaymentActionNotInitiated
TIMESTAMP=2014-09-14T14:54:43Z
CORRELATIONID=5cc68231a1b35
ACK=Success
VERSION=109.0
BUILD=12786467
EMAIL=XXXXXXXXXXXXXX
PAYERID=XXXXXXXXXXXX
PAYERSTATUS=verified
FIRSTNAME=Eshan Personal Test
LASTNAME=Account
COUNTRYCODE=US
CURRENCYCODE=USD
AMT=0.00
SHIPPINGAMT=0.00
HANDLINGAMT=0.00
TAXAMT=0.00
INSURANCEAMT=0.00
SHIPDISCAMT=0.00
PAYMENTREQUEST_0_CURRENCYCODE=USD
PAYMENTREQUEST_0_AMT=0.00
PAYMENTREQUEST_0_SHIPPINGAMT=0.00
PAYMENTREQUEST_0_HANDLINGAMT=0.00
PAYMENTREQUEST_0_TAXAMT=0.00
PAYMENTREQUEST_0_INSURANCEAMT=0.00
PAYMENTREQUEST_0_SHIPDISCAMT=0.00
PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false
PAYMENTREQUEST_0_ADDRESSNORMALIZATIONSTATUS=None
PAYMENTREQUESTINFO_0_ERRORCODE=0
For acceptance after log in :
NVP Response:
TOKEN=EC-1EX65013S71914041
PHONENUM=408-767-7151
**BILLINGAGREEMENTACCEPTEDSTATUS=1**
CHECKOUTSTATUS=PaymentActionNotInitiated
TIMESTAMP=2014-09-14T14:56:24Z
CORRELATIONID=aae4de7a4b356
ACK=Success
VERSION=109.0
BUILD=XXXXXXXXXXXXX
PAYERID=XXXXXXXXXXXXXX
PAYERSTATUS=verified
FIRSTNAME=Eshan Personal Test
LASTNAME=Account
COUNTRYCODE=US
SHIPTONAME=Eshan Personal Test Account
SHIPTOSTREET=cxas
SHIPTOSTREET2=asa
SHIPTOCITY=FL
SHIPTOSTATE=FL
SHIPTOZIP=95616
SHIPTOCOUNTRYCODE=US
SHIPTOCOUNTRYNAME=United States
ADDRESSSTATUS=Confirmed
CURRENCYCODE=USD
AMT=0.00
SHIPPINGAMT=0.00
HANDLINGAMT=0.00
TAXAMT=0.00
INSURANCEAMT=0.00
SHIPDISCAMT=0.00
PAYMENTREQUEST_0_CURRENCYCODE=USD
PAYMENTREQUEST_0_AMT=0.00
PAYMENTREQUEST_0_SHIPPINGAMT=0.00
PAYMENTREQUEST_0_HANDLINGAMT=0.00
PAYMENTREQUEST_0_TAXAMT=0.00
PAYMENTREQUEST_0_INSURANCEAMT=0.00
PAYMENTREQUEST_0_SHIPDISCAMT=0.00
PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false
PAYMENTREQUEST_0_SHIPTONAME=Eshan Personal Test Account
PAYMENTREQUEST_0_SHIPTOSTREET=cxas
PAYMENTREQUEST_0_SHIPTOSTREET2=asa
PAYMENTREQUEST_0_SHIPTOCITY=FL
PAYMENTREQUEST_0_SHIPTOSTATE=FL
PAYMENTREQUEST_0_SHIPTOZIP=95616
PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=US
PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United States
PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed
PAYMENTREQUEST_0_ADDRESSNORMALIZATIONSTATUS=None
PAYMENTREQUESTINFO_0_ERRORCODE=0

Validating payment amounts with WorldPay

We are using WorldPay to process payments for a tiered membership system, for which the payment amount varies dependent upon the membership tier selected.
The payment is passed to WorldPay via a form post from a number of hidden fields, including:
<input type="hidden" name="amount" value="295.00" />
Essentially, the form is submitted via POST to WorldPay and the user follows a number of steps to process their payment. Once complete, the user is redirected to a specified confirmation page.
This appears to be the typical manner in which WorldPay accepts payments. There's an obvious issue here, in that the value of the hidden field could easily be tampered with by anyone with a basic knowledge of HTML. The form is posted directly to WorldPay, so we have no PostBack in which to validate the amount against the membership tier.
We have the option to validate the payment amount when a payment notification is returned to us from WorldPay by routing the callback through a handler before the confirmation page; however, I would like to avoid the situation where user submits a tampered form, pays the incorrect amount and receives no membership, then has to contact the company to have their money returned.
How might we validate that the amount being submitted is correct before processing payment?
Update
It has occurred to me that we have an additional problem whereby, even if we validate the form post server-side, there is nothing stopping a malicious user from spoofing the form post direct to WorldPay.
It is a vulnerability indeed, it can be solved easily using a signature. Check out this link:
http://culttt.com/2012/07/25/integrating-worldpay-into-a-database-driven-website/
This method should be better promoted on the help page, too bad.
One solution I can think of is this, capture the form tag's submit:
<form id="myForm" onsubmit="return validatePayment();">
and then create that JavaScript file that looks like this:
var isValidAmount = false;
function validatePayment() {
if (isValidAmount) { return true; }
// in here you want to issue an AJAX call back to your server
// with the appropriate information ... I would recommend using
// jQuery and so it might look something like this:
$.ajax( {
type: "POST",
url: url,
data: { amount: $("#amount").val(), someotherfield: somevalue },
success: function(data, textStatus, jqXHR) {
// set the flag so that it can succeed the next time through
isValidAmount = true;
// resubmit the form ... it will reenter this function but leave
// immediately returning true so the submit will actually occur
$("myForm").submit();
},
});
// this will keep the form from actually submitting the first time
return false;
}

Categories