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 Nilnice\Payment\Exception\GatewayException; |
||
| 9 | use Nilnice\Payment\Wechat\Traits\RequestTrait; |
||
| 10 | use Nilnice\Payment\Wechat\Traits\SecurityTrait; |
||
| 11 | use Symfony\Component\HttpFoundation\Request; |
||
| 12 | |||
| 13 | /** |
||
| 14 | * @method Wechat\AppPayment app(array $array) |
||
| 15 | * @method Wechat\WapPayment wap(array $array) |
||
| 16 | * @method Wechat\ScanPayment scan(array $array) |
||
| 17 | * @method Wechat\PubPayment pub(array $array) |
||
| 18 | */ |
||
| 19 | class Wechat implements GatewayInterface |
||
| 20 | { |
||
| 21 | use LogTrait; |
||
| 22 | use RequestTrait; |
||
| 23 | use SecurityTrait; |
||
| 24 | |||
| 25 | /** |
||
| 26 | * @var \Illuminate\Contracts\Config\Repository |
||
| 27 | */ |
||
| 28 | protected $config; |
||
| 29 | |||
| 30 | /** |
||
| 31 | * @var array |
||
| 32 | */ |
||
| 33 | protected $payload; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var string |
||
| 37 | */ |
||
| 38 | protected $gateway; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * Wechat constructor. |
||
| 42 | * |
||
| 43 | * @param array $config |
||
| 44 | * |
||
| 45 | * @throws \Exception |
||
| 46 | */ |
||
| 47 | 6 | public function __construct(array $config) |
|
| 48 | { |
||
| 49 | 6 | $this->config = new Repository($config); |
|
| 50 | 6 | $env = $this->config->get('env', 'pro'); |
|
| 51 | 6 | $this->gateway = self::getGatewayUrl($env); |
|
| 52 | 6 | $this->payload = [ |
|
| 53 | // 公众账号 ID - 微信分配的公众账号 ID |
||
| 54 | 6 | 'appid' => '', |
|
| 55 | |||
| 56 | // 商户号 - 微信支付分配的商户号 |
||
| 57 | 6 | 'mch_id' => $this->config->get('mch_id', ''), |
|
| 58 | |||
| 59 | // 随机字符串 - 随机字符串,不长于32位 |
||
| 60 | 6 | 'nonce_str' => Str::random(), |
|
| 61 | |||
| 62 | // 签名 |
||
| 63 | 6 | 'sign' => '', |
|
| 64 | |||
| 65 | // 终端 IP - 必须传正确的客户端 IP |
||
| 66 | 6 | 'spbill_create_ip' => Request::createFromGlobals()->getClientIp(), |
|
| 67 | |||
| 68 | // 通知地址 - 接收微信支付异步通知回调地址,通知 url 必须为直接可访问的 url,不能携带参数 |
||
| 69 | 6 | 'notify_url' => $this->config->get('notify_url'), |
|
| 70 | |||
| 71 | // 交易类型 - H5 支付的交易类型为 MWEB |
||
| 72 | 6 | 'trade_type' => '', |
|
| 73 | ]; |
||
| 74 | |||
| 75 | 6 | if ($this->config->has('log.file')) { |
|
| 76 | $this->registerLogger($this->config, 'Wxpay'); |
||
| 77 | } |
||
| 78 | 6 | } |
|
| 79 | |||
| 80 | /** |
||
| 81 | * @param string $method |
||
| 82 | * @param array $arguments |
||
| 83 | * |
||
| 84 | * @return mixed |
||
| 85 | * |
||
| 86 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 87 | */ |
||
| 88 | 3 | public function __call(string $method, array $arguments) |
|
| 89 | { |
||
| 90 | 3 | $this->setAppId($method); |
|
| 91 | |||
| 92 | 3 | return $this->dispatcher($method, ...$arguments); |
|
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * Query an order information. |
||
| 97 | * |
||
| 98 | * @param array|string $order |
||
| 99 | * |
||
| 100 | * @return \Illuminate\Support\Collection |
||
| 101 | * |
||
| 102 | * @throws \InvalidArgumentException |
||
| 103 | * |
||
| 104 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 105 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 106 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 107 | */ |
||
| 108 | public function query($order) : Collection |
||
| 109 | { |
||
| 110 | $this->setAppId(); |
||
| 111 | $this->payload = self::filterPayload( |
||
| 112 | $this->payload, |
||
| 113 | $order, |
||
| 114 | $this->config |
||
| 115 | ); |
||
| 116 | $gateway = Constant::WX_PAY_QUERY; |
||
| 117 | |||
| 118 | return $this->send($gateway, $this->payload, $this->config->get('key')); |
||
| 119 | } |
||
| 120 | |||
| 121 | /** |
||
| 122 | * Close an order. |
||
| 123 | * |
||
| 124 | * @param array|string $order |
||
| 125 | * |
||
| 126 | * @return \Illuminate\Support\Collection |
||
| 127 | * |
||
| 128 | * @throws \InvalidArgumentException |
||
| 129 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 130 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 131 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 132 | */ |
||
| 133 | public function close($order) : Collection |
||
| 134 | { |
||
| 135 | $this->setAppId(); |
||
| 136 | unset($this->payload['spbill_create_ip']); |
||
| 137 | $this->payload = self::filterPayload( |
||
| 138 | $this->payload, |
||
| 139 | $order, |
||
| 140 | $this->config |
||
| 141 | ); |
||
| 142 | $gateway = Constant::WX_PAY_CLOSE; |
||
| 143 | |||
| 144 | return $this->send($gateway, $this->payload, $this->config->get('key')); |
||
| 145 | } |
||
| 146 | |||
| 147 | /** |
||
| 148 | * Cancel an order. |
||
| 149 | * |
||
| 150 | * @param array|string $order |
||
| 151 | * |
||
| 152 | * @return \Illuminate\Support\Collection |
||
| 153 | */ |
||
| 154 | public function cancel($order) : Collection |
||
| 155 | { |
||
| 156 | trigger_error('Wechat did not cancel API, please use close API.'); |
||
| 157 | |||
| 158 | return new Collection(); |
||
| 159 | } |
||
| 160 | |||
| 161 | /** |
||
| 162 | * Refund an order. |
||
| 163 | * |
||
| 164 | * @param array|string $order |
||
| 165 | * |
||
| 166 | * @return \Illuminate\Support\Collection |
||
| 167 | * |
||
| 168 | * @throws \InvalidArgumentException |
||
| 169 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 170 | * @throws \Nilnice\Payment\Exception\InvalidKeyException |
||
| 171 | * @throws \Nilnice\Payment\Exception\InvalidSignException |
||
| 172 | */ |
||
| 173 | public function refund($order) : Collection |
||
| 174 | { |
||
| 175 | $this->payload = self::filterPayload( |
||
| 176 | $this->payload, |
||
| 177 | $order, |
||
| 178 | $this->config |
||
| 179 | ); |
||
| 180 | |||
| 181 | return $this->send( |
||
| 182 | Constant::WX_PAY_REFUND, |
||
| 183 | $this->payload, |
||
| 184 | $this->config->get('key'), |
||
| 185 | $this->config->get('cert_client'), |
||
| 186 | $this->config->get('cert_key') |
||
| 187 | ); |
||
| 188 | } |
||
| 189 | |||
| 190 | /** |
||
| 191 | * To pay. |
||
| 192 | * |
||
| 193 | * @param string $gateway |
||
| 194 | * |
||
| 195 | * @return mixed |
||
| 196 | * |
||
| 197 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 198 | */ |
||
| 199 | 3 | protected function toPay(string $gateway) |
|
| 200 | { |
||
| 201 | 3 | $class = new $gateway($this->config); // Instantiate different gateways. |
|
| 202 | |||
| 203 | 3 | if ($class instanceof PaymentInterface) { |
|
| 204 | 3 | return $class->toPay($this->gateway, $this->payload); |
|
| 205 | } |
||
| 206 | |||
| 207 | throw new GatewayException( |
||
| 208 | "Pay gateway [{$gateway}] must be an instance of the GatewayInterface.", |
||
| 209 | 2 |
||
| 210 | ); |
||
| 211 | } |
||
| 212 | |||
| 213 | /** |
||
| 214 | * Pay dispatcher. |
||
| 215 | * |
||
| 216 | * @param string $gateway |
||
| 217 | * @param array $array |
||
| 218 | * |
||
| 219 | * @return mixed |
||
| 220 | * |
||
| 221 | * @throws \Nilnice\Payment\Exception\GatewayException |
||
| 222 | */ |
||
| 223 | 3 | private function dispatcher(string $gateway, array $array = []) |
|
| 224 | { |
||
| 225 | 3 | $this->payload = array_merge($this->payload, $array); |
|
| 226 | 3 | $class = \get_class($this) . '\\' . Str::studly($gateway) . 'Payment'; |
|
| 227 | |||
| 228 | 3 | if (class_exists($class)) { |
|
| 229 | 3 | return $this->toPay($class); |
|
| 230 | } |
||
| 231 | |||
| 232 | throw new GatewayException("Pay gateway [{$gateway}] not exists", 1); |
||
| 233 | } |
||
| 234 | |||
| 235 | /** |
||
| 236 | * Set app identify. |
||
| 237 | * |
||
| 238 | * @param string $method |
||
| 239 | */ |
||
| 240 | 3 | private function setAppId($method = 'wap') |
|
| 241 | { |
||
| 242 | 1 | switch ($method) { |
|
| 243 | 2 | case 'app': // APP 支付 |
|
| 244 | $this->payload['appid'] = $this->config->get('app_appid'); |
||
| 245 | $this->payload['mch_id'] = $this->config->get('app_mchid'); |
||
| 246 | break; |
||
| 247 | 2 | case 'wap': // H5 支付 |
|
| 248 | case 'bar': // 刷卡支付 |
||
| 249 | case 'scan': // 扫码支付 |
||
| 250 | 3 | $this->payload['appid'] = $this->config->get('app_id'); |
|
| 251 | 3 | break; |
|
| 252 | case 'pub': // 公众号支付 |
||
| 253 | $this->payload['appid'] = $this->config->get('pub_appid'); |
||
| 254 | break; |
||
| 255 | case 'xcx': // 小程序支付 |
||
| 256 | $this->payload['appid'] = $this->config->get('xcx_appid'); |
||
| 257 | break; |
||
| 258 | } |
||
| 259 | 3 | } |
|
| 260 | |||
| 261 | /** |
||
| 262 | * Get gateway url. |
||
| 263 | * |
||
| 264 | * @param string $env |
||
| 265 | * |
||
| 266 | * @return string |
||
| 267 | */ |
||
| 268 | 6 | private static function getGatewayUrl($env = '') : string |
|
| 269 | { |
||
| 270 | 6 | $uri = ''; |
|
| 271 | 2 | switch ($env) { |
|
| 272 | 4 | case 'pro': |
|
| 273 | 3 | $uri = Constant::WX_PAY_PRO_URI; |
|
| 274 | 3 | break; |
|
| 275 | 2 | case 'dev': |
|
| 276 | 3 | $uri = Constant::WX_PAY_DEV_URI; |
|
| 277 | 3 | break; |
|
| 278 | case 'hk': |
||
| 279 | $uri = Constant::WX_PAY_PRO_HK_URI; |
||
| 280 | break; |
||
| 281 | default: |
||
| 282 | break; |
||
| 283 | } |
||
| 284 | |||
| 285 | 6 | return $uri; |
|
| 286 | } |
||
| 287 | } |
||
| 288 |