>백엔드 개발 >PHP 튜토리얼 >Paypal에서 반복 공제(구독) 기능을 구현하는 방법

Paypal에서 반복 공제(구독) 기능을 구현하는 방법

墨辰丷
墨辰丷원래의
2018-05-24 16:18:482138검색

이 글에서는 반복 공제(구독)를 구현하기 위한 Paypal의 아이디어와 방법을 주로 소개하고, 참고할 가치가 있는 Paypal의 결제 인터페이스를 사용하는 방법도 요약합니다.

원인

반복 공제 기능을 구현하려면 Paypal을 통합해야 합니다. 그러나 Baidu와 GOOGLE은 공식 웹사이트 외에는 관련 개발 튜토리얼을 찾지 못했습니다. 통합이 성공적으로 이루어졌습니다. 다음은 Paypal 결제 인터페이스 사용 방법에 대한 요약입니다.

Paypal에는 이제 여러 소켓이 있습니다.

  • Braintree를 통해 Express Checkout을 구현합니다(Braintree에 대해서는 나중에 설명하겠습니다).

  • REST Api 인터페이스 방법(현재 주류 인터페이스 방법)을 통해 앱을 만듭니다.

  • NVP/SOAP API 앱의 인터페이스(기존 인터페이스)
Interface of Braintree

Braintree는 Paypal 결제 지원 외에도 업그레이드 플랜, 신용 카드, 고객 서비스도 제공하는 회사입니다. 정보 전체 관리를 기다리면 사용하는 것이 더 편리합니다. 실제로 Paypal의 두 번째 REST 인터페이스 세트는 이러한 기능의 대부분을 통합하지만 Paypal의 Dashboard는 이 정보를 직접 관리할 수 없지만 Braintree는 가능하므로 실제로 Braintree를 사용하는 것을 선호합니다. 중요한 점은 제가 사용하는 백엔드 프레임워크가 Laravel이고 그 계산원 솔루션이 기본적으로 Braintee를 지원하므로 이 인터페이스 세트가 제가 첫 번째 선택이라는 것입니다. 하지만 모든 기능을 구현해 보니 뼈아픈 문제가 발견되었습니다. Braintree는 중국에서는 지원되지 않습니다. . . . . . 죽음. . .

REST API

이것은 시대의 발전에 적응한 제품입니다. 이전에 OAuth 2.0 및 REST API를 사용해 본 적이 있다면 이러한 인터페이스를 볼 때 혼란이 없어야 합니다.

이전 인터페이스

REST API 인터페이스가 정책 제한 등의 요구 사항을 충족할 수 없는 경우가 아니면 사용하지 않는 것이 좋습니다. 전 세계가 OAuth 2.0 인증 방식과 REST API의 API 활용 방식으로 마이그레이션하고 있습니다. 따라서 REST API가 문제를 해결할 수 있을 때 이 인터페이스 세트를 심층적으로 비교하지 않았습니다.

REST API 소개

공식 API 참조 문서 https://developer.paypal.com/webapps/developer/docs/api/에는 API 및 사용법에 대한 자세한 소개가 있지만 직접 조정하면 이러한 API는 여전히 매우 번거롭고 동시에 API에 대한 심층적인 이해에 갇히는 대신 비즈니스 요구 사항을 최대한 빨리 완료하고 싶습니다.

그렇다면 어떻게 시작해야 할까요? 공식적으로 제공되는 PayPal-PHP-SDK를 직접 설치하고 해당 Wiki를 시작점으로 사용하는 것이 좋습니다.

첫 번째 예를 완료하기 전에 샌드박스 계정이 있는지 확인하고 올바르게 구성하세요.

    Client ID
  • Client Secret
  • Webhook API(https로 시작하고 포트 443, 로컬이어야 함) 디버깅 제안은 ngrok 역방향 프록시와 결합되어 주소를 생성합니다.)
  • Returnurl(참고는 위와 동일)
  • Wiki의 첫 번째 예를 완료한 후 인터페이스 분류를 이해하면 비즈니스 요구 사항을 완료하는 데 도움이 됩니다. 아래에서 설명하겠습니다. 인터페이스 분류에 대한 소개는 http://paypal.github.io/PayPal-PHP-SDK/sample/#paids를 예시와 함께 이해하시기 바랍니다.

  • Payments 일회성 결제 인터페이스는 반복 기부를 지원하지 않습니다. 주요 결제 콘텐츠에는 Paypal 결제 지원, 신용 카드 결제, 저장된 신용 카드를 통한 지원(Vault 인터페이스 사용이 필요하며 이러한 인터페이스는 주로 PCI 요구 사항으로 인해 발생하며 일반 웹사이트에서는 민감한 신용 카드 정보를 수집할 수 없습니다), 제3자 수취인에 대한 결제를 지원합니다.

  • 지불 사용되지 않음, 무시

  • 승인 및 캡처 Paypal 계정을 통해 직접 웹사이트에 로그인하고 관련 정보를 얻을 수 있도록 지원합니다.

  • 세일 쇼핑몰 관련, 미사용, 무시;

  • Order 쇼핑몰 관련, 미사용, 무시;

  • Billing Plan & Agreements 업그레이드 계획 및 계약, 즉 구독 기능, 이 글의 초점인 반복 공제를 달성하려면 여기에서 기능을 사용해야 합니다.

  • Vault 신용 카드 정보 저장

  • Payment Experience 사용되지 않음, 무시;

  • Notifications 처리 Webhook 정보, 중요하지만 이 기사의 초점은 아님

  • Invoice 청구 처리, OAuth 2.0 로그인 및 구현 획득하다 다른 API를 요청하기 위한 해당 토큰입니다. 이 Paypal-PHP-SDK는 이미 구현되었으므로 이 문서에서는 설명하지 않습니다.

  • 반복 공제 구현 방법

    4단계:

  • 업그레이드 계획 생성 및 활성화
  • 구독을 생성(계약 생성)한 다음 PayPal 웹사이트로 이동하여 사용자의 동의를 기다립니다.

  • 사용자가 동의한 후 구독을 실행합니다.

  • 직불 청구서 받기

  • 1. 업그레이드 계획 생성

    업그레이드 계획은 계획 클래스에 해당합니다. 이 단계에서 주의해야 할 몇 가지 사항이 있습니다.

    • 업그레이드 계획이 생성된 후에는 CREATED 상태이며 정상적으로 사용하려면 먼저 ACTIVE로 변경해야 합니다.

    • Plan에는 PaymentDefinition과 MerchantPreferences라는 두 개의 개체가 있으며 둘 다 비워둘 수 없습니다.

    • 평가판 유형 계획을 생성하려면 계획에 일치하는 REGULAR 지불 정의도 있어야 합니다. 그렇지 않으면 오류가 발생합니다.

    • 코드를 보면 setSetupFee(매우, 매우, 매우 중요) 메소드가 호출되어 구독 완료 후 첫 번째 공제에 대한 수수료를 설정하는 반면 계약 객체의 순환 공제 메소드는 두 번째 비용이 시작될 때 수수료.

    표준 계획을 생성하는 경우 해당 매개변수는 다음과 같습니다.

    $param = [
     "name" => "standard_monthly",
     "display_name" => "Standard Plan",
     "desc" => "standard Plan for one month",
     "type" => "REGULAR",
     "frequency" => "MONTH",
     "frequency_interval" => 1,
     "cycles" => 0,
     "amount" => 20,
     "currency" => "USD"
     ];

    계획을 생성하고 활성화하는 코드는 다음과 같습니다.

     //上面的$param例子是个数组,我的实际应用传入的实际是个对象,用户理解下就好。
     public function createPlan($param)
     {
     $apiContext = $this->getApiContext();
     $plan = new Plan();
     // # Basic Information
     // Fill up the basic information that is required for the plan
     $plan->setName($param->name)
     ->setDescription($param->desc)
     ->setType('INFINITE');//例子总是设置为无限循环
     // # Payment definitions for this billing plan.
     $paymentDefinition = new PaymentDefinition();
     // The possible values for such setters are mentioned in the setter method documentation.
     // Just open the class file. e.g. lib/PayPal/Api/PaymentDefinition.php and look for setFrequency method.
     // You should be able to see the acceptable values in the comments.
     $paymentDefinition->setName($param->name)
     ->setType($param->type)
     ->setFrequency($param->frequency)
     ->setFrequencyInterval((string)$param->frequency_interval)
     ->setCycles((string)$param->cycles)
     ->setAmount(new Currency(array('value' => $param->amount, 'currency' => $param->currency)));
     // Charge Models
     $chargeModel = new ChargeModel();
     $chargeModel->setType('TAX')
     ->setAmount(new Currency(array('value' => 0, 'currency' => $param->currency)));
     $returnUrl = config('payment.returnurl');
     $merchantPreferences = new MerchantPreferences();
     $merchantPreferences->setReturnUrl("$returnUrl?success=true")
     ->setCancelUrl("$returnUrl?success=false")
     ->setAutoBillAmount("yes")
     ->setInitialFailAmountAction("CONTINUE")
     ->setMaxFailAttempts("0")
     ->setSetupFee(new Currency(array('value' => $param->amount, 'currency' => 'USD')));
     $plan->setPaymentDefinitions(array($paymentDefinition));
     $plan->setMerchantPreferences($merchantPreferences);
     // For Sample Purposes Only.
     $request = clone $plan;
     // ### Create Plan
     try {
     $output = $plan->create($apiContext);
     } catch (Exception $ex) {
     return false;
     }
     $patch = new Patch();
     $value = new PayPalModel('{"state":"ACTIVE"}');
     $patch->setOp('replace')
     ->setPath('/')
     ->setValue($value);
     $patchRequest = new PatchRequest();
     $patchRequest->addPatch($patch);
     $output->update($patchRequest, $apiContext);
     return $output;
     }

    2. 생성 구독(계약 생성)을 한 다음 PayPal 웹사이트로 이동하여 사용자의 동의를 기다립니다

    플랜이 생성된 후 사용자가 구독하도록 하려면 어떻게 해야 할까요?

    • 앞서 언급한 바와 같이 Plan 객체 setSetupFee 메소드는 구독 완료 후 첫 번째 차감에 대한 수수료를 설정하는 반면, Agreement 객체의 순환 공제 메소드는 구독에 대한 수수료를 설정합니다. 두 번째 시작.

    • setStartDate 메소드는 두 번째 공제 시간을 설정하므로 월 단위로 순환하는 경우 현재 시간에 한 달을 더한 시간이어야 합니다. 동시에 이 메소드에서는 시간 형식이 ISO8601 형식이어야 합니다. Carbon 라이브러리를 사용하면 쉽게 해결할 수 있습니다.

    • 계약을 생성할 때 고유 ID가 아직 생성되지 않았기 때문에 약간의 어려움이 있었습니다. 사용자가 구독을 완료하면 어떤 사용자가 구독을 하는지 어떻게 알 수 있습니까? 속해 있나요? 계약의 getApprovalLink 메소드를 통해 얻은 URL의 토큰은 고유합니다. 식별 방법으로 토큰을 추출하고 사용자가 구독을 완료한 후 이를 실제 ID로 대체합니다.

    예제 매개변수는 다음과 같습니다.

    $param = [
     'id' => 'P-26T36113JT475352643KGIHY',//上一步创建Plan时生成的ID
     'name' => 'Standard', 
     'desc' => 'Standard Plan for one month'
    ];

    코드는 다음과 같습니다.

     public function createPayment($param)
     {
     $apiContext = $this->getApiContext();
     $agreement = new Agreement();
     $agreement->setName($param['name'])
     ->setDescription($param['desc'])
     ->setStartDate(Carbon::now()->addMonths(1)->toIso8601String());
     // Add Plan ID
     // Please note that the plan Id should be only set in this case.
     $plan = new Plan();
     $plan->setId($param['id']);
     $agreement->setPlan($plan);
     // Add Payer
     $payer = new Payer();
     $payer->setPaymentMethod('paypal');
     $agreement->setPayer($payer);
     // For Sample Purposes Only.
     $request = clone $agreement;
     // ### Create Agreement
     try {
     // Please note that as the agreement has not yet activated, we wont be receiving the ID just yet.
     $agreement = $agreement->create($apiContext);
     // ### Get redirect url
     // The API response provides the url that you must redirect
     // the buyer to. Retrieve the url from the $agreement->getApprovalLink()
     // method
     $approvalUrl = $agreement->getApprovalLink();
     } catch (Exception $ex) {
     return "create payment failed, please retry or contact the merchant.";
     }
     return $approvalUrl;//跳转到$approvalUrl,等待用户同意
     }

    함수가 실행된 후 $approvalUrl을 반환합니다. 사용자가 지불할 때까지 기다립니다.

    사용자가 동의한 후 구독을 실행합니다

    사용자가 동의한 후에도 구독이 완료되지 않은 상태에서 실제 구독이 완료됩니다. 이 단계에서 중요한 점은

    • 구독을 완료했다고 해서 결제가 차감되는 것은 아니며 몇 분 정도 지연될 수 있다는 것입니다.

    • 처음에 setupFee 수수료가 단계가 0으로 설정되면 반복 차감 시간이 끝날 때까지 기다려야 합니다. 주문이 생성됩니다.

    코드 조각은 다음과 같습니다.

     public function onPay($request)
     {
     $apiContext = $this->getApiContext();
     if ($request->has('success') && $request->success == 'true') {
     $token = $request->token;
     $agreement = new \PayPal\Api\Agreement();
     try {
     $agreement->execute($token, $apiContext);
     } catch(\Exception $e) {
     return ull;
     return $agreement;
     }
     return null;
     }

    거래 기록 가져오기

    가입 후 거래 차감 거래 기록이 즉시 생성되지 않을 수 있습니다. 비어 있는 경우 다시 시도하는 데 며칠이 소요됩니다. 이 단계에 대한 참고 사항:

    • start_date 및 end_date는 비워둘 수 없습니다

    • 실제 테스트 중에 이 함수에서 반환된 개체는 항상 빈 JSON 개체를 반환할 수 없으므로 JSON을 출력해야 하는 경우 API 지침을 따르세요. AgreementTransactions 에서 해당 매개변수를 수동으로 추출합니다.

     /** 获取交易记录
     * @param $id subscription payment_id
     * @warning 总是获取该subscription的所有记录
     */
     public function transactions($id)
     {
     $apiContext = $this->getApiContext();
     $params = ['start_date' => date('Y-m-d', strtotime('-15 years')), 'end_date' => date('Y-m-d', strtotime('+5 days'))];
     try {
     $result = Agreement::searchTransactions($id, $params, $apiContext);
     } catch(\Exception $e) {
     Log::error("get transactions failed" . $e->getMessage());
     return null;
     }
     return $result->getAgreementTransactionList() ;
     }

    물론 Paypal에도 해당하는 공식 튜토리얼이 있지만 위 프로세스와의 차이점은 관심 있는 참조를 위해 처음 3단계만 설명한다는 것입니다. :/ /developer.paypal.com/docs/integration/direct/billing-plans-and-agreements/.

    고려해야 할 문제

    기능이 구현되었지만 주의할 점도 많이 발견되었습니다.

    • 중국에서 샌드박스 테스트를 사용할 때 특히 연결이 느리고, 오류가 자주 발생합니다. 시간 초과 또는 오류가 발생하므로 실행 도중에 사용자가 종료하는 경우 특별한 고려가 필요합니다. 페이지 상황

    • 반드시 웹훅을 구현하세요. 그렇지 않으면 사용자가 PayPal을 통해 구독을 취소할 때 웹사이트에 알림이 전송되지 않습니다.

    • 구독(계약)이 생성되면 적극적으로 취소하지 않는 한 유효하게 유지됩니다. 따라서 웹사이트가 여러 업그레이드 계획(예: 기본, 표준, 고급)으로 설계된 경우 사용자가 특정 계획을 구독하고 업그레이드 계획으로 전환하면 개발자는 이전 업그레이드 계획을 취소해야 합니다.

    • 사용자가 구독에 동의함 - (이전 구독 취소 - 새 구독 서명 완료 - 새 구독에 대한 사용자 정보 수정) 괄호의 전체 프로세스는 원자적 작업이어야 하며 시간이 오래 걸리므로 성공할 때까지 실행 대기열에 넣으면 경험이 더 좋아질 것입니다.

    위 내용은 이 글의 전체 내용입니다. 모든 분들의 공부에 도움이 되었으면 좋겠습니다.


    관련 추천:

    Paypal반복 공제(구독) 기능 구현을 위한 샘플 코드 공유

    zen 카트 메소드를 통해 PayPal에 예약된 전화번호를 주문에 추가

    paypal의 가장 간단한 PHP 온라인 결제 SDK

    위 내용은 Paypal에서 반복 공제(구독) 기능을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.