Статьи

Интеграция с PayPal, часть 2: API PayPal REST

Конечный продукт
Что вы будете создавать

В этом уроке я собираюсь показать вам, как вы можете принимать платежи, используя PayPal REST API и C #. Все библиотеки, которые они имеют для разных языков, таких как Ruby, Node.js, Python, PHP, очень похожи, поэтому все приведенные здесь понятия применимы ко всем библиотекам.

Для начала я создал проект MVC в Visual Studio 2015: « Файл»> «Создать»> «Проект» и выбрал приложение ASP.NET .

Настройка проекта

Выберите шаблон веб-приложения ASP.NET 5 , в котором используется новый MVC 6. Он похож на MVC 5, если вы с ним знакомы.

ASPNET MVC5

Как вы можете видеть на фотографии ниже, я добавил несколько файлов и папок к решению. Основные две вещи, на которые стоит обратить внимание:

  1. В разделе « Ссылки» я удалил целевой DNX Core 5.0, что позволило бы нам запустить этот проект в Mac OS X или Linux, но нужная нам библиотека PayPal еще не была обновлена.
  2. Я добавил папку «Службы», где я собираюсь обернуть логику для вызовов PayPal, чтобы мы могли сохранять контроллеры хорошими и короткими.
Обозреватель решений

Установите PayPal SDK с помощью NuGet. Щелкните правой кнопкой мыши на имени решения и выберите « Управление пакетами NuGet» , а затем найдите «PayPal» и установите его.

Менеджер пакетов

Чтобы интегрировать наше приложение с PayPal, нам нужно перейти к PayPal Developers , а затем в разделе « Приложения REST API» нажать « Создать приложение» .

Панель разработчика приложений PayPal

Дайте вашему приложению имя и выберите учетную запись разработчика песочницы, связанную с приложением. В целях тестирования мы можем затем перейти по адресу http://sandbox.paypal.com и войти в систему с данными для входа в песочницу, чтобы увидеть тестовую учетную запись PayPal и транзакции.

PayPal Developer App

После нажатия кнопки « Создать приложение» мы видим экран подтверждения с идентификатором клиента и секретными токенами.

Учетные данные приложения PayPal

Скопируйте токены clientId и clientSecret в appsettings.json , как показано на appsettings.json экрана ниже:

Настройки приложения JSON

PayPal предоставляет среду Sandbox для тестирования . Оттуда вы можете создать тестовые аккаунты покупателя и продавца. Когда вы зарегистрируетесь, у вас будет песочница Business, которая привязана к вашей учетной записи разработчика.

Чтобы создать новую тестовую учетную запись, войдите на сайт разработчика , а затем перейдите на вкладку « Панель инструментов » и выберите « Песочница»> «Учетные записи». Здесь вы можете увидеть список тестовых аккаунтов, если у вас есть:

PayPal Sandbox

Если вы еще не создали свои тестовые учетные записи, нажмите « Создать учетную запись» в правом верхнем углу, чтобы создать хотя бы одну тестовую личную учетную запись и одну тестовую бизнес-учетную запись.

Тестовый аккаунт PayPal

После создания тестовых учетных записей вы можете войти на сайт www.sandbox.paypal.com с тестовым адресом электронной почты и паролем, которые вы присвоили каждой учетной записи в предыдущей форме. Это действительно полезно для проверки того, что при покупке чего-либо с помощью «личного тестового счета» средства переводятся на ваш «тестовый бизнес-счет». Теперь вы готовы начать интеграцию с PayPal и проверить, что средства перемещаются с одного счета на другой.

PayPal предлагает разные способы оплаты. Вы можете использовать прямые платежи по кредитным картам, что означает, что ваши клиенты не увидят страницу входа в систему PayPal или сводную информацию — все это происходит на вашем веб-сайте. Для этого вам нужно быть PCI-совместимым, и я рекомендую использовать Stripe, поскольку вам нужен только SSL с использованием их библиотеки JavaScript. С другой стороны, чтобы принимать платежи через платежи PayPal, необходимо выполнить три шага:

  1. Укажите платежную информацию для создания платежа.
  2. Получите подтверждение оплаты , перенаправив своего клиента в PayPal для подтверждения транзакции.
  3. Выполните платеж, чтобы получить средства после того, как PayPal перенаправит вашего клиента обратно на ваш сайт.

В моем проекте MVC в папке Services я создал класс PayPalPaymentService, в который я добавил следующие методы:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
public static Payment CreatePayment(string baseUrl, string intent)
{
    // ### Api Context
    // Pass in a `APIContext` object to authenticate
    // the call and to send a unique request id
    // (that ensures idempotency).
    // a request id if you do not pass one explicitly.
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    // Payment Resource
    var payment = new Payment()
    {
        intent = intent, // `sale` or `authorize`
        payer = new Payer() { payment_method = «paypal» },
        transactions = GetTransactionsList(),
        redirect_urls = GetReturnUrls(baseUrl, intent)
    };
 
    // Create a payment using a valid APIContext
    var createdPayment = payment.Create(apiContext);
 
    return createdPayment;
}
 
private static List<Transaction> GetTransactionsList()
{
    // A transaction defines the contract of a payment
    // what is the payment for and who is fulfilling it.
    var transactionList = new List<Transaction>();
 
    // The Payment creation API requires a list of Transaction;
    // add the created Transaction to a List
    transactionList.Add(new Transaction()
    {
        description = «Transaction description.»,
        invoice_number = GetRandomInvoiceNumber(),
        amount = new Amount()
        {
            currency = «USD»,
            total = «100.00», // Total must be equal to sum of shipping, tax and subtotal.
            details = new Details() // Details: Let’s you specify details of a payment amount.
            {
                tax = «15»,
                shipping = «10»,
                subtotal = «75»
            }
        },
        item_list = new ItemList()
        {
            items = new List<Item>()
            {
                new Item()
                {
                    name = «Item Name»,
                    currency = «USD»,
                    price = «15»,
                    quantity = «5»,
                    sku = «sku»
                }
            }
        }
    });
    return transactionList;
}
 
private static RedirectUrls GetReturnUrls(string baseUrl, string intent)
{
    var returnUrl = intent == «sale» ?
 
    // Redirect URLS
    // These URLs will determine how the user is redirected from PayPal
    // once they have either approved or canceled the payment.
    return new RedirectUrls()
    {
        cancel_url = baseUrl + «/Home/PaymentCancelled»,
        return_url = baseUrl + returnUrl
    };
}
 
public static Payment ExecutePayment(string paymentId, string payerId)
{
    // ### Api Context
    // Pass in a `APIContext` object to authenticate
    // the call and to send a unique request id
    // (that ensures idempotency).
    // a request id if you do not pass one explicitly.
    var apiContext = PayPalConfiguration.GetAPIContext();
     
    var paymentExecution = new PaymentExecution() { payer_id = payerId };
    var payment = new Payment() { id = paymentId };
 
    // Execute the payment.
    var executedPayment = payment.Execute(apiContext, paymentExecution);
 
    return executedPayment;
}

В этом вызове передается несколько параметров:

  • Намерение: три возможных значения: «продажа» для немедленных платежей, «авторизовать», чтобы авторизовать платеж для получения позже, или «заказ» для создания заказа. Когда вы получите авторизацию для получения платежа позже, у вас будет гарантия 3 дня, хотя вы можете попытаться получить платеж до 29 дней спустя.
  • Плательщик: источник средств для этого платежа, используемый метод оплаты — платеж через PayPal Wallet, банковская прямая дебетовая или прямая кредитная карта.
  • Транзакции: используется для указания суммы платежа и, при желании, для оплаченных товаров. Вы также можете указать промежуточный итог, доставку и налог при необходимости.
  • URL-адреса перенаправления. Укажите URL-адрес, на который PayPal будет перенаправлять ваших клиентов после транзакции, чтобы вы могли обновить свою базу данных и отобразить подтверждающее сообщение.

Предыдущие функции могут быть использованы с вашего контроллера следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public IActionResult CreatePayment()
{
    var payment = PayPalPaymentService.CreatePayment(GetBaseUrl(), «sale»);
     
    return Redirect(payment.GetApprovalUrl());
}
 
public IActionResult PaymentCancelled()
{
    // TODO: Handle cancelled payment
    return RedirectToAction(«Error»);
}
 
public IActionResult PaymentSuccessful(string paymentId, string token, string PayerID)
{
    // Execute Payment
    var payment = PayPalPaymentService.ExecutePayment(paymentId, PayerID);
 
    return View();
}

Как видите, я создал три действия:

  • CreatePayment : это действие, инициирующее платеж. Он вызывает PayPal для создания платежа, затем перенаправляет пользователя в PayPal для подтверждения транзакции.
  • PaymentSuccessful : это действие, при котором PayPal перенаправляет клиента после успешной оплаты. В этот момент мы можем выполнить платеж, чтобы получить средства, переведенные на наш торговый счет.
  • PaymentCancelled : это действие, когда пользователь перенаправляется из PayPal, если пользователь отменяет процесс утверждения. В это время вы, вероятно, захотите дать возможность клиенту попробовать еще раз или связаться с вами.

Этот сценарий очень похож на предыдущий случай. Возможно, вы захотите использовать этот метод, если вы пытаетесь принять предварительные заказы на продукт, который еще не доступен. Шаги, чтобы получить этот платеж:

  1. Авторизовать платеж. Параметр «намерение» для этого вызова должен быть «авторизовать».
  2. Захват платежа. Помните, что авторизация гарантируется на срок до 3 дней, хотя вы можете попытаться получить платеж на срок до 29 дней.

Чтобы реализовать этот тип оплаты, я добавил только один новый метод в класс PayPalPaymentService для захвата платежа:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static Capture CapturePayment(string paymentId)
{
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    var payment = Payment.Get(apiContext, paymentId);
    var auth = payment.transactions[0].related_resources[0].authorization;
 
    // Specify an amount to capture.
    var capture = new Capture()
    {
        amount = new Amount()
        {
            currency = «USD»,
            total = «4.54»
        },
        is_final_capture = true
    };
 
    // Capture an authorized payment by POSTing to
    // URI v1/payments/authorization/{authorization_id}/capture
    var responseCapture = auth.Capture(apiContext, capture);
 
    return responseCapture;
}

Затем из HomeController я добавил два новых действия, чтобы показать этот тип оплаты:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public IActionResult AuthorizePayment()
{
    var payment = PayPalPaymentService.CreatePayment(GetBaseUrl(), «authorize»);
     
    return Redirect(payment.GetApprovalUrl());
}
 
public IActionResult AuthorizeSuccessful(string paymentId, string token, string PayerID)
{
    // Capture Payment
    var capture = PayPalPaymentService.CapturePayment(paymentId);
 
    return View();
}
  • AuthorizePayment — это действие, инициирующее платеж. Это очень похоже на предыдущую функцию «CreatePayment», но мы передаем «authorize» в качестве параметра намерения в этом случае.
  • AuthorizeSuccessful — это действие, при котором ваш клиент будет перенаправлен после успешного подтверждения платежа через PayPal. На данный момент я получаю платеж, но вы можете сохранить в своей базе данных paymentId и захватить платеж, когда вам это нужно.

В этих примерах кода для простоты я жестко закодировал значения переменных платежа. В вашем реальном приложении вы, вероятно, будете заключать их в методы, которые принимают все эти значения в качестве переменных, чтобы все можно было динамически задавать и использовать повторно.

В PayPal это называется «Планы выставления счетов» — вы можете создавать повторяющиеся планы платежей и подписывать своих клиентов на план выставления счетов, создав соглашение о выставлении счетов. Используя PayPal REST API, вы можете создавать, обновлять или удалять тарифные планы; это то, что вы могли бы использовать, если вы хотите создать панель администратора для управления этими вещами для вашего бизнеса.

Шаги для создания регулярных платежей для ваших клиентов:

  1. Создайте тарифный план и активируйте его . После создания тарифного плана он находится в СОЗДАННОМ состоянии. Его нужно активировать, сделав запрос PATCH.
  2. Создайте соглашение о выставлении счета и выполните его : ответ на вызов «Создание соглашения о выставлении счета» включает ссылки на Approval_url и execute_url. Нам нужно получить одобрение для биллингового соглашения и затем выполнить биллинговое соглашение.

Создайте тарифный план, который определяет расчетные периоды. Это сводка параметров, которые мы должны передать, чтобы создать план.

  • Имя: Название тарифного плана.
  • Описание: Описание тарифного плана.
  • Тип: Допустимые значения: «ИСПРАВЛЕНО» для установленного количества повторяющихся платежей или «БЕСКОНЕЧНО» для плана, который повторяется до тех пор, пока он не будет отменен вручную.
  • Настройки продавца: это объект, который задает такие параметры, как плата за установку, максимальное количество попыток сбоя платежа, возвратный URL, отмененный URL, уведомление, где PayPal перенаправит пользователя после оплаты.
  • Определения платежей : массив определений платежей для этого плана. Обычно этот массив имеет одно или два определения оплаты. Если мы хотим предложить бесплатную пробную версию или пробную версию по сниженной цене, мы устанавливаем два определения оплаты. Первым будет определение для пробного периода, а вторым будет регулярный платеж. Свойствами для определения платежа являются имя , тип (пробный или обычный), частота (день, неделя, месяц, год), частотный интервал (если мы установим частоту на «WEEK» и частотный интервал на «1», мы определение еженедельного платежа), сумма, взимаемая с клиента, и число циклов — это общее количество платежей. В моделях начислений указывается стоимость доставки и налог, добавляемый к стоимости суммы плана.

Это фрагмент кода, который показывает, как создать тарифный план:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Define the plan and attach the payment definitions and merchant preferences.
// More Information: https://developer.paypal.com/webapps/developer/docs/api/#create-a-plan
var billingPlan = new Plan
{
    name = «Tuts+ Plus»,
    description = «Monthly plan for courses.»,
    type = «fixed»,
    // Define the merchant preferences.
    // More Information: https://developer.paypal.com/webapps/developer/docs/api/#merchantpreferences-object
    merchant_preferences = new MerchantPreferences()
    {
        setup_fee = GetCurrency(«0»), // $0
        return_url = «returnURL», // Retrieve from config
        cancel_url = «cancelURL», // Retrieve from config
        auto_bill_amount = «YES»,
        initial_fail_amount_action = «CONTINUE»,
        max_fail_attempts = «0»
    },
    payment_definitions = new List<PaymentDefinition>
    {
        // Define a trial plan that will only charge $9.99 for the first
        // month.
        // remaining 11 months of the year.
        new PaymentDefinition()
        {
            name = «Trial Plan»,
            type = «TRIAL»,
            frequency = «MONTH»,
            frequency_interval = «1»,
            amount = GetCurrency(«0»), // Free for the 1st month
            cycles = «1»,
            charge_models = new List<ChargeModel>
            {
                new ChargeModel()
                {
                    type = «TAX»,
                    amount = GetCurrency(«1.65») // If we need to charge Tax
                },
                new ChargeModel()
                {
                    type = «SHIPPING»,
                    amount = GetCurrency(«9.99») // If we need to charge for Shipping
                }
            }
        },
        // Define the standard payment plan.
        // plan for $19.99 USD that charges once month for 11 months.
        new PaymentDefinition
        {
            name = «Standard Plan»,
            type = «REGULAR»,
            frequency = «MONTH»,
            frequency_interval = «1»,
            amount = GetCurrency(«15.00»),
            // > NOTE: For `IFNINITE` type plans, `cycles` should be 0 for a `REGULAR` `PaymentDefinition` object.
            cycles = «11»,
            charge_models = new List<ChargeModel>
            {
                new ChargeModel
                {
                    type = «TAX»,
                    amount = GetCurrency(«2.47»)
                },
                new ChargeModel()
                {
                    type = «SHIPPING»,
                    amount = GetCurrency(«9.99»)
                }
            }
        }
    }
};
 
// Get PayPal Config
var apiContext = PayPalConfiguration.GetAPIContext();
 
// Create Plan
plan.Create(apiContext);

Вновь созданный тарифный план находится в состоянии СОЗДАНО. Активируйте его в состояние ACTIVE, чтобы ваши клиенты могли подписаться на план. Чтобы активировать план, нам нужно сделать запрос PATCH:

01
02
03
04
05
06
07
08
09
10
11
// Activate the plan
var patchRequest = new PatchRequest()
{
    new Patch()
    {
        op = «replace»,
        path = «/»,
        value = new Plan() { state = «ACTIVE» }
    }
};
plan.Update(apiContext, patchRequest);

Как вы можете видеть, библиотеки PayPal являются прямой оболочкой для их REST API, что хорошо, но API также действительно сложен по сравнению с другими, такими как Stripe. По этой причине это действительно хороший вариант, чтобы обернуть все коммуникации PayPal в объекты с более понятными и простыми API для наших приложений. Здесь вы можете увидеть, как выглядит этот код в нескольких функциях, принимающих параметры:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public static Plan CreatePlanObject(string planName, string planDescription, string returnUrl, string cancelUrl,
    string frequency, int frequencyInterval, decimal planPrice,
    decimal shippingAmount = 0, decimal taxPercentage = 0, bool trial = false, int trialLength = 0, decimal trialPrice = 0)
{
    // Define the plan and attach the payment definitions and merchant preferences.
    // More Information: https://developer.paypal.com/docs/rest/api/payments.billing-plans/
    return new Plan
    {
        name = planName,
        description = planDescription,
        type = PlanType.Fixed,
 
        // Define the merchant preferences.
        // More Information: https://developer.paypal.com/webapps/developer/docs/api/#merchantpreferences-object
        merchant_preferences = new MerchantPreferences()
        {
            setup_fee = GetCurrency(«1»),
            return_url = returnUrl,
            cancel_url = cancelUrl,
            auto_bill_amount = «YES»,
            initial_fail_amount_action = «CONTINUE»,
            max_fail_attempts = «0»
        },
        payment_definitions = GetPaymentDefinitions(trial, trialLength, trialPrice, frequency, frequencyInterval, planPrice, shippingAmount, taxPercentage)
    };
}
 
private static List<PaymentDefinition> GetPaymentDefinitions(bool trial, int trialLength, decimal trialPrice,
    string frequency, int frequencyInterval, decimal planPrice, decimal shippingAmount, decimal taxPercentage)
{
    var paymentDefinitions = new List<PaymentDefinition>();
 
    if (trial)
    {
        // Define a trial plan that will charge ‘trialPrice’ for ‘trialLength’
        // After that, the standard plan will take over.
        paymentDefinitions.Add(
            new PaymentDefinition()
            {
                name = «Trial»,
                type = «TRIAL»,
                frequency = frequency,
                frequency_interval = frequencyInterval.ToString(),
                amount = GetCurrency(trialPrice.ToString()),
                cycles = trialLength.ToString(),
                charge_models = GetChargeModels(trialPrice, shippingAmount, taxPercentage)
            });
    }
 
    // Define the standard payment plan.
    // plan for ‘planPrice’ that charges ‘planPrice’ (once a month) for #cycles.
    var regularPayment = new PaymentDefinition
    {
        name = «Standard Plan»,
        type = «REGULAR»,
        frequency = frequency,
        frequency_interval = frequencyInterval.ToString(),
        amount = GetCurrency(planPrice.ToString()),
        // > NOTE: For `IFNINITE` type plans, `cycles` should be 0 for a `REGULAR` `PaymentDefinition` object.
        cycles = «11»,
        charge_models = GetChargeModels(trialPrice, shippingAmount, taxPercentage)
    };
    paymentDefinitions.Add(regularPayment);
 
    return paymentDefinitions;
}
 
private static List<ChargeModel> GetChargeModels(decimal planPrice, decimal shippingAmount, decimal taxPercentage)
{
    // Create the Billing Plan
    var chargeModels = new List<ChargeModel>();
    if (shippingAmount > 0)
    {
        chargeModels.Add(new ChargeModel()
        {
            type = «SHIPPING»,
            amount = GetCurrency(shippingAmount.ToString())
        });
    }
    if (taxPercentage > 0)
    {
        chargeModels.Add(new ChargeModel()
        {
            type = «TAX»,
            amount = GetCurrency(String.Format(«{0:f2}», planPrice * taxPercentage / 100))
        });
    }
 
    return chargeModels;
}

Вы можете обновить информацию для существующего тарифного плана, сделав запрос «PATCH». Это функция, которая переносит этот вызов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public static void UpdateBillingPlan(string planId, string path, object value)
{
    // PayPal Authentication tokens
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    // Retrieve Plan
    var plan = Plan.Get(apiContext, planId);
 
    // Activate the plan
    var patchRequest = new PatchRequest()
    {
        new Patch()
        {
            op = «replace»,
            path = path,
            value = value
        }
    };
    plan.Update(apiContext, patchRequest);
}

Чтобы обновить описание тарифного плана, мы можем вызвать эту функцию и передать правильные параметры:

1
2
3
4
UpdateBillingPlan(
   planId: «P-5FY40070P6526045UHFWUVEI»,
   path: «/»,
   value: new Plan { description = «new description» });

В идеале, если вы не хотите принимать новых клиентов в тарифный план, вам нужно обновить его до состояния «НЕАКТИВНО». Это не повлияет на существующие биллинговые соглашения по этому плану. Это можно сделать, просто вызвав функцию UpdateBillingPlan:

1
2
3
4
UpdateBillingPlan(
   planId: «P-5FY40070P6526045UHFWUVEI»,
   path: «/»,
   value: new Plan { state = «INACTIVE» });

Создав один или несколько тарифных планов, вы хотите, чтобы клиенты подписывались на ваши планы подписки. Для этого вам необходимо собрать данные своего клиента и отправить запрос в PayPal. Чтобы проверить эту функциональность, я добавил несколько действий в HomeController:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public IActionResult Subscribe()
{
    var plan = PayPalSubscriptionsService.CreateBillingPlan(«Tuts+ Plan», «Test plan for this article», GetBaseUrl());
 
    var subscription = PayPalSubscriptionsService.CreateBillingAgreement(plan.id,
        new PayPal.Api.ShippingAddress
        {
            city = «London»,
            line1 = «line 1»,
            postal_code = «SW1A 1AA»,
            country_code = «GB»
        }, «Pedro Alonso», «Tuts+», DateTime.Now);
     
    return Redirect(subscription.GetApprovalUrl());
}
 
public IActionResult SubscribeSuccess(string token)
{
    // Execute approved agreement
    PayPalSubscriptionsService.ExecuteBillingAgreement(token);
 
    return View();
}
 
public IActionResult SubscribeCancel(string token)
{
    // TODO: Handle cancelled payment
    return RedirectToAction(«Error»);
}
  • Подписка: это первое действие, которое называется. Он создает тестовый тарифный план, а затем создается соглашение о выставлении счетов (подписка) на этот план, и пользователь перенаправляется в PayPal для подтверждения платежа.
  • SubscribeSuccess : это действие используется как «URL возврата» после успешной подписки. Идентификатор токена соглашения передается в строке запроса, и мы используем этот токен, чтобы выполнить соглашение о выставлении счета и сделать его активным.
  • SubscribeCancel: это действие используется как «Отмена URL». Если по какой-либо причине платеж не проходит или ваш клиент отменяет платеж через PayPal, пользователь принимает это действие, и вам необходимо справиться с этим. Может быть, предложить вариант, чтобы попробовать еще раз.

Как вы можете видеть в предыдущем фрагменте кода, я обернул большую часть функциональности в несколько методов. Первый — «CreateBillingPlan», который был объяснен в предыдущем разделе. Второй — «CreateBillingAgreement», который используется для подписки пользователя на план:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public static Agreement CreateBillingAgreement(string planId, ShippingAddress shippingAddress,
    string name, string description, DateTime startDate)
{
    // PayPal Authentication tokens
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    var agreement = new Agreement()
    {
        name = name,
        description = description,
        start_date = startDate.ToString(«yyyy-MM-ddTHH:mm:ss») + «Z»,
        payer = new Payer() { payment_method = «paypal» },
        plan = new Plan() { id = planId },
        shipping_address = shippingAddress
    };
     
    var createdAgreement = agreement.Create(apiContext);
    return createdAgreement;
}

Третий метод — «ExecuteBillingAgreement». После успешного подтверждения подписки мы используем возвращенный токен для активации подписки:

1
2
3
4
5
6
7
8
public static void ExecuteBillingAgreement(string token)
{
    // PayPal Authentication tokens
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    var agreement = new Agreement() { token = token };
    var executedAgreement = agreement.Execute(apiContext);
}

Используйте этот метод, чтобы приостановить действие соглашения:

1
2
3
4
5
6
7
8
public static void SuspendBillingAgreement(string agreementId)
{
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    var agreement = new Agreement() { id = agreementId };
    agreement.Suspend(apiContext, new AgreementStateDescriptor()
        { note = «Suspending the agreement» });
}

Этот действительно похож на предыдущий:

1
2
3
4
5
6
7
8
public static void ReactivateBillingAgreement(string agreementId)
{
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    var agreement = new Agreement() { id = agreementId };
    agreement.ReActivate(apiContext, new AgreementStateDescriptor()
        { note = «Reactivating the agreement» });
}

Используйте эту функцию, чтобы отменить план:

1
2
3
4
5
6
7
8
public static void CancelBillingAgreement(string agreementId)
{
    var apiContext = PayPalConfiguration.GetAPIContext();
 
    var agreement = new Agreement() { id = agreementId };
    agreement.Cancel(apiContext, new AgreementStateDescriptor()
        { note = «Cancelling the agreement» });
}

Этот вариант очень ограничен, и я ожидаю от этого звонка возможности изменить план подписки для повышения или понижения рейтинга клиента. Это не поддерживается в одном вызове, как в Stripe. Вы должны справиться с этим сценарием, отменив текущее соглашение и создав новое для обновлений или понижений. Это не идеально, но это может измениться в будущем.

Это обзор наиболее распространенных функций, которые люди используют для интеграции с PayPal. Их API намного больше, чем методы интеграции, описанные в этой статье — вы также можете производить возвраты и частичные возвраты, и у них есть много разных вариантов для крайних случаев в примерах, описанных в этой статье. Если вы заинтересованы в получении более подробной информации о какой-либо конкретной интеграции, пожалуйста, оставьте предложение в комментариях.