get('merchants', []); $merchantId = $merchants[$school]['merchant_id'] ?? null; if (!$merchantId) { http_response_code(400); echo 'School not onboarded'; exit; } $client = new PayPalClient($config); $returnUrl = rtrim($config['base_url'], '/') . '/capture_order.php'; $cancelUrl = rtrim($config['base_url'], '/') . '/index.php'; // Orders v2 create, routing funds to payee.merchant_id $payload = [ 'intent' => 'CAPTURE', 'purchase_units' => [[ 'amount' => [ 'currency_code' => 'USD', 'value' => number_format((float)$amount, 2, '.', ''), ], 'payee' => [ 'merchant_id' => $merchantId, ], 'description' => 'School Lunch Payment for ' . $school, ]], 'application_context' => [ 'brand_name' => 'School Lunch Service', 'landing_page' => 'LOGIN', 'shipping_preference' => 'NO_SHIPPING', 'user_action' => 'PAY_NOW', 'return_url' => $returnUrl, 'cancel_url' => $cancelUrl, ], ]; $resp = $client->api('POST', '/v2/checkout/orders', $payload); if ($resp['status'] < 200 || $resp['status'] >= 300) { http_response_code(500); echo 'Create order failed: ' . htmlspecialchars(json_encode($resp)); exit; } $order = $resp['body']; $approve = null; foreach (($order['links'] ?? []) as $lnk) { if (($lnk['rel'] ?? '') === 'approve') { $approve = $lnk['href']; break; } } if (!$approve) { http_response_code(500); echo 'Missing approval link'; exit; } // Save a minimal order record for demo $orders = $storage->get('orders', []); $orders[$order['id']] = [ 'school' => $school, 'amount' => $payload['purchase_units'][0]['amount']['value'], 'merchant_id' => $merchantId, 'status' => 'CREATED', ]; $storage->set('orders', $orders); header('Location: ' . $approve); exit;