之前有项目使用支付宝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 条评论