* * @param array $config [description] */ public function __construct(array $config) { $this->user_config = new Config($config); if (is_null($this->user_config->get('app_id'))) { throw new InvalidArgumentException('Missing Config -- [app_id]'); } $this->config = [ 'app_id' => $this->user_config->get('app_id'), 'method' => '', 'format' => 'JSON', 'charset' => 'UTF-8', 'sign_type' => 'RSA2', 'version' => '1.0', 'return_url' => $this->user_config->get('return_url', ''), 'notify_url' => $this->user_config->get('notify_url', ''), 'timestamp' => date('Y-m-d H:i:s'), 'sign' => '', 'biz_content' => '', ]; } /** * pay a order. * * @author yansongda * * @param array $config_biz * * @return mixed */ public function pay(array $config_biz) { $config_biz['product_code'] = $this->getProductCode(); $this->config['method'] = $this->getMethod(); $this->config['biz_content'] = json_encode($config_biz); $this->config['sign'] = $this->getSign(); } /** * refund a order. * * @author yansongda * * @param mixed $config_biz * * @return array|bool */ public function refund($config_biz, $refund_amount = null) { if (!is_array($config_biz)) { $config_biz = [ 'out_trade_no' => $config_biz, 'refund_amount' => $refund_amount, ]; } return $this->getResult($config_biz, 'alipay.trade.refund'); } /** * close a order. * * @author yansongda * * @param array|string $config_biz * * @return array|bool */ public function close($config_biz) { if (!is_array($config_biz)) { $config_biz = [ 'out_trade_no' => $config_biz, ]; } return $this->getResult($config_biz, 'alipay.trade.close'); } /** * find a order. * * @author yansongda * * @param string $out_trade_no * * @return array|bool */ public function find($out_trade_no = '') { $config_biz = [ 'out_trade_no' => $out_trade_no, ]; return $this->getResult($config_biz, 'alipay.trade.query'); } /** * verify the notify. * * @author yansongda * * @param array $data * @param string $sign * @param bool $sync * * @return array|bool */ public function verify($data, $sign = null, $sync = false) { if (is_null($this->user_config->get('ali_public_key'))) { throw new InvalidArgumentException('Missing Config -- [ali_public_key]'); } $sign = is_null($sign) ? $data['sign'] : $sign; $res = "-----BEGIN PUBLIC KEY-----\n". wordwrap($this->user_config->get('ali_public_key'), 64, "\n", true). "\n-----END PUBLIC KEY-----"; $toVerify = $sync ? json_encode($data) : $this->getSignContent($data, true); return openssl_verify($toVerify, base64_decode($sign), $res, OPENSSL_ALGO_SHA256) === 1 ? $data : false; } /** * get method config. * * @author yansongda * * @return string */ abstract protected function getMethod(); /** * get productCode config. * * @author yansongda * * @return string */ abstract protected function getProductCode(); /** * build pay html. * * @author yansongda * * @return string */ protected function buildPayHtml() { $sHtml = "
"; foreach ($this->config as $key => $val) { $val = str_replace("'", ''', $val); $sHtml .= ""; } $sHtml .= "
"; $sHtml .= ""; return $sHtml; } /** * get alipay api result. * * @author yansongda * * @param array $config_biz * @param string $method * * @return array|bool */ protected function getResult($config_biz, $method) { $this->config['biz_content'] = json_encode($config_biz); $this->config['method'] = $method; $this->config['sign'] = $this->getSign(); $this->config = array_filter($this->config, function ($value) { return $value !== '' && !is_null($value); }); $method = str_replace('.', '_', $method).'_response'; $data = json_decode($this->post($this->gateway, $this->config), true); if (!isset($data[$method]['code']) || $data[$method]['code'] !== '10000') { throw new GatewayException( 'get result error:'.$data[$method]['msg'].' - '.$data[$method]['sub_code'], $data[$method]['code'], $data); } return $this->verify($data[$method], $data['sign'], true); } /** * get sign. * * @author yansongda * * @return string */ protected function getSign() { if (is_null($this->user_config->get('private_key'))) { throw new InvalidArgumentException('Missing Config -- [private_key]'); } $res = "-----BEGIN RSA PRIVATE KEY-----\n". wordwrap($this->user_config->get('private_key'), 64, "\n", true). "\n-----END RSA PRIVATE KEY-----"; openssl_sign($this->getSignContent($this->config), $sign, $res, OPENSSL_ALGO_SHA256); return base64_encode($sign); } /** * get signContent that is to be signed. * * @author yansongda * * @param array $toBeSigned * @param bool $verify * * @return string */ protected function getSignContent(array $toBeSigned, $verify = false) { ksort($toBeSigned); $stringToBeSigned = ''; foreach ($toBeSigned as $k => $v) { if ($verify && $k != 'sign' && $k != 'sign_type') { $stringToBeSigned .= $k.'='.$v.'&'; } if (!$verify && $v !== '' && !is_null($v) && $k != 'sign' && '@' != substr($v, 0, 1)) { $stringToBeSigned .= $k.'='.$v.'&'; } } $stringToBeSigned = substr($stringToBeSigned, 0, -1); unset($k, $v); return $stringToBeSigned; } }