diff --git a/doc/Shop.py b/doc/Shop.py index ec019caf..6fa119e5 100644 --- a/doc/Shop.py +++ b/doc/Shop.py @@ -208,6 +208,24 @@ class Shop(object): ['status', 0, '订单状态 0:未支付 1:已支付 2:支付失败'], ] }, + { + 'name':'inappPurchaseDiamonds', + 'desc': '内购回调', + 'group': 'Shop', + 'url': 'webapp/index.php?c=Shop&a=inappPurchaseDiamonds', + 'params': [ + ['channel', '', '渠道 goole or apple'], + ['sign', '', '签名'], + ['records', '', '购买记录,以下字段是一个record的表示'], + ['productId', '', '商品id'], + ['gameOrderId', '', '游戏订单id'], + ['orderId', '', 'google订单id'], + ['status', 0, '订单状态'], + ], + 'response': [ + _common.RspHead(), + ] + }, { 'name': 'getPayMethods', 'desc': '获取支付方式', diff --git a/doc/_common.py b/doc/_common.py index b82060f4..ebb62205 100644 --- a/doc/_common.py +++ b/doc/_common.py @@ -1236,4 +1236,13 @@ class BlindBoxResult(object): self.fields = [ ['item_id', 0, 'item_id'], ['item_num', 0, 'item_num'], + ] + +class InappPurchaseRecord(object): + def __init__(self): + self.fields = [ + ['productId', '', '商品id'], + ['gameOrderId', '', '游戏订单id'], + ['orderId', '', 'google订单id'], + ['status', 0, '订单状态'], ] \ No newline at end of file diff --git a/sql/gamedb.sql b/sql/gamedb.sql index 4acc6b22..b363e703 100644 --- a/sql/gamedb.sql +++ b/sql/gamedb.sql @@ -1267,3 +1267,24 @@ CREATE TABLE `t_user_honor` ( UNIQUE KEY `address` (`address`) ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; /*!40101 SET character_set_client = @saved_cs_client */; + +DROP TABLE IF EXISTS `t_web2_order`; +CREATE TABLE `t_web2_order` ( + `idx` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', + `status` int(11) NOT NULL COMMENT '订单状态 0-客户端申请了订单 1-订单完成 2-订单失败', + `order_id` varchar(64) DEFAULT NULL COMMENT '订单id', + `createtime` datetime NOT NULL COMMENT '创建时间', + `account_Id` varchar(64) NOT NULL COMMENT '申请账号id', + `address` varchar(64) DEFAULT NULL COMMENT '申请时账号绑定的钱包', + `item_id` int(11) NOT NULL COMMENT '物品id', + `item_num` int(11) NOT NULL COMMENT '物品数量', + `id` int(11) NOT NULL COMMENT '商店中的配置id,', + `goods_num` int(11) NOT NULL COMMENT '购买商品个数', + `price` varchar(64) DEFAULT NULL COMMENT '价格', + `ext_data` mediumblob COMMENT '扩展自定义数据', + `channel` varchar(64) DEFAULT NULL COMMENT 'google or apple', + `out_order_id` varchar(64) DEFAULT NULL COMMENT 'app store order_id', + PRIMARY KEY (`idx`), + UNIQUE KEY `order_id` (`order_id`) USING HASH, + KEY `out_order_id` (`out_order_id`) +) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/sql/gamedb2006_migrate_230710_01.sql b/sql/gamedb2006_migrate_230710_01.sql index 5b4f2db2..fa532b73 100644 --- a/sql/gamedb2006_migrate_230710_01.sql +++ b/sql/gamedb2006_migrate_230710_01.sql @@ -14,6 +14,26 @@ CREATE TABLE `t_user_honor` ( UNIQUE KEY `address` (`address`) ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +CREATE TABLE `t_web2_order` ( + `idx` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', + `status` int(11) NOT NULL COMMENT '订单状态 0-客户端申请了订单 1-订单完成 2-订单失败', + `order_id` varchar(64) DEFAULT NULL COMMENT '订单id', + `createtime` datetime NOT NULL COMMENT '创建时间', + `account_Id` varchar(64) NOT NULL COMMENT '申请账号id', + `address` varchar(64) DEFAULT NULL COMMENT '申请时账号绑定的钱包', + `item_id` int(11) NOT NULL COMMENT '物品id', + `item_num` int(11) NOT NULL COMMENT '物品数量', + `id` int(11) NOT NULL COMMENT '商店中的配置id,', + `goods_num` int(11) NOT NULL COMMENT '购买商品个数', + `price` varchar(64) DEFAULT NULL COMMENT '价格', + `ext_data` mediumblob COMMENT '扩展自定义数据', + `channel` varchar(64) DEFAULT NULL COMMENT 'google or apple', + `out_order_id` varchar(64) DEFAULT NULL COMMENT 'app store order_id', + PRIMARY KEY (`idx`), + UNIQUE KEY `order_id` (`order_id`) USING HASH, + KEY `out_order_id` (`out_order_id`) +) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8; + insert into version (version) values(2023071001); commit; \ No newline at end of file diff --git a/webapp/controller/ShopController.class.php b/webapp/controller/ShopController.class.php index 24b49c9b..52c3d739 100644 --- a/webapp/controller/ShopController.class.php +++ b/webapp/controller/ShopController.class.php @@ -50,10 +50,6 @@ use models\BcOrder; use services\LogService; use services\ShopAddItemService; -use function phpcommon\bnAdd_s; -use function phpcommon\bnDiv_s; -use function phpcommon\bnInit; - if (!function_exists('array_column')) { function array_column($arr2, $column_key) { @@ -420,8 +416,8 @@ class ShopController extends BaseAuthedController // gen order id $order_id_base = date('YmdHis') . "10000000"; $divIdx = ($lastId) % 9999999; - - $order_id = bnAdd_s($order_id_base, $divIdx); + + $order_id = phpcommon\bnAdd_s($order_id_base, $divIdx); $test = SqlHelper::update($conn, 't_web2_order', array('idx' => $lastId), array('order_id' => $order_id)); if (!$test) { $this->_rspErr(5, "start purchase failed"); @@ -446,10 +442,17 @@ class ShopController extends BaseAuthedController public function inappPurchaseDiamonds() { + error_log('----- inappPurchaseDiamonds -----'); + error_log('request:' . json_encode($_REQUEST)); + error_log('post:' . json_encode($_POST)); + $body = json_decode(file_get_contents('php://input'), true); + error_log('body:' . json_encode($body)); + $channel = $body['channel']; + $records = $body['records']; + $sign = $body['sign']; + + error_log('records:' . json_encode($records)); - error_log(json_encode($_REQUEST)); - - $order_id = getReqVal('order_id', ''); // { // channel: 'google', // sign: '123456677' // 签名字段 @@ -469,63 +472,102 @@ class ShopController extends BaseAuthedController // const sign = hmacsha256(signStr, hashSort) + // 定义一个空数组,用来存放每个记录的键值对字符串 + $record_strings = array(); + + // 遍历 records 数组,对每个记录进行排序和拼接 + foreach ($records as $record) { + // 对记录的键进行升序排序 + ksort($record); + // 把记录的键值对用等号连接,然后用 & 连接成一个字符串 + $record_string = http_build_query($record); + // 把字符串加入到 record_strings 数组中 + $record_strings[] = $record_string; + } + + // 把 record_strings 数组用 & 连接成一个字符串 + $records_string = implode("&", $record_strings); + + $hash_data = 'channel=' . $channel . '&' . $records_string; + + $signature = hash_hmac('sha256', $hash_data, 'iG4Rpsa)6U31$H#^T85$^^3'); + + if ($signature != $sign) { + $this->_rspErr(1, "signature error, signature: {$signature}, sign: {$sign}"); + return; + } + + $conn = myself()->_getMysql(''); // 有三种情况: // 1. 从商城购买钻石,有订单号 // 2. 站外充值钻石,没有订单号 // 3. appstore 退款,没有订单号 - $order_id = getReqVal('order_id', ''); + for ($i = 0; $i < count($records); $i++) { + $record = $records[$i]; - error_log('----- inappPurchaseDiamonds -----'); + $product_id = $record['productId']; + $order_id = $record['gameOrderId']; + $out_order_id = $record['orderId']; + $status = $record['status']; - $data = [ - 'channel' => 'google', - 'sign' => '123456677', - 'records' => [[ - 'productId' => '2999', // 从google play console获取的product id - 'gameOrderId' => '299', // 开始支付时, 从游戏相关服务那获得的订单id - 'orderId' => 'GPA.3355-1172-9416-16839', // 从google develope API 获取的订单id - 'status' => 9, // 订单状态, 上报的订单状态一般只有2种情况, 9: 支付成功, 96: 用户退款 - ]] - ]; + switch ($status) { + case 9: { + $status = 1; + if (empty($order_id)) { + if (empty($product_id)) { + $this->_rspErr(2, "product_id is empty"); + return; + } + // $goods = mt\ShopGoods::getByProductId($product_id); - $order_id = $data['records'][0]['gameOrderId']; - $data_str = json_encode($data); - $data_json = json_decode($data_str, true); - error_log('----- inappPurchaseDiamonds -----' . json_encode($data)); + return; + } - $conn = myself()->_getMysql(''); + $order = SqlHelper::selectOne($conn, 't_web2_order', array('address', 'id', 'item_id', 'goods_num', 'status'), array('order_id' => $order_id, 'status' => 0)); + error_log('process order '. json_encode($order)); + if (!$order) { + $this->_rspErr(3, "order not found, order_id: {$order_id}"); + return; + } + + SqlHelper::update($conn, 't_web2_order', array('order_id' => $order_id), array('status' => $status, 'channel' => $channel, 'out_order_id' => $out_order_id)); - $order = SqlHelper::selectOne($conn, 't_shop_buy_order', array('address', 'id', 'item_id', 'goods_num', 'status'), array('idx' => $order_id)); + $id = $order['id']; + $goods = mt\ShopGoods::get($id); + // 这里命名混乱了, 购买个数,一捆个数命名冲突 + $goods_num = $order['goods_num']; + $bundle_size = $goods['goods_num']; + $item_num = $goods_num * $bundle_size; + $item_id = $goods['goods_id']; + $address = $order['address']; + $account_id = $this->getAccountId($address); - $buyStatus = 1; + if ($item_id == V_ITEM_DIAMOND) { + $event = [ + 'name' => LogService::RECHARGE_DIAMOND, + 'val' => $item_num + ]; + LogService::productDiamond(['account_id' => $account_id], $event); + } - SqlHelper::update($conn, 't_shop_buy_order', array('idx' => $order_id), array('status' => $buyStatus)); - - $id = $order['id']; - $goods = mt\ShopGoods::get($id); - // 这里命名混乱了, 购买个数,一捆个数命名冲突 - $goods_num = $order['goods_num']; - $bundle_size = $goods['goods_num']; - $item_num = $goods_num * $bundle_size; - $item_id = $goods['goods_id']; - $address = $order['address']; - $account_id = $this->getAccountId($address); - - if ($item_id == V_ITEM_DIAMOND) { - $event = [ - 'name' => LogService::RECHARGE_DIAMOND, - 'val' => $item_num - ]; - LogService::productDiamond(['account_id' => $account_id], $event); + $this->_addGoods($address, array( + 'goods_id' => $item_id, + 'goods_num' => $item_num, + 'id' => $id, + )); + } + break; + case 96: + // 退款 + $status = 2; + break; + default: + $status = 0; + break; + } } - $this->_addGoods($address, array( - 'goods_id' => $item_id, - 'goods_num' => $item_num, - 'id' => $id, - )); - $this->_rspOk(); }