Modern websites connect to external services through their APIs. You send an HTTP request (usually JSON) with a secret key, and the service does the specialised work.
Payment gateways
A payment gateway securely takes card or wallet payments. Your site should never receive or store card numbers; the gateway's hosted page handles them (this keeps you out of the heaviest PCI-DSS obligations). Popular gateways include PayHere (widely used in Sri Lanka), Stripe, PayPal, and local bank gateways. All provide a sandbox (test mode) with fake cards.
Typical hosted-checkout flow
Illustrative PayHere-style form (check the gateway's current documentation for the exact field names and hash formula; the steps below are the same for any gateway):
<?php
$merchantId = getenv('PAYHERE_MERCHANT_ID'); // from environment/config, never from the browser
$merchantSecret = getenv('PAYHERE_SECRET');
$orderId = $order['id'];
$amount = number_format($order['total'], 2, '.', '');
$currency = 'LKR';
$hash = strtoupper(md5($merchantId . $orderId . $amount . $currency . strtoupper(md5($merchantSecret))));
?>
<form method='post' action='https://sandbox.payhere.lk/pay/checkout'>
<input type='hidden' name='merchant_id' value='<?= $merchantId ?>'>
<input type='hidden' name='return_url' value='https://yourshop.com/order_success.php'>
<input type='hidden' name='cancel_url' value='https://yourshop.com/cart.php'>
<input type='hidden' name='notify_url' value='https://yourshop.com/payment_notify.php'>
<input type='hidden' name='order_id' value='<?= $orderId ?>'>
<input type='hidden' name='items' value='My Shop order <?= $orderId ?>'>
<input type='hidden' name='currency' value='<?= $currency ?>'>
<input type='hidden' name='amount' value='<?= $amount ?>'>
<input type='hidden' name='hash' value='<?= $hash ?>'>
<!-- plus first_name, last_name, email, phone, address, city, country -->
<button type='submit'>Pay now</button>
</form>Webhook handler (payment_notify.php): the only place an order becomes "paid".
<?php
require 'config/db.php';
// 1. Recompute the signature from the posted fields using YOUR secret (see gateway docs)
// 2. Compare with the signature the gateway sent, using hash_equals
// 3. Confirm the status code means success and the amount equals the order total in YOUR database
// 4. Only then update: UPDATE orders SET status='paid' WHERE id=? AND status='pending'
// 5. Log everything; respond with HTTP 200Payment integration checklist: build and test fully in sandbox; keep keys in environment variables or a config file outside the web root; use HTTPS everywhere; recalculate amounts on the server; make the webhook idempotent (a repeated notification must not process the order twice); store the gateway's transaction id; handle cancel, failure and pending states.
Email integration
PHP's mail() function is unreliable (messages usually land in spam). Use SMTP through a library such as PHPMailer, installed with Composer (composer require phpmailer/phpmailer), and an email provider (your hosting mail server, Gmail SMTP with an app password, SendGrid, Mailgun, Amazon SES).
includes/mail.php:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require __DIR__ . '/../vendor/autoload.php';
function send_mail(string $to, string $subject, string $body): bool {
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = getenv('SMTP_HOST'); // e.g. smtp.gmail.com
$mail->SMTPAuth = true;
$mail->Username = getenv('SMTP_USER');
$mail->Password = getenv('SMTP_PASS');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('[email protected]', 'My Shop');
$mail->addAddress($to);
$mail->Subject = $subject;
$mail->Body = $body; // for HTML mail use isHTML(true)
$mail->send();
return true;
} catch (Exception $e) {
error_log('Mail error: ' . $mail->ErrorInfo);
return false;
}
}Use cases: welcome email, order confirmation with a summary, shipping notification, password reset link, contact form messages to the owner. Never put user-supplied text directly into email headers (header injection); validate the address with filter_var. For better delivery, configure SPF, DKIM and DMARC records in DNS (Unit 14).
Other common integrations
| Service | Purpose |
|---|---|
| Google Maps / OpenStreetMap | Show store locations, delivery addresses |
| SMS gateways | Order alerts and one-time passwords |
| Social login (Google, Facebook OAuth) | "Sign in with Google" |
| reCAPTCHA / hCaptcha | Stop bots on registration, login, contact forms |
| Shipping and courier APIs | Rates and tracking numbers |
| Analytics (Google Analytics) | Traffic and conversion statistics |
| Cloud storage (S3, Cloudinary) | Store and resize product images |
Calling any REST API from PHP with cURL:
$ch = curl_init('https://api.example.com/v1/rates');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . getenv('API_KEY')],
CURLOPT_POSTFIELDS => json_encode(['weight' => 2, 'city' => 'Colombo']),
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);Check yourself. The questions for this part are on the 13.9 Review Questions page, with answers to check your work.