Object.keys(record).sort().map(key => `${key}=${record[key]}`).join('&')).join('&') class InAppPurchase { public function process() { error_log('InappPurchase:' . json_encode($_REQUEST)); error_log('----- inappPurchaseDiamonds -----'); $data = json_decode(file_get_contents('php://input'), true); if (!$this->verifySign($data)) { $this->_rspErr(1, "signature error"); return; } // 有三种情况: // 1. 从商城购买钻石,有订单号 // 2. 站外充值钻石,没有订单号 // 3. appstore 退款,没有订单号 $records = $data['records']; for ($i = 0; $i < count($records); $i++) { $this->processOneOrder($records[i]); } $this->_rspOk(); } private function verifySign($data) { $channel = $data['channel']; $records = $data['records']; $sign = $data['sign']; $strings = array(); foreach ($records as $record) { ksort($record); foreach($record as $key => $val){ array_push($strings, $key . '=' . $val); } } $signStr = 'channel=' . $channel . '&' . implode("&", $strings); error_log('InAppPurchase verify ' . $signStr); $signature = hash_hmac('sha256', $singStr, BUY_SERVER_PKEY); return $sign == $signature; } private function processOneOrder($record) { $productId = $record['productId']; $orderId = $record['gameOrderId']; $spOrderId = $record['orderId']; $status = $record['status']; $orderDb = InAppOrder::find($orderId); if (!$orderDb) { error_log('InAppPurchase: not found order ' . json_encode($_REQUEST)); return; } 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); return; } $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)); $id = $order['id']; $goods = 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']; if (empty($address)) { $this->_rspErr(4, "address is empty"); return; } $account_id = $this->getAccountId($address); if (empty($account_id)) { $this->_rspErr(5, "account_id is empty"); return; } 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 = 3; if (empty($order_id)) { if (empty($product_id)) { $this->_rspErr(2, "product_id is empty"); return; } // $goods = mt\ShopGoods::getByProductId($product_id); return; } // 退款 $order = SqlHelper::selectOne($conn, 't_web2_order', array('address', 'id', 'item_id', 'goods_num', 'status'), array('order_id' => $order_id, 'status' => 1)); 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)); $id = $order['id']; $goods = 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']; if (empty($address)) { $this->_rspErr(4, "address is empty"); return; } $account_id = $this->getAccountId($address); if (empty($account_id)) { $this->_rspErr(5, "account_id is empty"); return; } if ($item_id == V_ITEM_DIAMOND) { $event = [ 'name' => LogService::RECHARGE_DIAMOND, 'val' => -$item_num ]; LogService::productDiamond(['account_id' => $account_id], $event); } $this->_decGoods($address, array( 'goods_id' => $item_id, 'goods_num' => $item_num, 'id' => $id, )); break; default: { myself()->_addLogEx($orderDb['account_id'], 'InAppPurchase', 'error_order_status', array( $ordreDb['order_id'], json_encode($orderDb) )); } break; } } }