Maison >développement back-end >tutoriel php >Exemple de partage de code pour Paypal afin de mettre en œuvre la fonction de déduction récurrente (abonnement)
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
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 :débogage local est recommandé pour générer l'adresse en combinaison avec le proxy inverse ngrok)
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é
En quatre étapes :
Créez un plan de mise à niveau et activez-le ;Après l'accord de l'utilisateur, exécutez l'abonnement
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
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 :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!