本文目录导读:

我来详细介绍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);
}
}
}
}
最佳实践建议
- 接口超时处理:设置合理的超时时间,避免接口挂起
- 数据一致性:对于关键操作(如扣减积分),使用事务机制
- 异步处理:非关键操作可以使用消息队列异步处理
- 监控告警:对接口调用成功率、响应时间进行监控
- 幂等性:确保重复调用不会产生错误结果
- 缓存策略:对不常变化的数据(如商品列表)使用缓存
这个框架可以根据具体的积分商城接口文档进行调整和扩展。