PayPal PHP SDK выполняет соглашение о выставлении счетов даже в случае сбоя платы за установку - PullRequest
0 голосов
/ 16 июня 2020

Моя проблема в том, что соглашения о выставлении счетов успешно выполняются, даже если плата за установку не оплачена. Глядя в журналы, можно увидеть, что событие IPN, уведомляющее о том, что плата за установку не прошла и соглашение было отменено, обычно занимает 5-10 минут, что является безумной задержкой.

Я использую официальный PayPal PHP SDK в https://github.com/paypal/PayPal-PHP-SDK. Он был объявлен устаревшим через месяц go, но его замена помечена как «не готово к производству».

Детали тарифного плана с намерением взимать плату за подписку за 29,99 долларов в год. Плата за установку используется для гарантии первоначального платежа.

Billing Plan settings

В соответствии с двухэтапным процессом, описанным в https://paypal.github.io/PayPal-PHP-SDK/sample/, с упаковкой Блоки try / catch удалены для удобочитаемости:

// Step 1: https://paypal.github.io/PayPal-PHP-SDK/sample/doc/billing/CreateBillingAgreementWithPayPal.html

use PayPal\Api\Agreement;
use PayPal\Api\MerchantPreferences;
use PayPal\Api\Payer;
use PayPal\Api\Plan;

/**
 * @var \PayPal\Rest\ApiContext $apiContext
 */
$plan = Plan::get('EXAMPLE-PLAN-ID', $apiContext);

$agreement = new Agreement();

date_default_timezone_set('America/Los_Angeles');
$agreement->setName($plan->getName())
    ->setDescription($plan->getDescription())
    // I'm not sure why +1 hour is used here, but that's how it is in the codebase.
    ->setStartDate(date('c', strtotime("+1 hour", time())));

$agreement->setPlan($plan);

/**
 * ------------------------------------------------------------------------------------------
 * I think overriding should be optional since they currently precisely match the given 
 * plan's data.  So for this particular plan, if I deleted everything between these comment
 * blocks, nothing bad should happen.
 * ------------------------------------------------------------------------------------------
 */
$preferences = new MerchantPreferences();
$preferences->setReturnUrl("https://www.example.com/actually-a-valid-site")
    ->setCancelUrl("https://www.example.com/actually-a-valid-site")
    ->setAutoBillAmount('no')
    ->setInitialFailAmountAction('CANCEL');

$agreement->setOverrideMerchantPreferences($preferences);
/**
 * ------------------------------------------------------------------------------------------
 * ------------------------------------------------------------------------------------------
 */

$payer = new Payer();
$payer->setPaymentMethod('paypal');
$agreement->setPayer($payer);

$agreement = $agreement->create($apiContext);
$approvalUrl = $agreement->getApprovalLink();

// This takes us to PayPal to login and confirm payment.
header("Location: ".$approvalUrl);
// Step 2: https://paypal.github.io/PayPal-PHP-SDK/sample/doc/billing/ExecuteAgreement.html

use PayPal\Api\Agreement;

/**
 * @var \PayPal\Rest\ApiContext $apiContext
 */
try {
    $agreement = new Agreement();
    $agreement->execute($_GET['token'], $apiContext);

    $agreement = Agreement::get($agreement->getId(), $apiContext);

    /**
     * I assume at this point the agreement is executed successfully.  Yet, the setup fee does not
     * have to be paid for us to get here.  This behavior is verified on live.
     */
} catch (\Exception $e) {
    // Do something.
}

Я не понимаю, что делаю неправильно, из-за чего соглашение о выставлении счетов будет выполнено даже без уплаты платы за установку. Помощь будет признательна!

Вот как создать план, который был использован:

use PayPal\Api\Currency;
use PayPal\Api\MerchantPreferences;
use PayPal\Api\Patch;
use PayPal\Api\PatchRequest;
use PayPal\Api\PaymentDefinition;
use PayPal\Api\Plan;
use PayPal\Common\PayPalModel;

$plan = new Plan();

$plan->setName('Test Name')
    ->setDescription('Test Description')
    ->setType('INFINITE');

$payment_definition = new PaymentDefinition();

$payment_definition->setName('Regular Payments')
    ->setType('REGULAR')
    ->setFrequency('YEAR')
    ->setFrequencyInterval(1)
    ->setCycles('0')
    ->setAmount(new Currency(['value' => '29.99', 'currency' => 'USD']));

$merchant_preferences = new MerchantPreferences();
$merchant_preferences->setReturnUrl'https://insert.actual.url.here')
    ->setCancelUrl('https://insert.actual.url.here')
    ->setAutoBillAmount('NO')
    ->setInitialFailAmountAction('CANCEL')
    ->setMaxFailAttempts('1')
    ->setSetupFee(new Currency(['value' => '29.99', 'currency' => 'USD']));

$plan->setPaymentDefinitions([$payment_definition]);
$plan->setMerchantPreferences($merchant_preferences);

$request = clone $plan;

try {
    /**
     * @var \Paypal\Rest\ApiContext $apiContext
     */
    $plan->create($apiContext);

    $patch = new Patch();
    $value = new PayPalModel(['state' => 'ACTIVE']);

    $patch->setOp('replace')
        ->setPath('/')
        ->setValue($value);

    $patchRequest = new PatchRequest();
    $patchRequest->addPatch($patch);

    if (!$plan->update($patchRequest, $apiContext)) {
        throw new \Exception("Failed to apply patch to plan.");
    }
    // Done.
} catch (\Exception $e) {
    // Some error handling.
    exit;
}

Ответы [ 2 ]

1 голос
/ 16 июня 2020

SDK на замену - https://github.com/paypal/Checkout-PHP-SDK, который не включает никаких соглашений о выставлении счетов или сценариев использования подписки. Для случаев использования, не охватываемых этим SDK, следует использовать прямую интеграцию HTTPS. Это задокументировано здесь: https://developer.paypal.com/docs/api/rest-sdks/

Код, который вы пытаетесь использовать, предназначен для устаревшего SDK для устаревшего API (старая версия соглашений о выставлении счетов, несовместимая с новыми подписками).

Вот API, который следует интегрировать без SDK: https://developer.paypal.com/docs/subscriptions/

0 голосов
/ 21 июня 2020

Оказалось, что исключение не должно создаваться при обычном исполнении соглашения. Чтобы проверить, была ли установка оплачена, проверьте значение $agreement->getState() после заключения соглашения.

...