目录

  1. 第一部分:核心概念

    php支付接口开发教程
    (图片来源网络,侵删)
    • 什么是支付接口?
    • 支付流程简介 (同步/异步通知)
    • 理解关键参数 (订单号, 金额, 回调地址等)
  2. 第二部分:准备工作

    • 开通支付宝商家服务
    • 开通微信支付商家服务
    • 获取必要的密钥和配置参数
  3. 第三部分:PHP 环境准备

    • 安装 Composer
    • 引入官方 SDK
  4. 第四部分:实战 - 支付宝网页支付 (电脑端)

    • 步骤 1: 创建订单页面
    • 步骤 2: 调用 SDK 创建支付请求
    • 步骤 3: 处理支付结果 (同步跳转)
    • 步骤 4: 接收和处理异步通知 (最重要!)
    • 步骤 5: 查询订单状态
  5. 第五部分:实战 - 微信扫码支付

    php支付接口开发教程
    (图片来源网络,侵删)
    • 步骤 1: 创建订单并生成支付二维码
    • 步骤 2: 接收和处理异步通知
    • 步骤 3: 查询订单状态
  6. 第六部分:安全最佳实践

    • 验证异步通知的签名
    • 防止重复通知
    • 重要操作使用数据库事务
  7. 第七部分:总结与进阶


第一部分:核心概念

什么是支付接口?

支付接口是第三方支付平台(如支付宝、微信支付)提供给开发者的一套 API,开发者通过调用这些 API,在自己的网站或 App 中集成支付功能,用户无需跳转到支付平台 App 或网站即可完成支付。

支付流程简介

一个标准的支付流程通常如下:

  1. 创建订单: 用户在你的网站点击“支付”,你的服务器生成一个唯一的订单号,并调用支付接口的“创建订单”API。
  2. 用户支付: 支付接口返回一个支付链接或二维码,你的网站将此链接或二维码展示给用户,用户使用支付宝/微信 App 扫描或点击链接完成支付。
  3. 同步跳转: 用户支付成功后,支付平台会根据你配置的 return_url 将用户浏览器同步跳转回你的网站。注意: 这个跳转只告诉用户“支付成功”,绝对不能作为订单最终成功的依据,因为用户可能中途取消,或者网络问题导致跳转失败。
  4. 异步通知: 这是最关键的一步! 支付平台会在用户支付成功后,主动向你在配置的 notify_url 服务器地址发送一个 HTTP POST 请求,这个请求包含了支付结果的详细信息(如订单号、支付金额、交易状态等),你的服务器必须接收并处理这个通知,并验证其签名以确保请求的真实性,验证通过后,更新你数据库中订单的状态为“已支付”。

理解关键参数

  • 订单号 (out_trade_no): 你自己系统里生成的唯一订单 ID,用于后续对账和查询。
  • 总金额 (total_amount): 订单金额,单位通常是,注意精度。
  • 产品码 (product_code): 指定支付方式,如 FAST_INSTANT_TRADE_PAY (网页即时到账)。
  • 异步通知地址 (notify_url): 支付平台用来通知你支付结果的 URL。必须是一个公网可以访问的地址,不能是本地开发地址。
  • 同步跳转地址 (return_url): 支付成功后,用户浏览器跳转回来的 URL。

第二部分:准备工作

支付宝

  1. 注册账号: 访问 支付宝开放平台,注册并完成实名认证。
  2. 创建应用: 在控制台 -> 我的应用 -> 网页应用 & 移动应用 -> 创建应用。
  3. 获取配置信息:
    • APPID: 应用的唯一标识。
    • 应用私钥: 在应用详情的“接口加签方式”处生成。请务必妥善保管,不要泄露!
    • 支付宝公钥: 上传你的应用私钥后,支付宝会生成对应的公钥,你需要下载这个公钥,用于验证异步通知的签名。
    • 签约产品: 在“产品服务”中,找到并签约“网页支付 (alipay.trade.page.pay)”产品。

微信支付

  1. 注册账号: 访问 微信支付商户平台,注册并完成实名认证。
  2. 获取配置信息:
    • 商户号 (mch_id): 商户的唯一标识。
    • API密钥 (32位密钥): 在账户中心 -> API安全 -> API密钥(32位)处设置和获取。请务必妥善保管!
    • AppID: 公众平台或开放平台的 AppID。
    • 证书: 微信支付部分接口需要使用证书,请下载并妥善保管。
    • 签约产品: 在“产品中心”中,找到并开通“Native支付”产品。

第三部分:PHP 环境准备

强烈建议使用 Composer 来管理依赖,这是 PHP 项目的标准做法。

  1. 安装 Composer: 如果你还没有安装,请访问 getcomposer.org 下载并安装。

  2. 引入官方 SDK:

    • 支付宝 SDK:
      composer require alipaysdk/alipay-php-sdk
    • 微信支付 SDK:
      composer require wechatpay/wechatpay

      注意:微信支付官方提供了两个 SDK,一个是 v3 版本(推荐),一个是 v2 版本,这里以较新的 v3 版本为例。


第四部分:实战 - 支付宝网页支付

步骤 1: 创建订单页面 (create_order.php)

这个页面用于展示一个“立即支付”按钮,点击后调用后端接口创建支付请求。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">支付宝支付测试</title>
</head>
<body>
    <h1>订单信息</h1>
    <p>订单号: <?php echo 'ORDER_'.time(); ?></p>
    <p>订单金额: 0.01 元</p>
    <form action="alipay/pay.php" method="post">
        <input type="hidden" name="order_no" value="ORDER_<?php echo time(); ?>">
        <input type="hidden" name="amount" value="0.01">
        <button type="submit">立即使用支付宝支付</button>
    </form>
</body>
</html>

步骤 2: 调用 SDK 创建支付请求 (alipay/pay.php)

<?php
// 引入Composer的自动加载文件
require_once __DIR__ . '/../vendor/autoload.php';
// 引入支付宝配置文件
require_once __DIR__ . '/config.php';
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Util\AES;
// 1. 实例化应用
$alipay = Factory::setOptions([
    'protocol'      => 'https',
    'gatewayUrl'    => 'https://openapi.alipay.com/gateway.do',
    'appId'         => $config['app_id'],
    'signType'      => 'RSA2',
    'alipayPublicKey' => $config['alipay_public_key'],
    'merchantPrivateKey' => $config['merchant_private_key']
])->payment();
// 2. 获取前端传来的订单信息
$orderNo = $_POST['order_no'];
$amount = $_POST['amount'];
// 3. 调用SDK创建支付请求
try {
    $result = $alipay->page()->pay($amount, $orderNo, '商品描述');
    // 4. 直接输出HTML表单,用户提交后会跳转到支付宝支付页面
    echo $result;
} catch (Exception $e) {
    // 处理异常
    echo "创建支付订单失败: " . $e->getMessage();
}

步骤 3: 处理同步跳转 (alipay/return.php)

用户支付成功后,支付宝会跳转到这里。仅用于展示成功页面,不更新订单状态!

<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/config.php';
use Alipay\EasySDK\Kernel\Factory;
$alipay = Factory::setOptions([
    'protocol'      => 'https',
    'gatewayUrl'    => 'https://openapi.alipay.com/gateway.do',
    'appId'         => $config['app_id'],
    'signType'      => 'RSA2',
    'alipayPublicKey' => $config['alipay_public_key'],
    'merchantPrivateKey' => $config['merchant_private_key']
])->payment();
// 1. 获取支付宝GET方式传过来的参数
$bizContent = $_GET['biz_content']; // 这里面包含了 out_trade_no
$data = json_decode($bizContent, true);
$outTradeNo = $data['out_trade_no'];
// 2. 验证签名 (非常重要!)
$verifyResult = $alipay->common()->verifyNotify($_GET);
if ($verifyResult) {
    // 验证成功
    // 这里可以显示一个“支付成功,感谢您的购买!”的页面
    // 但不要在这里更新数据库!
    echo "支付成功!订单号: " . htmlspecialchars($outTradeNo);
} else {
    // 验证失败
    echo '签名验证失败!';
}

步骤 4: 接收和处理异步通知 (alipay/notify.php)

这是支付逻辑的核心!

<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/config.php';
use Alipay\EasySDK\Kernel\Factory;
$alipay = Factory::setOptions([
    'protocol'      => 'https',
    'gatewayUrl'    => 'https://openapi.alipay.com/gateway.do',
    'appId'         => $config['app_id'],
    'signType'      => 'RSA2',
    'alipayPublicKey' => $config['alipay_public_key'],
    'merchantPrivateKey' => $config['merchant_private_key']
])->payment();
// 1. 获取POST过来的通知数据
$notifyData = $_POST;
// 2. 验证签名 (这是保障资金安全的关键!)
$verifyResult = $alipay->common()->verifyNotify($notifyData);
if ($verifyResult) {
    // 3. 验证成功,处理业务逻辑
    $outTradeNo = $notifyData['out_trade_no']; // 商户订单号
    $tradeNo = $notifyData['trade_no'];       // 支付宝交易号
    $tradeStatus = $notifyData['trade_status']; // 交易状态
    // 只处理交易成功的通知
    if ($tradeStatus == 'TRADE_SUCCESS' || $tradeStatus == 'TRADE_FINISHED') {
        // --- 在这里编写你的核心业务逻辑 ---
        // 1. 检查订单是否已经处理过,防止重复通知
        // 2. 使用数据库事务,确保数据一致性
        // 3. 更新你数据库中的订单状态为“已支付”
        // 4. 给用户发送购买成功邮件或短信通知
        // 5. 执行发货等后续操作
        // 示例伪代码:
        if (isOrderPaid($outTradeNo)) {
            // 订单已处理,直接返回成功
            echo 'success';
            exit;
        }
        // updateOrderStatus($outTradeNo, 'paid');
        // sendThankYouEmail($outTradeNo);
        echo 'success'; // 告诉支付宝服务器,我已成功处理通知
    } else {
        // 其他状态,如等待付款、交易关闭等
        echo 'success'; // 同样返回成功,避免支付宝重复通知
    }
} else {
    // 4. 签名验证失败
    // 记录日志,用于排查问题
    file_put_contents('alipay_notify_error.log', date('Y-m-d H:i:s') . " - " . json_encode($notifyData) . "\n", FILE_APPEND);
    echo 'fail';
}

步骤 5: 查询订单状态 (alipay/query.php)

当用户或管理员不确定支付状态时,可以主动调用此接口查询。

<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/config.php';
use Alipay\EasySDK\Kernel\Factory;
$alipay = Factory::setOptions($config)->payment();
// 假设我们从某个地方获取了订单号
$outTradeNo = 'ORDER_1234567890'; // 替换为实际的订单号
try {
    $result = $alipay->query()->queryByOutTradeNo($outTradeNo);
    if ($result['code'] == '10000' && $result['trade_status'] == 'TRADE_SUCCESS') {
        echo "订单支付成功!支付宝交易号: " . $result['trade_no'];
    } else {
        echo "订单未支付或查询失败。";
        print_r($result);
    }
} catch (Exception $e) {
    echo "查询失败: " . $e->getMessage();
}

第五部分:实战 - 微信扫码支付

微信扫码支付流程与支付宝类似,主要区别在于创建订单时生成的是二维码图片。

步骤 1: 创建订单并生成支付二维码 (wechat/create_qr.php)

<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/wechat_config.php';
use WeChatPay\Builder;
use WeChatPay\Crypto\AesUtil;
use WeChatPay\Util\RandomStringGenerator;
// 1. 构建微信支付客户端
$merchantId = $config['mch_id']; // 商户号
$serialNo = $config['serial_no']; // 证书序列号
privateKey = $config['private_key']; // 商户私钥
apiV3Key = $config['api_v3_key']; // API v3密钥
$client = Builder::factory([
    'mchid'    => $merchantId,
    'serial'   => $serialNo,
    'privateKey' => $privateKey,
    'cert'     => $config['cert_path'], // 证书路径
    'apiv3Key' => $apiV3Key,
]);
// 2. 准备订单数据
$outTradeNo = 'WX_ORDER_' . time();
$amount = 1; // 金额,单位:分
$description = '测试商品';
$payload = [
    'appid' => $config['app_id'],
    'mchid' => $merchantId,
    'out_trade_no' => $outTradeNo,
    'notify_url' => 'https://your-domain.com/wechat/notify.php', // 你的异步通知地址
    'amount' => [
        'total' => $amount,
        'currency' => 'CNY'
    ],
    'description' => $description,
];
// 3. 发起请求,创建订单
try {
    $result = $client->chain('v3/pay/transactions/native')->post($payload);
    $body = json_decode($result['body'], true);
    // 4. 解析响应,获取二维码码串
    $codeUrl = $body['code_url'];
    // 5. 生成二维码并展示
    // 这里可以使用任何二维码生成库,如 endroid/qr-code
    // require_once __DIR__ . '/../vendor/autoload.php';
    // use Endroid\QrCode\QrCode;
    // use Endroid\QrCode\Writer\PngWriter;
    // $qrCode = QrCode::create($codeUrl)
    //     ->setSize(300)
    //     ->setMargin(10);
    // $writer = new PngWriter();
    // $result = $writer->write($qrCode);
    // header('Content-Type: '.$result->getMimeType());
    // echo $result->getString();
    // 为了简化,这里直接输出码串,前端用JS生成二维码
    echo "<h1>请使用微信扫码支付</h1>";
    echo "<p>订单号: " . $outTradeNo . "</p>";
    echo "<div id='qrcode'></div>";
    echo "<script src='https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js'></script>";
    echo "<script>new QRCode(document.getElementById('qrcode'), { text: '" . htmlspecialchars($codeUrl) . "', width: 256, height: 256 });</script>";
} catch (Exception $e) {
    echo "创建订单失败: " . $e->getMessage();
}

步骤 2: 接收和处理异步通知 (wechat/notify.php)

微信支付的异步通知处理逻辑与支付宝类似,但验证方式不同。

<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/wechat_config.php';
use WeChatPay\Builder;
use WeChatPay\Crypto\AesUtil;
use WeChatPay\Validator\AccessToken;
// 1. 构建客户端
$client = Builder::factory($config);
// 2. 获取HTTP请求体
$notification = file_get_contents('php://input');
$notificationData = json_decode($notification, true);
// 3. 验证签名
// 从请求头中获取平台证书序列号和签名
$serialNo = $_SERVER['HTTP_WECHATPAY_SERIAL'];
$signature = $_SERVER['HTTP_WECHATPAY_SIGNATURE'];
$timestamp = $_SERVER['HTTP_WECHATPAY_TIMESTAMP'];
$nonce = $_SERVER['HTTP_WECHATPAY_NONCE'];
$verify = $client->verify(
    $signature,
    $timestamp,
    $nonce,
    $notification
);
if ($verify) {
    // 4. 签名验证成功,处理业务逻辑
    $outTradeNo = $notificationData['out_trade_no'];
    $transactionId = $notificationData['transaction_id'];
    $tradeState = $notificationData['trade_state']; // SUCCESS, CLOSED, REFUND 等
    if ($tradeState == 'SUCCESS') {
        // --- 在这里编写你的核心业务逻辑 ---
        // 1. 检查订单是否已处理
        // 2. 更新数据库订单状态
        // 3. 执行后续操作 (发货等)
        // 示例伪代码:
        // if (isOrderPaid($outTradeNo)) { echo 'SUCCESS'; exit; }
        // updateOrderStatus($outTradeNo, 'paid');
        echo 'SUCCESS'; // 告诉微信服务器,通知处理成功
    } else {
        echo 'SUCCESS'; // 对于非成功状态,也返回成功,避免重复通知
    }
} else {
    // 5. 签名验证失败
    file_put_contents('wechat_notify_error.log', date('Y-m-d H:i:s') . " - " . $notification . "\n", FILE_APPEND);
    http_response_code(500); // 返回服务器错误状态码
    echo 'FAIL';
}

第六部分:安全最佳实践

  1. 验证异步通知的签名: 这是防止伪造通知、确保资金安全的第一道防线,无论支付宝还是微信,都必须验证签名。
  2. 防止重复通知: 支付平台可能会因为网络问题多次发送通知,在你的业务逻辑中,必须根据 out_trade_no 检查订单是否已经处理过,如果已处理,直接返回 success,不要重复执行业务逻辑。
  3. 使用数据库事务: 在更新订单状态、减少库存、创建支付记录等多个操作时,务必使用数据库事务,确保所有操作要么全部成功,要么全部失败,避免数据不一致。
  4. 敏感信息保密: 私钥、API密钥等绝不能硬编码在代码里或提交到代码仓库,建议使用环境变量(如 getenv())或专门的配置文件,并设置好文件权限。
  5. HTTPS: 整个支付流程,特别是 notify_urlreturn_url,必须使用 HTTPS 协议,保证数据传输过程中的加密。

第七部分:总结与进阶

  • 本教程带你走通了从零开始集成支付宝和微信支付的全过程,核心在于理解同步跳转异步通知的区别,并牢牢把握验证异步通知签名这一安全关键点。
  • 进阶:
    • 退款功能: 实现调用退款接口,处理用户的退款请求。
    • 账单下载: 定期从支付平台下载交易账单,用于对账。
    • 移动端支付: 学习 App 支付(支付宝 App 支付、微信 App 支付)和 JSAPI 支付(在微信内置浏览器中调起支付)。
    • 使用设计模式: 将支付逻辑封装成独立的 Service 类,使代码更清晰、易于维护和扩展。
    • 多支付渠道: 设计一个统一的支付接口,可以动态选择使用支付宝还是微信支付。

希望这份详尽的教程能帮助你顺利完成 PHP 支付接口的开发!