Obsługa płatności za pomocą Stripe w php
W artykule pokażę jak obsłużyć płatności online za pomocą Stripe. Najpierw należy zarejestrować się na powyższej stronie. Po zalogowaniu na stronie dashboard.stripe.com będziemy mogli podglądać testowe płatności. Ponadto klikając na " Get your test API keys" zobaczymy nasze developerskie klucze api, które będą nam potrzebne.
composer require stripe/stripe-phpPobierze nam ono bibliotekę do obsługi płatności Stripe w php. Zanim przejdziemy do właściwego kodu projektu wykonajmy testowy request do api. Utwórz zatem dowolny plik php z następującą treścią.
require_once('vendor/autoload.php'); \Stripe\Stripe::setApiKey('twoj_secret_key'); $intent = \Stripe\PaymentIntent::create([ 'amount' => 25.00*100, 'currency' => 'gbp', 'payment_method_types' => ['card'], 'receipt_email' => '[email protected]', ]); echo '<pre>'; print_r($intent);Stripe powinien zwrócić obiekt PaymentIntent w odpowiedzi na żądanie API (spójrz na poniższy listing).
{ "id": "pi_1DRuHnHgsMRlo4MtwuIAUe6u", "object": "payment_intent", "amount": 1000, "amount_capturable": 0, "amount_received": 0, "application": null, "application_fee_amount": null, "canceled_at": null, "cancellation_reason": null, "capture_method": "automatic", "charges": { "object": "list", "data": [], "has_more": false, "total_count": 0, "url": "/v1/charges?payment_intent=pi_1DRuHnHgsMRlo4MtwuIAUe6u" }, "client_secret": "{{PAYMENT_INTENT_CLIENT_SECRET}}", "confirmation_method": "automatic", "created": 1556123069, "currency": "usd", "customer": null, "description": null, "invoice": null, "last_payment_error": null, "livemode": false, "metadata": {}, "next_action": null, "on_behalf_of": null, "payment_method": null, "payment_method_types": [ "card" ], "receipt_email": "[email protected]", "review": null, "shipping": null, "source": null, "statement_descriptor": null, "status": "requires_payment_method", "transfer_data": null, "transfer_group": null }Teraz przejdziemy do właściwego projektu. Utwórzmy plik start.html z następującą zawartością.
<html> <head> <!-- The Styling File --> <link rel="stylesheet" href="./style.css"/> </head> <body> <div class="form-row"> <label for="card-element">Credit or debit card</label> <input id="cardholder-name" type="text"> <!-- placeholder for Elements --> <div id="card-element"></div> <button id="card-button">Submit Payment</button> <!-- Used to display form errors --> <div id="card-errors"></div> </div> <!-- The needed JS files --> <!-- JQUERY File --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <!-- Stripe JS --> <script src="https://js.stripe.com/v3/"></script> <!-- Your JS File --> <script src="./charge2.js"></script> </body> </html>Jak widać zaciągamy w nim style, jquery oraz javascriptową bibliotekę stripe. Ponadto w kodzie umieszczamy kilka divów, w których wyświetlane będą odpowiednie informacje np. #card-element i #card-errors. Ponadto mamy link do pliku js charge2.js, którego treść poniżej.
var stripe = Stripe('twoj_public_key'); var elements = stripe.elements(); // Set up Stripe.js and Elements to use in checkout form var style = { base: { color: '#32325d', lineHeight: '24px', fontFamily: '"Helvetica Neue", Helvetica, sans-serif', fontSmoothing: 'antialiased', fontSize: '16px', '::placeholder': { color: '#aab7c4' } }, invalid: { color: '#fa755a', iconColor: '#fa755a' } }; var cardElement = elements.create('card', {style: style, hidePostalCode: true}); cardElement.mount('#card-element'); var cardholderName = document.getElementById('cardholder-name'); var cardButton = document.getElementById('card-button'); cardButton.addEventListener('click', function(ev) { stripe.createPaymentMethod('card', cardElement, { billing_details: {name: cardholderName.value} }).then(function(result) { if (result.error) { // Show error in payment form } else { // Otherwise send paymentMethod.id to your server (see Step 3) fetch('server.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payment_method_id: result.paymentMethod.id }) }).then(function(result) { // Handle server response (see Step 3) result.json().then(function(json) { handleServerResponse(json); }) }); } }); }); function handleServerResponse(response) { if (response.error) { // Show error from server on payment form } else if (response.requires_action) { // Use Stripe.js to handle required card action stripe.handleCardAction( response.payment_intent_client_secret ).then(function(result) { if (result.error) { // Show error in payment form } else { // The card action has been handled // The PaymentIntent can be confirmed again on the server fetch('server.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payment_intent_id: result.paymentIntent.id }) }).then(function(confirmResult) { return confirmResult.json(); }).then(handleServerResponse); } }); } else { // Show success message console.log('Success'); } }Korzystamy tu z instancji obiektu Stripe, któremu przekazujemy nasz klucz publiczny api. Następnie podczepiamy się pod element card-element. Będą się tam wyświetlać pola na wpisanie nr karty itd. W funkcji handleServerResponse potwierdzamy płatność łącząc się do pliku server.php, gdzie wykonujemy kod sprawdzający po stronie serwera.
require_once('vendor/autoload.php'); \Stripe\Stripe::setApiKey('twoj_secret_key'); header('Content-Type: application/json'); # retrieve json from POST body $json_str = file_get_contents('php://input'); $json_obj = json_decode($json_str); $intent = null; try { if (isset($json_obj->payment_method_id)) { # Create the PaymentIntent $intent = \Stripe\PaymentIntent::create([ 'payment_method' => $json_obj->payment_method_id, 'amount' => 1095, 'currency' => 'gbp', 'confirmation_method' => 'manual', 'confirm' => true, ]); } if (isset($json_obj->payment_intent_id)) { $intent = \Stripe\PaymentIntent::retrieve( $json_obj->payment_intent_id ); $intent->confirm(); } generateResponse($intent); } catch (\Stripe\Exception\ApiErrorException $e) { # Display error on client echo json_encode([ 'error' => $e->getMessage() ]); } function generateResponse($intent) { # Note that if your API version is before 2019-02-11, 'requires_action' # appears as 'requires_source_action'. if ($intent->status == 'requires_action' && $intent->next_action->type == 'use_stripe_sdk') { # Tell the client to handle the action echo json_encode([ 'requires_action' => true, 'payment_intent_client_secret' => $intent->client_secret ]); } else if ($intent->status == 'succeeded') { # The payment didn’t need any additional actions and completed! # Handle post-payment fulfillment echo json_encode([ "success" => true ]); } else { # Invalid status http_response_code(500); echo json_encode(['error' => 'Invalid PaymentIntent status']); } }Ważną informacją jest to, że kwoty w Stripe podawane są jako liczby typu int. Dlatego aby pobrać np. kwotę 10.95 GBP jako amount musimy podać 1095. Poniżej zamieszczam również kod pliku style.css
.StripeElement { background-color: white; padding: 8px 12px; border-radius: 4px; border: 1px solid transparent; box-shadow: 0 1px 3px 0 #e6ebf1; -webkit-transition: box-shadow 150ms ease; transition: box-shadow 150ms ease; } .StripeElement--focus { box-shadow: 0 1px 3px 0 #cfd7df; } .StripeElement--invalid { border-color: #fa755a; } .StripeElement--webkit-autofill { background-color: #fefde5 !important; }