nilnice /
payment
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Nilnice\Payment; |
||
| 4 | |||
| 5 | use Illuminate\Config\Repository; |
||
| 6 | use Illuminate\Support\Collection; |
||
| 7 | use Illuminate\Support\Str; |
||
| 8 | use Monolog\Formatter\LineFormatter; |
||
| 9 | use Monolog\Handler\StreamHandler; |
||
| 10 | use Monolog\Logger; |
||
| 11 | use Nilnice\Payment\Alipay\Traits\RequestTrait; |
||
| 12 | use Nilnice\Payment\Alipay\Traits\SecurityTrait; |
||
| 13 | use Nilnice\Payment\Exception\GatewayException; |
||
| 14 | |||
| 15 | /** |
||
| 16 | * @method Alipay\AppPayment app(array $array) |
||
| 17 | * @method Alipay\BarPayment bar(array $array) |
||
| 18 | * @method Alipay\ScanPayment scan(array $array) |
||
| 19 | * @method Alipay\TransferPayment transfer(array $array) |
||
| 20 | * @method Alipay\WapPayment wap(array $array) |
||
| 21 | * @method Alipay\WebPayment web(array $array) |
||
| 22 | */ |
||
| 23 | class Alipay implements GatewayInterface |
||
| 24 | { |
||
| 25 | use LogTrait; |
||
| 26 | use RequestTrait; |
||
| 27 | use SecurityTrait; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * @var \Illuminate\Contracts\Config\Repository |
||
| 31 | */ |
||
| 32 | protected $config; |
||
| 33 | |||
| 34 | /** |
||
| 35 | * @var array |
||
| 36 | */ |
||
| 37 | protected $payload; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @var string |
||
| 41 | */ |
||
| 42 | protected $gateway; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * Alipay constructor. |
||
| 46 | * |
||
| 47 | * @param array $config |
||
| 48 | * |
||
| 49 | * @throws \Exception |
||
| 50 | */ |
||
| 51 | 9 | public function __construct(array $config) |
|
| 52 | { |
||
| 53 | 9 | $this->config = new Repository($config); |
|
| 54 | 9 | $env = $this->config->get('env', 'pro'); |
|
| 55 | 9 | $this->gateway = self::getGatewayUrl($env); |
|
| 56 | 9 | $this->payload = [ |
|
| 57 | // 支付宝分配给开发者的应用 ID |
||
| 58 | 9 | 'app_id' => $this->config->get('app_id'), |
|
| 59 | |||
| 60 | // 接口名称 |
||
| 61 | 9 | 'method' => '', |
|
| 62 | |||
| 63 | // 数据格式,仅支持 JSON |
||
| 64 | 9 | 'format' => 'JSON', |
|
| 65 | |||
| 66 | // 同步返回地址,HTTP/HTTPS 开头字符串 |
||
| 67 | 9 | 'return_url' => $this->config->get('return_url'), |
|
| 68 | |||
| 69 | // 请求使用的编码格式,如:UTF-8, GBK, GB2312 等 |
||
| 70 | 9 | 'charset' => 'UTF-8', |
|
| 71 | |||
| 72 | // 商户生成签名字符串所使用的签名算法类型,目前支持 RSA2 和 RSA,推荐使用 RSA2 |
||
| 73 | 9 | 'sign_type' => 'RSA2', |
|
| 74 | |||
| 75 | // 商户请求参数的签名串,详见签名 |
||
| 76 | 9 | 'sign' => '', |
|
| 77 | |||
| 78 | // 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" |
||
| 79 | 9 | 'timestamp' => date('Y-m-d H:i:s'), |
|
| 80 | |||
| 81 | // 调用的接口版本,固定为:1.0 |
||
| 82 | 9 | 'version' => '1.0', |
|
| 83 | |||
| 84 | // 支付宝服务器主动通知商户服务器里指定的页面 http/https 路径 |
||
| 85 | 9 | 'notify_url' => $this->config->get('notify_url'), |
|
| 86 | |||
| 87 | // 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 |
||
| 88 | 9 | 'biz_content' => '', |
|
| 89 | ]; |
||
| 90 | |||
| 91 | 9 | if ($this->config->has('log.file')) { |
|
| 92 | $this->registerLogger($this->config, 'Alipay'); |
||
| 93 | } |
||
| 94 | 9 | } |
|
| 95 | |||
| 96 | /** |
||
| 97 | * @param string $method |
||
| 98 | * @param array $arguments |
||
| 99 | * |
||
| 100 | * @return mixed |
||
| 101 | * |
||
| 102 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 103 | */ |
||
| 104 | 6 | public function __call(string $method, array $arguments) |
|
| 105 | { |
||
| 106 | 6 | return $this->dispatcher($method, ...$arguments); |
|
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 107 | } |
||
| 108 | |||
| 109 | /** |
||
| 110 | * Query an order information. |
||
| 111 | * |
||
| 112 | * @param array|string $order |
||
| 113 | * |
||
| 114 | * @return \Illuminate\Support\Collection |
||
| 115 | * |
||
| 116 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 117 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 118 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 119 | * @throws \RuntimeException |
||
| 120 | */ |
||
| 121 | public function query($order) : Collection |
||
| 122 | { |
||
| 123 | return $this->getOrderResult($order); |
||
| 124 | } |
||
| 125 | |||
| 126 | /** |
||
| 127 | * Close an order. |
||
| 128 | * |
||
| 129 | * @param array|string $order |
||
| 130 | * |
||
| 131 | * @return \Illuminate\Support\Collection |
||
| 132 | * |
||
| 133 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 134 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 135 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 136 | * @throws \RuntimeException |
||
| 137 | */ |
||
| 138 | public function close($order) : Collection |
||
| 139 | { |
||
| 140 | return $this->getOrderResult($order, __FUNCTION__); |
||
| 141 | } |
||
| 142 | |||
| 143 | /** |
||
| 144 | * Cancel an order. |
||
| 145 | * |
||
| 146 | * @param array|string $order |
||
| 147 | * |
||
| 148 | * @return \Illuminate\Support\Collection |
||
| 149 | * |
||
| 150 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 151 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 152 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 153 | * @throws \RuntimeException |
||
| 154 | */ |
||
| 155 | public function cancel($order) : Collection |
||
| 156 | { |
||
| 157 | return $this->getOrderResult($order, __FUNCTION__); |
||
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * Refund an order. |
||
| 162 | * |
||
| 163 | * @param array|string $order |
||
| 164 | * |
||
| 165 | * @return \Illuminate\Support\Collection |
||
| 166 | * |
||
| 167 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 168 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 169 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 170 | * @throws \RuntimeException |
||
| 171 | */ |
||
| 172 | public function refund($order) : Collection |
||
| 173 | { |
||
| 174 | return $this->getOrderResult($order, __FUNCTION__); |
||
| 175 | } |
||
| 176 | |||
| 177 | /** |
||
| 178 | * To pay. |
||
| 179 | * |
||
| 180 | * @param string $gateway |
||
| 181 | * |
||
| 182 | * @return mixed |
||
| 183 | * |
||
| 184 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 185 | */ |
||
| 186 | 3 | protected function toPay(string $gateway) |
|
| 187 | { |
||
| 188 | 3 | $class = new $gateway($this->config); // Instantiate different gateways. |
|
| 189 | |||
| 190 | 3 | if ($class instanceof PaymentInterface) { |
|
| 191 | 3 | return $class->toPay($this->gateway, $this->payload); |
|
| 192 | } |
||
| 193 | |||
| 194 | throw new GatewayException( |
||
| 195 | "Pay gateway [{$gateway}] must be an instance of the GatewayInterface.", |
||
| 196 | 2 |
||
| 197 | ); |
||
| 198 | } |
||
| 199 | |||
| 200 | /** |
||
| 201 | * Pay dispatcher. |
||
| 202 | * |
||
| 203 | * @param string $gateway |
||
| 204 | * @param array $array |
||
| 205 | * |
||
| 206 | * @return mixed |
||
| 207 | * |
||
| 208 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 209 | */ |
||
| 210 | 6 | private function dispatcher(string $gateway, array $array = []) |
|
| 211 | { |
||
| 212 | 6 | $this->payload['biz_content'] = $array; |
|
| 213 | 6 | $class = \get_class($this) . '\\' . Str::studly($gateway) . 'Payment'; |
|
| 214 | |||
| 215 | 6 | if (class_exists($class)) { |
|
| 216 | 3 | return $this->toPay($class); |
|
| 217 | } |
||
| 218 | |||
| 219 | 3 | throw new GatewayException("Pay gateway [{$gateway}] not exists.", 1); |
|
| 220 | } |
||
| 221 | |||
| 222 | /** |
||
| 223 | * Get order result. |
||
| 224 | * |
||
| 225 | * @param array|string $order |
||
| 226 | * @param string $type |
||
| 227 | * |
||
| 228 | * @return \Illuminate\Support\Collection |
||
| 229 | * |
||
| 230 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 231 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 232 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 233 | * @throws \RuntimeException |
||
| 234 | */ |
||
| 235 | private function getOrderResult($order, $type = 'query') : Collection |
||
| 236 | { |
||
| 237 | $order = \is_array($order) ? $order : ['out_trade_no' => $order]; |
||
| 238 | switch (trim($type)) { |
||
| 239 | case 'close': |
||
| 240 | $method = Constant::ALI_PAY_CLOSE; |
||
| 241 | break; |
||
| 242 | case 'cancel': |
||
| 243 | $method = Constant::ALI_PAY_CANCEL; |
||
| 244 | break; |
||
| 245 | case 'refund': |
||
| 246 | $method = Constant::ALI_PAY_REFUND; |
||
| 247 | break; |
||
| 248 | default: |
||
| 249 | $method = Constant::ALI_PAY_QUERY; |
||
| 250 | break; |
||
| 251 | } |
||
| 252 | $this->payload['method'] = $method; |
||
| 253 | $this->payload['biz_content'] = json_encode($order); |
||
| 254 | $this->payload['sign'] = self::generateSign( |
||
| 255 | $this->payload, |
||
| 256 | $this->config->get('private_key') |
||
| 257 | ); |
||
| 258 | Log::debug(ucfirst($type) . ' an order:', [ |
||
| 259 | $this->gateway, |
||
| 260 | $this->payload, |
||
| 261 | ]); |
||
| 262 | |||
| 263 | return $this->send($this->payload, $this->config->get('public_key')); |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * Get gateway url. |
||
| 268 | * |
||
| 269 | * @param string $env |
||
| 270 | * |
||
| 271 | * @return string |
||
| 272 | */ |
||
| 273 | 9 | private static function getGatewayUrl($env = '') : string |
|
| 274 | { |
||
| 275 | 9 | $uri = ''; |
|
| 276 | 9 | if ($env === 'pro') { |
|
| 277 | 6 | $uri = Constant::ALI_PAY_PRO_URI; |
|
| 278 | 3 | } elseif ($env === 'dev') { |
|
| 279 | 3 | $uri = Constant::ALI_PAY_DEV_URI; |
|
| 280 | } |
||
| 281 | |||
| 282 | 9 | return $uri; |
|
| 283 | } |
||
| 284 | } |
||
| 285 |