Fovea Cordova内购插件数据库重复录入问题求助及TransactionID获取
问题排查与解决方案
一、重复记录问题根源及修复
1. 核心原因
你遇到的重复记录问题,主要来自两个点:
- Fovea内购插件的
owned状态回调和finished事件可能被多次触发(比如沙盒环境下Apple的重试机制、网络波动后的状态同步) - 代码未基于交易唯一标识做去重校验,导致同一交易被重复写入数据库
2. 修复步骤
(1)添加数据库唯一约束
在订阅记录表中,给transaction_id字段添加唯一索引,从底层阻止重复插入操作。
(2)修改插入逻辑:先校验再写入
不管是owned状态回调还是finished事件触发,都先通过transactionId检查该交易是否已存在,仅当不存在时才执行插入。
(3)优先依赖finished事件
owned状态可能在订阅恢复、本地状态同步时多次触发,建议优先在finished事件中处理交易记录——该事件仅在支付/恢复流程完成时触发一次(正常场景下),能减少重复触发概率。
二、iOS沙盒弹窗未弹出却生成记录的问题
沙盒环境下Apple会模拟异常场景,比如自动重试未完成交易、测试订阅状态同步,这时候插件可能误触发owned状态回调,但用户实际未完成支付。解决方式:
- 不要仅依赖
owned状态写入记录,必须同时校验是否存在有效的transactionId,只有拿到真实交易ID,才执行数据库写入。 - 沙盒测试时使用全新测试账号,避免之前的测试交易残留导致状态误判。
三、获取TransactionID的方法
在Fovea插件的事件回调中,Transaction对象包含transactionId字段,具体获取方式:
1. 在finished事件中获取
store.when("product").finished(function(product) { // 直接从交易对象中获取ID const transactionId = product.transaction.transactionId; // 执行带校验的数据库写入逻辑 checkAndInsertSubscription(transactionId, product); });
2. 订阅恢复场景下获取
通过store.refresh()恢复订阅状态时,可在owned回调中解析交易记录列表:
store.when("product").owned(function(product) { // 产品关联的所有交易记录 const transactions = product.transactions; if (transactions.length > 0) { // 取最新的交易记录ID const latestTransaction = transactions[transactions.length - 1]; const transactionId = latestTransaction.transactionId; checkAndInsertSubscription(transactionId, product); } });
四、关键代码示例
// 封装校验+插入的复用函数 function checkAndInsertSubscription(transactionId, product) { // 1. 查询数据库是否已存在该交易ID db.query("SELECT * FROM subscriptions WHERE transaction_id = ?", [transactionId], function(err, rows) { if (err) throw err; if (rows.length === 0) { // 2. 不存在则插入新记录 db.query("INSERT INTO subscriptions (user_id, product_id, transaction_id, purchase_date) VALUES (?, ?, ?, ?)", [currentUserId, product.id, transactionId, new Date()], function(err) { if (err) console.error("插入订阅记录失败:", err); } ); } }); }
内容的提问来源于stack exchange,提问作者n.Dr
相关产品推荐
相关产品推荐

