前置动作 :根据 友朋运营商平台第三方开放平台接口文档 完成开发者的appid、appSecret的创建,回调地址配置,及所需权限勾选。
此业务为第三方为消费者提供订单申诉全额退款的入口时使用,第三方需到友朋运营后台进行退款订单审核后才会发起退款通知 。如未完成此流程对接,第三方自行退款给消费者,会出现财务对账问题。
① 开发者通过 cabinet.order.refund.apply 发起退款:开发者允许消费者申请直接退款的情况下使用。
② 友朋回调开发者 cabinet.order.refunds.result.notify: 开发者需同步返回退款结果给友朋。
此业务为第三方为消费者提供在支付前进行订单申诉
① 开发者通过 cabinet.order.user.appeal 发起申诉:开发者在APP中提供了订单确定(非立即扣款)情况下使用。
② 友朋回调开发者 cabinet.order.vi.result.notify商品识别结果: 此结果需要开发者的客服到友朋运营商后台处理异常订单后才会进行回调。
③ 开发者回调支付结果给友朋该订单的NotifyUrl:NotifyUrl 为创建订单cabinet.open.door时,友朋提供的该订单回调地址 (请务必回调支付结果,否则友朋系统内订单会一直处于待支付状态,影响财务对账)
此业务 为第三方为消费者提供在支付后进行订单申诉使用
① 开发者通过 cabinet.order.user.appeal 发起申诉:已支付的订单的售后处理,会产生一个新订单,原订单退款。
② 友朋回调开发者 cabinet.order.product.modify 新订单的识别结果:此结果需要开发者的客服到友朋运营商后台处理异常订单后才会进行回调。
② 友朋回调开发者 cabinet.order.refunds.result.notify 原订单的退款:此结果需要开发者的客服到友朋运营商后台处理异常订单后才会进行回调
③ 开发者回调支付结果给新订单的PaySuccessNotifyUrl:在第②步友朋会提供新订单的回调地址PaySuccessNotifyUrl,请务必回调该新订单的支付结果,否则友朋系统内订单会一直处于待支付状态,影响财务对账。
前置逻辑: 每次调用 cabinet.open.door 接口开门后,友朋接口会同步返回 回调地址【NotifyUrl】,请务必保存每笔订单的回调地址。 实现业务: 第三方开发者接入自有支付通道,每笔开门订单完成支付(扣款)后,进行【异步回调 】。如回调接口失败,请确保重试补偿机制,确保两边的订单状态同步避免对账问题出现。
参数名称 | 类型 | 是否必须 | 参考值 |
---|---|---|---|
receipt_no | string | Y | 友朋业务订单号全局唯一 |
trade_no | string | Y | 支付渠道交易流水号 (尽可能采用支付通道的业务流水号,避免二次对账) |
trade_status | int | Y | 支付结果 1=支付成功 -1=交易关闭 |
trade_raw_data | object | N | 支付渠道回调的所有参数以 JSON 字符串方式传递,如果没值请传递 {} 空对象字符串 |
complete_status | string | Y | 完成状态 |
pay_time | int | Y | 支付时间 YYYYMMDDHHMMSS, 示例:20210122112001 |
sign | string | Y | 签名 |
success
除 sign 参数外所有参数必须参与签名,参数以文本方式字典排序,排序后使用 key=value&key=value 方式拼接字符串 得到字符串 tmpString 签名:md5(tmpString+"&"+appSecret) 得出的结果转换为小写字母 appSecret 由品牌商在后台配置(此文档里接口 appSecret 用的是支付配置中的签名秘钥,非支付业务接口签名均用开放平台 appSecret)
参数名称 | 类型 | 是否必须 | 说明 |
---|---|---|---|
method | string | Y | 业务方法,以下每个接口表示每个业务方法 (字母小写) |
biz_content | string | Y | 业务参数 json 字符串 |
timestamp | int | Y | unix 时间戳到秒 |
sign_type | string | Y | 签名方式,md5 (小写) |
sign | string | Y | 签名(小写) |
参数名称 | 类型 | 是否必须 | 说明 |
---|---|---|---|
error_code | int | 是 | 错误代码 =0 正常(操作成功,接口调用成功) !=0 异常错误 |
error_msg | string | 是 | 错误描述 |
data | object | 是 | 返回业务内容 |
【前置条件】:在调用cabinet.open.door接口后,友朋服务器收到机器关门后,异步触发通知开发者appid对应设置的回调 URL
【回调URL】: 免费 (开发者appid对应设置的回调URL)
【响应要求】: 无
参数名称 | 类型 | 是否必须 | 说明 |
---|---|---|---|
Status | int | Y | 1=机器有开门 2=机器 没有开门 |
ReceiptNo | string | Y | 单号 |
Msg | string | Y | 消息文案 |
【前置条件】: 此接口是用于当自取柜开门后,识别商品回调。当商品识别为异常状态时不会发起通知,需要运营商客服上运营商平台处理异常订单,完成后会发起回调。
【回调URL】: 付费 (开发者提供给友朋的支付回调URL)
【响应要求】: 同步返回
参数名称 | 类型 | 是否必须 | 说明 |
---|---|---|---|
ReceiptNo | string | Y | 友朋订单号 |
Products | array | Y | 商品列表 |
Products: [{
"Qty": 1,
"BarCode": "6925303723910",
"Name": "\u7edf\u4e00\u51b0\u7ea2\u83361L",
"Price": 1,
"CostPrice": 0,
"TotalPrice": 1
}]
//成功
{
"error_code": 0, //业务逻辑成功返回0 不成功返回非0
"error_msg": "SUCCESS",
"data": {
}
}
//失败
{
"error_code": -1,
"error_msg": "业务失败原因的描述",
}
【前置条件】: 此接口是用于消费者申诉时,运营商修改订单的识别结果后进行通知。
【回调URL】: 付费 (开发者提供给友朋的支付回调URL)
【响应要求】: 异步返回 (开发需保存PaySuccessNotifyUrl,用于异步回调通知友朋,参考 4.3 第三方支付业务回调参数说明)
参数名称 | 类型 | 是否必须 | 说明 |
---|---|---|---|
ReceiptNo | string | Y | 友朋原订单号 |
originalOrderRow | object | Y | 原订单 |
newOrderRow | object | Y | 调整后订单 |
PaySuccessNotifyUrl | string | Y | 调整后的订单支付成功后回调链接 |
originalOrderRow 对象 | 类型 | 是否必须 | 说明 |
---|---|---|---|
CID | string | 是 | 设备ID |
OID | string | 是 | 运营商ID |
BID | string | 是 | 品牌商ID |
UserID | string | 是 | 用户ID |
OpenID | string | 是 | 平台的OpenID, 如小程序的AppID,支付宝 |
PayType | integer | 是 | 支付方式 0=未知 1=微信(支付分) 2=支付宝 201=品牌商微信代收 99=第三方支付 |
- PayExtend | object | 是 | 支付商户的扩展 |
ClientIPAddress | string | 是 | 客户端ip |
ScenesType | integer | 是 | 支付场景 0=扫码支付 1=友朋刷脸 2=微信刷脸 3=支付宝刷脸 4=密码购 |
ServiceStatus | integer | 是 | 服务状态 0=未开始服务 1=服务中 2=服务结束 (通过回调来更新) 3=价格计算完成 4=价格已确认 |
TradeNo | string | 是 | 第三方交易流水号 |
ThirdpartyAppID | string | 是 | 开放平台调用的AppID |
ReceiptNo | string | 是 | 单据编号 唯一 |
- TradeRawData | object | 是 | 交易具体信息 |
-- no | integer | 是 | |
PayTime | integer | 是 | 支付时间 |
- Products | array | 是 | 商品信息 |
-- Qty | integer | 是 | 数量 |
-- BarCode | string | 是 | |
-- Name | string | 是 | |
-- Price | integer | 是 | 单价 单位:分 |
-- CostPrice | integer | 是 | 成本 单位:分 |
-- TotalPrice | integer | 是 | 总价 单位:分 |
DoorStatus | integer | 是 | 开门状态 -1=没有开门 0=已关门 1=已开门 |
TradeStatus | integer | 是 | 交易状态 0=等待结算 1=已支付成功 2=已退款成功 -1=已取消订单 |
Price | integer | 是 | 实收金额 单位分 |
IsSuspicious | integer | 是 | 订单是否可疑 |
- RefundsProducts | array | 是 | 退款商品 |
RefundsPrice | integer | 是 | 退款金额 单位分 |
- RefundsRawData | object | 是 | 退款具体信息 |
UserRefundsStatus | integer | 是 | 用户退款申请状态 0=未申请 1=申请退款 -1=拒绝退款 2=通过退款 |
UserRefundsTime | integer | 是 | 用户退款申请时间 |
UserRefundsReason | string | 是 | 用户退款原因 |
UserRefundsRemarks | string | 是 | 用户退款备注 |
- UserRefundsImageUrl | array | 是 | 用户退款上传的图片URL |
UserRefundsMobile | string | 是 | 用户退款时手机号码 |
UserOrderInfo | string | 是 | 用户对于 => 异常订单的 => 订单信息补充 |
RefundsTime | integer | 是 | 退款时间 |
OpAccountID | string | 是 | 退款操作的AccountID |
OpRefundsRemarks | string | 是 | 运营商 => 退款处理备注 |
DealResultStatus | integer | 是 | 运营商 => 处理结果 0=未知 1=本单未产生消费 2=修改订单明细结算 3=恶意行为 |
DealTime | integer | 是 | 运营商 => 处理时间 |
DealRemarks | string | 是 | 运营商 => 处理意见 |
SOpAccountID | string | 是 | 异常订单操作的AccountID |
CompleteStatus | null | 是 | 订单完成状态 SUCCESS=完成 |
CreateAt | integer | 是 | 创建时间 |
UpdatedAt | integer | 是 | 更新时间 |
id | string | 是 | 订单ID |
newOrderRow 对象 | 类型 | 是否必须 | 说明 |
---|---|---|---|
CID | string | 是 | 设备ID |
OID | string | 是 | 运营商ID |
BID | string | 是 | 品牌商ID |
UserID | string | 是 | 用户ID |
OpenID | string | 是 | 平台的OpenID, 如小程序的AppID,支付宝 |
PayType | integer | 是 | 支付方式 0=未知 1=微信(支付分) 2=支付宝 201=品牌商微信代收 99=第三方支付 |
- PayExtend | object | 是 | 支付商户的扩展 |
ClientIPAddress | string | 是 | 客户端ip |
ScenesType | integer | 是 | 支付场景 0=扫码支付 1=友朋刷脸 2=微信刷脸 3=支付宝刷脸 4=密码购 |
ServiceStatus | integer | 是 | 服务状态 0=未开始服务 1=服务中 2=服务结束 (通过回调来更新) 3=价格计算完成 4=价格已确认 |
TradeNo | string | 是 | 第三方交易流水号 |
ThirdpartyAppID | string | 是 | 开放平台调用的AppID |
ReceiptNo | string | 是 | 单据编号 唯一 |
- TradeRawData | object | 是 | 交易具体信息 |
-- no | integer | 是 | |
PayTime | integer | 是 | 支付时间 |
- Products | array | 是 | 商品信息 |
-- Qty | integer | 是 | 数量 |
-- BarCode | string | 是 | |
-- Name | string | 是 | |
-- Price | integer | 是 | 单价 单位:分 |
-- CostPrice | integer | 是 | 成本 单位:分 |
-- TotalPrice | integer | 是 | 总价 单位:分 |
DoorStatus | integer | 是 | 开门状态 -1=没有开门 0=已关门 1=已开门 |
TradeStatus | integer | 是 | 交易状态 0=等待结算 1=已支付成功 2=已退款成功 -1=已取消订单 |
Price | integer | 是 | 实收金额 单位分 |
IsSuspicious | integer | 是 | 订单是否可疑 |
- RefundsProducts | array | 是 | 退款商品 |
RefundsPrice | integer | 是 | 退款金额 单位分 |
- RefundsRawData | object | 是 | 退款具体信息 |
UserRefundsStatus | integer | 是 | 用户退款申请状态 0=未申请 1=申请退款 -1=拒绝退款 2=通过退款 |
UserRefundsTime | integer | 是 | 用户退款申请时间 |
UserRefundsReason | string | 是 | 用户退款原因 |
UserRefundsRemarks | string | 是 | 用户退款备注 |
- UserRefundsImageUrl | array | 是 | 用户退款上传的图片URL |
UserRefundsMobile | string | 是 | 用户退款时手机号码 |
UserOrderInfo | string | 是 | 用户对于 => 异常订单的 => 订单信息补充 |
RefundsTime | integer | 是 | 退款时间 |
OpAccountID | string | 是 | 退款操作的AccountID |
OpRefundsRemarks | string | 是 | 运营商 => 退款处理备注 |
DealResultStatus | integer | 是 | 运营商 => 处理结果 0=未知 1=本单未产生消费 2=修改订单明细结算 3=恶意行为 |
DealTime | integer | 是 | 运营商 => 处理时间 |
DealRemarks | string | 是 | 运营商 => 处理意见 |
SOpAccountID | string | 是 | 异常订单操作的AccountID |
CompleteStatus | null | 是 | 订单完成状态 SUCCESS=完成 |
CreateAt | integer | 是 | 创建时间 |
UpdatedAt | integer | 是 | 更新时间 |
id | string | 是 | 订单ID |
originalOrderRow
{
"CID": "5f519ebf4405f00010750ef5", // 设备ID
"OID": "5db266d87bd4810010954b0e", // 运营商ID
"BID": "5d254c16683ead0011492950", // 品牌商ID
"UserID": "5fcf260311ab6d0010c8b20e", // 用户ID
"OpenID": "13715352279", // 平台的OpenID, 如小程序的AppID,支付宝
"PayType": 99, // 支付方式 0=未知 1=微信(支付分) 2=支付宝 201=品牌商微信代收 99=第三方支付
"PayExtend": {}, // 支付商户的扩展
"ClientIPAddress": "127.0.0.1", // 客户端ip
"ScenesType": 0, // 支付场景 0=扫码支付 1=友朋刷脸 2=微信刷脸 3=支付宝刷脸 4=密码购
"ServiceStatus": 2, // 服务状态 0=未开始服务 1=服务中 2=服务结束 (通过回调来更新) 3=价格计算完成 4=价格已确认
"TradeNo": "9927749809022", // 第三方交易流水号
"ThirdpartyAppID": "106267743528", // 开放平台调用的AppID
"ReceiptNo": "OD210122112202688925", // 单据编号 唯一
"TradeRawData": { // 交易具体信息
"no": 1
},
"PayTime": 1611285601, // 支付时间
"Products": [// 商品信息
{
"Qty": 1, // 数量
"BarCode": "6902538004045",
"Name": "脉动青柠口味瓶装600ml",
"Price": 2, // 单价 单位:分
"CostPrice": 0, // 成本 单位:分
"TotalPrice": 2 // 总价 单位:分
}
],
"DoorStatus": 0, // 开门状态 -1=没有开门 0=已关门 1=已开门
"TradeStatus": 1, // 交易状态 0=等待结算 1=已支付成功 2=已退款成功 -1=已取消订单
"Price": 0, // 实收金额 单位分
"IsSuspicious": 0, // 订单是否可疑
"RefundsProducts": [], // 退款商品
"RefundsPrice": 0, // 退款金额 单位分
"RefundsRawData": {}, // 退款具体信息
"UserRefundsStatus": 1, // 用户退款申请状态 0=未申请 1=申请退款 -1=拒绝退款 2=通过退款
"RefundsType": 1, // 退款处理方式 => 1=拒绝退款 2=仅退款 3=补扣新订单、原订单退款 4=补扣新订单支付成功后,原订单退款
"UserRefundsTime": 1611285756, // 用户退款申请时间
"UserRefundsReason": "REFUNDS_REASON_PRODUCT_NOT_MATCH", // 用户退款原因 REFUNDS_REASON_PRODUCT_VI_MORE = 多识别商品 REFUNDS_REASON_PRODUCT_EXPIRED = 商品已过期 REFUNDS_REASON_PRODUCT_NOT_MATCH = 识别错商品 REFUNDS_REASON_PRODUCT_VI_LESS = 算漏商品 REFUNDS_REASON_OFFLINE_PAYMENT = 线下收款 REFUNDS_REASON_WECHAT_COMPLAINT = 微信投诉
"UserRefundsRemarks": "20e10122001", // 用户退款备注
"UserRefundsImageUrl": [], // 用户退款上传的图片URL
"UserRefundsMobile": "13715352279", // 用户退款时手机号码
"UserOrderInfo": "", // 用户对于 => 异常订单的 => 订单信息补充
"RefundsTime": 0, // 退款时间
"OpAccountID": "", // 退款操作的AccountID
"OpRefundsRemarks": "", // 运营商 => 退款处理备注
"DealResultStatus": 0, // 运营商 => 处理结果 0=未知 1=本单未产生消费 2=修改订单明细结算 3=恶意行为罚款
"DealTime": 0, // 运营商 => 处理时间
"DealRemarks": "", // 运营商 => 处理意见
"SOpAccountID": "", // 异常订单操作的AccountID
"CompleteStatus": null, // 订单完成状态 SUCCESS=完成
"CreateAt": 1611285723, // 创建时间
"UpdatedAt": 1611285756, // 更新时间
"id": "600a44db524b3420fc218c2c" // 订单ID
}
newOrderRow
{
"CID": "5f519ebf4405f00010750ef5", // 设备ID
"OID": "5db266d87bd4810010954b0e", // 运营商ID
"BID": "5d254c16683ead0011492950", // 品牌商ID
"UserID": "5fcf260311ab6d0010c8b20e", // 用户ID
"OpenID": "13715352279", // 平台的OpenID, 如小程序的AppID,支付宝
"PayType": 99, // 支付方式 0=未知 1=微信(支付分) 2=支付宝 201=品牌商微信代收 99=第三方支付
"PayExtend": {}, // 支付商户的扩展
"ClientIPAddress": "127.0.0.1", // 客户端ip
"ScenesType": 0, // 支付场景 0=扫码支付 1=友朋刷脸 2=微信刷脸 3=支付宝刷脸 4=密码购
"ServiceStatus": 2, // 服务状态 0=未开始服务 1=服务中 2=服务结束 (通过回调来更新) 3=价格计算完成 4=价格已确认
"TradeNo": "9927749809022", // 第三方交易流水号
"ThirdpartyAppID": "106267743528", // 开放平台调用的AppID
"ReceiptNo": "OD210122112202688925", // 单据编号 唯一
"TradeRawData": { // 交易具体信息
"no": 1
},
"PayTime": 1611285601, // 支付时间
"Products": [// 商品信息
{
"Qty": 1, // 数量
"BarCode": "6902538004045",
"Name": "脉动青柠口味瓶装600ml",
"Price": 2, // 单价 单位:分
"CostPrice": 0, // 成本 单位:分
"TotalPrice": 2 // 总价 单位:分
}
],
"DoorStatus": 0, // 开门状态 -1=没有开门 0=已关门 1=已开门
"TradeStatus": 1, // 交易状态 0=等待结算 1=已支付成功 2=已退款成功 -1=已取消订单
"Price": 0, // 实收金额 单位分
"IsSuspicious": 0, // 订单是否可疑
"RefundsProducts": [], // 退款商品
"RefundsPrice": 0, // 退款金额 单位分
"RefundsRawData": {}, // 退款具体信息
"UserRefundsStatus": 1, // 用户退款申请状态 0=未申请 1=申请退款 -1=拒绝退款 2=通过退款
"UserRefundsTime": 1611285756, // 用户退款申请时间
"UserRefundsReason": "REFUNDS_REASON_PRODUCT_NOT_MATCH", // 用户退款原因 REFUNDS_REASON_PRODUCT_VI_MORE = 多识别商品 REFUNDS_REASON_PRODUCT_EXPIRED = 商品已过期 REFUNDS_REASON_PRODUCT_NOT_MATCH = 识别错商品 REFUNDS_REASON_PRODUCT_VI_LESS = 算漏商品 REFUNDS_REASON_OFFLINE_PAYMENT = 线下收款 REFUNDS_REASON_WECHAT_COMPLAINT = 微信投诉
"UserRefundsRemarks": "20210122001", // 用户退款备注
"UserRefundsImageUrl": [], // 用户退款上传的图片URL
"UserRefundsMobile": "13715352279", // 用户退款时手机号码
"UserOrderInfo": "", // 用户对于 => 异常订单的 => 订单信息补充
"RefundsTime": 0, // 退款时间
"OpAccountID": "", // 退款操作的AccountID
"OpRefundsRemarks": "", // 运营商 => 退款处理备注
"DealResultStatus": 0, // 运营商 => 处理结果 0=未知 1=本单未产生消费 2=修改订单明细结算 3=恶意行为罚款
"DealTime": 0, // 运营商 => 处理时间
"DealRemarks": "", // 运营商 => 处理意见
"SOpAccountID": "", // 异常订单操作的AccountID
"CompleteStatus": null, // 订单完成状态 SUCCESS=完成
"CreateAt": 1611285723, // 创建时间
"UpdatedAt": 1611285756, // 更新时间
"id": "600a44db524b3420fc218c2c" // 订单ID
}
//业务成功
{
"error_code": 0, //业务逻辑成功返回0 不成功返回非0
"error_msg": "SUCCESS"
}
//业务失败
{
"error_code": -1,
"error_msg": "业务失败原因的描述",
}
【前置条件】: 此接口是用于消费者申诉退款(或修改订单原订单退款)时,运营商进行订单全额退款通知。
【回调URL】: 付费 (开发者提供给友朋的支付回调URL)
【响应要求】: 同步返回
参数名称 | 类型 | 是否必须 | 说明 |
---|---|---|---|
ReceiptNo | string | Y | 订单交易编号 |
UserRefundsStatus | Number | Y | 退款状态 -1=拒绝退款 2=通过退款 |
OpRefundsRemarks | string | Y | 审核备注 |
RefundsPrice | Number | N | 退款金额 单位:分 |
RefundsTime | Number | N | 退款时间 |
//业务成功
{
"error_code": 0, //业务逻辑成功返回0 不成功返回非0
"error_msg": "SUCCESS"
}
//业务失败
{
"error_code": -1,
"error_msg": "业务失败原因的描述",
}