Payment::STATUS_IN_PROGRESS, 1 => Payment::STATUS_IN_PROGRESS, 2 => Payment::STATUS_SUCCESS, 3 => Payment::STATUS_SUCCESS, -1 => Payment::STATUS_FAIL, -2 => Payment::STATUS_FAIL, -3 => Payment::STATUS_REFUND, -4 => Payment::STATUS_IN_PROGRESS, ]; public function __construct($config = []) { if (!$config) { $config = config('pay.StarPay'); } $this->config = $config; } public function create($orderSn, $amount, $options = []) { $data = []; $data['appId'] = $this->config['appID']; $data['merOrderNo'] = $orderSn; $data['currency'] = 'MXN'; $data['amount'] = strval($amount); $data['extra'] = [ 'single' => false, 'minAmount' => $this->config['minOrderAmount'] ?? 20, 'maxAmount' => $this->config['maxOrderAmount'] ?? 50000, ]; $data['returnUrl'] = $this->config['syncNotify']; $data['notifyUrl'] = $this->config['notify']; $data['attach'] = strval($options['userId'] ?? '0'); $data['sign'] = $this->sign($this->config['secretKey'], $data); $client = new Client(['verify' => false, 'timeout' => 10]); $url = $this->config['baseUrl'] . '/api/v1/payment/order/create'; $request_extra = \GuzzleHttp\json_encode($data); CreateLog::pay_request('', $request_extra, $orderSn, '', '', ''); Util::WriteLog('StarPay', 'payin request: ' . $url . ' | ' . $request_extra); $resp = $client->post($url, [ 'json' => $data, ]); if ($resp->getStatusCode() !== 200) { return $resp->getReasonPhrase(); } $content = $resp->getBody()->getContents(); Util::WriteLog('StarPay', 'payin response: ' . $url . ' | ' . $request_extra . '|' . $content); $json = json_decode($content, true); if (json_last_error() !== JSON_ERROR_NONE) { Util::WriteLog('StarPay_error', [ 'result' => $content, 'url' => $url, ]); } return $json; } public function cash($OrderId, $amount, $bankCode, $bankName, $accountNo, $accountName) { $data = [ 'appId' => $this->config['appID'], 'merOrderNo' => $OrderId, 'currency' => 'MXN', 'amount' => strval(round($amount, 2)), 'notifyUrl' => $this->config['notify'], 'extra' => [ 'bankCode' => $bankCode, 'bankName' => $bankName, 'accountNo' => $accountNo, 'accountName' => $accountName, 'accountType' => strlen($accountNo) == 16 ? 3 : 40, ], ]; $data['sign'] = $this->sign($this->config['secretKey'], $data); $url = $this->config['baseUrl'] . '/api/v1/payout/order/create'; Util::WriteLog('StarPay', 'payout request: ' . $url . ' | ' . json_encode($data, JSON_UNESCAPED_UNICODE)); $client = new Client(['verify' => false, 'timeout' => 10]); $resp = $client->post($url, [ 'json' => $data, ]); $content = $resp->getBody()->getContents(); Util::WriteLog('StarPay', 'payout response: ' . $content); $json = json_decode($content, true); if (json_last_error() !== JSON_ERROR_NONE) { Util::WriteLog('StarPay_error', ['decode fail', json_last_error_msg()]); return false; } return $json; } public function verifySign($data, $headers = []): bool { $sign = $this->sign($this->config['secretKey'], $data); return $sign == $data['sign']; } public function notifyFail() { return 'fail'; } public function notifySuccess() { return 'success'; } public function notify($data) { if (!isset($data['orderStatus'])) { throw new \RuntimeException('invalid notify data'); } $r = new \stdClass(); $r->status = self::STATUS_MAP[$data['orderStatus']] ?? Payment::STATUS_UNKNOWN; $r->orderNo = $data['orderNo']; $r->orderSn = $data['merOrderNo']; $r->amount = $data['paidAmount']; $r->buyerId = $data['attach']; return $r; } public function cashNotify($data) { $r = new \stdClass(); $r->status = self::STATUS_MAP[$data['orderStatus']] ?? Payment::STATUS_UNKNOWN; $r->orderNo = $data['orderNo']; $r->orderSn = $data['merOrderNo']; $r->amount = $data['amount']; return $r; } public function search($orderNo, $orderSn) { $data = []; $data['appId'] = $this->config['appID']; $data['orderNo'] = $orderNo; $data['sign'] = $this->sign($this->config['secretKey'], $data); $client = new Client(['verify' => false, 'timeout' => 10]); $url = $this->config['baseUrl'] . '/api/v1/payment/order/query'; Log::info('StarPay查询参数', [ 'data' => $data, ]); $resp = $client->get($url . '?' . http_build_query($data)); $r = new \stdClass(); $r->status = false; if ($resp->getStatusCode() !== 200) { $this->error = $resp->getReasonPhrase(); return $r; } $content = $resp->getBody()->getContents(); Log::info('StarPay查询返回结果.', ['res' => $content, 'url' => $url]); $json = json_decode($content, true); if (json_last_error() !== JSON_ERROR_NONE) { Log::error('StarPay json_decode error', [ 'result' => $content, 'url' => $url, ]); return $r; } $r->status = self::STATUS_MAP[$json['orderStatus']] ?? Payment::STATUS_UNKNOWN; return $r; } public function sign($secretKey, $data) { $copy = $data; unset($copy['sign']); $str = self::joinMap($copy); $str .= "&key=$secretKey"; return hash('sha256', $str); } protected static function joinMap($arr) { ksort($arr); $pair = []; foreach ($arr as $k => $v) { if (is_array($v)) { $pair[] = "$k=" . self::joinMap($v); } else { $pair[] = "$k=" . (is_bool($v) ? json_encode($v) : $v); } } return implode('&', $pair); } }