| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- <?php
- namespace App\Services;
- use App\Constant\Payment;
- use App\Util;
- use GuzzleHttp\Client;
- use Illuminate\Support\Facades\Log;
- class StarPayService
- {
- protected $code = 'StarPay';
- protected $config;
- const STATUS_MAP = [
- 0 => 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);
- }
- }
|