Commit 31655d1d authored by luhongguang's avatar luhongguang

update:商品下单tcc

parent 38d4250a
...@@ -35,5 +35,6 @@ class GoodsException extends BaseException ...@@ -35,5 +35,6 @@ class GoodsException extends BaseException
21 => '商品介绍存在敏感词,请修改后提交', 21 => '商品介绍存在敏感词,请修改后提交',
22 => '规则说明存在敏感词,请修改后提交', 22 => '规则说明存在敏感词,请修改后提交',
23 => '商品快照数据不存在', 23 => '商品快照数据不存在',
24 => '当前商品库存不足',
]; ];
} }
\ No newline at end of file
<?php
namespace Validate;
/**
* Class GoodsTccValidate
*
* @package Validate
*/
class GoodsTccValidate extends BaseValidate
{
protected $rule = [
't_id' => 'require',
'goods_id' => 'require',
];
protected $message = [
"t_id" => "tcc事务id不能为空",
"goods_id" => "商品id不能为空",
];
}
\ No newline at end of file
<?php
namespace App\Models\goods\mysql;
use Api\PhpUtils\Mysql\MysqlBase;
/**
* Tcc
* tcc操作记录
* @package App\Models\goods\mysql
*/
class Tcc extends MysqlBase
{
const TABLE_NAME = 'inventory_tcc_record';
const CONFIG_INDEX = 'goods';
const STATUS_TRY = 1;// try
const STATUS_CONFIRM = 2;// confirm
const STATUS_CANCEL = 3;// cancel
const OPERATOR_RESULT_FAIL = 0;// 失败
const OPERATOR_RESULT_SUCCESS = 1;// 成功
public static function getRecord($where, $columns = [])
{
if (empty($columns)) {
$columns = '*';
}
return self::get($columns, $where);
}
public static function getRecordMaster($where, $columns = [])
{
if (empty($columns)) {
$columns = '*';
}
return self::selectMaster($columns, $where);
}
public static function save($data, $where = [])
{
if (empty($where)) {
return self::insert($data);
}
return self::update($data, $where);
}
}
\ No newline at end of file
<?php
use App\Base\Base;
use \Validate\GoodsTccValidate;
use \App\Services\tcc\TccService;
class TccController extends Base
{
/**
* 下单商品 tcc try
* @throws \App\Exception\custom\ParamException
*/
public function place_an_order_tryAction()
{
(new GoodsTccValidate())->validate();
$res = TccService::placeAnOrderTry($this->params["goods_id"], $this->params["t_id"]);
$this->success(["result"=>$res]);
}
/**
* 下单商品 tcc confirm
* @throws \App\Exception\custom\ParamException
*/
public function place_an_order_confirmAction()
{
(new GoodsTccValidate())->validate();
$res = TccService::placeAnOrderConfirm($this->params["goods_id"], $this->params["t_id"]);
$this->success(["result"=>$res]);
}
/**
* 下单商品 tcc cancel
* @throws \App\Exception\custom\ParamException
*/
public function place_an_order_cancelAction()
{
(new GoodsTccValidate())->validate();
$res = TccService::placeAnOrderCancel($this->params["goods_id"], $this->params["t_id"]);
$this->success(["result"=>$res]);
}
public function cancel_order_tryAction()
{
}
public function cancel_order_confirmAction()
{
}
public function cancel_order_cancelAction()
{
}
}
\ No newline at end of file
<?php
namespace App\Services\tcc;
use Api\PhpUtils\Common\BaseConvert;
use App\Exception\custom\GoodsException;
use App\Models\goods\mysql\GoodsSku;
use App\Models\goods\mysql\Tcc;
class TccService
{
const TCC_RESULT_FAIL = 0;
const TCC_RESULT_SUCCESS = 1;
/**
* 下单 商品tcc try
* @param $encryptGoodsSkuId
* @param $tid
* @return int
*/
public static function placeAnOrderTry($encryptGoodsSkuId, $tid)
{
$goodsSkuId = BaseConvert::otherToDec($encryptGoodsSkuId);
$tccInfo = Tcc::getRecordMaster(["t_id" => $tid, "goods_sku_id" => $goodsSkuId, "status" => Tcc::STATUS_TRY]);
//有结果返回原来的结果,幂等
if (!empty($tccInfo)) {
if ($tccInfo[0]["operator_result"] == Tcc::OPERATOR_RESULT_FAIL) {
return self::TCC_RESULT_FAIL;
} else {
return self::TCC_RESULT_SUCCESS;
}
}
//如果已经有 confirm 或者 cancel,则直接失败
$cTccInfo = Tcc::getRecordMaster(["t_id" => $tid, "goods_sku_id" => $goodsSkuId, "status" => [Tcc::STATUS_CONFIRM, Tcc::STATUS_CANCEL], "operator_result"=>Tcc::OPERATOR_RESULT_SUCCESS]);
if (empty($cTccInfo)) {
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_TRY,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
$sku = GoodsSku::getRecord(["goods_sku_id" => $goodsSkuId]);
if (!empty($sku["inventory_rest"]) && $sku["online_status"] == GoodsSku::ONLINE_STATUS_ONLINE) {
GoodsSku::beginTransaction();
GoodsSku::save([
"inventory_lock" => $sku["inventory_lock"] + 1,
"inventory_rest" => $sku["inventory_rest"] - 1,
], ["goods_sku_id" => $goodsSkuId]);
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_TRY,
"operator_result" => Tcc::OPERATOR_RESULT_SUCCESS,
]);
if (!GoodsSku::commit()) {
GoodsSku::rollback();
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_TRY,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
} else {
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_TRY,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
return self::TCC_RESULT_SUCCESS;
}
/**
* 下单 商品tcc confirm
* @param $encryptGoodsSkuId
* @param $tid
* @return int
*/
public static function placeAnOrderConfirm($encryptGoodsSkuId, $tid)
{
$goodsSkuId = BaseConvert::otherToDec($encryptGoodsSkuId);
$tccInfo = Tcc::getRecordMaster(["t_id" => $tid, "goods_sku_id" => $goodsSkuId, "status" => Tcc::STATUS_CONFIRM]);
//有结果返回原来的结果,幂等
if (!empty($tccInfo)) {
if ($tccInfo[0]["operator_result"] == Tcc::OPERATOR_RESULT_FAIL) {
return self::TCC_RESULT_FAIL;
} else {
return self::TCC_RESULT_SUCCESS;
}
}
//在confirm时候必须已经有try,如果没有就直接返回fail
$tryTccInfo = Tcc::getRecordMaster(["t_id" => $tid, "goods_sku_id" => $goodsSkuId, "status" => Tcc::STATUS_TRY, "operator_result"=>Tcc::OPERATOR_RESULT_SUCCESS]);
if (empty($tryTccInfo)) {
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CONFIRM,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
$sku = GoodsSku::getRecord(["goods_sku_id" => $goodsSkuId]);
if (!empty($sku["inventory_rest"]) && $sku["online_status"] == GoodsSku::ONLINE_STATUS_ONLINE) {
GoodsSku::beginTransaction();
GoodsSku::save([
"inventory_lock" => $sku["inventory_lock"] - 1,
"total_amount_order" => $sku["total_amount_order"] + 1,
], ["goods_sku_id" => $goodsSkuId]);
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CONFIRM,
"operator_result" => Tcc::OPERATOR_RESULT_SUCCESS,
]);
if (!GoodsSku::commit()) {
GoodsSku::rollback();
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CONFIRM,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
} else {
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CONFIRM,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
return self::TCC_RESULT_SUCCESS;
}
/**
* 下单 商品tcc cancel
* @param $encryptGoodsSkuId
* @param $tid
* @return int
*/
public static function placeAnOrderCancel($encryptGoodsSkuId, $tid)
{
$goodsSkuId = BaseConvert::otherToDec($encryptGoodsSkuId);
$tccInfo = Tcc::getRecordMaster(["t_id" => $tid, "goods_sku_id" => $goodsSkuId, "status" => Tcc::STATUS_CANCEL]);
//有结果返回原来的结果,幂等
if (!empty($tccInfo)) {
if ($tccInfo[0]["operator_result"] == Tcc::OPERATOR_RESULT_FAIL) {
return self::TCC_RESULT_FAIL;
} else {
return self::TCC_RESULT_SUCCESS;
}
}
//在cancel时候必须已经有try,如果没有就直接返回fail
$tryTccInfo = Tcc::getRecordMaster(["t_id" => $tid, "goods_sku_id" => $goodsSkuId, "status" => Tcc::STATUS_TRY, "operator_result"=>Tcc::OPERATOR_RESULT_SUCCESS]);
if (empty($tryTccInfo)) {
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CANCEL,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
//如果已经 confirm 成功
$confirmTccInfo = Tcc::getRecordMaster(["t_id" => $tid, "goods_sku_id" => $goodsSkuId, "status" => Tcc::STATUS_CONFIRM, "operator_result"=>Tcc::OPERATOR_RESULT_SUCCESS]);
if (!empty($confirmTccInfo)) {
return self::TCC_RESULT_FAIL;
}
$sku = GoodsSku::getRecord(["goods_sku_id" => $goodsSkuId]);
if (!empty($sku["inventory_rest"]) && $sku["online_status"] == GoodsSku::ONLINE_STATUS_ONLINE) {
GoodsSku::beginTransaction();
GoodsSku::save([
"inventory_lock" => $sku["inventory_lock"] - 1,
"inventory_rest" => $sku["inventory_rest"] + 1,
], ["goods_sku_id" => $goodsSkuId]);
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CANCEL,
"operator_result" => Tcc::OPERATOR_RESULT_SUCCESS,
]);
if (!GoodsSku::commit()) {
GoodsSku::rollback();
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CANCEL,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
} else {
Tcc::save([
"t_id" => $tid,
"goods_sku_id" => $goodsSkuId,
"status" => Tcc::STATUS_CANCEL,
"operator_result" => Tcc::OPERATOR_RESULT_FAIL,
]);
return self::TCC_RESULT_FAIL;
}
return self::TCC_RESULT_SUCCESS;
}
public static function cancelOrderTry()
{
}
public static function cancelOrderConfirm()
{
}
public static function cancelOrderCancel()
{
}
}
\ No newline at end of file
...@@ -3,7 +3,7 @@ application.directory = APP_PATH ...@@ -3,7 +3,7 @@ application.directory = APP_PATH
application.bootstrap = APP_PATH "/Bootstrap.php" application.bootstrap = APP_PATH "/Bootstrap.php"
application.library = APP_PATH"/library" application.library = APP_PATH"/library"
application.library.namespace = "" application.library.namespace = ""
application.modules="Index,Test,Goods,Shop,Distribution" application.modules="Index,Test,Goods,Shop,Distribution,Tcc"
appid = "goods" appid = "goods"
;AES密钥 ;AES密钥
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment