PHP项目如何对接积分商城接口?

wen PHP项目 50

本文目录导读:

PHP项目如何对接积分商城接口?

  1. 接口对接基础准备
  2. 核心接口封装类
  3. 业务整合示例
  4. 安全处理
  5. 错误处理与日志
  6. 最佳实践建议

我来详细介绍PHP项目对接积分商城接口的完整流程。

接口对接基础准备

1 确认接口文档

首先需要获取积分商城提供的API文档,通常包含:

  • 接口地址(URL)
  • 请求方式(GET/POST)
  • 认证方式(API Key/OAuth)
  • 请求参数格式
  • 返回数据格式

2 建立接口配置

<?php
// config/api.php
return [
    'point_mall' => [
        'base_url' => 'https://api.point-mall.com/v1',
        'api_key' => 'your_api_key_here',
        'api_secret' => 'your_api_secret_here',
        'timeout' => 10,
        'retry_times' => 3
    ]
];

核心接口封装类

1 基础HTTP请求类

<?php
// lib/HttpClient.php
class HttpClient
{
    private $baseUrl;
    private $apiKey;
    private $timeout;
    public function __construct($config)
    {
        $this->baseUrl = $config['base_url'];
        $this->apiKey = $config['api_key'];
        $this->timeout = $config['timeout'];
    }
    /**
     * GET请求
     */
    public function get($endpoint, $params = [])
    {
        $url = $this->baseUrl . $endpoint;
        if (!empty($params)) {
            $url .= '?' . http_build_query($params);
        }
        return $this->sendRequest($url, 'GET');
    }
    /**
     * POST请求
     */
    public function post($endpoint, $data = [])
    {
        $url = $this->baseUrl . $endpoint;
        return $this->sendRequest($url, 'POST', $data);
    }
    /**
     * 发送HTTP请求
     */
    private function sendRequest($url, $method, $data = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        // 设置请求头
        $headers = [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $this->apiKey
        ];
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($error) {
            return ['success' => false, 'message' => $error];
        }
        return json_decode($response, true);
    }
}

2 积分商城接口类

<?php
// lib/PointMallClient.php
class PointMallClient
{
    private $httpClient;
    private $config;
    public function __construct($config)
    {
        $this->config = $config;
        $this->httpClient = new HttpClient($config);
    }
    /**
     * 用户积分查询
     */
    public function getUserPoints($userId)
    {
        return $this->httpClient->get('/user/points', [
            'user_id' => $userId
        ]);
    }
    /**
     * 积分扣减
     */
    public function deductPoints($userId, $points, $orderId, $remark = '')
    {
        return $this->httpClient->post('/points/deduct', [
            'user_id' => $userId,
            'points' => $points,
            'order_id' => $orderId,
            'remark' => $remark,
            'timestamp' => time()
        ]);
    }
    /**
     * 积分增加
     */
    public function addPoints($userId, $points, $source, $remark = '')
    {
        return $this->httpClient->post('/points/add', [
            'user_id' => $userId,
            'points' => $points,
            'source' => $source,
            'remark' => $remark,
            'timestamp' => time()
        ]);
    }
    /**
     * 获取商品列表
     */
    public function getProductList($page = 1, $pageSize = 20)
    {
        return $this->httpClient->get('/products', [
            'page' => $page,
            'page_size' => $pageSize
        ]);
    }
    /**
     * 创建积分兑换订单
     */
    public function createExchangeOrder($userId, $productId, $quantity = 1)
    {
        return $this->httpClient->post('/orders/create', [
            'user_id' => $userId,
            'product_id' => $productId,
            'quantity' => $quantity,
            'timestamp' => time()
        ]);
    }
    /**
     * 查询订单状态
     */
    public function getOrderStatus($orderId)
    {
        return $this->httpClient->get('/orders/status', [
            'order_id' => $orderId
        ]);
    }
}

业务整合示例

1 控制器示例

<?php
// controller/PointMallController.php
class PointMallController
{
    private $pointMallClient;
    public function __construct()
    {
        $config = require 'config/api.php';
        $this->pointMallClient = new PointMallClient($config['point_mall']);
    }
    /**
     * 用户积分兑换商品
     */
    public function exchangeProduct($userId, $productId, $quantity = 1)
    {
        try {
            // 1. 查询用户积分
            $userPoints = $this->pointMallClient->getUserPoints($userId);
            if (!$userPoints['success']) {
                throw new Exception('查询积分失败');
            }
            // 2. 获取商品信息
            $product = $this->pointMallClient->getProductList(1, 1);
            // 根据商品ID筛选商品...
            // 3. 检查积分是否足够
            $requiredPoints = $product['data']['points'] * $quantity;
            if ($userPoints['data']['points'] < $requiredPoints) {
                throw new Exception('积分不足');
            }
            // 4. 创建兑换订单
            $orderResult = $this->pointMallClient->createExchangeOrder(
                $userId, 
                $productId, 
                $quantity
            );
            if (!$orderResult['success']) {
                throw new Exception('创建订单失败');
            }
            // 5. 扣减积分
            $deductResult = $this->pointMallClient->deductPoints(
                $userId,
                $requiredPoints,
                $orderResult['data']['order_id'],
                '兑换商品:' . $product['data']['name']
            );
            return [
                'success' => true,
                'data' => [
                    'order_id' => $orderResult['data']['order_id'],
                    'deducted_points' => $requiredPoints
                ]
            ];
        } catch (Exception $e) {
            return [
                'success' => false,
                'message' => $e->getMessage()
            ];
        }
    }
}

安全处理

1 签名验证

<?php
// lib/SignUtil.php
class SignUtil
{
    /**
     * 生成签名
     */
    public static function generateSign($params, $secret)
    {
        ksort($params);
        $string = '';
        foreach ($params as $key => $value) {
            $string .= $key . '=' . $value . '&';
        }
        $string .= 'key=' . $secret;
        return strtoupper(md5($string));
    }
    /**
     * 验证回调签名
     */
    public static function verifySign($params, $sign, $secret)
    {
        $expectedSign = self::generateSign($params, $secret);
        return $expectedSign === $sign;
    }
}

2 回调处理

<?php
// controller/PointMallNotifyController.php
class PointMallNotifyController
{
    public function handleNotify()
    {
        $input = file_get_contents('php://input');
        $data = json_decode($input, true);
        // 验证签名
        $config = require 'config/api.php';
        $signUtil = new SignUtil();
        if (!$signUtil->verifySign(
            $data['params'],
            $data['sign'],
            $config['point_mall']['api_secret']
        )) {
            return json_encode(['code' => 400, 'message' => '签名验证失败']);
        }
        // 处理不同类型的回调
        switch ($data['type']) {
            case 'order_status':
                $this->handleOrderStatus($data['params']);
                break;
            case 'points_change':
                $this->handlePointsChange($data['params']);
                break;
            // 其他回调类型...
        }
        return json_encode(['code' => 200, 'message' => 'success']);
    }
    private function handleOrderStatus($params)
    {
        // 更新本地订单状态
        OrderModel::updateStatus(
            $params['order_id'],
            $params['status']
        );
    }
    private function handlePointsChange($params)
    {
        // 更新本地用户积分
        UserModel::updatePoints(
            $params['user_id'],
            $params['points']
        );
    }
}

错误处理与日志

1 日志记录

<?php
// lib/Logger.php
class Logger
{
    public static function log($message, $level = 'info')
    {
        $logFile = 'logs/api_' . date('Y-m-d') . '.log';
        $logMessage = '[' . date('Y-m-d H:i:s') . '] [' . $level . '] ' . $message . PHP_EOL;
        file_put_contents($logFile, $logMessage, FILE_APPEND);
    }
}

2 重试机制

<?php
// lib/RetryHandler.php
class RetryHandler
{
    private $maxRetries = 3;
    private $delay = 1; // 秒
    public function executeWithRetry($callback)
    {
        $attempts = 0;
        while ($attempts < $this->maxRetries) {
            try {
                return $callback();
            } catch (Exception $e) {
                $attempts++;
                Logger::log("请求失败,第{$attempts}次重试:" . $e->getMessage());
                if ($attempts >= $this->maxRetries) {
                    throw $e;
                }
                sleep($this->delay * $attempts);
            }
        }
    }
}

最佳实践建议

  1. 接口超时处理:设置合理的超时时间,避免接口挂起
  2. 数据一致性:对于关键操作(如扣减积分),使用事务机制
  3. 异步处理:非关键操作可以使用消息队列异步处理
  4. 监控告警:对接口调用成功率、响应时间进行监控
  5. 幂等性:确保重复调用不会产生错误结果
  6. 缓存策略:对不常变化的数据(如商品列表)使用缓存

这个框架可以根据具体的积分商城接口文档进行调整和扩展。

抱歉,评论功能暂时关闭!