class pieceAction extends baseAction{
private
parameters;//合作方的私钥公钥对如果加解密不行请注意格式头尾以及每行64位private
p
a
r
a
m
e
t
e
r
s
;
/
/
合
作
方
的
私
钥
公
钥
对
如
果
加
解
密
不
行
请
注
意
格
式
头
尾
以
及
每
行
64
位
p
r
i
v
a
t
e
public_key = “—–BEGIN PUBLIC KEY—–
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo/fi2xqinU/MdQ6ie3sN
m8F278V7a1Y8Rwdfar/gICFkA6GVNqovqGINWQxn/nfzMTcHZazJlGfv5YhIbDfE
AqByzseibvQfbluDG/pEJsSCMoicxyaAQmSpNpFT72f+FpmHR0wrnYSNWs2fyQdt
GuqD+RIcPfiBMTQh/Cy7yOyT395CLveNFNurxffW0EJpaJCslYrBLqye76kcVOx1
Y0VPU/3PKSDQoJ3FC9DGn6zQ8bKZNmD10yW1LgJqtO2XivX7JJVKW4gJpdEmjslr
WwcVhKbbA27UX3lf+XoC1KkFLmfbVRoDo7x5DRUl28izmSFFas//WJ6GYYjzlmhq
PwIDAQAB
—–END PUBLIC KEY—–”;
private
privatekey=”—–BEGINPRIVATEKEY—–MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCj9+LbGqKdT8x1DqJ7ew2bwXbvxXtrVjxHB19qv+AgIWQDoZU2qi+oYg1ZDGf+d/MxNwdlrMmUZ+/liEhsN8QCoHLOx6Ju9B9uW4Mb+kQmxIIyiJzHJoBCZKk2kVPvZ/4WmYdHTCudhI1azZ/JB20a6oP5Ehw9+IExNCH8LLvI7JPf3kIu940U26vF99bQQmlokKyVisEurJ7vqRxU7HVjRU9T/c8pINCgncUL0MafrNDxspk2YPXTJbUuAmq07ZeK9fsklUpbiAml0SaOyWtbBxWEptsDbtRfeV/5egLUqQUuZ9tVGgOjvHkNFSXbyLOZIUVqz/9YnoZhiPOWaGo/AgMBAAECggEAO72nc/kiYnqenc+1N5RAAw3cDcRAEX2b/K0dAMHkIRDJZeFLgl1De/AtuNIiWb7OZpIMKelokJ/F8jVTXcp7qhFXgyuNbSuZABZrkJgAmLdkUJEhvhWzCX2vgWg10rZrB0Ts2vdPtNaEwh7FJvODtxjW+Lq2e4W9XHYII98QlEW4n4nT1YON8EfoqvhsbRGgNoi59jOSNsji4qxlHcaQQFLDz49Z55VMXk+uvoeA0xe8ga2BGOITxudn/HrpB0xlM+T3C/WWv0oAyZvwb/J0OYqgzg7f9mESqGd0qTXfXycBqI5+uR32zMnOq2H2bQr1ZjhxZMimQ3D0iebQY5CEIQKBgQDYP6imE3hxYi2/92zVXLs6ipTOzi8YwUShERpfgTLQoKXqdTDko+SY80mIgBbhMp0CVlSbygjjPutDi6WD+7LfmCVFGaDy9edGhB6KPYhW4RY++UHSKfGXIGLmAtrYC7B5cxuInYzqLx3CSmcL4PzAjBiZbOWuFssyYxfGNd9CyQKBgQDCG/284Nu5NxDjhUjG2tYvL+IsT+LpZNFG7Ziq6753w8UGHPiDm9KSVuT7fMy1QpmUDd58SxiIKILCYyQrjRtzQ/6AeE20mO5ybUYtHmIp5bNm7ghnSiLZRDYXqiGYNzkqEQXfD6v6Lz9dnKfzGAz1NDXw1Hz+QL2Ffr0O/T+AxwKBgQDSHViCtZxrnteRFJn83jNVeF2Ka7A7P16tmW6kqWZ0bAOKQgAVyGFPc+RY6wxQF9uS78sZ7D6ifvodEUzrZt6wfqaH85T9PY1QaQM7kvosYFw7J/maeQKystclYlS9Yu4/s2ZnYZ4P1WP26lAhrKQpenZUbQjmFGOvO7VX8/RQcQKBgE3T9U/XBKJlrtLa7Qw2UCyJUXEc8slL0BFVUKIvdaYFi6jg0s/KGYrtZlBjgJyowHU5flxtq79kJtGT+LuxjzEPMSsHkXh43RpqL/oFNazA2cbKZ/oqIoDktZ+VanTip3vzaVw/p1/fs9Nv7XMt0Hw8W+hc+mTjRloRL/KjneOfAoGBANcCV1d9gF1MupNt/JAQzS+iPVuRdDyOAvy8WrD2ctmdSSVN0KAYb+4ADBYblUFt1LzjVm/Kb6jMTSlZaHytybDjABKU6qjM0F1EYgH5LaDA8EQBV4a6abPFpL2r4qXB5n68H6KYILV8UwEqTUTG5+ngaIkyeQBFfXY4Ixm871iL—–ENDPRIVATEKEY—–”;//以下为合作方随机生成的aes密匙和aes向量//为安全考虑应随机生成private
p
r
i
v
a
t
e
k
e
y
=
”
—
–
B
E
G
I
N
P
R
I
V
A
T
E
K
E
Y
—
–
M
I
I
E
v
g
I
B
A
D
A
N
B
g
k
q
h
k
i
G
9
w
0
B
A
Q
E
F
A
A
S
C
B
K
g
w
g
g
S
k
A
g
E
A
A
o
I
B
A
Q
C
j
9
+
L
b
G
q
K
d
T
8
x
1
D
q
J
7
e
w
2
b
w
X
b
v
x
X
t
r
V
j
x
H
B
19
q
v
+
A
g
I
W
Q
D
o
Z
U
2
q
i
+
o
Y
g
1
Z
D
G
f
+
d
/
M
x
N
w
d
l
r
M
m
U
Z
+
/
l
i
E
h
s
N
8
Q
C
o
H
L
O
x
6
J
u
9
B
9
u
W
4
M
b
+
k
Q
m
x
I
I
y
i
J
z
H
J
o
B
C
Z
K
k
2
k
V
P
v
Z
/
4
W
m
Y
d
H
T
C
u
d
h
I
1
a
z
Z
/
J
B
20
a
6
o
P
5
E
h
w
9
+
I
E
x
N
C
H
8
L
L
v
I
7
J
P
f
3
k
I
u
940
U
26
v
F
99
b
Q
Q
m
l
o
k
K
y
V
i
s
E
u
r
J
7
v
q
R
x
U
7
H
V
j
R
U
9
T
/
c
8
p
I
N
C
g
n
c
U
L
0
M
a
f
r
N
D
x
s
p
k
2
Y
P
X
T
J
b
U
u
A
m
q
07
Z
e
K
9
f
s
k
l
U
p
b
i
A
m
l
0
S
a
O
y
W
t
b
B
x
W
E
p
t
s
D
b
t
R
f
e
V
/
5
e
g
L
U
q
Q
U
u
Z
9
t
V
G
g
O
j
v
H
k
N
F
S
X
b
y
L
O
Z
I
U
V
q
z
/
9
Y
n
o
Z
h
i
P
O
W
a
G
o
/
A
g
M
B
A
A
E
C
g
g
E
A
O
72
n
c
/
k
i
Y
n
q
e
n
c
+
1
N
5
R
A
A
w
3
c
D
c
R
A
E
X
2
b
/
K
0
d
A
M
H
k
I
R
D
J
Z
e
F
L
g
l
1
D
e
/
A
t
u
N
I
i
W
b
7
O
Z
p
I
M
K
e
l
o
k
J
/
F
8
j
V
T
X
c
p
7
q
h
F
X
g
y
u
N
b
S
u
Z
A
B
Z
r
k
J
g
A
m
L
d
k
U
J
E
h
v
h
W
z
C
X
2
v
g
W
g
10
r
Z
r
B
0
T
s
2
v
d
P
t
N
a
E
w
h
7
F
J
v
O
D
t
x
j
W
+
L
q
2
e
4
W
9
X
H
Y
I
I
98
Q
l
E
W
4
n
4
n
T
1
Y
O
N
8
E
f
o
q
v
h
s
b
R
G
g
N
o
i
59
j
O
S
N
s
j
i
4
q
x
l
H
c
a
Q
Q
F
L
D
z
49
Z
55
V
M
X
k
+
u
v
o
e
A
0
x
e
8
g
a
2
B
G
O
I
T
x
u
d
n
/
H
r
p
B
0
x
l
M
+
T
3
C
/
W
W
v
0
o
A
y
Z
v
w
b
/
J
0
O
Y
q
g
z
g
7
f
9
m
E
S
q
G
d
0
q
T
X
f
X
y
c
B
q
I
5
+
u
R
32
z
M
n
O
q
2
H
2
b
Q
r
1
Z
j
h
x
Z
M
i
m
Q
3
D
0
i
e
b
Q
Y
5
C
E
I
Q
K
B
g
Q
D
Y
P
6
i
m
E
3
h
x
Y
i
2
/
92
z
V
X
L
s
6
i
p
T
O
z
i
8
Y
w
U
S
h
E
R
p
f
g
T
L
Q
o
K
X
q
d
T
D
k
o
+
S
Y
80
m
I
g
B
b
h
M
p
0
C
V
l
S
b
y
g
j
j
P
u
t
D
i
6
W
D
+
7
L
f
m
C
V
F
G
a
D
y
9
e
d
G
h
B
6
K
P
Y
h
W
4
R
Y
+
+
U
H
S
K
f
G
X
I
G
L
m
A
t
r
Y
C
7
B
5
c
x
u
I
n
Y
z
q
L
x
3
C
S
m
c
L
4
P
z
A
j
B
i
Z
b
O
W
u
F
s
s
y
Y
x
f
G
N
d
9
C
y
Q
K
B
g
Q
D
C
G
/
284
N
u
5
N
x
D
j
h
U
j
G
2
t
Y
v
L
+
I
s
T
+
L
p
Z
N
F
G
7
Z
i
q
6753
w
8
U
G
H
P
i
D
m
9
K
S
V
u
T
7
f
M
y
1
Q
p
m
U
D
d
58
S
x
i
I
K
I
L
C
Y
y
Q
r
j
R
t
z
Q
/
6
A
e
E
20
m
O
5
y
b
U
Y
t
H
m
I
p
5
b
N
m
7
g
h
n
S
i
L
Z
R
D
Y
X
q
i
G
Y
N
z
k
q
E
Q
X
f
D
6
v
6
L
z
9
d
n
K
f
z
G
A
z
1
N
D
X
w
1
H
z
+
Q
L
2
F
f
r
0
O
/
T
+
A
x
w
K
B
g
Q
D
S
H
V
i
C
t
Z
x
r
n
t
e
R
F
J
n
83
j
N
V
e
F
2
K
a
7
A
7
P
16
t
m
W
6
k
q
W
Z
0
b
A
O
K
Q
g
A
V
y
G
F
P
c
+
R
Y
6
w
x
Q
F
9
u
S
78
s
Z
7
D
6
i
f
v
o
d
E
U
z
r
Z
t
6
w
f
q
a
H
85
T
9
P
Y
1
Q
a
Q
M
7
k
v
o
s
Y
F
w
7
J
/
m
a
e
Q
K
y
s
t
c
l
Y
l
S
9
Y
u
4
/
s
2
Z
n
Y
Z
4
P
1
W
P
26
l
A
h
r
K
Q
p
e
n
Z
U
b
Q
j
m
F
G
O
v
O
7
V
X
8
/
R
Q
c
Q
K
B
g
E
3
T
9
U
/
X
B
K
J
l
r
t
L
a
7
Q
w
2
U
C
y
J
U
X
E
c
8
s
l
L
0
B
F
V
U
K
I
v
d
a
Y
F
i
6
j
g
0
s
/
K
G
Y
r
t
Z
l
B
j
g
J
y
o
w
H
U
5
f
l
x
t
q
79
k
J
t
G
T
+
L
u
x
j
z
E
P
M
S
s
H
k
X
h
43
R
p
q
L
/
o
F
N
a
z
A
2
c
b
K
Z
/
o
q
I
o
D
k
t
Z
+
V
a
n
T
i
p
3
v
z
a
V
w
/
p
1
/
f
s
9
N
v
7
X
M
t
0
H
w
8
W
+
h
c
+
m
T
j
R
l
o
R
L
/
K
j
n
e
O
f
A
o
G
B
A
N
c
C
V
1
d
9
g
F
1
M
u
p
N
t
/
J
A
Q
z
S
+
i
P
V
u
R
d
D
y
O
A
v
y
8
W
r
D
2
c
t
m
d
S
S
V
N
0
K
A
Y
b
+
4
A
D
B
Y
b
l
U
F
t
1
L
z
j
V
m
/
K
b
6
j
M
T
S
l
Z
a
H
y
t
y
b
D
j
A
B
K
U
6
q
j
M
0
F
1
E
Y
g
H
5
L
a
D
A
8
E
Q
B
V
4
a
6
a
b
P
F
p
L
2
r
4
q
X
B
5
n
68
H
6
K
Y
I
L
V
8
U
w
E
q
T
U
T
G
5
+
n
g
a
I
k
y
e
Q
B
F
f
X
Y
4
I
x
m
871
i
L
—
–
E
N
D
P
R
I
V
A
T
E
K
E
Y
—
–
”
;
/
/
以
下
为
合
作
方
随
机
生
成
的
a
e
s
密
匙
和
a
e
s
向
量
/
/
为
安
全
考
虑
应
随
机
生
成
p
r
i
v
a
t
e
aes_key;
private
keyiv;//平台的公钥private
k
e
y
i
v
;
/
/
平
台
的
公
钥
p
r
i
v
a
t
e
other_public_key =”MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqVzL/VFmIrW4QZAtHZ+NShHdEAl+0QquI7u2ya2AMwMycHOvvLVI95gSM5oC0GEcAN1PhfotSAoeXKW1J3t0o/zMnPrFhsa486VJysHapWnv7DjDunN7i0OCJ+3Jit5DDM2CfSpot/4DSfeXY+s/szEsf1n0837q1UPlRyHzHWCZ3I79mUAQdU+7dr/mJ9XNnG0s79uUJxTfShyGqDONaTwj5Ebed5IrO7QMZWSNjMCeEYpy2xi46TFw/TImCkNM7c1q+28VwzgKIybx+YJbdXSlQuBJvzLh8hVIIPh8UvIiGe7LayKVywWj6Bq06Ts2X85G1oRN3X6GasdbLiOlUwIDAQAB”;
private
cfg=”;protected
c
f
g
=
”
;
p
r
o
t
e
c
t
e
d
method=”;
public function _initialize()
{
parent::_initialize();
if ( !function_exists( 'hex2bin' ) ) {
function hex2bin( $str ) {
$sbin = "";
$len = strlen( $str );
for ( $i = 0; $i < $len; $i += 2 ) {
$sbin .= pack( "H*", substr( $str, $i, 2 ) );
}
return $sbin;
}
}
$this->_cfg = array(
'second_url'=>'http://tapi.hrtxpay.com/router',
'pay_url' =>'http://testapi.xmkzry.com/router',
'gate_url'=>'http://api.xmkzry.com/router',
// ‘notify_url’=>’111’,//支付异步回调地址
‘app_key’=>’WQ4G6HPWE05UMU47’,//’1234567890123456’,//’WQ4G6HPWE05UMU47’,
‘app_account’=>’165080754535613288’,//’123456’,//’165080754535613288’,
‘app_secret’=>’WQ4G6HPWE05UMU47’,//’1234567890123456’,//’WQ4G6HPWE05UMU47’,
‘method’=>$this->method,
‘v’=>’1.0’,
‘format’=>’json’,
‘callBack’=>’http://csqht.hespay.com/api.php/piece/callback‘,
);
}
/**
* 生成指定长度的随机字符串(包含大写英文字母, 小写英文字母, 数字)
*/
public function random_str($length)
{
//生成一个包含 大写英文字母, 小写英文字母, 数字 的数组
$arr = array_merge(range(0, 9), range('a', 'z'), range('A', 'Z'));
$str = '';
$arr_len = count($arr);
for ($i = 0; $i < $length; $i++)
{
$rand = mt_rand(0, $arr_len-1);
$str.=$arr[$rand];
}
return $str;
}
/**
* 请求处理
* $data 请求业务数据
* $url 请求地址
* $n_sign不参与加密的参数数组
* 返回数组 应答报文数组,验签失败返回 array('errorCode'=>"9999","message"=>"验签失败")
*/
public function postData($data,$url,$n_sign,$method_name = "idCard") {
ksort($data);
$post_string = '';
foreach ($data as $key => $value) {
if ($value !== '') {
$post_string .= $key . '=' . $value . '&';
}
}
$post_string = substr($post_string, 0, -1);
//随机生成16位的aes密匙key和向量
$this->aes_key = $this->random_str(16);//'6AAeB6eA6B9FdaAd';//$this->random_str(16);
$this->key_iv = $this->random_str(16);//'FF0505949fE5DA86';//$this->random_str(16);
//aes加密
$encrypt_data = $this->encrypt($post_string,$this->aes_key,$this->key_iv); //aes加密
//组合aes的密匙和向量
$aes_string = $this->aes_key.'-'.$this->key_iv;
//用rsa公钥加密aes密匙-组合 内部包含了base64编码
$encrypt_key = $this->publicEncrypt($this->other_public_key,$aes_string);
//rsa密匙签名请求报文 内部包含了base64编码
$sign_data = $this->privateEncrypt($this->private_key,$post_string);
$this->setParameter('method',$method_name);
$this->setParameter('appKey',$this->_cfg['app_account']); //165080754535613288
$this->setParameter('v','1.0');
$this->setParameter('format','json');
$this->setParameter('encryptData',$encrypt_data);
$this->setParameter('encrtptKey',$encrypt_key);
$this->setParameter('signData',$sign_data);
$this->setParameter('sign',$this->getSign());
//照片不参与签名
foreach ($n_sign as $key => $value) {
$this->setParameter($key,$value);
}
$this->_fileLog($this->getAllParameters(),"请求参数发送地址:".$url);
$result = $this->requestCurl($url);
//返回数据
//得到返回的结果 接下来对返回结果进行解密和验证签名
$result = json_decode($result,1);
$this->_fileLog($result,"返回结果记录:");
if($result['data']) {
//平台公钥加密的结果 我方用私钥解密 得到aes密钥-向量
$get_encrtpt_Key = $result['data']['encrtptKey'];
//先获取aes的key 和 向量
$aes_data = $this->privateDecrypt($get_encrtpt_Key, $this->private_key);
$aes_data = explode('-', $aes_data);
$put_aes_key = $aes_data['0'];
$pur_aes_vi = $aes_data['1'];
//aes解密获取报文数据
$get_encrypt_data = $result['data']['encryptData'];
$put_data = $this->decrypt($get_encrypt_data, $put_aes_key, $pur_aes_vi);
//对报文数据 去掉空格
$put_data = trim($put_data);
//对报文数据 进行RSA签名验证
$get_signData = $result['data']['signData'];
$sign_info = $this->publicDecrypt($get_signData, $put_data, $this->other_public_key);
//验证返回为true表明验证通过,否则验证没通过
if ($sign_info) {
$new_data = '';
$put_data = explode('&', $put_data);
foreach ($put_data as $key => $value) {
$name = explode('=', $value);
$new_data[$name['0']] = $name['1'];
}
$this->_fileLog($new_data,"返回解密数据:");
return $new_data;//返回解密后的业务数据
} else {
return array('errorCode' => "9999", "message" => "验签解密失败");
}
}else{
return $result;//返回结果 无加密数据
}
}
public function hasstring($source,$target){
preg_match_all("/$target/sim", $source, $strResult, PREG_PATTERN_ORDER);
return !empty($strResult[0]);
}
/*
* 子商户认证接口
* 所有的参数来源将用$this->params 数组 进行存储
*/
public function auth()
{
//1组装参数数据
//2获取银行简码处理
if(this->params['bankName'] != '中国银行' &&
this->params['bankName'] != '中国银行' &&
this->hasstring(
this−>params[‘bankName′],′中国′))$bank=substr($this−>params[‘bankName′],6);else$bank=$this−>params[‘bankName′];
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
b
a
n
k
N
a
m
e
′
]
,
′
中
国
′
)
)
$
b
a
n
k
=
s
u
b
s
t
r
(
$
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
b
a
n
k
N
a
m
e
′
]
,
6
)
;
e
l
s
e
$
b
a
n
k
=
$
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
b
a
n
k
N
a
m
e
′
]
;
bank = D("bank_code")->where(array('bank_name'=>
bank))−>find();
b
a
n
k
)
)
−
>
f
i
n
d
(
)
;
shortcode =
bank[‘bankcode′];if(!
b
a
n
k
[
‘
b
a
n
k
c
o
d
e
′
]
;
i
f
(
!
shortcode){
this->resError(“未找到对应的银行简码”);
}
this->resError(“未找到对应的银行简码”); }
data = array(
‘accName’ =>
this−>params[‘accName′],‘accNo′=>
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
a
c
c
N
a
m
e
′
]
,
‘
a
c
c
N
o
′
=>
this->params[‘accNo’],
‘bankName’ =>
this−>params[‘bankName′],‘bankShortcode′=>
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
b
a
n
k
N
a
m
e
′
]
,
‘
b
a
n
k
S
h
o
r
t
c
o
d
e
′
=>
shortcode,
‘branchName’ =>
this−>params[‘branchName′],‘contactMobile′=>
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
b
r
a
n
c
h
N
a
m
e
′
]
,
‘
c
o
n
t
a
c
t
M
o
b
i
l
e
′
=>
this->params[‘contactMobile’],
‘contactName’ =>
this−>params[‘contactName′],‘idcard′=>
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
c
o
n
t
a
c
t
N
a
m
e
′
]
,
‘
i
d
c
a
r
d
′
=>
this->params[‘idcard’],
‘merCityCode’ =>
this−>params[‘merCityCode′],‘merDistrictCode′=>
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
m
e
r
C
i
t
y
C
o
d
e
′
]
,
‘
m
e
r
D
i
s
t
r
i
c
t
C
o
d
e
′
=>
this->params[‘merDistrictCode’],
‘merFullname’ =>
this−>params[‘merFullname′],‘merProvinceCode′=>
t
h
i
s
−
>
p
a
r
a
m
s
[
‘
m
e
r
F
u
l
l
n
a
m
e
′
]
,
‘
m
e
r
P
r
o
v
i
n
c
e
C
o
d
e
′
=>
this->params[‘merProvinceCode’],
);
//2@todo请求数据保存数据库
$add = array(
'name' => $this->params['merFullname'],
'idcard' => $this->params['idcard'],
'mobile' => $this->params['contactMobile'],
'bankno' => $this->params['accNo'],
'channelno' => $this->params['channelno'],
);
$res = D("qht_user")->where(array('channelno'=>$this->params['channelno'],'idcard'=>$this->params['idcard'], 'bankno' => $this->params['accNo']))->find();
if($res){
//认证
if($res['subcode'] && $res['status_auth'] == 1){
$return = array(
'status'=>200,
'data'=>$res['subcode'],
);
exit(json_encode($return));
}
}else{
D("qht_user")->add($add);
}
//3不验签数据
$n_sign = array(
'legalPhotoPos' => 'jpg@' . $this->base64EncodeImage($this->params['legalPhotoPos']),
'legalPhotoNeg' => 'jpg@' . $this->base64EncodeImage($this->params['legalPhotoNeg']),
'idcardPhotoHalf' => 'jpg@' . $this->base64EncodeImage($this->params['idcardPhotoHalf']),
'idcardDebitPhoto' => 'jpg@' . $this->base64EncodeImage($this->params['idcardDebitPhoto'])
);
//@todo未认证false请填写变量
$url = $this->_cfg['second_url'];
$method_name = "certification";
$json = $this->postData($data, $url, $n_sign, $method_name);
if(!empty($json['subCode'])){
$save = array(
'subcode'=>$json['subCode'],
'status_auth'=>1
);
D("qht_user")->where(array('channelno'=>$this->params['channelno'],'idcard'=>$this->params['idcard'], 'bankno' => $this->params['accNo']))->save($save);
$return = array(
'status'=>200,
'data'=>$json['subCode'],
);
echo json_encode($return);
}else{
$save = array(
'status_auth'=>2
);
D("qht_user")->where(array('channelno'=>$this->params['channelno'],'idcard'=>$this->params['idcard'], 'bankno' => $this->params['accNo']))->save($save);
$return = array(
'status'=>201,
'messgae'=>'认证失败',
);
echo json_encode($return);
}
}
/**
*子商户进件接口
*/
public function report(){
$data = array(
'channelNumber'=>$this->params['channelNumber'],
'drawalFee'=>$this->params['drawalFee'],
'tradeRate'=>$this->params['tradeRate'],
'subCode'=>$this->params['subcode'],
);
//保存进件数据
$save = array(
'fee'=>$this->params['drawalFee'],
'rate'=>$this->params['tradeRate'],
'channelno'=>$this->params['channelNumber'],
);
$re = D("qht_user")->where(array('channelno'=>$this->params['channelno'],'idcard'=>$this->params['idcard'], 'bankno' => $this->params['bankno']))->find();
if($re){
$res = D("qht_user")->where(array('channelno'=>$this->params['channelno'],'idcard'=>$this->params['idcard'], 'bankno' => $this->params['bankno']))->save($save);
if($res['status_reg'] == 1){
$return = array(
'status'=>200,
'message'=>'进件成功'
);
exit(json_encode($return));
}
}
$url = $this->_cfg['second_url'];
$method_name = "merchantChannel";
$n_sign = array();
$json = $this->postData($data, $url, $n_sign,$method_name);
//$json['errorCode'] == 200
if($json['errorCode'] == "200"){
$save = array(
'status_reg'=>1
);
D("qht_user")->where(array('channelno'=>$this->params['channelno'],'idcard'=>$this->params['idcard'], 'bankno' => $this->params['accNo']))->save($save);
$return = array(
'status'=>200,
'message'=>'进件成功'
);
echo json_encode($return);
} elseif ($json['errorCode'] == "100"){
$return = array(
'status'=>200,
'message'=>$json['message']
);
echo json_encode($return);
}else{
$return = array(
'status'=>201,
'message'=>$json['message']
);
echo json_encode($return);
}
}
/**
*子商户支付接口
*/
public function pay(){
$order = D('order_ftf')->where(array('orderid'=>$this->params['orderId']))->find();
if(!$order){
//生成订单记录
$order = array(
'orderid'=>$this->params['orderId'],
'name'=>$this->params['accName'],
'card_no'=>$this->params['idcard'],
'bank_sub'=>$this->params['bank_sub'],
//银行卡号
'bank_no'=>$this->params['bank_no'],
'bank_province'=>$this->params['bank_province'],
'bank_city'=>$this->params['bank_city'],
//信用卡号
'paybanknum'=>$this->params['creditCard'],
'mobile'=>$this->params['mobile'],
'amount'=>$this->params['amount'],
'notify_url'=>$this->params['notifyUrl'],
'front_url'=>$this->params['frontUrl'],
'addtime'=>time(),
'partner'=>$this->params['partner'],
'userrate'=>$this->params['userrate'],
'fees'=>$this->params['fee']
);
//生成订单记录
$order = D('order_ftf')->add($order);
}
//组装数据,发送请求
$data = array(
'accName'=>$this->params['accName'],
'amount'=>$this->params['amount'],
'callBackUrl'=>$this->_cfg['callBack'],
'channelNumber'=>$this->params['channelNumber'],
'channelTag'=>'1',
'creditCard'=>$this->params['creditCard'],
'frontUrl'=>$this->params['frontUrl'],
'idcard'=>$this->params['idcard'],
'orderId'=>$this->params['orderId'],
'settleType'=>'1',
'subCode'=>$this->params['subcode'],
);
$url = $this->_cfg['second_url'];
$method_name = "quickPay";
$n_sign = array();
$result = $this->postData($data, $url, $n_sign,$method_name);
//$result['RetCode'] == '0000'
if($result['RetCode'] == '0000'){
$up = D('order_ftf')->where(array('sn' => $this->params['orderId']))->save(array('payurl'=>$result['Page']));
$rs = array(
'status' => 200,
'data' =>array(
'Amount'=>$result['Amount'],
'MerchOrderId'=>$result['MerchOrderId'],
'MerchantId'=>$result['MerchantId'],
'OrderId'=>$result['OrderId'],
'Page'=>$result['Page'],
'Sign'=>$result['Sign'],
'TradeTime'=>$result['TradeTime'],
'Version'=>$result['Version'],
),
);
echo json_encode($rs);
}else{
$rs = array(
'status' => 201,
'message' =>'请求失败',
);
echo json_encode($rs);
}
}
/**
*认证信息变更接口
*/
public function updateauth(){
//1组装参数数据
//2获取银行简码处理
if($this->params['bankName'] != '中国银行' && $this->hasstring($this->params['bankName'],'中国')){
$bank = substr($this->params['bankName'],6);
}else{
$bank = $this->params['bankName'];
}
$bank = D("bank_code")->where(array('bank_name'=>$bank))->find();
$shortcode = $bank['bank_code'];
if(!$shortcode){
$this->resError("未找到对应的银行简码");
}
$data = array(
'subCode'=>$this->params['subCode'],
'merProvinceCode'=>$this->params['merProvinceCode'],
'merCityCode'=>$this->params['merCityCode'],
'merDistrictCode'=>$this->params['merDistrictCode'],
'accNo'=>$this->params['accNo'],
'bankShortcode'=>$shortcode,
'bankName'=>$this->params['bankName'],
'branchName'=>$this->params['branchName'],
);
$url = $this->_cfg['second_url'];
$method_name = "updateCertification";
$n_sign = array();
$result = $this->postData($data, $url, $n_sign,$method_name);
if($result['errorCode'] == 200){
$save = array(
'bankno'=>$this->params['accNo'],
);
D("qht_user")->where(array('channelno'=>$this->params['channelNumber'],'idcard'=>$this->params['idcard'],'bankno'=>$this->params['bankno']))->save($save);
$return = array(
'status'=>200,
'message'=>$result['message']
);
echo json_encode($return);
}else{
$return = array(
'status'=>201,
'message'=>$result['message']
);
echo json_encode($return);
}
}
/**
*费率变更接口
*/
public function updaterate(){
$data = array(
'tradeRate'=>$this->params['tradeRate'],
'drawalFee'=>$this->params['drawalFee'],
'channelNumber'=>$this->params['channelNumber'],
'subCode'=>$this->params['subCode'],
);
$url = $this->_cfg['second_url'];
$method_name = "updateMerchantChannel";
$n_sign = array();
$result = $this->postData($data, $url, $n_sign,$method_name);
if($result['errorCode'] == 200){
$save = array(
'rate'=>$this->params['tradeRate'],
'fee'=>$this->params['drawalFee'],
);
D("qht_user")->where(array('channelno'=>$this->params['channelNumber'],'idcard'=>$this->params['idcard'], 'bankno' => $this->params['bankno']))->save($save);
$return = array(
'status'=>200,
'message'=>$result['message']
);
echo json_encode($return);
}else{
$return = array(
'status'=>201,
'message'=>$result['message']
);
echo json_encode($return);
}
}
private function decdata($rs){
$rs = str_replace(' ','',$rs);
$new_data = '';//分解后的数组数据
$put_data = explode('&', $rs);
foreach ($put_data as $key => $value) {
$name = explode('=', $value);
$new_data[$name['0']] = $name['1'];
}
//1先获取aes的key 和 向量
$get_encrtpt_Key = $new_data['encrtptKey'];
$aes_data = $this->privateDecrypt($get_encrtpt_Key, $this->private_key);
$aes_data = explode('-', $aes_data);
$put_aes_key = $aes_data['0'];
$pur_aes_vi = $aes_data['1'];
$data = $this->decrypt($new_data['encryptData'], $put_aes_key, $pur_aes_vi); //解密数据
$this->_fileLog($data,"解密结果:");
return $data;
}
/**
*支付异步回调地址
*
*/
public function callback(){
$rsHttp = file_get_contents('php://input');
$bb = urldecode($rsHttp);
$str = $this->decdata($bb);
$params = '';//分解后的数组数据
$put_data = explode('&', $str);
foreach ($put_data as $key => $value) {
$name = explode('=', $value);
$params[$name['0']] = $name['1'];
}
$merchantCode = $params['merchantCode'];
$orderId = $params['orderId'];
$supOrderId = $params['supOrderId'];
$status = $params['status'];
$amount = $params['amount'];
$incomeAmount = $params['incomeAmount'];
$payTime = $params['payTime'];
$message = $params['message'];
$subcode = $params['subCode'];
if($status==1){
$order = M('order_ftf')->where(array('orderid'=>$orderId))->find();
// 订单数据
if (!$order) {
return $this->ajaxReturn(null, '查无订单信息', 3001);
}
$save = array(
'paytime'=>$payTime,
'status'=>$status,
'supOrderId'=>$supOrderId,
'subcode'=>$subcode,
'merchantcode'=>$merchantCode,
'incomeamount'=>$incomeAmount,
'message'=>$message,
);
D('order_ftf')->where(array('orderid'=>$orderId))->save($save);
$notifyData = array(
'orderid' => $orderId, // 订单号
'paytime' => $payTime, // 支付时间
'amount' => $amount, // 支付金额
);
$notifyData = apiUtil::argSort($notifyData);
$res = strtoupper($this->notifyClient($order, $notifyData));
if ($res == 'SUCCESS') {
M('order_ftf')->where(array('orderid' => $orderId))->save(array('callback' => 1)); //是否回调成功
//商户回调成功返回字符串1
//$this->notifySuccess();
}
}else{
M('order_ftf')->where(array('orderid'=>$orderId))->save(array('status'=>'3'));
return $this->ajaxReturn(null, '支付接口回掉数据有误!', 3001);
}
}
/**
*支付订单查询
*/
public function order_select($orderid){
//1获取参数
$order = D("order_ftf")->where(array('orderid'=>$orderid))->find();
if($order){
$data = array(
'orderId'=>$order['orderid'],
'subCode'=>$order['subcode'],
'supOrderId'=>$order['supOrderId'],
);
$url = $this->_cfg['second_url'];
$method_name = "queryOrder";
$n_sign = array();
$data = $this->postData($data, $url, $n_sign,$method_name);
if(!$data){
return false;
}else{
return $data;
}
}
}
/**
* post请求
*/
public function requestCurl($url){
$data = $this->getAllParameters();
$ch = curl_init();
// 设置curl允许执行的最长秒数
curl_setopt($ch, CURLOPT_TIMEOUT, 500);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_URL,$url);
//发送一个常规的POST请求。
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));
curl_setopt($ch, CURLOPT_HEADER,0);//是否需要头部信息(否)
// 执行操作
$result = curl_exec($ch);
if($result){
curl_close($ch);
}else{
$err_str=curl_error($ch);
echo($err_str);
curl_close($ch);
}
#返回数据
return $result;
}
/**
* 获取签名
*/
public function getSign(){
data=
d
a
t
a
=
this->getAllParameters();
$sign_string = '';
if (is_array($data)) {
ksort($data);
foreach ($data as $key => $value) {
$sign_string .= $key . $value;
}
}
$sign_string = $this->_cfg['app_secret'].$sign_string.$this->_cfg['app_secret'];
//echo '签名'.$sign_string."<br>";
//$new_sign = sha1($sign_string);
$new_sign = strtoupper(sha1($sign_string));
//echo "<br>sign值:".$new_sign;
//$new_sign = strtoupper('af0358995ce7e6e8fcbc8d80f0af81519561d620');
//var_dump($new_sign);
return $new_sign;
}
/**
* 获取图片base64位编码
* @param $image_file
* @return string
*/
public function base64EncodeImage (url) {
url) {
image_data = file_get_contents(
url);
u
r
l
)
;
base64_image = base64_encode(
imagedata);return
i
m
a
g
e
d
a
t
a
)
;
r
e
t
u
r
n
base64_image;
}
/**
* aes解密
*/
public function decrypt($input, $key,$key_iv)
{
$encryptedData = base64_decode($input);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encryptedData, MCRYPT_MODE_CBC, $key_iv);
return $decrypted;
}
/**AES加密
* @param $input
* @param $key
* @return string
*/
public function encrypt($input, $key,$key_iv) {
$data = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $input, MCRYPT_MODE_CBC, $key_iv);
return base64_encode($data);
}
/**
* RSA私钥加密
* @param string $private_key 私钥
* @param string $data 要加密的字符串
* @return string $encrypted 返回加密后的字符串
* @author mosishu
*/
public function privateEncrypt(
privateKey,
p
r
i
v
a
t
e
K
e
y
,
data){
// 私钥密码
//
passphrase=”;//
p
a
s
s
p
h
r
a
s
e
=
”
;
/
/
key_width = 64;
//
pkey=array();////如果私钥是1行//if(!stripos(
p
k
e
y
=
a
r
r
a
y
(
)
;
/
/
/
/
如
果
私
钥
是
1
行
/
/
i
f
(
!
s
t
r
i
p
o
s
(
privateKey, “\n” ) ){
//
i=0;//while(
i
=
0
;
/
/
w
h
i
l
e
(
key_str = substr(
privateKey,
p
r
i
v
a
t
e
K
e
y
,
i *
keywidth,
k
e
y
w
i
d
t
h
,
key_width) ){
//
pkey[]=
p
k
e
y
[
]
=
key_str;
// i ++ ;
// }
// }else{
// //echo ‘一行?’;
// }
//
i ++ ; // } // }else{ // //echo ‘一行?’; // } //
privateKey = "-----BEGIN PRIVATE KEY-----\n" . implode("\n",
pkey);//
p
k
e
y
)
;
/
/
privateKey = $privateKey .”\n—–END PRIVATE KEY—–”;
//如果秘钥是不带头和尾的 就需要用上面这个转化成 带头尾的秘钥
//私钥
$private_id = openssl_pkey_get_private( $privateKey);
openssl_sign($data, $signature, $private_id, OPENSSL_ALGO_SHA1 );
openssl_free_key( $private_id );
//加密后的内容通常含有特殊字符,需要编码转换下
$signature = base64_encode($signature);
return $signature;
//下面的不可用 应删除
//
encrypted=”;//
e
n
c
r
y
p
t
e
d
=
”
;
/
/
pi_key = openssl_pkey_get_private(
privatekeytwo);//这个函数可用来判断私钥是否是可用的,可用返回资源idResourceid//opensslprivateencrypt(
p
r
i
v
a
t
e
k
e
y
t
w
o
)
;
/
/
这
个
函
数
可
用
来
判
断
私
钥
是
否
是
可
用
的
,
可
用
返
回
资
源
i
d
R
e
s
o
u
r
c
e
i
d
/
/
o
p
e
n
s
s
l
p
r
i
v
a
t
e
e
n
c
r
y
p
t
(
data,
encrypted,
e
n
c
r
y
p
t
e
d
,
pi_key);//私钥加密
//
encrypted=base64encode(
e
n
c
r
y
p
t
e
d
=
b
a
s
e
64
e
n
c
o
d
e
(
encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
// return $encrypted;
//最大允许加密长度为117,得分段加密
//
plainData=strsplit(
p
l
a
i
n
D
a
t
a
=
s
t
r
s
p
l
i
t
(
data,1);//生成密钥位数 1024 bit key
// foreach(
plainDataas
p
l
a
i
n
D
a
t
a
a
s
chunk){
//
partialEncrypted=”;//
p
a
r
t
i
a
l
E
n
c
r
y
p
t
e
d
=
”
;
/
/
encryptionOk = openssl_private_encrypt(
chunk,
c
h
u
n
k
,
partialEncrypted,
privatekey);//私钥加密//if(
p
r
i
v
a
t
e
k
e
y
)
;
/
/
私
钥
加
密
/
/
i
f
(
encryptionOk === false){
// return false;
// }
//
encrypted.=
e
n
c
r
y
p
t
e
d
.
=
partialEncrypted;
// }
//
//
encrypted=base64encode(
e
n
c
r
y
p
t
e
d
=
b
a
s
e
64
e
n
c
o
d
e
(
encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
// return $encrypted;
}
/**
* RSA公钥解密(私钥加密的内容通过公钥可以解密出来)
* @param string $public_key 公钥
* @param string $data 私钥加密后的字符串
* @return string $decrypted 返回解密后的字符串
* @author mosishu
*/
public function publicDecrypt(
sign,
s
i
g
n
,
data,public_key){
public_key){
key_width = 64;
pkey=array();//如果私钥是1行
p
k
e
y
=
a
r
r
a
y
(
)
;
/
/
如
果
私
钥
是
1
行
privateKey = “”;
if( ! stripos( public_key, “\n” ) ){
public_key, “\n” ) ){
i = 0;
while(
keystr=substr(
k
e
y
s
t
r
=
s
u
b
s
t
r
(
public_key ,
i∗
i
∗
key_width ,
keywidth))$pkey[]=$keystr;$i++;
k
e
y
w
i
d
t
h
)
)
$
p
k
e
y
[
]
=
$
k
e
y
s
t
r
;
$
i
+
+
;
privateKey = "-----BEGIN PUBLIC KEY-----\n" . implode("\n",
pkey);
p
k
e
y
)
;
privateKey .= “\n—–END PUBLIC KEY—–”;
}else{
privateKey=
p
r
i
v
a
t
e
K
e
y
=
public_key;
}
$pkeyid = openssl_pkey_get_public($privateKey);
$sign = base64_decode($sign);
$verify = openssl_verify($data, $sign, $pkeyid);
openssl_free_key($pkeyid);
return $verify;
}
//RSA公钥加密
public function publicEncrypt(
publickey,
p
u
b
l
i
c
k
e
y
,
data){
//—–BEGIN PUBLIC KEY—– —–END PUBLIC KEY—–
passphrase=”;
p
a
s
s
p
h
r
a
s
e
=
”
;
key_width = 64;
pkey=array();//如果私钥是1行
p
k
e
y
=
a
r
r
a
y
(
)
;
/
/
如
果
私
钥
是
1
行
privateKey = “”;
if( ! stripos( public_key, “\n” ) ){
public_key, “\n” ) ){
i = 0;
while(
keystr=substr(
k
e
y
s
t
r
=
s
u
b
s
t
r
(
public_key ,
i∗
i
∗
key_width ,
keywidth))$pkey[]=$keystr;$i++;
k
e
y
w
i
d
t
h
)
)
$
p
k
e
y
[
]
=
$
k
e
y
s
t
r
;
$
i
+
+
;
privateKey = "-----BEGIN PUBLIC KEY-----\n" . implode("\n",
pkey);
p
k
e
y
)
;
privateKey .= “\n—–END PUBLIC KEY—–”;
}else{
privateKey=
p
r
i
v
a
t
e
K
e
y
=
public_key;
}
$private_id = openssl_pkey_get_public( $privateKey);
$encrypted = '';
//$pu_key = openssl_pkey_get_public($privateKey);
openssl_public_encrypt($data,$encrypted,$private_id);//公钥加密
$encrypted = bin2hex($encrypted);
$encrypted = base64_encode($encrypted);
return $encrypted;
}
//RSA私钥解密
public function privateDecrypt(
data,
d
a
t
a
,
private_key){
data=base64decode(
d
a
t
a
=
b
a
s
e
64
d
e
c
o
d
e
(
data);
$data = hex2bin($data);
$pi_key = openssl_pkey_get_private($private_key);
openssl_private_decrypt($data,$output,$pi_key);
return $output;
}
/**
* @param 设置方法
*/
public function setMethod(
methodname)$this−>method=$methodname;/∗∗∗获取参数值∗/publicfunctiongetParameter(
m
e
t
h
o
d
n
a
m
e
)
$
t
h
i
s
−
>
m
e
t
h
o
d
=
$
m
e
t
h
o
d
n
a
m
e
;
/
∗
∗
∗
获
取
参
数
值
∗
/
p
u
b
l
i
c
f
u
n
c
t
i
o
n
g
e
t
P
a
r
a
m
e
t
e
r
(
parameter) {
return isset(
this−>parameters[
t
h
i
s
−
>
p
a
r
a
m
e
t
e
r
s
[
parameter])?
this−>parameters[
t
h
i
s
−
>
p
a
r
a
m
e
t
e
r
s
[
parameter]:”;
}
/**
*设置参数值
*/
public function setParameter(
parameter,
p
a
r
a
m
e
t
e
r
,
parameterValue) {
this−>parameters[
t
h
i
s
−
>
p
a
r
a
m
e
t
e
r
s
[
parameter] = $parameterValue;
}
/**
*获取所有请求的参数
*@return array
*/
public function getAllParameters() {
return $this->parameters;
}
/**
* 文件日志
* @DateTime 2017-08-18T08:52:34+0800
* @param [type] $data [description]
* @return [type] [description]
*/
protected function _fileLog($data, $tag, $task = '')
{
$content = (is_array($data) || is_object($data)) ? var_export($data, true) : $data;
$file = MODULE_NAME . '_' . ACTION_NAME . '_' . date('Y-m-d') . '.php';
$tag = ($tag ? "_{$tag}" : '') . ($task ? "_{$task}" : '');
return flog($content, $tag, $file);
}
/**
* 记录 请求参数 和 回调记录
* @param $params
* @param $rs
*/
public function log($params='', $rs='')
{
$dir = PATH_VAR . 'runtime/Api/Logs/';
if (!file_exists($dir)) mkdir($dir);
$datetime = date('Y-m-d H:i:s');
$module = MODULE_NAME;
$action = ACTION_NAME;
$str = "[{$datetime}] {$module}/{$action} \n";
$str .= (var_export($params, true) . "\n");
$str .= (var_export($rs, true) . "\n\n\n\n");
$date = date('Ymd');
file_put_contents($dir . "{$date}.log", $str, FILE_APPEND);
// 删除8天前日志
$oldDate = date('Ymd', (time() - (60 * 60 * 24 * 8)));
if (file_exists($dir . "{$oldDate}.log")) {
unlink($dir . "{$oldDate}.log");
}
}
}