Send Money to Paypal Account ASP.Net Server Side Code - paypal

I am having a difficult time finding halfway descent documentation or examples on how to send money to another Paypal account.
I have installed the Nuget package PaypalSDK version 1.0.4. I have read the documentation at https://developer.paypal.com/home. I have browsed and tried to implement the sample code at https://github.com/paypal/Checkout-NET-SDK.
The problem I am having is that I am having is that I am not seeing notifications of payments sent or received in my sandbox account. I can successfully execute a checkout with the Javascript button in my shopping cart view. But eventually I want to add the capability to send money from my Paypal business account to another Paypal business account, without the other Paypal Business Account owner having to be logged in to my website.
Does the money recipient have to authorize the money I send, or should it just get deposited into their account once I send it?
Here is my code:
namespace MyShoppingCart.Helpers.Paypal
{
public class CaptureOrderSample
{
static string PayPalClientID = Startup.StaticConfig.GetValue<string>("Paypal:ClientID");
static string PayPalClientSecret = Startup.StaticConfig.GetValue<string>("Paypal:ClientSecret");
public static HttpClient client()
{
// Creating a sandbox environment
PayPalEnvironment environment = new SandboxEnvironment(PayPalClientID, PayPalClientSecret);
// Creating a client for the environment
PayPalHttpClient client = new PayPalHttpClient(environment);
return client;
}
public async static Task<HttpResponse> createOrder(string Email)
{
HttpResponse response;
// Construct a request object and set desired parameters
// Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
var order = new OrderRequest()
{
CheckoutPaymentIntent = "CAPTURE",
PurchaseUnits = new List<PurchaseUnitRequest>()
{
new PurchaseUnitRequest()
{
AmountWithBreakdown = new AmountWithBreakdown()
{
CurrencyCode = "USD",
Value = "100.00"
},
Payee = new Payee
{
Email = Email // "payee#email.com"
}
}
}
//,
//ApplicationContext = new ApplicationContext()
//{
// ReturnUrl = "https://www.example.com",
// CancelUrl = "https://www.example.com"
//}
};
// Call API with your client and get a response for your call
var request = new OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(order);
response = await client().Execute(request);
var statusCode = response.StatusCode;
Order result = response.Result<Order>();
Debug.WriteLine($"Status: {result.Status}");
Debug.WriteLine($"Order Id: {result.Id}");
Debug.WriteLine($"Intent: {result.CheckoutPaymentIntent}");
Debug.WriteLine("Links:");
foreach (LinkDescription link in result.Links)
{
Debug.WriteLine($"\t{link.Rel}: {link.Href}\tCall Type: { link.Method}");
}
return response;
}
}
}
And this is currently called from my Orders controller when an order is completed. This is just for testing purposes.
[Authorize]
public async Task<IActionResult> CompleteOrder()
{
var items = _shoppingCart.GetShoppingCartItems();
Models.Order order = await _ordersService.StoreOrderAsync(items);
PrepareSellerEmail(items, order, "You Have a New Order!");
PrepareBuyerEmail(items, order, "Thank You for Your Order!");
await _shoppingCart.ClearShoppingCartAsync(_serviceProvider);
DeleteCartIDCookie();
//OrderRequest request = Helpers.CreateOrderSample.BuildRequestBody("USD", "100.00", "sb-r43z1e9186231#business.example.com");
//var client = Helpers.Paypal.CaptureOrderSample.client();
var result = Helpers.Paypal.CaptureOrderSample.createOrder("sb-r43z1e9186231#business.example.com");
//var response = await PayPalClient.client().execute.(request);
return View("OrderCompleted");
}
The output of the result is:
Status: CREATED
Order Id: 51577255GE4475222
Intent: CAPTURE
Links:
self: https://api.sandbox.paypal.com/v2/checkout/orders/51577255GE4475222 Call Type: GET
approve: https://www.sandbox.paypal.com/checkoutnow?token=51577255GE4475222 Call Type: GET
update: https://api.sandbox.paypal.com/v2/checkout/orders/51577255GE4475222 Call Type: PATCH
capture: https://api.sandbox.paypal.com/v2/checkout/orders/51577255GE4475222/capture Call Type: POST
This is a screen capture from my sandbox account:
Am I supposed to do something else to actually execute the transfer?
Edit: I figured out how to use the Paypal Payouts API.
First I installed the Nuget Package. It's simply called PayoutsSdk. I'm using version 1.1.1.
For the payout to execute, you need the client() method that is listed above in this post, and this CreatePayout() method listed below.
public async static Task<HttpResponse> CreatePayout()
{
var body = new CreatePayoutRequest()
{
SenderBatchHeader = new SenderBatchHeader()
{
EmailMessage = "Congrats on recieving 1$",
EmailSubject = "You recieved a payout!!"
},
Items = new List<PayoutItem>()
{
new PayoutItem()
{
RecipientType="EMAIL",
Amount=new Currency()
{
CurrencyCode="USD",
Value="1",
},
Receiver="sb-r43z1e9186231#business.example.com",
}
}
};
PayoutsPostRequest request = new PayoutsPostRequest();
request.RequestBody(body);
var response = await client().Execute(request);
var result = response.Result<CreatePayoutResponse>();
Debug.WriteLine($"Status: {result.BatchHeader.BatchStatus}");
Debug.WriteLine($"Batch Id: {result.BatchHeader.PayoutBatchId}");
Debug.WriteLine("Links:");
foreach (PayoutsSdk.Payouts.LinkDescription link in result.Links)
{
Debug.WriteLine($"\t{link.Rel}: {link.Href}\tCall Type: {link.Method}");
}
return response;
}
Of course I'll add parameters to the method for email, amount, currency code, email message, and subject.
Right now, I am calling this method from the controller method like this: var result = Helpers.Paypal.CaptureOrderSample.CreatePayout(); where Helpers.Paypal are folders that contain a class called CaptureOrderSample, which I will probably rename.

To send money from your account to another account, there are several different options:
Automate the sending with the Payouts API or Payouts Web (spreadsheet upload). For live, payouts can only be used if the live account sending the payment is approved for payouts.
Log into the account that is going to send the money in https://www.paypal.com or https://www.sandbox.paypal.com and click on the menu for Pay & Get Paid -> Send Money .
Use a PayPal Checkout integration, with or without the Orders API, and specify a payee that is to receive the money. You must log in with the paying (sending) account to approve the sending, and finally the order must be captured (via API or client side actions.order.capture()) which is what results in a PayPal transaction. If the final capture step is not performed, no money will be sent and the order will merely remain created or approved and eventually expire (72 hours after creation or 3 hours after approval)
In the sandbox, no actual emails are sent with notifications. Instead, the developer.paypal.com dashboard has a "Notifications" tab on the left, and of course activity will also be visible in each sandbox account by logging into the account. Only captured activity is likely to be visible.

Related

how to calculate tax using paypal api

i installed the .net sdk of paypal and created an app in sandbox environment
next i picked up the clientId and secret and used the following sample code to make a payment.
static void Main(string[] args)
{
// Get a reference to the config
var config = ConfigManager.Instance.GetProperties();
// Use OAuthTokenCredential to request an access token from PayPal
var accessToken = new OAuthTokenCredential(config["clientId"], config["clientSecret"]);
var apiContext = new APIContext(accessToken.GetAccessToken());
var payment = Payment.Create(apiContext, new Payment
{
intent = "sale",
payer = new Payer
{
payment_method = "paypal"
},
transactions = new List<Transaction>
{
new Transaction
{
description = "Test",
invoice_number = "009",
amount = new Amount
{
currency = "EUR",
total = "41.00",
details = new Details
{
tax = "0",
shipping = "0",
subtotal = "40",
handling_fee = "1"
}
},
item_list = new ItemList
{
items = new List<Item>
{
new Item
{
name = "Room 12",
currency = "EUR",
price = "10",
quantity = "4",
}
}
}
}
},
redirect_urls = new RedirectUrls
{
return_url = "https://google.de/",
cancel_url = "https://google.de/"
}
});
}
in the transaction i have to pass Tax information.
Is there was that i let paypal calculate the tax and i just pass amount information along with address and some other information if required ?
No, you must calculate the tax yourself.
By default the user will be able to select their shipping address at PayPal, which is recommended as this saves them from having to type it manually. Given that their address can change during the PayPal checkout, you may wish to calculate a new tax amount and/or shipping amount based on the selected address. You can do this using the JS SDK's onShippingChange callback.
Firstly, though, it appears you may be using a deprecated SDK and deprecated v1/payments API, and also a redirect away from your site to PayPal, all of which is old. Don't do any of this.
Instead: follow the PayPal Checkout integration guide and make 2 routes on your server, one for 'Create Order' and one for 'Capture Order' (see the optional step 5 in 'Add and modify the code'). Both of these routes should return only JSON data (no HTML or text). There is a Checkout-Java-SDK you can use, or integrate with your own direct HTTPS API calls (obtain an access_token first, it can be cached but expires in 9 hours).
Inside the 2nd capture route on your server, when the capture API call is successful you should store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as sending confirmation emails or reserving product) immediately before forwarding your return JSON to the frontend caller.
Pair those 2 routes with the frontend approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server

Paypal P2P payments API

I want to build a webapp where users can pay to another users via their paypal accounts.
What I want is something similar to this:
https://developer.paypal.com/demo/checkout/#/pattern/client
A page where the users can click a button to either pay with Paypal or credit card, to another user.
But I can't see how in this example can I configure the receiver account. Seems that the payment is made to my account, but I want the payment to be made to another user that he selects.
I have also looked to all these APIs:
https://developer.paypal.com/docs/api/rest-sdks/#
but am not able to find an example that allows to build a client where an user pays to another user. And of course, I need to get the confirmation that the payment has been done.
EDIT:
I have tried the code here: https://www.npmjs.com/package/#paypal/checkout-server-sdk
And updated to add the payee field:
exports.pay = function (req, res) {
// 1. Set up your server to make calls to PayPal
// 1a. Import the SDK package
const paypal = require('#paypal/checkout-server-sdk');
// 1b. Add your client ID and secret
const PAYPAL_CLIENT = 'xxx';
const PAYPAL_SECRET = 'yyy';
// 1c. Set up the SDK client
const env = new paypal.core.SandboxEnvironment(PAYPAL_CLIENT, PAYPAL_SECRET);
const client = new paypal.core.PayPalHttpClient(env);
// 2. Set up your server to receive a call from the client
// 3. Call PayPal to set up a transaction with payee
const request = new paypal.orders.OrdersCreateRequest();
request.requestBody({
"intent": "CAPTURE",
"purchase_units": [
{
"amount": {
"currency_code": "USD",
"value": "100.00"
},
"payee": {
"email_address": "payee#gmail.com"
}
}
]
});
const createOrder = async function () {
const response = await client.execute(request);
console.log(`Response: ${JSON.stringify(response)}`);
// If call returns body in response, you can get the deserialized version from the result attribute of the response.
console.log(`Order: ${JSON.stringify(response.result)}`);
return res.status(200).json(response.result);
};
createOrder();
};
This returns a list of 4 links. The second one seems to be the one to redirect the client to (https://www.sandbox.paypal.com/checkoutnow?token=9RM83779YH010823U). But if I go there, I still can't see the payee address (payee#gmail.com) in the "sent to".
What you want is to set a payee object: https://developer.paypal.com/docs/checkout/integration-features/custom-payee/

Application creates classroom invitation, but no email is being sent to student

After creating a classroom invitation the method classroom.create returns with the return status 200 but the user never receives email with the invitation message.
I have given the the client id associated with the service account that I am using, the scopes classroom.roster and mail.google.com, but nothing seems to work.
Am I missing something?
Thank you very much,
Andres
This is the fragment of code that creates the invitation:
//get authorization client
const auth = await google.auth.getClient({
scopes
});
//impersonate teacher account
if (auth instanceof google.auth.JWT) {
auth.subject = 'teacher_email#dom.edu';
}
const options = { auth,
requestBody: {
courseId: '19220887720',
role: 'STUDENT',
userId: 'student_email#dom.edu'
}
};
//send invitation
try {
const invitation = await classroom.invitations.create(options);
console.log('invitation was sent:', invitation);
} catch (err) {
console.error('error: ' , err);
}
Response: status 200.
The invitation is really created. Response includes an invitation id and If you check on the ClassRoom home page->people you can see the correct student was invited.
Based from this forum, students need to have the same settings on in their account, which they may not by default. They should also choose to be a student first.
Also, notification e-mails of Google Classroom are sent from classroom.google.com domain. See Email notifications - Classroom Help for further details.

Error 500 when calling payment creation via REST API

I trying the new Paypal REST API and want integrate it in sandbox mode into a simple site just to see is it possible to implement one of the following payment flows:
Flow1
1) user fills the payment form, including credit card information
2) user clicks Buy
3) browser stores credit card information in paypal vault via REST API for credit cards (card id used later).
4) browser creates payment for the purchase via REST API call.
5) browser calls app server to ensure that purchase is going on.
5) browser redirects user to url provided by paypal.
6) when user consent/approval received at paypal website, and site redirected back to welcome page,
7) under the hood the IPN callback receives the conformation of payment and marks purchase as paid
8) user obtains access to the service app provides
Flow 2
1) user fills the payment form, including credit card information
2) user clicks Buy
4) browser creates payment for the purchase via REST API call.
5) browser calls app server to ensure that purchase is going on.
5) browser redirects user to url provided by paypal.
6) when user consent/approval received at paypal website, and site redirected back to welcome page,
7) under the hood the IPN callback receives the conformation of payment and marks purchase as paid and uses a bit more pf purchase details like credit card type and last 4 digits to add this info to my purchase object.
8) user obtains the access to services the application provides
8) user obtains access to the service app provides
Reasons to implement all this in such way
Mostly I going this path because i don't want deal with all this PCI compliance, and hones;ty i don't care where customers of my app live, which exactly card numbers they used, or when the card expire, since i don't want use automated subscription like payment, i want use different model:
user gets some pats of service for free, but to use rest of service, user buys time intervals of improved access (e. g. X months or 1 year).
This is what i trying to implement without storing credit cards information or storing as less as possible (paypal credit card id is enough i guess).
Question
Can i implement all this with Paypal REST API?
What i trying to do:
PaypalAdapter.prototype.sendCreditCardPayment = function (amount, description, creditCard, success, failure) {
var ccNumberResult = this.impl.validator.validateCardNumber(creditCard.number);
if (!ccNumberResult.success) {
return this.impl.$q.reject(ccNumberResult);
}
var cardInfo = {
number: ccNumberResult.number,
type: ccNumberResult.type,
expire_month: creditCard.expireMonth,
expire_year: String(creditCard.expireYear),
cvv2: creditCard.securityCode,
first_name: creditCard.firstName,
last_name: creditCard.lastName
};
var self = this;
var defer = self.impl.$q.defer();
this.impl.storeCardAPI(cardInfo,
function cardTokenCreated(cardTokenReply) {
var paymentSettings = {
intent: self.PaymentIntents.Sale,
redirect_urls: {
return_url: self.urls.returnUrl,
cancel_url: self.urls.cancelUrl
},
payer: {
payment_method: self.PayMethods.CreditCard,
funding_instruments: [
{
credit_card_token: {
credit_card_id: cardTokenReply.id
}
}
]
},
transactions: [
{
amount: {
total: String(amount.toFixed(2)),
currency: self.currencyCode
},
description: description
}
]
};
self.impl.createPaymentAPI(paymentSettings, function paymentCreated(payment) {
defer.resolve(payment);
}, function failedToCreatePayment(pcErr) {
defer.reject(pcErr);
});
},
function failedToStoreCard(ctErr) {
defer.reject(ctErr);
});
return defer.promise.then(success, failure);
};
To keep context more clean, here some more pieces of code:
var defaultHeaders = {
Authorization: 'Bearer ' + securityContext.tokens.paypal.access_token,
Accept: 'application/json'
};
var createPaymentResource = $resource(securityContext.configuration.paypal.endPoint + 'payments/payment', {}, {
sendPayment : {
method:'POST',
headers: defaultHeaders
}
});
var saveCreditCardResource = $resource(securityContext.configuration.paypal.endPoint + "vault/credit-cards", {}, {
storeCreditCard: {
method: 'POST',
headers: defaultHeaders
}
});
function storeCardFunc(cardInfo, success, failure) {
return saveCreditCardResource.storeCreditCard(null, cardInfo, success, failure);
}
function createPaymentFunc(paymentInformation, success, failure) {
return createPaymentResource.sendPayment(null, paymentInformation, success, failure);
}
var adapter = new PaypalAdapter($q, securityContext, creditCardValidator, storeCardFunc, createPaymentFunc);
return adapter;
Current "Results"
What i getting:
1) I can store credit card into vault via REST API.
2) i getting error 500 on try to create payment whether i use plain credit card properties to fill credit card funding instrument or try to use credit card token instead.
What i'm doing wrong?
Update
My mistake is a sort of logical with a lack of knowledge.
1) The direct credit cards payments (weather user approves them manually (with intent 'order' and payment_method = 'credit_card'), or not ('sale' intent and payment method 'credit_card') are not available for my country (Republic of Georgia). This is a single reason for the error i see.
Discovered this via Paypal account pages at developer.paypal.com website... It is a frustrating thing. Especially with all this too cryptic "internal server error". I t would be VERY helpful if Paypal would provide at least an informative message "Requested feature not available for your account" with info link to that page with available/enabled features.
Also documentation s a bit broken - some fields like first_name or last_name of payer object of order/payment request are NOT expected by the /payments/payment endpoint...

paypal masspay allways returning success, even with inexisting users

I'm currently testing my paypal integration. When using Masspay, every user name that I enter who hace a mail-like format(an # and a ".") I get a "success" response. I'm using the following code:
def emails =[]
def amounts = []
emails[0]=params.cuenta;
amounts[0]=params.cantidad;
//masspay.massPayCode("Dinero recibido de TikCode.com", "info#tikcode.com", emails, amount, "EUR");
String emailSub = "Dinero recibido de TikCode.com";
String emailAddress = "info#tikcode.com";
String [] receiverEmailItems = emails;
String [] amountItems = amounts;
String currencyCode = "EUR";
CallerServices caller = new CallerServices();
String responseValue = null;
APIProfile profile = ProfileFactory.createSignatureAPIProfile();
/*
WARNING: Do not embed plaintext credentials in your application code.
Doing so is insecure and against best practices.
Your API credentials must be handled securely. Please consider
encrypting them for use in any production environment, and ensure
that only authorized individuals may view or modify them.
*/
// Set up your API credentials, PayPal end point, and API version.
profile.setAPIUsername("myusername");
profile.setAPIPassword("mypasswordapi");
//profile.setSignature("AFcWxV21C7fd0v3bYYYRCpSSRl31ARykt6evANuQsOANN9TjehZjqIl3");
profile.setSignature("mysignature");
profile.setEnvironment("sandbox");
caller.setAPIProfile(profile);
MassPayRequestType pprequest = new MassPayRequestType();
pprequest.setVersion("90.0");
println("llegas aqui?")
// Add request-specific fields to the request.
MassPayRequestItemType[] massPayItem = new MassPayRequestItemType[receiverEmailItems.length];
int j = 0
for(int i=0;i<receiverEmailItems.length; i++)
{
String recreceiverEmail=receiverEmailItems[i];
if(recreceiverEmail != null && recreceiverEmail.length()!= 0)
{
MassPayRequestItemType massItemReq = new MassPayRequestItemType();
massItemReq.setReceiverEmail(receiverEmailItems[i]);
BasicAmountType amount = new BasicAmountType();
amount.set_value(amountItems[i]);
amount.setCurrencyID(CurrencyCodeType.fromString(currencyCode));
//massItemReq.setUniqueId(uniqueIdItems[i]);
//massItemReq.setNote(noteItems[i]);
massItemReq.setAmount(amount);
massPayItem[j]=massItemReq;
j++;
}
}
pprequest.setEmailSubject(emailSub);
// pprequest.setReceiverType(ReceiverInfoCodeType.fromString("abdel#publidirecta.com"));
pprequest.setMassPayItem(massPayItem);
// Execute the API operation and obtain the response.
MassPayResponseType ppresponse = (MassPayResponseType) caller.call("MassPay", pprequest);
responseValue = ppresponse.getAck().toString();
// println(ex)
// ex.printStackTrace();
return responseValue;
That's as intended; MassPay allows money to be transferred to non-registered users.
These people will then receive an email from PayPal, letting them know that money is waiting for them, and they'll just need to sign up to PayPal and confirm their email address to receive it.
The money will then be available to be withdrawn to a bank account, or spent as PayPal balance.