Object.keys(record).sort().map(key => `${key}=${record[key]}`).join('&')).join('&') class InAppPurchase { public function process() { $data = json_decode(file_get_contents('php://input'), true); error_log('InappPurchase:' . json_encode($_REQUEST)); error_log('----- inappPurchaseDiamonds -----' . json_encode($data)); if (!$this->verifySign($data)) { myself()->_rspErr(1, "signature error"); return; } // 有三种情况: // 1. 从商城购买钻石,有订单号 // 2. 站外充值钻石,没有订单号 // 3. appstore 退款,没有订单号 $records = $data['records']; for ($i = 0; $i < count($records); $i++) { $this->processOneOrder($records[$i]); } myself()->_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); $signature = hash_hmac('sha256', $signStr, BUY_SERVER_PKEY); error_log('InAppPurchase verify ' . $signStr . ' sign1=' . $sign . ' sign2=' . $signature); 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 ' . $orderId . ' ' . json_encode($_REQUEST)); return; } if ($orderDb['status'] == InAppOrder::FINISHED_STATE) { return; } if ($orderDb['status'] == InAppOrder::FAILED_STATE) { return; } $accountId = $orderDb['account_id']; switch ($status) { case 9: { InAppOrder::update( $orderId, array( 'status' => InAppOrder::FINISHED_STATE, 'sp_order_id' => $spOrderId )); FirstTopup::add($accountId); $goodsMeta = mt\ShopGoods::get($orderDb['goods_id']); if (!$goodsMeta) { myself()->_addLogEx($orderDb['account_id'], 'InAppPurchase', 'error_not_found_goods', array( $ordreDb['order_id'], json_encode($orderDb) )); return; } $itemId = $goodsMeta['item_id']; $itemNum = $goodsMeta['item_num']; if ($itemId == V_ITEM_DIAMOND) { InAppRecord::addAmountOk($orderDb['account_id'], $orderDb['price']); $addItemService = new ShopAddItemService(); $addItemService->addItemByAccountId($orderDb['account_id'], $itemId, $itemNum); myself()->_addLogEx($orderDb['account_id'], 'InAppPurchase', 'ok', array( $orderDb['order_id'], json_encode($orderDb) )); } else { myself()->_addLogEx($orderDb['account_id'], 'InAppPurchase', 'error_goods_item_id', array( $ordreDb['order_id'], json_encode($orderDb) )); return; } } break; case 96: { myself()->_addLogEx($orderDb['account_id'], 'InAppPurchase', 'refund', array( $ordreDb['order_id'], json_encode($orderDb) )); return; } break; default: { myself()->_addLogEx($orderDb['account_id'], 'InAppPurchase', 'error_order_status', array( $ordreDb['order_id'], json_encode($orderDb) )); } break; } } }