appid = $appid; $this->rsaPrivateKey = $rsaPrivateKey; $this->alipayrsaPublicKey = $alipayrsaPublicKey; } /** * 外部商户APP唤起快捷SDK创建订单并支付 * 官方文档地址: https://docs.open.alipay.com/api_1/alipay.trade.app.pay */ public function appPay($orderData) { // 获取业务请求参数集合 $return = self::getAppPayBizContent($orderData); if(!$return->isSuccess()){ return ResultWrapper::fail($return->getData(), $return->getErrorCode()); } $biz_content = $return->getData(); // 公共请求参数 $params = [ 'app_id' => $this->appid, 'method' => 'alipay.trade.app.pay', 'format' => 'json', 'charset' => 'UTF-8', 'sign_type' => 'RSA2', 'timestamp' => date("Y-m-d H:i:s"), 'version' => '1.0', 'notify_url'=> $this->notifyUrl, ]; $params['biz_content'] = $biz_content; ksort($params); // 生成签名 $params['sign'] = self::sign($params); foreach ($params as &$value) { $value = $this->characet($value, $params['charset']); } $return = http_build_query($params); return ResultWrapper::success($return); } /** * 业务参数 * 请求字符编码必须是UTF-8 */ private function getAppPayBizContent($orderData) { $bizcontent = []; $bizcontent['subject'] = $orderData['subject']; // 商品的标题/交易标题/订单标题/订单关键字 $bizcontent['out_trade_no'] = $orderData['out_trade_no']; // 商户网站唯一订单号 $bizcontent['timeout_express'] = isset($orderData['timeout_express'])?$orderData['timeout_express']:'30m'; // 最晚付款时间 $bizcontent['total_amount'] = $orderData['total_amount']; // 订单总金额,单位为元,精确到小数点后两位 $bizcontent['passback_params'] = urlencode($orderData['passback_params']); // 回调数据 $bizcontent['product_code'] = 'QUICK_MSECURITY_PAY'; foreach ($bizcontent as $key => $value){ if(empty($value)){ return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError); } } return ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE)); } /** * 单笔转账接口 * 官网文档地址: https://opendocs.alipay.com/apis/api_28/alipay.fund.trans.uni.transfer */ public function transfer($orderData) { // 获取业务请求参数集合 $return = self::getTransferBizContent($orderData); if(!$return->isSuccess()){ return ResultWrapper::fail($return->getData(), $return->getErrorCode()); } $biz_content = $return->getData(); // 公共请求参数 $params = [ 'app_id' => $this->appid, 'method' => 'alipay.fund.trans.uni.transfer', 'format' => 'json', 'charset' => 'UTF-8', 'sign_type' => 'RSA2', 'timestamp' => date("Y-m-d H:i:s"), 'version' => '1.0', 'notify_url'=> $this->notifyUrl, ]; $params['biz_content'] = $biz_content; ksort($params); // 生成签名 $params['sign'] = self::sign($params); foreach ($params as &$value) { $value = $this->characet($value, $params['charset']); } $return = http_build_query($params); return ResultWrapper::success($return); } /** * 业务参数 * 请求字符编码必须是UTF-8 */ private function getTransferBizContent($orderData) { $bizcontent = []; $bizcontent['out_biz_no'] = $orderData['out_biz_no']; // 商户网站唯一订单号 $bizcontent['trans_amount'] = $orderData['trans_amount']; // 订单总金额,单位为元,精确到小数点后两位 $bizcontent['product_code'] = 'TRANS_ACCOUNT_NO_PWD'; $bizcontent['payee_info'] = [ 'identity' => $orderData['userCenterId'], // 参与方的唯一标识 'identity_type' => 'ALIPAY_LOGON_ID', // 支付宝登陆账号 'name' => $orderData['customerName'], // 支付宝对应的正式名称 ]; foreach ($bizcontent as $key => $value){ if(empty($value)){ return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError); } } return ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE)); } /** * 生成签名 */ private function sign($params) { if($this->checkEmpty($this->rsaPrivateKeyFilePath)){ $priKey=$this->rsaPrivateKey; $res = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($priKey, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----"; }else { $priKey = file_get_contents($this->rsaPrivateKeyFilePath); $res = openssl_get_privatekey($priKey); } ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置'); $data = self::getSignContent($params); if ("RSA2" == $params['sign_type']) { openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256); } else { openssl_sign($data, $sign, $res); } if(!empty($this->rsaPrivateKeyFilePath)){ openssl_free_key($res); } $sign = base64_encode($sign); return $sign; } /** * 获取要签名的参数内容 * @param $params * @return string */ public function getSignContent($params) { ksort($params); $stringToBeSigned = ""; $i = 0; foreach ($params as $k => $v) { if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) { // 转换成目标字符集 $v = $this->characet($v, "UTF-8"); if ($i == 0) { $stringToBeSigned .= "$k" . "=" . "$v"; } else { $stringToBeSigned .= "&" . "$k" . "=" . "$v"; } $i++; } } unset ($k, $v); return $stringToBeSigned; } /** * 转换字符集编码 * @param $data * @param $targetCharset * @return string */ function characet($data, $targetCharset) { if (!empty($data)) { $fileType = "UTF-8"; if (strcasecmp($fileType, $targetCharset) != 0) { $data = mb_convert_encoding($data, $targetCharset, $fileType); // $data = iconv($fileType, $targetCharset.'//IGNORE', $data); } } return $data; } /** * 校验$value是否非空 * if not set ,return true; * if is null , return true; **/ protected function checkEmpty($value) { if (!isset($value)) return true; if ($value === null) return true; if (trim($value) === "") return true; return false; } }