订单结果通知事件
接口提供方
该接口需要由开发者提供给燃豆
接口说明
如果积分俱乐部使用的是自有积分体系,则该接口必须配置,查看自有积分和平台积分的区别
使用场景
使用场景请参考积分预扣接口
业务流程说明
业务流程请参考积分预扣接口流程
参数说明
该接口除了公共必传参数外,还包括以下参数:
参数 | 是否必须 | 类型[长度限制] | 说明 |
---|---|---|---|
uid | 是 | string[1,64] | 下单用户id,该id由开发者在免登接口中传给燃豆的用户唯一标志 |
mall_no | 是 | string[6,6] | 商城的唯一编号,表示用户下单的所在商城编号,如JF_001 |
orderNo | 是 | string[18,20] | 预扣订单编号,即预扣积分时推送的预扣订单编号,如T388364710157766657 |
bizNo | 是 | string[10,32] | 开发者在积分预扣接口传递给燃豆的订单号 |
status | 是 | string[4,7] | 订单成功为success,订单失败为fail,请以该值作为订单失败或者成功的依据 |
message | 否 | string[0,255] | status为fail的情况下,会返回失败原因 |
返回结果
开发者服务端在接收到请求后需要对结果做相应的处理,如订单失败需要把预扣的积分返回给用户。 在收到接口通知后,开发者需要以HTTP响应码为200且body为“success”纯文本字符串(不包含引号)给燃豆,表示已正确处理了该通知,其他返回均视作失败,如果失败燃豆服务端会发起重试,重试逻辑如下;
重试逻辑
由于网络和系统存在不确定性,有可能存在接口调用超时或失败的情况或者开发者没有正确返回等原因,燃豆会对接口进行重试处理,在调用该接口时,设置了超时时间为10s,如果接口响应时间超过了10s,燃豆会认为该次调用失败,此时燃豆发起重试逻辑,直到开发者接口正常返回200和“success”,调用时间间隔分别为1m,5m,60m,3h,10h共5次(即一笔订单开发者在极端情况下有可能最多会收到6次通知请求),如果这5次重试全部失败,燃豆会标记该笔订单为异常订单,此时需要开发者在燃豆后台手工进行处理;
注意事项
- 由于接口有可能重复调用,因此开发者必须做好去重的逻辑处理,确保接口的幂等性,建议根据orderNo来做去重判断,切勿对本地数据做重复处理;
- 由于订单可能涉及到付款、人工审核、人工发货等流程,因此该接口通知和预扣积分接口有可能有比较长的时间差;
- 对于优惠券等不需要人工审核审核或发货的兑换流程,积分预扣接口和预扣结果通知接口也有可能时间差很小,开发者需要做好相应处理。
代码示例
PHP
use Randou\Exception\RdException;
use Randou\RdClient;
use Randou\RdClientBuilder;
$appid = 'aaaaaaaaaaaaaaaaaaaaaaaa';
$appsecret = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
$params = $request->all();
try {
$client = RdClientBuilder::getClient($appid, $appSecret);
$event = $client->creditsNotify($params);
} catch (RdException $e) {
print_r($e);
return response('fail', 400);
}
// 获取通知全部数据
$data = $event->all();
save($data);
return response('success', 200);
JAVA
import com.randou_tech.ClientBuilder;
import com.randou_tech.RdClient;
import com.randou_tech.RdException;
import com.randou_tech.event.CreditsNotifyEvent;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/notify")
public String notify(HttpServletRequest request) {
String appid = "aaaaaaaaaaaaaaaaaaaaaaaa";
String appsecret = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
RdClient client = ClientBuilder.build(appid, appsecret);
try {
// 解析数据
CreditsNotifyEvent event = client.creditsNotify(request);
// 如果项目中没有javax.servlet.http.HttpServletRequest,可从request中自行获取出全部参数,以下为从jakarta.servlet.http.HttpServletRequest对象中获取参数
// Enumeration<String> parameterNames = request.getParameterNames();
// Map<String, String> params = new HashMap<>();
// // 遍历参数名并获取对应的值
// while (parameterNames.hasMoreElements()) {
// String paramName = parameterNames.nextElement();
// String paramValue = request.getParameter(paramName); // 只取第一个值
// params.put(paramName, paramValue);
// }
// CreditsNotifyEvent event = client.creditsNotifyWithParams(params);
System.out.println(event.toString());
// 处理本地业务
todo();
// 返回成功
return "success";
} catch (RdException e) {
// e.printStackTrace();
return "fail";
}
}