之前有项目使用支付宝PHP SDK v2版本不知道出现什么问题,老是出现各种各样的报错,由于用到支付宝的API功能不是很多使用SDK有点浪费,所以准备手动写个身份认证的类。
一、授权申请
1、支付宝身份认证能力开通:https://open.alipay.com/api/detail?code=I1080300001000044085(需要企业认证才可以开通,个人认证无法开通)
2、申请一个应用和密钥,绑定支付宝身份认证能力(教程请去支付宝支持帮助)
二、身份认证类
<?php class Ali{ private $charset = 'utf-8'; private $config; public function __construct($conf){ $this->config = $conf; } // 实名初始化 public function real_init($name,$card){ $biz_content = [ 'outer_order_no' => md5(time().rand()), 'biz_code' => 'FACE', 'identity_param' => [ 'cert_type' => 'IDENTITY_CARD', 'cert_name' => $name, 'cert_no' => $card, 'identity_type' => 'CERT_INFO' ], 'merchant_config' => [ 'face_reserve_strategy' => 'reserve', 'return_url' => $this->config['return_url'] ] ]; $param = [ 'app_id' => $this->config['appid'], 'method' => 'alipay.user.certify.open.initialize', 'charset' => 'utf-8', 'sign_type' => 'RSA2', 'sign' => '', 'timestamp' => date('Y-m-d H:i:s'), 'version' => '1.0', 'notify_url' => $this->config['notify_url'], 'biz_content' => json_encode($biz_content) ]; $signdata = []; $signdata['app_id'] = $param['app_id']; $signdata['method'] = $param['method']; $signdata['charset'] = $param['charset']; $signdata['sign_type'] = $param['sign_type']; $signdata['timestamp'] = $param['timestamp']; $signdata['version'] = $param['version']; $signdata['notify_url'] = $param['notify_url']; $signdata['biz_content'] = $param['biz_content']; $sign = $this->generateSign($signdata, 'RSA2'); $param['sign'] = $sign; $content = $this->curlPost('https://openapi.alipay.com/gateway.do',$param); if(!empty($content)){ $return = json_decode($content,true); $result = $return['alipay_user_certify_open_initialize_response']; if($result['code'] == 10000){ return $result['certify_id']; } } return false; } // 实名生成 public function real_make($cid){ $biz_content['certify_id'] = $cid; $param = [ 'app_id' => $this->config['appid'], 'method' => 'alipay.user.certify.open.certify', 'charset' => 'utf-8', 'sign_type' => 'RSA2', 'sign' => '', 'timestamp' => date('Y-m-d H:i:s'), 'version' => '1.0', 'return_url' => $this->config['return_url'], 'biz_content' => json_encode($biz_content) ]; $signdata = []; $signdata['app_id'] = $param['app_id']; $signdata['method'] = $param['method']; $signdata['charset'] = $param['charset']; $signdata['sign_type'] = $param['sign_type']; $signdata['timestamp'] = $param['timestamp']; $signdata['version'] = $param['version']; $signdata['return_url'] = $param['return_url']; $signdata['biz_content'] = $param['biz_content']; $sign = $this->generateSign($signdata, 'RSA2'); $param['sign'] = str_replace(' ','+',$sign); foreach($param as $k=>$v){ $arr[] = $k . '=' . urlencode($v); } return 'https://openapi.alipay.com/gateway.do?'.implode('&',$arr); } // 实名查询 public function real_view($cid){ $biz_content['certify_id'] = $cid; $param = [ 'app_id' => $this->config['appid'], 'method' => 'alipay.user.certify.open.query', 'charset' => 'utf-8', 'sign_type' => 'RSA2', 'sign' => '', 'timestamp' => date('Y-m-d H:i:s'), 'version' => '1.0', 'biz_content' => json_encode($biz_content) ]; $signdata = []; $signdata['app_id'] = $param['app_id']; $signdata['method'] = $param['method']; $signdata['charset'] = $param['charset']; $signdata['sign_type'] = $param['sign_type']; $signdata['timestamp'] = $param['timestamp']; $signdata['version'] = $param['version']; $signdata['biz_content'] = $param['biz_content']; $sign = $this->generateSign($signdata, 'RSA2'); $param['sign'] = $sign; $content = $this->curlPost('https://openapi.alipay.com/gateway.do',$param); $return = json_decode($content, true); $result = $return['alipay_user_certify_open_query_response']; if($result['code'] == 10000){ if($result['passed']=='T'){ return true; } } return false; } public function generateSign($params, $signType = "RSA") { return $this->sign($this->getSignContent($params), $signType); } public function getSignContent($params) { ksort($params); $stringarr = array(); foreach ($params as $k => $v) { if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) { $v = $this->characet($v, $this->charset); $stringarr[] = $k . '=' . $v; } } return implode('&',$stringarr); } protected function checkEmpty($value) { if (!isset($value)) return true; if ($value === null) return true; if (trim($value) === "") return true; return false; } function characet($data, $targetCharset) { if (!empty($data)) { $fileType = $this->charset; if (strcasecmp($fileType, $targetCharset) != 0) { $data = mb_convert_encoding($data, $targetCharset, $fileType); } } return $data; } protected function sign($data, $signType = "RSA") { $priKey = $this->config['private']; $res = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($priKey, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----"; ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置'); if ("RSA2" == $signType) { openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256); } else { openssl_sign($data, $sign, $res); } $sign = base64_encode($sign); return $sign; } public function curlPost($url, $postData = '', $options = array()){ if (is_array($postData)) { $postData = http_build_query($postData); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 30); if (!empty($options)) { curl_setopt_array($ch, $options); } curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } //验签 public function rsaCheck($params, $signType='RSA') { $sign = str_replace(' ','+',$params['sign']); //修复+和空格导致验签失败 $signType = $params['sign_type']; $params['sign_type'] = null; $params['sign'] = null; return $this->verify($this->getSignContent($params), $sign, $signType); } function verify($data, $sign, $signType = 'RSA') { $pubKey = $this->config['public']; $res = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----"; ($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确'); if ("RSA2" == $signType) { $result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256); } else { $result = (bool)openssl_verify($data, base64_decode($sign), $res); } if(!$this->checkEmpty($this->config['public'])) { @openssl_free_key($res); } return $result; } }
三、代码案例
$config = [ 'appid' => 'app id', 'private' => '私钥', 'public' => '公钥', 'return_url' => 'https://www.77bx.com', 'notify_url' => 'https://www.77bx.com' ]; $ali = new Ali($config); // 实名初始化 $certify_id = $ali->real_init('姓名','身份证'); // 实名开始认证,需要对$url生成二维码 $url = $ali->real_make($certify_id); // 实名查询,如果上述步骤通过二维码扫描认证后显示True $isdo = $ali->real_view($certify_id);
return_url表示支付宝认证成功后,支付宝跳转页面。
注意:实名开始认证是本地生成一个链接,但是这个链接参数比较多,生成二维码不容易扫描,这个链接可以利用短域名的技术进行缩短,支付宝支持的。
目前有 0 条评论