碰一碰营销系统双端源码开发:API 接口对接全指南

"碰一碰" 营销系统核心是通过 NFC / 蓝牙 "碰一碰" 触发营销动作(如领券、跳转商城、会员注册),双端(前端:安卓 /iOS App / 小程序;后端:管理系统)需对接各类 API 接口实现核心功能。以下从接口对接核心逻辑、全流程开发步骤、关键场景实操、避坑要点 展开,覆盖源码开发中的 API 对接全环节。
一、先明确接口对接核心框架
1. 核心角色与数据流向
| 角色 | 职责 | 对接的核心 API 类型 |
|---|---|---|
| 前端(App / 小程序) | 触发 "碰一碰"、展示营销内容、用户交互 | 设备 NFC / 蓝牙 API、后端业务 API、第三方支付 / 券码 API |
| 后端(服务端) | 业务逻辑处理、数据存储、接口鉴权 | 前端请求 API、第三方平台开放 API、数据库操作 API |
| 第三方平台(支付 / 券 / 短信) | 提供营销配套能力 | 开放 API(RESTful/SDK 形式) |
2. 接口对接通用规范(双端统一)
-
通信协议:优先 HTTPS(避免数据泄露),接口格式推荐 RESTful(GET/POST/PUT/DELETE),小型交互可采用 WebSocket(如实时推送营销活动);
-
数据格式:JSON(跨端兼容性最好),避免 XML;
-
鉴权方式 :
- 前端→后端:Token 鉴权(JWT / 自定义 Token),每次请求携带
token参数; - 后端→第三方:API Key+Secret、签名(MD5/SHA256)、OAuth2.0(如对接微信 / 支付宝);
- 前端→后端:Token 鉴权(JWT / 自定义 Token),每次请求携带
-
错误处理 :统一错误码(如
10001=接口鉴权失败、20001=NFC设备未识别),返回格式示例:json
{ "code": 0, "msg": "success", "data": {}, "requestId": "xxx-xxx-xxx" // 便于排查问题 }
二、双端源码开发:API 对接全流程
阶段 1:接口规划(先定规则,再写代码)
1. 梳理核心业务接口清单(碰一碰营销系统核心)
| 业务场景 | 接口类型 | 前端→后端接口示例 | 后端→第三方接口示例 |
|---|---|---|---|
| 碰一碰触发营销 | 核心业务接口 | POST /api/v1/touch/trigger(携带设备 ID/NFC 标签 ID) | - |
| 领取优惠券 | 核心业务接口 | POST /api/v1/coupon/receive(携带用户 ID / 券 ID) | 对接券平台 API:/coupon/send |
| 支付核销 | 支付接口 | POST /api/v1/pay/verify(携带订单 ID) | 对接微信 / 支付宝支付:/pay/unifiedorder |
| 用户注册 / 登录 | 用户接口 | POST /api/v1/user/login(手机号 / 验证码) | 对接短信平台:/sms/sendCode |
| 营销数据统计 | 统计接口 | GET /api/v1/stat/touch(时间范围 / 商户 ID) | - |
2. 定义接口文档(必备!双端开发统一标准)
推荐使用 Swagger/OpenAPI、Apifox 等工具生成接口文档,包含:
- 接口 URL、请求方法、请求头、参数(必填 / 可选、类型、示例);
- 返回参数、错误码、响应示例;
- 接口调用频率限制、鉴权规则。
阶段 2:后端源码对接 API(核心:接口开发 + 第三方适配)
以 Java(Spring Boot)/Python(FastAPI)为例,核心步骤:
1. 搭建后端接口基础框架
-
集成鉴权组件:如 Spring Boot 集成 JWT,生成 / 验证前端 Token;
-
封装 HTTP 请求工具:对接第三方 API 需统一封装请求类(处理超时、重试、签名),示例(Python): python
运行
import requests import hashlib class ThirdPartyApiClient: def __init__(self, api_key, api_secret): self.api_key = api_key self.api_secret = api_secret # 生成签名(第三方接口通用) def generate_sign(self, params): sorted_params = sorted(params.items()) sign_str = f"{''.join([f'{k}{v}' for k,v in sorted_params])}{self.api_secret}" return hashlib.md5(sign_str.encode()).hexdigest() # 发送请求 def post(self, url, params): params["apiKey"] = self.api_key params["sign"] = self.generate_sign(params) try: resp = requests.post(url, json=params, timeout=10) return resp.json() except Exception as e: raise Exception(f"第三方接口调用失败:{str(e)}")
2. 开发内部业务接口(供前端调用)
以 "碰一碰触发营销" 接口为例(Spring Boot):
java
运行
@RestController
@RequestMapping("/api/v1/touch")
public class TouchTriggerController {
@Autowired
private TouchService touchService;
// 接口鉴权注解(自定义)
@AuthCheck
@PostMapping("/trigger")
public Result<?> triggerTouch(@RequestBody TouchTriggerReq req) {
// 1. 参数校验(NFC标签ID、设备ID非空)
if (StringUtils.isEmpty(req.getNfcTagId()) || StringUtils.isEmpty(req.getDeviceId())) {
return Result.error(10002, "参数缺失");
}
// 2. 业务逻辑:根据NFC标签ID查询对应的营销活动
MarketingActivity activity = touchService.getActivityByNfcTag(req.getNfcTagId());
if (activity == null) {
return Result.error(20001, "未配置营销活动");
}
// 3. 返回营销活动数据(供前端展示)
return Result.success(activity);
}
}
3. 对接第三方 API(支付 / 券 / 短信)
以对接微信支付 "统一下单接口" 为例:
- 步骤 1:引入微信支付 SDK(或用上述封装的 HTTP 工具);
- 步骤 2:封装请求参数(商户号、订单号、金额、签名等);
- 步骤 3:调用接口并处理返回结果(成功则返回预付单 ID,失败则返回错误码);
- 步骤 4:异步接收微信支付的回调(需暴露公网接口,校验签名后更新订单状态)。
阶段 3:前端源码对接 API(安卓 /iOS/ 小程序)
1. 通用对接原则
- 封装统一的 API 请求工具:统一处理 BaseURL、请求头(Token)、超时、错误提示;
- 区分环境:开发 / 测试 / 生产环境的 API 地址隔离;
- 异步处理:避免主线程阻塞(如安卓用 Retrofit+Coroutine,iOS 用 Alamofire,小程序用 wx.request)。
2. 不同端的实操示例
(1)安卓端(Kotlin + Retrofit)
-
步骤 1:定义接口接口 kotlin
interface TouchApiService { // 携带Token请求头 @Headers("Content-Type: application/json") @POST("api/v1/touch/trigger") suspend fun triggerTouch(@Header("token") token: String, @Body req: TouchTriggerReq): Result<MarketingActivity> } -
步骤 2:初始化 Retrofit 并调用 kotlin
val retrofit = Retrofit.Builder() .baseUrl("https://api.xxx.com/") .addConverterFactory(GsonConverterFactory.create()) .build() val apiService = retrofit.create(TouchApiService::class.java) // 协程中调用(避免主线程) lifecycleScope.launch { try { val token = SPUtils.get("token") // 从SharedPreferences获取Token val req = TouchTriggerReq(nfcTagId = "NFC123456", deviceId = "ANDROID789") val resp = apiService.triggerTouch(token, req) if (resp.code == 0) { // 展示营销活动(如领券弹窗) showCouponDialog(resp.data) } else { Toast.makeText(context, resp.msg, Toast.LENGTH_SHORT).show() } } catch (e: Exception) { Toast.makeText(context, "接口调用失败", Toast.LENGTH_SHORT).show() } }
(2)iOS 端(Swift + Alamofire)
swift
// 封装请求工具
class ApiClient {
static let shared = ApiClient()
private let baseUrl = "https://api.xxx.com/"
private let token = UserDefaults.standard.string(forKey: "token") ?? ""
func triggerTouch(nfcTagId: String, deviceId: String, completion: @escaping (Result<MarketingActivity, Error>) -> Void) {
let url = baseUrl + "api/v1/touch/trigger"
let params = ["nfcTagId": nfcTagId, "deviceId": deviceId]
let headers: HTTPHeaders = [
"token": token,
"Content-Type": "application/json"
]
AF.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers)
.validate()
.responseDecodable(of: Result<MarketingActivity>.self) { response in
switch response.result {
case .success(let result):
if result.code == 0 {
completion(.success(result.data!))
} else {
completion(.failure(NSError(domain: "", code: result.code, userInfo: [NSLocalizedDescriptionKey: result.msg])))
}
case .failure(let error):
completion(.failure(error))
}
}
}
}
// 调用接口
ApiClient.shared.triggerTouch(nfcTagId: "NFC123456", deviceId: "IOS789") { result in
DispatchQueue.main.async {
switch result {
case .success(let activity):
// 展示营销活动
self.showCouponDialog(activity)
case .failure(let error):
print("接口调用失败:\(error.localizedDescription)")
}
}
}
(3)微信小程序端
javascript
运行
// 封装request工具
const request = (url, data, method = 'POST') => {
return new Promise((resolve, reject) => {
wx.request({
url: `https://api.xxx.com/${url}`,
data,
method,
header: {
'token': wx.getStorageSync('token'),
'Content-Type': 'application/json'
},
success: (res) => {
if (res.data.code === 0) {
resolve(res.data.data);
} else {
wx.showToast({ title: res.data.msg, icon: 'none' });
reject(res.data);
}
},
fail: (err) => {
wx.showToast({ title: '网络错误', icon: 'none' });
reject(err);
}
});
});
};
// 调用"碰一碰触发"接口
Page({
// NFC碰一碰触发事件(小程序需配置NFC权限)
onNFCTagDiscovered(e) {
const nfcTagId = e.tag.id; // 获取NFC标签ID
request('api/v1/touch/trigger', {
nfcTagId,
deviceId: wx.getSystemInfoSync().deviceId
}).then((activity) => {
// 展示营销活动
this.setData({ showCoupon: true, couponInfo: activity.coupon });
}).catch((err) => {
console.error(err);
});
}
});
阶段 4:联调与测试(关键!避免上线后出问题)
- 接口连通性测试:用 Postman/Apifox 模拟前端请求,验证后端接口返回是否符合预期;
- 双端联调 :前端真机 / 模拟器调用后端接口,重点测试:
- Token 失效、参数错误等异常场景;
- NFC / 蓝牙触发接口的稳定性(如多次碰一碰是否重复请求);
- 第三方接口联调 :
- 先用第三方测试环境(如微信支付沙箱)验证;
- 测试边界场景(如券已领完、支付超时);
- 压测:针对 "碰一碰" 高并发场景,用 JMeter 压测后端接口,确保 QPS 满足需求。
三、关键避坑点
- NFC 标签 ID 兼容性:不同安卓 /iOS 设备读取的 NFC 标签 ID 格式可能不同,后端需统一格式(如转大写、去除空格);
- 接口签名安全:对接第三方 API 时,签名密钥不要硬编码在源码中,安卓 /iOS 可放在安全存储(如 KeyStore/Keychain),后端放在配置中心;
- 网络异常处理:"碰一碰" 场景多在户外,需处理网络超时 / 断网,前端可增加加载动画、重试机制;
- 数据加密:用户手机号、支付信息等敏感数据,传输时需加密(如 AES),避免明文传输;
- 接口幂等性:如 "领券接口" 需做幂等处理(通过用户 ID + 券 ID 唯一标识),防止用户重复领券。
四、源码开发额外建议
- 日志埋点:在接口调用处增加日志(请求参数、返回结果、耗时),便于排查问题(如后端用 SLF4J,前端用埋点 SDK);
- 版本控制 :接口采用版本号(如
/api/v1/),后续迭代不影响旧版本; - 文档同步:接口变更后及时更新文档,双端开发同步调整;
- 异常兜底:前端接口调用失败时,提供兜底方案(如展示默认营销活动、提示用户重试)。