Search code examples
paypalasp.net-core-mvcpaypal-sandbox

Send Money to Paypal Account ASP.Net Server Side Code


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 // "[email protected]"
                            }
                    }
                }
                
                //,
                //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", "[email protected]");
    //var client =  Helpers.Paypal.CaptureOrderSample.client();

    var result = Helpers.Paypal.CaptureOrderSample.createOrder("[email protected]");

    //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: enter image description here

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="[email protected]",
            }
        }
    };
    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.


Solution

  • 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.