7.19 糖果充值【未授权拦截通过,待登录态联调】

POST /tieup/api/v1/candy-recharges

鉴权:需要 Authorization: Bearer <access_token>

请求头:

Idempotency-Key: candy_recharge_10001_20260602143000_x7f9k2

请求体:

{
  "package_code": "candy_300",
  "payment_method": "apple_iap",
  "product_id": "tieup.candy.300"
}

请求字段:

字段 类型 必填 说明
package_code string 充值套餐代码,来自 GET /tieup/api/v1/recharge-packages
payment_method string wechatalipayapple_iap
product_id string Apple IAP Product ID;仅用于与服务端充值套餐 config.ios_product_id 做一致性校验,商品来源以服务端配置为准
return_url string 仅微信 H5、支付宝 WAP 支持的支付完成回跳地址;完整 HTTP(S) 地址,最长 2048 字符。非空值优先于后台配置,未传、null、空字符串或纯空白时使用后台配置;APP、Apple IAP 传入会返回 422

响应:

{
  "recharge_no": "RC202606101430001234567890",
  "order_no": "TO202606101430001234567890",
  "transaction_no": "TP202606101430001234567890",
  "recharge_package_code": "candy_300",
  "product_name_snapshot": "300糖果",
  "amount_cent": 3000,
  "paid_amount_cent": 0,
  "currency": "CNY",
  "candy_amount": "300.00",
  "gift_candy_amount": "30.00",
  "total_candy_amount": "330.00",
  "status": 1,
  "paid_at": null,
  "closed_at": null,
  "delivered_at": null,
  "payment": {
    "order_no": "TO202606101430001234567890",
    "transaction_no": "TP202606101430001234567890",
    "payment_status": 1,
    "payment_method": "apple_iap",
    "provider_code": "apple_iap",
    "payment_account_id": 1,
    "amount_cent": 3000,
    "currency": "CNY",
    "pay_params": {
      "bundle_id": "com.tieup.app",
      "product_id": "tieup.candy.300",
      "application_username": "550e8400-e29b-41d4-a716-446655440000",
      "sandbox": false,
      "requires_client_receipt_confirm": true,
      "storekit": "storekit1"
    }
  }
}

响应字段:

字段 类型 说明
recharge_no string 糖果充值业务单号
order_no string 平台订单号
transaction_no string 支付流水号
recharge_package_code string 充值套餐代码
product_name_snapshot string 套餐名称快照
amount_cent integer 内部订单金额,单位分
paid_amount_cent integer 内部实付金额,单位分
currency string 币种
candy_amount string 购买糖果数量
gift_candy_amount string 赠送糖果数量
total_candy_amount string 到账糖果总量
status integer 充值业务单状态
paid_at string/null 支付成功时间
closed_at string/null 关闭时间
delivered_at string/null 糖果到账时间
payment object 本次支付信息
payment.order_no string 平台订单号
payment.transaction_no string 支付流水号
payment.payment_status integer 支付流水状态:0=创建,1=预支付成功,2=支付成功,3=支付失败,4=已关闭,5=已退款
payment.payment_method string wechat=微信,alipay=支付宝,apple_iap=苹果内购
payment.provider_code string 接入产品代码
payment.payment_account_id integer 实际命中的支付账号 ID
payment.amount_cent integer 内部支付金额,单位分
payment.currency string 币种
payment.pay_params object 客户端拉起支付所需参数
payment.pay_params.trade_type string APP、MWEB 或 WAP
payment.pay_params.pay_url string H5 支付跳转地址,仅 MWEB/WAP 返回
payment.pay_params.h5_url string 微信原始 H5 地址,仅 MWEB 返回
payment.pay_params.return_url string 本次支付最终使用的完成回跳地址,仅微信 H5、支付宝 WAP 返回;客户端非空值优先,否则为后台配置
payment.pay_params.product_id string Apple IAP Product ID
payment.pay_params.application_username string StoreKit 1 / SwiftyStoreKit 购买时传入的 applicationUsername
payment.pay_params.requires_client_receipt_confirm boolean Apple IAP 是否需要客户端提交小票确认

响应示例:

{
  "code": 200,
  "message": "成功",
  "data": {
    "order_no": "TO202606170001",
    "payment_no": "TP202606170001",
    "payment_method": "apple_iap",
    "pay_params": {
      "product_id": "tieup.candy.300",
      "application_username": "550e8400-e29b-41d4-a716-446655440000",
      "requires_client_receipt_confirm": true,
      "storekit": "storekit1"
    },
    "pay_status": 1
  }
}

H5 支付宝糖果充值请求完整示例:

POST /tieup/api/v1/candy-recharges
Authorization: Bearer <access_token>
X-App-Platform: h5
Idempotency-Key: candy_recharge_h5_10001_20260731143000_x7f9k2
Content-Type: application/json
{
  "package_code": "candy_300",
  "payment_method": "alipay",
  "return_url": "https://h5.example.com/payment/result?source=recharge"
}

H5 支付宝糖果充值响应完整示例:

{
  "code": 200,
  "message": "成功",
  "data": {
    "recharge_no": "RC202607150002",
    "order_no": "TO202607150002",
    "transaction_no": "TP202607150002",
    "recharge_package_code": "candy_300",
    "product_name_snapshot": "300糖果",
    "amount_cent": 3000,
    "paid_amount_cent": 0,
    "currency": "CNY",
    "candy_amount": "300.00",
    "gift_candy_amount": "30.00",
    "total_candy_amount": "330.00",
    "status": 1,
    "paid_at": null,
    "closed_at": null,
    "delivered_at": null,
    "payment": {
      "order_no": "TO202607150002",
      "transaction_no": "TP202607150002",
      "order_status": 1,
      "payment_status": 1,
      "payment_method": "alipay",
      "provider_code": "alipay_wap",
      "payment_account_id": 4,
      "amount_cent": 3000,
      "currency": "CNY",
      "pay_params": {
        "trade_type": "WAP",
        "pay_url": "https://openapi.alipay.com/gateway.do?app_id=2026000000000000&method=alipay.trade.wap.pay&sign=example",
        "return_url": "https://h5.example.com/payment/result?source=recharge"
      }
    }
  }
}

业务规则:

  • 必须传 Idempotency-Key,同一用户同一幂等键只创建一笔 tieup_user_recharge
  • 服务端使用当前渠道、平台、市场筛选可用充值套餐,并快照套餐名称、金额和糖果数量。
  • 创建时写入 tieup_ordertieup_user_rechargebusiness_type = candy_rechargerecharge_type = 1
  • 同一 Idempotency-Key 重复请求:已生成可支付参数时返回原支付参数;上一请求仍在创建支付流水时返回 422,提示“支付流水已创建或正在创建中,请稍后查询订单支付状态”,避免重复拉起第三方支付;同一个幂等键不能更换套餐、金额、支付方式或 Apple 商品 ID。
  • 支付参数已生成后,重复请求省略 return_url 时沿用首次地址,显式传相同地址时复用;显式传不同地址,或历史支付流水缺少地址快照但本次传入地址时返回 422data.error_code = payment_return_url_conflict,不会创建新流水或重新预下单。
  • 客户端 return_url 允许任意完整 HTTP(S) 域名,客户端必须只提交可信业务页面,避免支付完成后跳转到不可信站点。
  • 回跳地址冲突响应为 422{"code":422,"message":"return_url与首次支付请求不一致","data":{"error_code":"payment_return_url_conflict"}}
  • 微信和支付宝支付成功回调后由糖果账户服务锁定用户行,增加 tieup_user.candy_balance 并写入 tieup_user_transactionchange_type = 1
  • H5 充值必须传 X-App-Platform: h5;微信 MWEB 或支付宝 WAP 返回 payment.pay_params.pay_url,回跳后通过充值详情或订单详情确认最终状态。
  • Apple IAP 仅支持 iOS 客户端。创建订单时服务端以充值套餐 config.ios_product_id 为准固化商品 ID,客户端购买成功后只提交完整小票到 POST /tieup/api/v1/payment-orders/apple-iap-receipts;服务端从 Apple 返回的 app_account_token 定位订单,小票校验通过后走糖果账户服务入账,重复小票或重复交易不会重复增加糖果。