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