Maison  >  Article  >  développement back-end  >  Exemple de partage de code pour Paypal afin de mettre en œuvre la fonction de déduction récurrente (abonnement)

Exemple de partage de code pour Paypal afin de mettre en œuvre la fonction de déduction récurrente (abonnement)

黄舟
黄舟original
2017-03-24 09:26:063010parcourir

Cet article présente principalement les idées et méthodes de Paypal pour mettre en œuvre des déductions récurrentes (abonnements) ; il résume également comment utiliser l'interface de paiement de Paypal, qui a une bonne valeur de référence. Jetons-y un coup d'œil avec l'éditeur ci-dessous

Cause

L'entreprise doit intégrer Paypal pour réaliser la fonction de déduction récurrente. Cependant, Baidu et GOOGLE ont fait le tour. , à l'exception du site officiel De plus, je n'ai trouvé aucun tutoriel de développement pertinent, j'ai donc dû consulter Paypal. Après deux jours, l'intégration a réussi Voici un résumé de l'utilisation de l'interface de paiement de Paypal.

Paypal dispose désormais de plusieurs sockets :

  • Le paiement express est implémenté via Braintree (nous parlerons de Braintree plus tard

  • Créer une application via l'interface de REST Api (l'interface grand public actuelle) ;

  • L'interface des applications API NVP/SOAP (ancienne interface) ;

Interface de Braintree

Braintree est une société acquise par Paypal. En plus de prendre en charge le paiement Paypal, elle propose également des plans de mise à niveau, des cartes de crédit, des informations client, etc. Une série complète de gestion, plus pratique à utiliser ; le deuxième ensemble d'interfaces REST de Paypal intègre en fait la plupart de ces fonctions, mais le tableau de bord de Paypal ne peut pas gérer directement ces informations mais Braintree le peut, donc je préfère en fait utiliser Braintree. La clé est que le framework backend que j'utilise est Laravel et que sa solution de caisse prend en charge Braintee par défaut, donc cet ensemble d'interfaces est mon premier choix. Mais lorsque j'ai implémenté toutes ses fonctions, j'ai découvert un problème douloureux : Braintree n'est pas supporté en Chine. . . . . . La mort. . .

API REST

Il s'agit d'un produit qui s'adapte à l'évolution de l'époque. Si vous avez déjà utilisé OAuth 2.0 et l'API REST, il ne devrait y avoir aucune confusion quand. en regardant ces interfaces.

Ancienne interface

À moins que l'interface de l'API REST ne puisse pas répondre aux exigences, telles que les restrictions de politique, il n'est pas recommandé de l'utiliser. Le monde entier migre vers la méthode d'authentification OAuth 2.0 et la méthode d'utilisation de l'API REST, alors pourquoi aller à contre-courant ? Par conséquent, lorsque l'API REST peut résoudre le problème, je n'ai pas fait de comparaison approfondie de cet ensemble d'interfaces.

Introduction à l'API REST

Il est encore très fastidieux d'ajuster directement ces API. En même temps, nous voulons simplement répondre aux exigences commerciales le plus rapidement possible. au lieu d'entrer dans une compréhension approfondie de l'API.

Alors, comment commencer ? Il est recommandé d'installer directement le PayPal-PHP-SDK officiellement fourni et d'utiliser son Wiki comme point de départ.

Avant de compléter le premier exemple, assurez-vous d'avoir un compte Sandbox et configurez-le correctement :

  • ID client

  • Client Secret

  • API Webhook (doit commencer par https et être le port 443, le

    débogage local est recommandé pour générer l'adresse en combinaison avec le proxy inverse ngrok)

  • Returnurl (notez la même chose que ci-dessus)

  • Paiements Interface de paiement unique, ne ne prend pas en charge les dons récurrents. Le contenu principal du paiement comprend la prise en charge du paiement Paypal, le paiement par carte de crédit, la prise en charge via une carte de crédit enregistrée (nécessite l'utilisation de l'interface Vault, une telle interface est principalement due aux exigences PCI, les sites Web généraux ne sont pas autorisés à collecter des informations sensibles sur les cartes de crédit), et prend en charge le paiement à des tiers.

  • Paiements Non utilisé, ignorer

  • Autorisation et Capture prend en charge la connexion à votre site Web directement via votre compte Paypal et obtient des informations pertinentes

  • Vente Suivre pertinent ; au centre commercial, non utilisé, ignorer ;

  • Commande Pertinent pour le centre commercial, non utilisé, ignoré ;

  • Plan de facturation et accords Plans et contrats de mise à niveau, c'est-à-dire les fonctions d'abonnement, vous devez utiliser les fonctions ici pour obtenir des déductions récurrentes, ce qui est au centre de ce document. article ;

  • Coffre-fort Stocker les informations de carte de crédit

  • Paiement ExpérienceNon utilisé, ignorer; Important, mais ce n'est pas l'objet de cet article

  • FactureTraitement des factures ;

    Identité
  • Traitement de l'authentification, réalisation de la connexion OAuth 2.0 et obtention du jeton correspondant pour demander d'autres API. Ce Paypal-PHP-SDK possède. ont déjà été mises en œuvre et ne seront pas abordées dans cet article.

  • Comment mettre en place les déductions récurrentes
  • En quatre étapes :

    Créez un plan de mise à niveau et activez-le ;
    Créez un abonnement (créez un accord), puis accédez au site Web de Paypal pour attendre l'approbation de l'utilisateur

    Après l'accord de l'utilisateur, exécutez l'abonnement

    1. Obtenir la facture de débit

    2. 1 Créer une mise à niveau. planifier
    3. Le plan de mise à niveau correspond à la classe Plan. Il y a plusieurs points à noter dans cette étape :

      • Une fois le plan de mise à niveau créé, il est dans l'état CRÉÉ et doit être changé en ACTIF avant de pouvoir être utilisé normalement.

      • Le plan a deux objets, PaymentDefinition et MerchantPreferences, qui ne peuvent pas tous deux être vides

      • Si vous souhaitez créer un plan de type TRIAL, Le plan doit également avoir une définition de paiement REGULIER correspondante, sinon une erreur sera signalée

      • En regardant le code, une méthode setSetupFee (très, très, très importante) est appelée, qui fixe la réalisation de l'abonnement. Les frais pour le premier débit suivant, tandis que la méthode de déduction récurrente de l'objet du Contrat fixe les frais au début de la deuxième fois.

      Prenons comme exemple la création d'un plan Standard. Ses paramètres sont les suivants :

      $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"
       ];

      Le code pour créer et activer le plan est le suivant :

       //上面的$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. Créez un abonnement (créez un accord), puis accédez au site Web de Paypal pour attendre le consentement de l'utilisateur

      Une fois le plan terminé. créé, comment permettre aux utilisateurs de s'abonner ? En fait, il s'agit de créer un accord. Concernant l'accord, il y a les points suivants à noter :

      • Comme mentionné précédemment, la méthode setSetupFee du. L'objet Plan fixe les frais pour la première déduction après avoir terminé l'abonnement, et l'objet Accord La méthode de déduction récurrente fixe le coût au début de la deuxième fois.

      • La méthode setStartDate définit l'heure de la deuxième déduction, donc si vous faites du vélo sur une base mensuelle, ce devrait être l'heure actuelle plus un mois. En même temps, cette méthode nécessite. que le format de l'heure est au format ISO8601, peut être facilement résolu en utilisant la bibliothèque Carbon

      • Lors de la création de l'accord, l'identifiant unique n'avait pas encore été généré, j'ai donc rencontré une petite difficulté : c'est à ce moment-là que l'utilisateur termine l'abonnement, comment savoir à quel utilisateur appartient cet abonnement ? Le jeton dans l'URL obtenu via la méthode getApprovalLink de l'accord est unique. J'extrait le jeton comme méthode d'identification et je le remplace par le véritable identifiant une fois que l'utilisateur a terminé l'abonnement.

      Les exemples de paramètres sont les suivants :

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

      Le code est le suivant :

       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,等待用户同意
       }

      La fonction renvoie $approvalUrl après l'exécution. N'oubliez pas d'accéder au site Web de Paypal via la redirection ($approvalUrl) pour attendre le paiement de l'utilisateur.

      Après l'accord de l'utilisateur, exécutez l'abonnement

      Après l'accord de l'utilisateur, l'abonnement n'est pas terminé et la méthode d'exécution de l'accord doit être exécuté pour être véritablement complété. La chose importante à noter dans cette étape est que

      • Après avoir finalisé l'abonnement, cela ne signifie pas que le paiement sera déduit, et il peut être retardé de quelques minutes

      • Si la première étape Si les frais setSetupFee sont fixés à 0, la commande ne sera pas générée tant que le délai de déduction récurrent n'est pas écoulé

      Le L'extrait de code est le suivant :

       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;
       }

      Obtenir les enregistrements de transaction

      Après l'abonnement, l'enregistrement de transaction de déduction de transaction peut ne pas être généré immédiatement . S'il est vide, réessayez après quelques minutes. Notes sur cette étape :

       /** 获取交易记录
       * @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() ;
       }
      Enfin, bien sûr, Paypal dispose également d'un tutoriel officiel correspondant, mais il appelle l'interface native. La différence avec le processus ci-dessus est qu'il ne parle que des 3 premières étapes.

      Problèmes à prendre en compte

      La fonction a été implémentée, mais de nombreux points d'attention ont également été trouvés :

      • La connexion est spéciale lors de l'utilisation du test Sandbox en Chine Lent, provoquant souvent un délai d'attente ou une erreur, une attention particulière doit donc être accordée à la situation dans laquelle l'utilisateur ferme la page pendant l'exécution

      • Assurez-vous d'implémenter le webhook, sinon lorsque l'utilisateur annule l'abonnement dans Paypal, votre site Web ne recevra aucune notification
      • Une fois qu'un abonnement (accord) est généré, il le sera ; restent en vigueur à moins d’être annulés activement. Par conséquent, si votre site Web est conçu avec plusieurs plans de mise à niveau (tels que Basic, Standard, Advanced), lorsqu'un utilisateur s'est abonné à un plan et passe à un plan de mise à niveau, le plan de mise à niveau précédent doit être annulé pendant le développement
      • L'utilisateur accepte de s'abonner - (annuler l'ancien abonnement - terminer la signature du nouvel abonnement -
      • modifier les informations de l'utilisateur
      • pour le nouvel abonnement), l'ensemble du processus de parenthèses devrait être une opération atomique, et elle prend du temps et est longue. Par conséquent, elle doit être placée dans la

        file d'attente et exécutée jusqu'à ce qu'elle réussisse, ce qui offrira une meilleure expérience.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn