Paypal REST API - Passing parameter during the payment process - asp.net-mvc

I am integrating Paypal direct payment into my ASP.NET MVC 5 project, by using Paypal's .NET SDK. Below are the steps:
I call PayPal.Api.Payment.Create(APIContext) to redirect to Paypal site, with a successful url;
In the callback action which corresponds to the successful url, call PayPal.Api.Payment.Execute(APIContext, ExecutionContext).
What I need is pass the new order's id to Paypal when calling Payment.Create(), and receive its value in Payment.Execute(), so it can know with which order the payment is associated.
Is it possible? Thanks a lot.

Based on the SDK and the API help pages, I would leverage off of the invoice_number property in the Transaction that you are sending to the Payments.Create() end point. This transaction will be part of the Response back from PayPal, meaning you can get the OrderNumber (now called invoice_number) back from the API.
Locate this line below: invoice_number = YOUR_ORDER_NUMBER
Your PayPal Request: (taken from SDK Samples)
var apiContext = Configuration.GetAPIContext();
// A transaction defines the contract of a payment - what is the payment for and who is fulfilling it.
var transaction = new Transaction()
{
amount = new Amount(){...},
description = "This is the payment transaction description.",
item_list = new ItemList(){...},
//SET YOUR ORDER NUMBER HERE
invoice_number = YOUR_ORDER_NUMBER
};
// A resource representing a Payer that funds a payment.
var payer = new Payer(){...};
// A Payment resource; create one using the above types and intent as `sale` or `authorize`
var payment = new Payment()
{
intent = "sale",
payer = payer,
transactions = new List<Transaction>() { transaction }
};
this.flow.AddNewRequest("Create credit card payment", payment);
// Create a payment using a valid APIContext
var createdPayment = payment.Create(apiContext);
The response from PayPal (Taken From Here):

Related

Microsoft Graph API 403 error Failed to get license

As part of an automated process to create teams and channels need to provision the email.
Provisioning the email is a delegated operation whereas the initial teams and channel creation is 'application' thus requires no user involvement.
Have created an 'automation' AD user with minimal system access and created the associtated Azure 'application' with the appropriate Graph permissions - and this works no problem however for the 'automation' user getting:
Failed to get license information for the user. Ensure user has a valid Office365 license assigned to them
The message is self explanatory - so the question is, is it possible to perform basic Teams graphAPI operations such as provisioning email addresses and maybe sending messages without an O365 license - something like a Guest account?
The following code works for accounts with o365 licenses:
var UserName = "automationbotuser#somewhere.com";
var Password= "2w234234##$$%^^&^&*(erfwerwepassword";
var TenantId= "azuretentant";
var Client_Id= "azureappclientid";
var teamId = "b2342300d12-923e-46sdfsd5e-ae98-9132424db2250bc";
var projectChannel = "19:e5fe8e53ee6brwerwf8b3323438ab59913ef42#thread.tacv2";
// using Azure.Identity;
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
//create credentials
var userNamePasswordCredential = new UsernamePasswordCredential(
UserName, Password, TenantId, Client_Id, options);
var graphClient = new GraphServiceClient(userNamePasswordCredential);
//do a basic call to verify we can see something..
var user = await graphClient.Me.Request().GetAsync();
//provision the email address
await graphClient.Teams[$"{teamId}"].Channels[$"{projectChannel}"].ProvisionEmail()
.Request().PostAsync();
//remove it
await graphClient.Teams[$"{teamId}"].Channels[$"{projectChannel}"].RemoveEmail()
.Request().PostAsync();

Automatic Update to Microsoft Graph API Subscription

I have created webhook project with Microsoft Graph API to monitor Office 365 inbox.
I made a UpdateSubscription action method which renews it for 3 days only as according to the documentation provide on https://graph.microsoft.io/en-us/docs/api-reference/v1.0/resources/subscription
Below is the code snippet of how I'am facilitating the HTTP request to update the subscription
AuthenticationResult authResult = await AuthHelper.GetAccessTokenAsync();
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Build the request.
string subscriptionsEndpoint = "https://graph.microsoft.com/v1.0/subscriptions/"+id;
var method = new HttpMethod("PATCH");
HttpRequestMessage request = new HttpRequestMessage(method, subscriptionsEndpoint);
//get the current time
var subscription = new Subscription
{
//Id = id,
ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 4230, 0)
};
Is there a way to auto update without the user pressing the button to 'update'?
since the authorization-headers requires AuthResult.accessToken which will require the user to sign in to Office365 account.
Please advice
An option available to you is the service or daemon approach (https://graph.microsoft.io/en-us/docs/authorization/app_only). Instead of authenticating with a logged-in user you're able to renew the subscription at the application level using a Bearer token which is in turn generated by the CLIENT_SECRET from Azure AD.
I don't think storing tokens in the database is the right approach here. My understanding is that security tokens are never appropriate for a database.
In fact, I don't quite understand the need to have the user log in at all here, unless there are parts to the program that you didn't mention. A service like the one I mentioned can monitor a mailbox without a user being there, or else if the program requires the user to be there, there really isn't an issue of lost credentials.
You can use this approach to fetch accesstoken from azure using grant_type a password. PLease find the below screenshot.

How to properly handle POST request from the server in Ruby on Rails

I am working on a payment system (gateway) in which the server sends the POST request to the API when the users request for payment using a cash card with PIN and SERIAL NO. I include the query-string in the return URL with the reference data for querying after the transaction for displaying the result.
The API returns the payment URL which is used to redirect users from my application to the payment gateway. Then the users are required to enter the cash card pin and serial number and the API then submit them. After checking the validity of the cash card entered the API will do two things:
It sends the POST request to the predefined callback URL with the result data such as status code, reference ID and amount of the cash card. This is for storing the payment result to the database and add the credit to the users based on the amount of the cash card returned.
It redirects the user back to the predefined return URL made when making a request for the first time, when we get the payment url, in which I query for the result recently stored in the database to display the payment result to the users.
The problem is that the application never accepts the POST request but gets "422: UNPROCESSABLE ENTITY".
This is the first POST data to the API and the redirection to the payment gateway:
def topup
ref = 'ref'+Time.now.strftime('%Y%m%d%H%M%S')
params = {'app_code'=>'xxxx', 'secret'=>'xxxx', 'ref'=>ref, 'returnurl'=>'http://xxx.xxx.xxx/returnpath?=reference='+ref}
api = 'http://api.xxx.xxx/topuprequest'
raw = Net::HTTP.post_form(URI.parse(api), params)
response = ActiveSupport::JSON.decode(raw.body)
# Redirect the user to the gateway using the URL returned from the API
redirect_to response['paymentUrl']
end
This is the most important part which saves all returned data from the API to the database and updates the user credit, and is where the problem arises as the application rejects all requests to it and returns "422: Unprocessable Entity":
def callback
# Retrieve POST data of the payment recently made from the API
status = params[:status]
amount = params[:amount]
referenceId = params[:reference]
# Create the transaction
transaction = Transaction.new
transaction.reference = referenceId
transaction.amount = amount
transaction.status = status
transaction.save
# Update the user credit with the amount returned (Just an example, in the production I query the userid from the transaction before an update)
u = User.first
u.update(credit:credit+amount.to_i)
render nothing: true
end
This is the return URL which is defined in the first request. It queries the information recently stored in the database and displays it to the users. It uses the reference ID from the query string sent at the first step to search for the matched transaction, then queries for the status and the amount and finally displays the result to the user:
def returnpath
# Retrieve the query string data
ref = params[:ref]
transaction = Transaction.where(ref = ?, ref).first
status = transaction.status
amount = transaction.amount
message = 'You topup #{amount} to your account and the status is #{status}'
render plain: message
end
The users request the payment and then get redirected to the gateway, Then enter the cash card PIN and SERIAL, then the system checks for the validity and its amount and sends the POST request as a callback to the application. Finally it redirects the users back to the return path that we initially define.
The problem is the callback, which is the POST request, is always rejected by the application. It responds with "422: Unprocessable Entity". I still can't figure it out why this happens.

Recurly: How i can Update the Recurly subscription & Billing Token in one request

I've a free plan among some other plans. when user signup with Free Plan I create the Account in RECURLY without subscription & Billing Information. When user tries to upgrade to some paid plan. I create a subscription. But with subscription, I also need to set the Billing account token in 1 Request, How i can do that in Recurly using Ruby on rails.
if account.present && subscription.blank?
recurly_result =subscription.update_attributes(subscription attributes & Account billing token)
end
You can use the Recurly.js functionality to do this. When you make the subscription call, just use the existing account_code, so that the subscription and billing information generated during the signup will get associated with the existing account. Take a look at the code samples at https://github.com/recurly/recurly-js-examples
Try this
// Specify the minimum subscription attributes: plan_code, account, and currency
$subscription = new Recurly_Subscription();
$identity_token = "identity token"
$subscription = Recurly_Subscription::get($identity_token);
try{
$accountcode = "account code";
$account = Recurly_Account::get($accountcode);
$account->first_name = $_POST['first-name'];
$account->last_name = $_POST['last-name'];
$account->email = $_POST['email'];
$account->update();
$billing_info = new Recurly_BillingInfo();
$billing_info->account_code = $accountcode;
$billing_info->token_id = $_POST['recurly-token'];
$billing_info->update();
$sub_response = $subscription->updateImmediately();
$uuid = $subscription->uuid;
.........
.........
}catch (Exception $e){
echo $e->getMessage();
}
Its PHP code , you can adjust it as per ROR

Stripe - check if a customer exists

In the stripe documentation they have this:
customer = Stripe::Customer.create(email: params[:stripeEmail], card: params[:stripeToken])
charge = Stripe::Charge.create(customer: customer.id, amount: price, description: '123', currency: 'usd')
But I think it's wrong as for each payment we have to check if a customer exists first, I just tried it with a test account and it turned out there were created a number of different customers with the same email but different ids.
How do I check if a customer already exists?
There is no check on Stripe's end to ensure uniqueness of customers (email, card, name, etc,) and this is something you have to do on your end.
Usually, when you create a customer with a specific email address you need to associate the customer id you got back from the API with the email address. Then next time, you check whether this email address is already in your system and either create a new customer or re-use the customer id from the previous time.
You may check if the customer exists or not by calling GET /customers with the email as a form-urlencoded parameter. You will get 200 OK response but the returned data[] will be empty if this customer email is not there.
https://stripe.com/docs/api/customers/list
I think a simple "exists" test is essential to avoid unwanted exceptions being generated.
If your customer is new then they won't have a stripe ID, which is fine. However you might get a situation where you are using an existing customer with an existing stripe ID, but have performed some sort of dormant clean-up Stripe side. In which case its good practice to test the supplied stripeID to see if its still valid.
For example I store the stripeID with the customer profile. When I make a payment I check to see if the stripeID field in the profile exists. If it does I fire off a API request to my backend to check its existence.
Something like this (.net backend example).
[HttpGet]
public ActionResult<bool> CheckCustomer(string id)
{
var service = new CustomerService();
Customer cust;
try
{
service.Get(id);
}
catch
{
return Ok(false);
}
if (cust.Deleted ?? false)
{
return Ok(false);
}
return Ok(true);
}
I don't need the result, just it not throwing an exception is good enough. However, when you delete customers in Stripe live it keeps a copy of the ID stub and sets the delete property to true, so you need to check for that too.
The front end then can either use the stripeId for the payment or create a new stripe customer first then take the payment.
You can search for the customer by email address...
public async Task<Customer> GetCustomerByEmail(string oneEmail)
{
var service = new CustomerService();
try
{
StripeList<Customer> customerList = await service.ListAsync(new CustomerListOptions() { Email=oneEmail },null);
Debug.WriteLine(customerList.ToList().Count);
return customerList.ToList().FirstOrDefault();
}
catch
{
return null;
}
}

Resources