Integrasi Web Stripe Apple Pay dengan Contoh

oleh Vincy. Terakhir diubah pada 7 Desember 2021.

Mengintegrasikan pembayaran Stripe Apple ke dalam aplikasi web itu mudah. Diperlukan beberapa langkah untuk mencapai integrasi ini. Artikel ini menunjukkan cara mengaktifkan opsi pembayaran Apple atau Google menggunakan Stripe.

Kita bisa membagi artikel ini menjadi 2 bagian. Ini menceritakan item tindakan, prasyarat, dan kode untuk integrasi pembayaran.

  1. Mempersiapkan lingkungan web Anda untuk menampilkan opsi permintaan pembayaran.
  2. Membangun contoh PHP untuk integrasi Stripe Apple Pay.

Jika Anda baru mengenal integrasi pembayaran Stripe, periksa dengan artikel tertaut. Ini menjelaskan cara mendapatkan kredensial aplikasi Stripe API dan pengetahuan dasar lainnya.

Tentang Elemen Tombol Permintaan Pembayaran Stripe

Metode pembayaran ini mengumpulkan detail dari pelanggan yang menggunakan Stripe Apple Pay dialog. Kami telah melihat cara mengumpulkan pembayaran berulang menggunakan langganan Stripe.

Metode Tombol Permintaan Pembayaran Stripe memasang kontrol UI untuk memungkinkan pembayaran. Ini adalah satu titik integrasi untuk Apple Pay, Google Pay, dan Microsoft Pay.

Dengan mencentang daftar prasyarat dalam dokumentasi, kita dapat melihat salah satu tombol di bawah ini di UI.

pembayaran apel garis

1. Mempersiapkan lingkungan web Anda untuk menampilkan opsi permintaan pembayaran

Bagian ini akan memberi tahu langkah-langkah untuk menampilkan pembayaran apel Stripe. Di Chrome atau Microsoft edge, ini akan menampilkan tombol permintaan pembayaran lainnya di antarmuka web.

  1. Pastikan domain tersebut mengaktifkan HTTPS.
  2. Biarkan domain melewati proses verifikasi pembayaran Apple.
  3. Simpan kartu atau metode pembayaran lainnya ke browser. Spesifikasinya bervariasi berdasarkan metode pembayaran dan browser.

Bagaimana cara memverifikasi domain dengan Apple Pay?

Ikuti langkah-langkah di bawah ini untuk menampilkan tombol pembayaran Stripe Apple di antarmuka Anda.

  1. Unduh dan letakkan file asosiasi domain di jalur berikut dari root web Anda. /.well-known/apple-developer-merchantid-domain-association.
  2. Permintaan untuk membuat domain Stripe Apple Pay. Ini dapat dilakukan dengan salah satu metode di bawah ini.
    • Dengan menavigasi ke tab Stripe Apple Pay di Pengaturan Akun Dasbor Anda.
    • Dengan menggunakan API dengan kunci rahasia langsung Anda.
  3. Gunakan kunci API untuk melakukan pembayaran melalui situs web yang terdaftar di Apple Pay Stripe.

Catatan: Tidak perlu membuat id pedagang Apple atau membuat permintaan penandatanganan sertifikat (CSR). Stripe akan menangani ini di bagian belakang.

Permintaan API untuk membuat domain Stripe Apple Pay

Skrip PHP berikut menunjukkan cara membuat API Stripe.


StripeStripe::setApiKey("STRIPE SECRET KEY HERE");

StripeApplePayDomain::create([
  'domain_name' => 'example.com',
]);

2. Membangun contoh PHP untuk integrasi pembayaran Stripe Apple

Ini adalah langkah-langkah untuk mengintegrasikan Stripe Apple pay dalam aplikasi web PHP. Beberapa di bawah ini serupa seperti yang telah kita lihat dalam contoh integrasi gateway pembayaran Stripe.

  1. Unduh klien API Stripe.
  2. Konfigurasikan kunci dan token API Stripe.
  3. Verifikasi permintaan pembayaran dan pasang tombol pembayaran Stripe Apple.
  4. Minta dan Konfirmasi pembayaran.
  5. Menangani acara perubahan alamat pengiriman/pengiriman.
  6. Membuat titik akhir PHP untuk mempersiapkan dan memulai permintaan API Stripe.

Unduh klien Stripe

Unduh klien API stripe PHP dan tambahkan dalam ketergantungan aplikasi. Ini akan membantu untuk membuat objek AppleDomain dan PaymentIntent melalui API.

Ini tersedia di Github. Anda dapat menginstal ini melalui komposer juga. Perintah untuk menginstal perpustakaan Stripe-PHP adalah,


composer require stripe/stripe-php

Konfigurasikan kunci dan token API Stripe

Ini adalah file konfigurasi aplikasi web. Ini termasuk kunci yang digunakan untuk mengakses API permintaan pembayaran untuk integrasi pembayaran Stripe Apple.

Ini juga berisi root aplikasi web dan URL titik akhir pembayaran atau pesanan. Ini mendefinisikan detail Produk dan jumlah pengiriman untuk membangun permintaan pembayaran.

Umum/config.php


<?php
namespace Phppot;

class Config
{

    const ROOT_PATH = "http://localhost/stripe-apple-pay";

    /* Stripe API test keys */

    const STRIPE_PUBLISHIABLE_KEY = "";

    const STRIPE_SECRET_KEY = "";
    
    const STRIPE_WEBHOOK_SECRET = "";
    
    const RETURN_URL = Config::ROOT_PATH . "/success.php";


    /* PRODUCT CONFIGURATIONS BEGINS */

    const PRODUCT_NAME = 'A6900 MirrorLess Camera';

    const PRODUCT_IMAGE = Config::ROOT_PATH . '/images/camera.jpg';

    const PRODUCT_PRICE = '289.61';

    const CURRENCY = 'usd';
    
    const US_SHIPPING = 7;
    
    const UK_SHIPPING = 12;
}


Verifikasi permintaan pembayaran dan pasang tombol pembayaran Stripe Apple

Index.php adalah halaman arahan yang berisi ubin produk. Ini memiliki wadah untuk memasang tombol bayar Stripe Apple.

Elemen HTML memiliki atribut data untuk memiliki konfigurasi pembayaran.

Dalam mengimpor perpustakaan Stripe.js dan file payment.js dibuat untuk contoh ini.

index.php


<?php
namespace Phppot;

require_once __DIR__ . '/Common/Config.php';
?>
<html>
<title>Stripe Apple Pay integration</title>
<head>
<link href="https://phppot.com/php/stripe-apple-pay/assets/css/style.css" type="text/css" rel="stylesheet" />
</head>
<body>
	<div class="phppot-container">
		<h1>Stripe Apple Pay integration</h1>
		<div id="payment-box" data-pk="<?php echo Config::STRIPE_PUBLISHIABLE_KEY; ?>" data-return-url="<?php echo Config::RETURN_URL; ?>">
			<input type="hidden" id="unit-price" value="<?php echo Config::PRODUCT_PRICE; ?>" />
			<input type="hidden" id="product-label" value="<?php echo Config::PRODUCT_NAME; ?>" />
			<input type="hidden" id="currency" value="<?php echo Config::CURRENCY; ?>" />
			<input type="hidden" id="shipping-amount" value="<?php echo Config::US_SHIPPING; ?>" />
			<img src="<?php echo Config::PRODUCT_IMAGE; ?>" />
			<h4 class="txt-title"><?php echo Config::PRODUCT_NAME; ?></h4>
			<div class="txt-price">$<?php echo Config::PRODUCT_PRICE; ?></div>
		</div>
		
		<!-- Element target to render Stripe apple pay button -->
		<div id="payment-request-button">
			<!-- A Stripe Element will be inserted here. -->
		</div>
	</div>
	<script src="https://js.stripe.com/v3/"></script>

	<script src="assets/js/payment.js"></script>
</body>
</html>

Ini adalah sebagian kode dari file payment.js. Ini menunjukkan skrip yang diperlukan untuk merender tombol pembayaran Stripe Apple ke UI. Itu membangun objek permintaan pembayaran Stripe dengan menggunakan detail berikut.

  • Detail pelanggan: nama, email, alamat.
  • Jumlah
  • Mata uang
  • Rincian pengiriman: jumlah, deskripsi.

Data untuk detail ini berasal dari file konfigurasi. HTML formulir pembayaran berisi bidang tersembunyi dan atribut data untuk menyimpan konfigurasi. Skrip ini menggunakan atribut data dan data tersembunyi untuk menyiapkan permintaan.

Setelah menyiapkan badan permintaan, ia memanggil canMakePayment() untuk memverifikasi paymentRequest obyek. Setelah diverifikasi, maka itu akan membuat tombol bayar Apple di UI.

aset/js/pembayaran.js


var publishableKey = document.querySelector('#payment-box').dataset.pk;
var returnURL = document.querySelector('#payment-box').dataset.returnUrl;
var unitPrice = document.querySelector('#unit-price').value;
unitPrice = Math.round((unitPrice * 100));
var productLabel = document.querySelector('#product-label').value;
var currency = document.querySelector('#currency').value;
var shippingAmount = document.querySelector('#shipping-amount').value;
shippingAmount = Math.round((shippingAmount * 100));

var stripe = Stripe(publishableKey, {
	apiVersion: "2020-08-27",
});
var paymentRequest = stripe.paymentRequest({
	country: 'US',
	currency: currency,
	total: {
		label: productLabel,
		amount: unitPrice,
	},
	requestPayerName: true,
	requestPayerEmail: true,
	requestShipping: true,
	shippingOptions: [
		{
			id: 'Default Shipping',
			label: 'Default Shipping',
			detail: '',
			amount: shippingAmount,
		},
	],
});

var elements = stripe.elements();
var prButton = elements.create('paymentRequestButton', {
	paymentRequest: paymentRequest,
});

// Verify payment parameters with the the Payment Request API.
paymentRequest.canMakePayment().then(function(result) {
	if (result) {
		prButton.mount('#payment-request-button');
	} else {
		document.getElementById('payment-request-button').style.display = 'none';
	}
});

Minta dan Konfirmasi pembayaran

Bagian ini berisi sisa kode payment.js. Itu membuat objek paymentIntent dengan mengklik tombol ‘bayar’ pada overlay pembayaran.

Setelah paymentIntent dibuat, titik akhir mengembalikan kunci rahasia klien. Kemudian, skrip memanggil stripe.confirmCardPayment dengan referensi kunci rahasia klien.

aset/js/pembayaran.js


paymentRequest.on('paymentmethod', function(ev) {
	//Create Stripe payment intent
	var requestParam = {
		email: ev.payerEmail,
		unitPrice: unitPrice,
		currency: currency,
		name: ev.payerName,
		address: ev.shippingAddress.addressLine[0],
		country: ev.shippingAddress.country,
		postalCode: ev.shippingAddress.postalCode,
		shippingPrice: ev.shippingOption.amount,
	};
	var createOrderUrl = "ajax-endpoint/create-stripe-order.php";
	fetch(createOrderUrl, {
		method: "POST",
		headers: {
			"Content-Type": "application/json"
		},
		body: JSON.stringify(requestParam)
	}).then(function(result) {
		return result.json();
	}).then(function(data) {
		// Script to confirm payment 
		stripe.confirmCardPayment(
			data.clientSecret,
			{ payment_method: ev.paymentMethod.id },
			{ handleActions: false }
		).then(function(confirmResult) {
			if (confirmResult.error) {
				// Report to the browser that the payment failed, prompting it to
				// re-show the payment interface, or show an error message and close
				// the payment interface.
				ev.complete('fail');
			} else {
				// Report to the browser that the confirmation was successful, prompting
				// it to close the browser payment method collection interface.
				ev.complete('success');
				// Check if the PaymentIntent requires any actions and if so let Stripe.js
				// handle the flow. If using an API version older than "2019-02-11" instead
				// instead check for: `paymentIntent.status === "requires_source_action"`.
				if (confirmResult.paymentIntent.status === "requires_action") {
					// Let Stripe.js handle the rest of the payment flow.
					stripe.confirmCardPayment(clientSecret).then(function(result) {
						if (result.error) {
							// The payment failed -- ask your customer for a new payment method.
						} else {
							// The payment has succeeded.
							window.location.replace(returnURL + "?orderno=" + data.orderHash);
						}
					});
				} else {
					// The payment has succeeded.
					window.location.replace(returnURL + "?orderno=" + data.orderHash);
				}
			}
		});
	});
});

Menangani pengiriman/pengiriman acara perubahan alamat

Bagian ini berkaitan dengan opsi pengiriman pada acara perubahan. Kode ini hanya berlaku jika objek pembayaran diaktifkan dengan opsi pengiriman.

Itu menyentuh titik akhir PHP melalui AJAX dan membuat JSON mengubah opsi pengiriman. Ini melewati alamat pengiriman yang dipilih ke PHP.

aset/js/pembayaran.js


paymentRequest.on('shippingaddresschange', function(ev) {
	// Perform server-side request to fetch shipping options
	fetch('ajax-endpoint/calculate-product-shipping.php', {
		method: "POST",
		headers: {
			"Content-Type": "application/json"
		},
		body: JSON.stringify({
			adress: ev.shippingAddress
		})
	}).then(function(response) {
		return response.json();
	}).then(function(result) {
		ev.updateWith({
			status: 'success',
			shippingOptions: result.shippingOptions,
		});
	});
});

Ini adalah file titik akhir PHP yang membaca data pengiriman yang dikirim melalui AJAX. Ini mem-parsing data pengiriman dan mendapatkan negara darinya.

Ini menggunakan jumlah pengiriman yang sesuai dari konfigurasi berdasarkan negara. Anda dapat memasukkan perhitungan pengiriman tambahan Anda di sini jika diperlukan.

Ini mengembalikan respons JSON dengan alamat pengiriman dan jumlah yang sesuai.

ajax-endpoint/calculate-product-shipping.php


<?php
require_once __DIR__ . '/../Common/Config.php';

$content = trim(file_get_contents("php://input"));

$jsondecoded = json_decode($content, true);
$country = filter_var($jsondecoded["adress"]["country"], FILTER_SANITIZE_STRING);
if ($country == 'UK') {
    $shippingAmount = Config::UK_SHIPPING;
} else {
    $shippingAmount = Config::US_SHIPPING;
}

$shippingOptions = array(
    "shippingOptions" => array(
        array(
            "id" => 'Edited shipping',
            'label' => "Shipping Costs based on Country",
            'detail' => $detail,
            'amount' => $shippingAmount
        )
    )
);

echo json_encode($shippingOptions);
exit();

?>

Membuat titik akhir PHP untuk mempersiapkan dan memulai permintaan API Stripe

File PHP di bawah ini berisi kode sisi server yang mengenai API. Itu membaca badan permintaan dan membuat objek pembayaran saat mengirim permintaan pembayaran apel Stripe.

File StripeService.php menyetel kunci rahasia API ke objek Stripe. Ini berisi fungsi captureResponse() fungsi yang memperbarui pesanan dan entitas pembayaran.

Stripe memanggil titik akhir webhook seperti yang dikonfigurasi di config.php. Titik akhir ini membaca respons Stripe. Kemudian, ia memanggil fungsi captureResponse() untuk memperbarui database.

Titik akhir PHP AJAX untuk membuat pesanan

ajax-endpoint/create-stripe-order.php


<?php
namespace Phppot;

use PhppotStripeService;
use PhppotStripePayment;
require_once __DIR__ . '/../Common/Config.php';

$content = trim(file_get_contents("php://input"));

$jsondecoded = json_decode($content, true);

if (! empty($jsondecoded)) {
    require_once __DIR__ . "/../lib/StripeService.php";
    $stripeService = new StripeService();

    $email = filter_var($jsondecoded["email"], FILTER_SANITIZE_EMAIL);
    $name = filter_var($jsondecoded["name"], FILTER_SANITIZE_STRING);
    $address = filter_var($jsondecoded["address"], FILTER_SANITIZE_STRING);
    $country = filter_var($jsondecoded["country"], FILTER_SANITIZE_STRING);
    $postalCode = filter_var($jsondecoded["postalCode"], FILTER_SANITIZE_STRING);
    $notes="Stripe Apple Pay Payment";
    $currency = filter_var($jsondecoded["currency"], FILTER_SANITIZE_STRING);
    $orderReferenceId = $stripeService->getToken();
    $unitPrice = ($jsondecoded["unitPrice"] + $jsondecoded["shippingPrice"]);
    $orderStatus = "Pending";
    $paymentType = "stripe";
    $customerDetailsArray = array(
        "email" => $email,
        "name" => $name,
        "address" => $address,
        "country" => $country,
        "postalCode" => $postalCode
    );
    $metaData = array(
        "email" => $email,
        "order_id" => $orderReferenceId
    );

    require_once __DIR__ . '/../lib/StripePayment.php';
    $stripePayment = new StripePayment();

    $orderId = $stripePayment->insertOrder($orderReferenceId, $unitPrice, $currency, $orderStatus, $name, $email);
    $result = $stripeService->createPaymentIntent($orderReferenceId, $unitPrice, $currency, $email, $customerDetailsArray, $notes, $metaData);

    if (! empty($result) && $result["status"] == "error") {
        http_response_code(500);
    }
    $response = json_encode($result["response"]);
    echo $response;
    exit();
}

Titik akhir webhook pembayaran apel garis

webhook-ep/capture-response.php


<?php
namespace Phppot;

use PhppotStriService;

require_once __DIR__ . "/../lib/StripeService.php";

$stripeService = new StripeService();

$stripeService->captureResponse();

?>

Layanan Stripe dengan penangan permintaan-tanggapan

lib/StripeService.php


<?php
namespace Phppot;

use PhppotStripePayment;
use StripeStripe;
use StripeWebhookEndpoint;
require_once __DIR__ . '/../vendor/autoload.php';

class StripeService
{

    private $apiKey;
    
    private $webhookSecret;

    private $stripeService;

    function __construct()
    {
        require_once __DIR__ . '/../Common/Config.php';
        $this->apiKey = Config::STRIPE_SECRET_KEY;
        $this->webhookSecret = Config::STRIPE_WEBHOOK_SECRET;
        $this->stripeService = new Stripe();
        $this->stripeService->setVerifySslCerts(false);
    }

    public function createPaymentIntent($orderReferenceId, $amount, $currency, $email, $customerDetailsArray, $notes, $metaData)
    {
        try {
            $this->stripeService->setApiKey($this->apiKey);

            $paymentIntent = StripePaymentIntent::create([
                'description' => $notes,
                'shipping' => [
                    'name' => $customerDetailsArray["name"],
                    'address' => [
                        'line1' => $customerDetailsArray["address"],
                        'postal_code' => $customerDetailsArray["postalCode"],
                        'country' => $customerDetailsArray["country"]
                    ]
                ],
                'amount' => $amount,
                'currency' => $currency,
                'payment_method_types' => [
                    'card'
                ],
                'metadata' => $metaData
            ]);
            $output = array(
                "status" => "success",
                "response" => array(
                    'orderHash' => $orderReferenceId,
                    'clientSecret' => $paymentIntent->client_secret
                )
            );
        } catch (Error $e) {
            $output = array(
                "status" => "error",
                "response" => $e->getMessage()
            );
        }
        return $output;
    }

    public function captureResponse()
    {
        $payload = @file_get_contents('php://input');

        $sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
        $event = null;
        try {
            $event = StripeWebhook::constructEvent($payload, $sig_header, $this->webhookSecret);
        } catch (UnexpectedValueException $e) {
            // Invalid payload
            http_response_code(400);
            exit();
        } catch (StripeExceptionSignatureVerificationException $e) {
            // Invalid signature
            http_response_code(400);
            exit();
        }

        if (! empty($event)) {

            $eventType = $event->type;

            $orderReferenceId = $event->data->object->metadata->order_id;
            $paymentIntentId = $event->data->object->id;
            $amount = $event->data->object->amount;
            
            require_once __DIR__ . '/../lib/StripePayment.php';
            $stripePayment = new StripePayment();
            
            if ($eventType == "payment_intent.payment_failed") {
                $orderStatus="Payement Failure";

                $paymentStatus="Unpaid";

                $amount = $amount / 100;

                $stripePayment->updateOrder($paymentIntentId, $orderReferenceId, $orderStatus, $paymentStatus);
                $stripePayment->insertPaymentLog($orderReferenceId, $payload);
            }
            if ($eventType == "payment_intent.succeeded") {
                /*
                 * Json values assign to php variables
                 *
                 */
                $orderStatus="Completed";

                $paymentStatus="Paid";

                $amount = $amount / 100;

                $stripePayment->updateOrder($paymentIntentId, $orderReferenceId, $orderStatus, $paymentStatus);
                $stripePayment->insertPaymentLog($orderReferenceId, $payload);

                http_response_code(200);
            }
        }
    }
}

Memperbarui pesanan dan pembayaran dalam database

lib/StripePayment.php


<?php
namespace Phppot;

use PhppotDataSource;

class StripePayment
{

    private $ds;

    function __construct()
    {
        require_once __DIR__ . "/../lib/DataSource.php";
        $this->ds = new DataSource();
    }

    public function insertOrder($orderReferenceId, $unitAmount, $currency, $orderStatus, $name, $email)
    {
        $orderAt = date("Y-m-d H:i:s");

        $insertQuery = "INSERT INTO tbl_order(order_reference_id, amount, currency, order_at, order_status, billing_name, billing_email) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ";

        $paramValue = array(
            $orderReferenceId,
            $unitAmount,
            $currency,
            $orderAt,
            $orderStatus,
            $name,
            $email
        );

        $paramType = "sdssssss";
        $insertId = $this->ds->insert($insertQuery, $paramType, $paramValue);
        return $insertId;
    }

    public function updateOrder($paymentIntentId, $orderReferenceId, $orderStatus, $paymentStatus)
    {   
        $query = "UPDATE tbl_order SET stripe_payment_intent_id = ?, order_status = ?, payment_status = ? WHERE order_reference_id = ?";

        $paramValue = array(
            $paymentIntentId,
            $orderStatus,
            $paymentStatus,
            $orderReferenceId
        );

        $paramType = "ssss";
        $this->ds->execute($query, $paramType, $paramValue);
    }

    public function insertPaymentLog($orderReferenceId, $response)
    {
        $insertQuery = "INSERT INTO tbl_stripe_payment_log(order_id, stripe_payment_response) VALUES (?, ?) ";

        $paramValue = array(
            $orderReferenceId,
            $response
        );

        $paramType = "ss";
        $this->ds->insert($insertQuery, $paramType, $paramValue);
    }
}
?>

Keluaran Pembayaran Apple Stripe

Tangkapan layar di bawah ini menunjukkan ubin produk dengan tombol pembayaran Stripe Apple. Detailnya dinamis dari konfigurasi aplikasi web.

integrasi pembayaran apel garis

Dengan mengklik tombol Bayar Stripe Apple di ubin di atas, dialog pembayaran berikut akan muncul. Ini akan memiliki opsi untuk melanjutkan pembayaran dengan menggunakan id sentuh Apple.

formulir pembayaran apel garis

Kesimpulan

Jadi, kami telah mengintegrasikan pembayaran Stripe Apple dalam aplikasi web menggunakan PHP. Kami menggunakan Tombol Permintaan Pembayaran Stripe untuk menampilkan opsi pembayaran Apple di UI.

Kami telah melihat pra-syarat dan langkah-langkah konfigurasi yang diperlukan untuk integrasi ini. Saya harap, kode contoh membantu untuk memahami langkah-langkahnya dengan mudah.
Unduh

Kembali ke Atas


Source link