支付宝芝麻信用支付接口对接

支付宝芝麻信用的接口分几种不同的类型,下面以 h5 认证形式为例说明。

这种形式的基本流程是:

  • 需要自已建网页收集用户填写的姓名和身份证号,
  • 程序拿到姓名和身份证号信息根据 SDK 的加密操作获取跳转地址,
  • 网站跳转到该地址引导用户输入验证码进行认证,
  • 用户认证完成后跳转到程序指定的页面中。

其中回调地址不是在程序中指定的,是在芝麻应用创建的时候填写的,在回调地址中填写需要跳转到的程序页面地址。

可以到 https://b.zmxy.com.cn/technology/sdkDownload.htm 下载最新 SDK,其中的秘钥配置和支付宝类似,也是自已生成,再上传公钥,再从应用那里复制公钥,需要注意的是复制过来的公钥是一行字符串,需要对其过换行处理可参考生成的私钥格式。

下载后的 sdk 需要修改\zmoop\ZmopClient.php 的 include 路径一下。

下面是芝麻信用的服务类

ZmopService.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<?php
namespace Home\Service;

class ZmopService {
/**
* 芝麻信用配置信息
* 有修改ZmopClient里的错误日志记录函数,因为SDK里的lotus框架函数和TP函数冲突
* 在商户后台需要填写回调地址、商家公钥,私钥和公钥使用penSSL工具生成后在创建应用时填写公钥和回跳地址,下面的公钥要从应用列表那里复制过来的“芝麻公钥”放下面
*/
function __construct() {
$zmopConfig = array(
'appId' => '*********', //应用ID,非商家id
'privateKeyFile' => __ROOT__ . '/Pem/rsa_private_key.pem', //私钥
'zmPublicKeyFile' => __ROOT__ . '/Pem/rsazfb_public_key.pem', //公钥,这里复制过来的公钥要换行,否则openssl_get_publickey将返回false
'charset' => 'UTF-8', //编码格式
'method' => 'zhima.auth.info.authorize', //要调用的接口名
'version' => '1.0', //签名方式
'platform' => 'zmop', //支付宝网关
'gatewayUrl' => 'https://zmopenapi.zmxy.com.cn/openapi.do', //芝麻信用网关地址
'zmop_log_txt' => __ROOT__ . '/Public/zmop_log_bef74b0ac451f8e6e5301453f9474p99.txt', //支付日志(需要先建立此文件)
);
//获取证书实际路径
import("Org.Util.File");
$file = new\File();
$zmopConfig['privateKeyFile'] = $file->getRealFile($zmopConfig['privateKeyFile']);
$zmopConfig['zmPublicKeyFile'] = $file->getRealFile($zmopConfig['zmPublicKeyFile']);
$this->zmopConfig = $zmopConfig;
}

/**
* 获取配置参数
* @return array
*/
public function getConfig() {
return $this->zmopConfig;
}

/**
* 获取跳转验证链接
* @param $data name/姓名 certno/身份证号 zid/商户自定义
* @return string
*/
public function getZmopUrl($data) {
Vendor('zmxy.zmop.ZmopClient');
Vendor('zmxy.zmop.request.ZhimaAuthInfoAuthorizeRequest');
$zmopConfig = $this->getConfig();
$client = new \ZmopClient($zmopConfig['gatewayUrl'], $zmopConfig['appId'], $zmopConfig['charset'], $zmopConfig['privateKeyFile'], $zmopConfig['zmPublicKeyFile']);
$request = new \ZhimaAuthInfoAuthorizeRequest();
$request->setChannel("apppc");
$request->setPlatform($zmopConfig['platform']);
$request->setIdentityType("2"); // 必要参数
$request->setIdentityParam("{\"name\":\"" . $data['name'] . "\",\"certType\":\"IDENTITY_CARD\",\"certNo\":\"" . $data['certno'] . "\"}"); // 必要参数
$request->setBizParams("{\"auth_code\":\"M_H5\",\"channelType\":\"app\",\"state\":\"" . $data['state'] . "\"}");
$url = $client->generatePageRedirectInvokeUrl($request);
return $url;
}

/**
* 获取解密结果
* @param $data
* @return mixed
*/
public function getResult($data) {
$zmopConfig = $this->getConfig();
Vendor('zmxy.zmop.ZmopClient');
$params = $data['params'];
//从回调URL中获取params参数,此处为示例值
$sign = $data['sign'];
//从回调URL中获取sign参数,此处为示例值
// 判断串中是否有%,有则需要decode
$params = strstr($params, '%') ? urldecode($params) : $params;
$sign = strstr($sign, '%') ? urldecode($sign) : $sign;

$client = new \ZmopClient ($zmopConfig['gatewayUrl'], $zmopConfig['appId'], $zmopConfig['charset'], $zmopConfig['privateKeyFile'], $zmopConfig['zmPublicKeyFile']);
$result = $client->decryptAndVerifySign($params, $sign);
$resultArr = explode('&', $result);
$arr = array();
if (is_array($resultArr) && $resultArr[0]) {
foreach ($resultArr as $k => $v) {
$parr = explode('=', $v);
$arr[$parr[0]] = $parr[1];
}
}
return array(
'result' => $result,
'arr' => $arr,
);
}

/**
* 获取芝麻积分
* @param $data transaction_id/业务id product_code/产品码 open_id
* @return string
*/
public function getScore($data) {
$zmopConfig = $this->getConfig();
Vendor('zmxy.zmop.ZmopClient');
Vendor('zmxy.zmop.request.ZhimaCreditScoreGetRequest');
$client = new \ZmopClient($zmopConfig['gatewayUrl'], $zmopConfig['appId'], $zmopConfig['charset'], $zmopConfig['privateKeyFile'], $zmopConfig['zmPublicKeyFile']);
$request = new \ZhimaCreditScoreGetRequest();
$request->setChannel("apppc");
$request->setPlatform($zmopConfig['platform']);
$request->setTransactionId($data['transaction_id']); // 必要参数业务id
$request->setProductCode($data['product_code']); // 必要参数产品码
$request->setOpenId($data['open_id']); // 必要参数openid
$response = $client->execute($request);
return json_decode(json_encode($response), true);
}

/**
* 记录记录
* @param $data
*/
public function setLog($data) {
$config = $this->payConfig;
$str = serialize($data);
import("Org.Util.File");
$file = new \File($config['zmop_log_txt']);
$realfiel = $file->getRealFile();
file_put_contents($realfiel, $str, FILE_APPEND);
}

/**
* 传入一个id整数值获取13位的业务id
* @param $id
* @return string
*/
public function getTransactionId($id) {
if (strlen($id) < 13) {
$str = '';
$cz = 13 - strlen($id);
for ($i = 0; $i < $cz; $i++) {
$str .= '0';
}
$id = $str . $id;
} else {
$id = substr($id, 0, 13);
}
return $id;
}
}

下面是芝麻信用的应用控制器

ZmopController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
namespace Home\Controller;

use Think\Controller;
use Common\Controller\HomeController;
use Home\Form;

class ZmopController extends HomeController {

function __construct() {
parent::__construct();
$fromurl = urldecode(I('fromurl'));
session('fromurl', $fromurl);
$uid = session('uid');
$action_name = array(
'notifyurl',
);
if (!$uid && !in_array(ACTION_NAME, $action_name)) {
$this->redirect('Members/login');
exit();
}
$publicData = array(
'uid' => $uid,
'name' => S('zmop_name_' . $uid), //姓名
'certno' => S('zmop_certno_' . $uid), //身份证号
);
$this->publicData = $publicData;
}

/**
* 芝麻应用说明页
*/
public function index() {
$publicData = $this->publicData;
//查询当前会员有没有验证过
$zmdata = D('Zmop')->ishave($publicData['uid']);
if ($zmdata) {
//查询芝麻信用分
$sdata = array(
'transaction_id' => date('YmdHisu', time()) . D('Zmop', 'Service')->getTransactionId(1),
'product_code' => 'w1010100100000000001',
'open_id' => $zmdata['open_id'],
);
$reback = D('Zmop', 'Logic')->doscore($sdata, $publicData, $zmdata['uid']);
if ($reback['status']) {
session('yyzzmop_' . $publicData['uid'], $reback['zm_score']); //记录已经验证了芝麻分
header('Location: ' . (session('fromurl') ? session('fromurl') : U('Cart/index')));
} elseif ($reback['reback']['error_code'] == 'ZMCREDIT.authentication_fail') {
//鉴权失败重要调起授权
$this->display();
} else {
echo $reback['info'];
}
} else {
$this->display();
}
}

/**
* 芝麻授权页面页
*/
public function authorization() {
$publicData = $this->publicData;
$ZmopForm = new Form\ZmopForm();
$this->ZmopForm = $ZmopForm;
//鉴权失败重要调起授权时直接获取已有的信息
$zmdata = D('Zmop')->ishave($publicData['uid']);
$this->zmdata = $zmdata;
$this->display();
}

/**
* 向芝麻发起授权请求
*/
public function request() {
header('Content-Type: text/html; charset=utf-8');
$publicData = $this->publicData;
$data = array(
'name' => $publicData['name'],
'certno' => $publicData['certno'],
'state' => $publicData['uid'], //商户自定义数据
);
//dump($data);
$url = D('Zmop', 'Service')->getZmopUrl($data);
header('Location:' . $url);
}

/**
* 芝麻信息回调地址
*/
public function notifyurl() {
$publicData = $this->publicData;
$data = array(
'params' => I('params'),
'sign' => I('sign'),
);
$result = D('Zmop', 'Logic')->decrypt($data);
$arr = $result['arr'];
$uid = $state = $arr['state']; //自定义原样返回的数据,定义为用户id
if ($arr['success'] == 'true' && $arr['open_id']) {
//查询芝麻信用分
$sdata = array(
'transaction_id' => date('YmdHisu', time()) . D('Zmop', 'Service')->getTransactionId(1),
'product_code' => 'w1010100100000000001',
'open_id' => $arr['open_id'],
);
$reback = D('Zmop', 'Logic')->doscore($sdata, $publicData, $uid);
if ($reback['status']) {
session('yyzzmop_' . $publicData['uid'], $reback['zm_score']); //记录已经验证了芝麻分
header('Location: ' . (session('fromurl') ? session('fromurl') : U('Cart/index')));
} else {
echo $reback['info'];
}
} else {
echo $arr['success'] . $arr['error_message'];
}
}
}