@@ -0,0 +1,260 @@
package com.gxwebsoft.common.system.controller ;
import com.alibaba.fastjson.JSONArray ;
import com.alibaba.fastjson.JSONObject ;
import cn.hutool.core.util.IdUtil ;
import com.gxwebsoft.common.core.Constants ;
import com.gxwebsoft.common.core.web.ApiResult ;
import com.gxwebsoft.common.core.web.BaseController ;
import com.gxwebsoft.common.system.entity.Order ;
import com.gxwebsoft.common.system.entity.User ;
import com.gxwebsoft.common.system.param.SubscriptionOrderParam ;
import com.gxwebsoft.common.system.result.SubscriptionOrderCreateResult ;
import com.gxwebsoft.common.system.result.SubscriptionOrderPayResult ;
import com.gxwebsoft.common.system.result.SubscriptionPriceResult ;
import com.gxwebsoft.common.system.service.SettingService ;
import io.swagger.v3.oas.annotations.Operation ;
import io.swagger.v3.oas.annotations.tags.Tag ;
import org.springframework.web.bind.annotation.PostMapping ;
import org.springframework.web.bind.annotation.RequestBody ;
import org.springframework.web.bind.annotation.RequestMapping ;
import org.springframework.web.bind.annotation.RestController ;
import javax.annotation.Resource ;
import java.math.BigDecimal ;
import java.math.RoundingMode ;
import java.util.Arrays ;
import java.util.List ;
/**
* 订阅订单接口
*/
@Tag ( name = " 订阅订单 " )
@RestController
@RequestMapping ( " /api/system/subscription-order " )
public class SubscriptionOrderController extends BaseController {
@Resource
private SettingService settingService ;
@Resource
private WxNativePayController wxNativePayController ;
@Operation ( summary = " 计算订阅订单价格 " )
@PostMapping ( " /calculate-price " )
public ApiResult < SubscriptionPriceResult > calculatePrice ( @RequestBody SubscriptionOrderParam param ) {
final User loginUser = getLoginUser ( ) ;
if ( loginUser = = null ) {
return fail ( " 请先登录 " , null ) ;
}
if ( param . getPackageId ( ) = = null ) {
return fail ( " 套餐ID不能为空 " , null ) ;
}
JSONObject config = loadSubscriptionConfig ( ) ;
final SubscriptionPriceResult result = buildPriceResult ( param , config ) ;
return success ( result ) ;
}
@Operation ( summary = " 创建订阅订单 " )
@PostMapping ( " /create " )
public ApiResult < SubscriptionOrderCreateResult > create ( @RequestBody SubscriptionOrderParam param ) {
final User loginUser = getLoginUser ( ) ;
if ( loginUser = = null ) {
return fail ( " 请先登录 " , null ) ;
}
if ( param . getPackageId ( ) = = null ) {
return fail ( " 套餐ID不能为空 " , null ) ;
}
JSONObject config = loadSubscriptionConfig ( ) ;
final SubscriptionPriceResult price = buildPriceResult ( param , config ) ;
SubscriptionOrderCreateResult result = new SubscriptionOrderCreateResult ( ) ;
result . setOrderNo ( IdUtil . getSnowflakeNextIdStr ( ) ) ;
result . setPrice ( price ) ;
return success ( result ) ;
}
@Operation ( summary = " 订阅订单支付( 生成微信Native二维码) " )
@PostMapping ( " /pay " )
public ApiResult < SubscriptionOrderPayResult > pay ( @RequestBody SubscriptionOrderParam param ) {
final User loginUser = getLoginUser ( ) ;
if ( loginUser = = null ) {
return fail ( " 请先登录 " , null ) ;
}
if ( param . getPackageId ( ) = = null ) {
return fail ( " 套餐ID不能为空 " , null ) ;
}
JSONObject config = loadSubscriptionConfig ( ) ;
final SubscriptionPriceResult price = buildPriceResult ( param , config ) ;
if ( price . getPayPrice ( ) = = null | | price . getPayPrice ( ) . compareTo ( BigDecimal . ZERO ) < = 0 ) {
return fail ( " 支付金额必须大于0 " , null ) ;
}
// 构造订单用于生成支付二维码
Order order = new Order ( ) ;
order . setPayPrice ( price . getPayPrice ( ) ) ;
order . setTotalPrice ( price . getTotalPrice ( ) ) ;
order . setComments ( " 订阅套餐- " + param . getPackageId ( ) ) ;
order . setPayType ( param . getPayType ( ) ) ;
order . setUserId ( loginUser . getUserId ( ) ) ;
order . setTenantId ( loginUser . getTenantId ( ) ) ;
ApiResult < ? > payResp = wxNativePayController . getCodeUrl ( order ) ;
if ( payResp . getCode ( ) = = null | | ! payResp . getCode ( ) . equals ( Constants . RESULT_OK_CODE ) ) {
return fail ( payResp . getMessage ( ) , null ) ;
}
SubscriptionOrderPayResult result = new SubscriptionOrderPayResult ( ) ;
result . setOrderNo ( order . getOrderNo ( ) ) ;
result . setCodeUrl ( String . valueOf ( payResp . getData ( ) ) ) ;
result . setPrice ( price ) ;
return success ( result ) ;
}
/**
* 从配置表读取订阅套餐配置( 尝试多种key以兼容历史数据)
*/
private JSONObject loadSubscriptionConfig ( ) {
final List < String > keys = Arrays . asList ( " subscription " , " subscription-package " , " subscriptionOrder " ) ;
for ( String key : keys ) {
try {
JSONObject cfg = settingService . getBySettingKey ( key ) ;
if ( cfg ! = null ) {
return cfg ;
}
} catch ( Exception ignored ) {
}
}
return new JSONObject ( ) ;
}
/**
* 计算价格结果
*/
private SubscriptionPriceResult buildPriceResult ( SubscriptionOrderParam param , JSONObject config ) {
BigDecimal originalPrice = resolveBasePrice ( param . getPackageId ( ) , config ) ;
BigDecimal factor = BigDecimal . ONE ;
StringBuilder remark = new StringBuilder ( ) ;
if ( config = = null | | config . isEmpty ( ) ) {
remark . append ( " 未查询到订阅价格配置, 已按0元试算; " ) ;
}
if ( originalPrice . compareTo ( BigDecimal . ZERO ) = = 0 & & config ! = null & & ! config . isEmpty ( ) ) {
remark . append ( " 未找到套餐价格, 已按0元试算; " ) ;
}
if ( isTrue ( param . getIsRenewal ( ) ) ) {
BigDecimal renewalFactor = resolveFactor ( config , " renewalDiscount " ) ;
factor = factor . multiply ( renewalFactor ) ;
remark . append ( " 续费系数: " ) . append ( renewalFactor ) . append ( " ; " ) ;
}
if ( isTrue ( param . getIsUpgrade ( ) ) ) {
BigDecimal upgradeFactor = resolveFactor ( config , " upgradeDiscount " ) ;
factor = factor . multiply ( upgradeFactor ) ;
remark . append ( " 升级系数: " ) . append ( upgradeFactor ) . append ( " ; " ) ;
}
BigDecimal payTypeFactor = resolvePayTypeFactor ( config , param . getPayType ( ) ) ;
factor = factor . multiply ( payTypeFactor ) ;
if ( param . getPayType ( ) ! = null ) {
remark . append ( " 支付系数: " ) . append ( payTypeFactor ) . append ( " ; " ) ;
}
BigDecimal payPrice = originalPrice . multiply ( factor ) . setScale ( 2 , RoundingMode . HALF_UP ) ;
BigDecimal discount = originalPrice . subtract ( payPrice ) ;
if ( discount . compareTo ( BigDecimal . ZERO ) < 0 ) {
discount = BigDecimal . ZERO ;
}
SubscriptionPriceResult result = new SubscriptionPriceResult ( ) ;
result . setPackageId ( param . getPackageId ( ) ) ;
result . setIsRenewal ( param . getIsRenewal ( ) ) ;
result . setIsUpgrade ( param . getIsUpgrade ( ) ) ;
result . setPayType ( param . getPayType ( ) ) ;
result . setOriginalPrice ( originalPrice . setScale ( 2 , RoundingMode . HALF_UP ) ) ;
result . setTotalPrice ( originalPrice . setScale ( 2 , RoundingMode . HALF_UP ) ) ;
result . setPayPrice ( payPrice ) ;
result . setDiscountAmount ( discount . setScale ( 2 , RoundingMode . HALF_UP ) ) ;
result . setRemark ( remark . toString ( ) ) ;
return result ;
}
private boolean isTrue ( Integer value ) {
return value ! = null & & value . equals ( 1 ) ;
}
/**
* 解析套餐价格,支持 packages 数组、priceMap 或单价配置
*/
private BigDecimal resolveBasePrice ( Integer packageId , JSONObject config ) {
if ( config ! = null ) {
JSONArray packages = config . getJSONArray ( " packages " ) ;
if ( packages ! = null ) {
for ( Object item : packages ) {
if ( item instanceof JSONObject ) {
JSONObject pkg = ( JSONObject ) item ;
Integer id = pkg . getInteger ( " id " ) ;
if ( id = = null ) {
id = pkg . getInteger ( " packageId " ) ;
}
if ( packageId . equals ( id ) ) {
BigDecimal price = pkg . getBigDecimal ( " price " ) ;
if ( price ! = null ) {
return price ;
}
}
}
}
}
JSONObject priceMap = config . getJSONObject ( " priceMap " ) ;
if ( priceMap ! = null ) {
BigDecimal price = priceMap . getBigDecimal ( packageId . toString ( ) ) ;
if ( price ! = null ) {
return price ;
}
}
BigDecimal fallbackPrice = config . getBigDecimal ( " price " ) ;
if ( fallbackPrice ! = null ) {
return fallbackPrice ;
}
}
return BigDecimal . ZERO ;
}
/**
* 获取折扣系数,默认 1
*/
private BigDecimal resolveFactor ( JSONObject config , String key ) {
if ( config ! = null ) {
BigDecimal factor = config . getBigDecimal ( key ) ;
if ( factor ! = null ) {
return factor ;
}
}
return BigDecimal . ONE ;
}
/**
* 支付方式系数,可在配置中通过 payTypeDiscount 或 payTypeAdjustments 定义
*/
private BigDecimal resolvePayTypeFactor ( JSONObject config , Integer payType ) {
if ( config ! = null & & payType ! = null ) {
JSONObject payTypeDiscount = config . getJSONObject ( " payTypeDiscount " ) ;
if ( payTypeDiscount = = null ) {
payTypeDiscount = config . getJSONObject ( " payTypeAdjustments " ) ;
}
if ( payTypeDiscount ! = null ) {
BigDecimal factor = payTypeDiscount . getBigDecimal ( payType . toString ( ) ) ;
if ( factor ! = null ) {
return factor ;
}
}
}
return BigDecimal . ONE ;
}
}