123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- <?php
- // +----------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +----------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +----------------------------------------------------------------------
- namespace crmeb\services\pay\extend\allinpay;
- use crmeb\exceptions\ApiException;
- use crmeb\services\HttpService;
- use think\facade\Log;
- /**
- * Class Client
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/12/27
- * @package crmeb\services\pay\extend\allinpay
- */
- class Client
- {
- //生产地址
- const API_URL = 'https://vsp.allinpay.com/apiweb/';
- //测试接口地址
- const BETA_API_URL = 'https://syb-test.allinpay.com/apiweb/';
- //版本号
- const VERSION_NUM_11 = '11';
- //版本号
- const VERSION_NUM_12 = '12';
- protected $signType = 'MD5';
- /**
- * @var string
- */
- protected $cusid = '';
- /**
- * @var string
- */
- protected $appid = '';
- /**
- * @var string
- */
- protected $privateKey = '';
- /**
- * @var
- */
- protected $publicKey = '';
- /**
- * 回调地址
- * @var string
- */
- protected $notifyUrl = '';
- /**
- * 是否测试
- * @var bool
- */
- protected $isBeta = true;
- /**
- * debug模式
- * @var bool
- */
- protected $isDebug = true;
- /**
- * Client constructor.
- * @param array $config
- */
- public function __construct(array $config = [])
- {
- $this->appid = $config['appid'] ?? '';
- $this->cusid = $config['cusid'] ?? '';
- $this->privateKey = $config['privateKey'] ?? '';
- $this->publicKey = $config['publicKey'] ?? '';
- $this->notifyUrl = $config['notifyUrl'] ?? '';
- $this->isBeta = $config['isBeta'] ?? true;
- }
- /**
- * 发送请求
- * @param string $url
- * @param array $options
- * @return mixed
- */
- public function send(string $url, array $options = [])
- {
- $data = $options['data'] ?? [];
- $header = $options['header'] ?? [];
- $data['cusid'] = $this->cusid;
- $data['appid'] = $this->appid;
- if (!isset($data['version'])) {
- $data['version'] = self::VERSION_NUM_11;
- }
- $data['signtype'] = $this->signType;
- $data['randomstr'] = uniqid();
- if (!empty($options['form'])) {
- $data['charset'] = 'UTF-8';
- $data['version'] = self::VERSION_NUM_12;
- $data['sign'] = $this->sign($data);
- return $data;
- }
- $data['sign'] = $this->sign($data);
- $response = $this->request($url, $data, 'post', $header);
- if ('SUCCESS' !== $response['retcode']) {
- throw new ApiException($response['retmsg']);
- }
- if (!empty($response['trxstatus']) && !in_array($response['trxstatus'], ['0000', '2008', '2000'])) {
- throw new ApiException($response['errmsg']);
- }
- if ($this->validSign($response)) {
- return $response;
- }
- throw new ApiException('创建订单成功验签失败');
- }
- /**
- * @param string $url
- * @param array $data
- * @param string $method
- * @param array $header
- * @param int $timeout
- * @return mixed
- */
- public function request(string $url, array $data = [], string $method = 'post', array $header = [], int $timeout = 10)
- {
- $headerData = [];
- if ($header) {
- foreach ($header as $key => $item) {
- $headerData[] = $key . ':' . $item;
- }
- }
- $content = HttpService::request($this->baseUrl($url), $method, $data, $headerData, $timeout);
- $respones = json_decode($content, true, 512, JSON_BIGINT_AS_STRING);
- $this->debugLog('API response decoded:', ['content' => $respones, 'header' => $header]);
- if (JSON_ERROR_NONE !== json_last_error()) {
- throw new ApiException('Failed to parse JSON: ' . json_last_error_msg());
- }
- return $respones;
- }
- /**
- * @param string $message
- * @param array $contents
- */
- protected function debugLog(string $message, array $contents = [])
- {
- $this->isDebug && Log::debug($message, $contents);
- }
- /**
- * @param string|null $url
- * @return string
- */
- protected function baseUrl(string $url = null)
- {
- $baseUrl = $this->isBeta ? self::BETA_API_URL : self::API_URL;
- if ($url) {
- $baseUrl .= $url;
- }
- return $baseUrl;
- }
- /**
- * @param array $data
- * @return string
- */
- public function sign(array $data)
- {
- $private_key = $this->privateKey;
- if ($this->signType === 'MD5') {
- $data['key'] = $private_key;
- ksort($data);
- $bufSignSrc = $this->toUrlParams($data);
- return md5($bufSignSrc);
- } else {
- ksort($data);
- $bufSignSrc = $this->toUrlParams($data);
- $private_key = chunk_split($private_key, 64, "\n");
- $key = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($private_key) . "-----END RSA PRIVATE KEY-----";
- openssl_sign($bufSignSrc, $signature, $key);
- $sign = base64_encode($signature);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
- return $sign;
- }
- }
- /**
- * @param array $data
- * @return string
- */
- public function toUrlParams(array $data)
- {
- $buff = "";
- foreach ($data as $k => $v) {
- if ($v != "" && !is_array($v)) {
- $buff .= $k . "=" . $v . "&";
- }
- }
- $buff = trim($buff, "&");
- return $buff;
- }
- /**
- * @param array $data
- * @return false|int
- */
- public function validSign(array $data)
- {
- $sign = $data['sign'];
- unset($data['sign']);
- if ($this->signType === 'MD5') {
- $data['key'] = $this->privateKey;
- ksort($data);
- $bufSignSrc = $this->toUrlParams($data);
- return strtolower($sign) == strtolower(md5($bufSignSrc));
- } else {
- ksort($data);
- $bufSignSrc = $this->toUrlParams($data);
- $public_key = $this->publicKey;
- $public_key = chunk_split($public_key, 64, "\n");
- $key = "-----BEGIN PUBLIC KEY-----\n$public_key-----END PUBLIC KEY-----\n";
- return openssl_verify($bufSignSrc, base64_decode($sign), $key);
- }
- }
- /**
- * @param string $notifyUrl
- * @return $this
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2023/2/7
- */
- public function setNotifyUrl(string $notifyUrl)
- {
- $this->notifyUrl = $notifyUrl;
- return $this;
- }
- }
|