app_id = $config['app_id']; $class->secret = $config['secret']; $class->token = isset($config['token'])?$config['token']:''; $class->merchant_id = isset($config['merchant_id'])?$config['merchant_id']:''; $class->salt = isset($config['salt'])?$config['salt']:''; $class->settle_url = isset($config['settle_url']) ? $config['settle_url'] : ''; $class->notify_url = isset($config['notify_url'])?$config['notify_url']:''; $class->valid_time = isset($config['valid_time']) ? $config['valid_time'] : time() + 900; return $class; } /** * 获取下单信息 */ public function getParam() { return $this->orderParam; } /** * 获取异步订单信息 */ public function getNotifyOrder() { $data = file_get_contents("php://input"); $order = json_decode($data, true); $order['msg'] = json_decode($order['msg'], true); $this->notifyOrder = $order; return $this->notifyOrder; } /** * 获取token */ public function getToken() { $arr = [ 'grant_type' => 'client_credential', 'appid' => $this->app_id, 'secret' => $this->secret, ]; return json_decode($this->curl_post($this->tokenUrl, json_encode($arr)), true); } /** * 获取 openid * * @param string $code * @param string $anonymous_code * @return void * @author LiJie */ public function getOpenid($code, $anonymous_code = "") { $url = $this->codeUrl . "appid=" . $this->app_id . "&secret=" . $this->secret . "&code=" . $code; if ($anonymous_code) { $url .= "&anonymous_code=" . $anonymous_code; } return json_decode($this->curl_get($url), true); } /** * 异步回调 * @param $order 回调数据 * @return bool true 验签通过|false 验签不通过 */ public function notifyCheck() { $order = $this->getNotifyOrder(); $data = [ $order['timestamp'], $order['nonce'], json_encode($order['msg']), $this->token, ]; sort($data, SORT_STRING); $str = implode('', $data); \Log::info('notifyCheck:mysign:'.sha1($str).' byte_sign:'.$order['msg_signature']); if (!strcmp(sha1($str), $order['msg_signature'])) { return true; } return false; } /** * 创建订单 * 设置订单号 金额 描述 * @param string $rder_no 平台订单号 * @param int $money 订单金额 * @param int $store_uid 商户号 * @param string $title 描述 * */ public function applyOrderCreate($order_no, $money,$store_uid, $title, $desc = '',$phone_type) { $orderParam["out_order_no"] = $order_no; $orderParam["total_amount"] = $money; $orderParam["store_uid"] = $store_uid; $orderParam["subject"] = $title; $orderParam["body"] = $desc; $orderParam["notify_url"] = $this->notify_url; $orderParam["valid_time"] = $this->valid_time; $orderParam["app_id"] = $this->app_id; if($phone_type == 'ios'){ // ios唤起支付url需要 $orderParam["pay_scene"] = 'LinkPay'; } $data = json_encode(["sign" => $this->sign($orderParam)] + $orderParam); \Log::info('applyOrderCreate_before_request:'.json_encode($data)); $this->orderParam = json_decode($this->curl_post($this->payUrl, $data), true); return $this->orderParam; } /** * 申请退款 * */ public function applyOrderRefund2($order) { $order['notify_url'] = $this->refund_notify_url; $order['app_id'] = $this->app_id; return json_decode($this->curl_post($this->refundUrl, json_encode(['sign' => $this->sign($order)] + $order)), true); } /** * 订单查询 * @param string $out_order_no 订单号 * @return array 订单信息 */ public function findOrder($out_order_no) { if (empty($out_order_no)) { return false; } $order = [ 'out_order_no' => $out_order_no, 'app_id' => $this->app_id, ]; $order['sign'] = $this->sign($order); return json_decode($this->curl_post($this->query, json_encode($order)), true); } /** * 分账 * * @param [type] $order * @return void * @author LiJie */ public function settle($order) { $data = [ 'app_id' => $this->app_id, 'out_settle_no' => $order['out_settle_no'], 'out_order_no' => $order['out_order_no'], 'settle_desc' => $order['settle_desc'], 'notify_url' => $this->settle_url, 'cp_extra' => $order['cp_extra'], ]; $data['sign'] = $this->sign($data); $result = json_decode($this->curl_post($this->settle, json_encode($data)), true); return $result; } /** * 退款 * @return mixed */ public function applyOrderRefund($order){ $orderParam["out_order_no"] = $order['out_order_no']; $orderParam["out_refund_no"] = $order['out_refund_no']; $orderParam["reason"] = $order['reason']; $orderParam["refund_amount"] = $order['refund_amount']; // $orderParam["cp_extra"] = $order['cp_extra']; $orderParam["notify_url"] = $order['notify_url']; $orderParam["app_id"] = $this->app_id; $data = json_encode(["sign" => $this->sign_gf($orderParam)] + $orderParam); \LOg::info('applyOrderRefund_request:'.json_encode($data)); $this->refundResult = json_decode($this->curl_post($this->refundUrl, $data), true); return $this->refundResult; } /** * 发送模版消息 * * @param [type] $data * @param [type] $token */ public function sendMsg($data, $token) { $data['access_token'] = $token; $data['app_id'] = $this->app_id; return json_decode($this->curl_post($this->sendMsgUrl, json_encode($data)), true); } /** * 解密手机号 * * @param string $session_key 前端传递的session_key * @param string $iv 前端传递的iv * @param string $encryptedData 前端传递的encryptedData */ public function decryptPhone($session_key, $iv, $encryptedData) { if (strlen($session_key) != 24) { return false; } $aesKey = base64_decode($session_key); if (strlen($iv) != 24) { return false; } $aesIV = base64_decode($iv); $aesCipher = base64_decode($encryptedData); $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV); $dataObj = json_decode($result); if ($dataObj == null) { return false; } if ($dataObj->watermark->appid != $this->app_id) { return false; } return json_decode($result, true); } protected static function curl_get($url) { $headerArr = array("Content-type:application/x-www-form-urlencoded"); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); $output = curl_exec($ch); if (!$output) { throw new \Exception(curl_errno($ch)); } curl_close($ch); return $output; } /** * @desc post 用于退款 */ protected static function curl_post($url, $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json;charset=utf-8', 'Content-Length: ' . strlen($data), ) ); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $output = curl_exec($ch); if (!$output) { throw new \Exception(curl_errno($ch)); } curl_close($ch); return $output; } /** * @param array $map * @return string */ public function sign(array $map) { $rList = array(); foreach ($map as $k => $v) { if ($k == "other_settle_params" || $k == "app_id" || $k == "sign" || $k == "thirdparty_id") { continue; } $value = trim(strval($v)); $len = strlen($value); if ($len > 1 && substr($value, 0, 1) == "\"" && substr($value, $len, $len - 1) == "\"") { $value = substr($value, 1, $len - 1); } $value = trim($value); if ($value == "" || $value == "null") { continue; } array_push($rList, $value); } array_push($rList, $this->salt); sort($rList, 2); return md5(implode('&', $rList)); } // 官方签名 public function sign_gf($map) { $rList = []; foreach($map as $k =>$v) { if ($k == "other_settle_params" || $k == "app_id" || $k == "sign" || $k == "thirdparty_id") continue; $value = trim(strval($v)); if (is_array($v)) { $value = arrayToStr($v); } $len = strlen($value); if ($len > 1 && substr($value, 0,1)=="\"" && substr($value, $len-1)=="\"") $value = substr($value,1, $len-1); $value = trim($value); if ($value == "" || $value == "null") continue; $rList[] = $value; } $rList[] = $this->salt; sort($rList, SORT_STRING); return md5(implode('&', $rList)); } }