海尔消费金融简称“嗨付”,公司要求接入海尔金融分期,第一次听说这种支付,官方只有java的demo,没有php的,所以下面会提供一些php实战用到的代码
介绍
海尔会拉一个微信群,给一个word文档,上面会写着测试环境地址,很简洁,没有在线的接口文档,效率极低,我一共收到了3个word文档了,他们给的接口实例每次都要少点什么。开发完后,发现要注册他们平台的账号、身份证认证、人脸识别、银行卡添加,各种隐私,而且又是贷款,给人一种很不安全的感觉。作为后端,要测试自己写的代码,只能注册了。只要能写出来php的demo,官方给的文档在标准一些,接入就比较方便了,这两样还得自己摸索。。。
实战代码
线上和测试配置切换需要修改url(接口地址)
公共配置文件
公钥私钥文件夹
- hai_pay/ 海尔金融配置文件夹
- hai_pay/config/ 公钥私钥
- hai_pay/config/private.pem 私钥
- hai_pay/config/public.pem 公钥
- hai_pay/RSAUtils.php
- hai_pay/SignUtil.php
文件名:private.pem
-----BEGIN PRIVATE KEY-----
***
-----END PRIVATE KEY-----
文件名:public.pem
-----BEGIN PUBLIC KEY-----
***
-----END PUBLIC KEY-----
文件名:RSAUtils.php
dir = 'config';
$this->privateKey = openssl_pkey_get_private(file_get_contents(dirname(__FILE__).'/'.$this->dir.'/private.pem'));//私钥,用于加密
$this->publicKey = openssl_pkey_get_public(file_get_contents(dirname(__FILE__).'/'.$this->dir.'/public.pem'));//公钥,用于解密
}
/**
* 私钥加密
* @param 原始数据 $data
* @return 密文结果 string
*/
public function encryptByPrivateKey($data) {
openssl_private_encrypt($data,$encrypted,$this->privateKey,OPENSSL_PKCS1_PADDING);//私钥加密
$encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
return $encrypted;
}
/**
* 私钥解密
* @param 密文数据 $data
* @return 原文数据结果 string
*/
public function decryptByPrivateKey($data){
$data = base64_decode($data);
openssl_private_decrypt($data,$encrypted,$this->privateKey,OPENSSL_PKCS1_PADDING);//私钥解密
return $encrypted;
}
/**
* 私钥签名
* @param unknown $data
*/
public function signByPrivateKey($data){
openssl_sign($data, $signature, $this->privateKey);
$encrypted = base64_encode($signature);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
return $encrypted;
}
/**
* 公钥加密
* @param 原文数据 $data
* @return 加密结果 string
*/
public function encryptByPublicKey($data) {
openssl_public_encrypt($data,$decrypted,$this->publicKey,OPENSSL_PKCS1_PADDING);//公钥加密
return base64_encode($decrypted);
}
/**
* 公钥解密
* @param 密文数据 $data
* @return 原文结果 string
*/
public function decryptByPublicKey($data) {
$data = base64_decode($data);
openssl_public_decrypt($data,$decrypted,$this->publicKey,OPENSSL_PKCS1_PADDING);//公钥解密
return $decrypted;
}
/**
* 公钥验签
* @param unknown $data
* @param unknown $sign
*/
public function verifyByPublicKey($data,$sign){
$sign = base64_decode($sign);
return openssl_verify($data, $sign, $this->publicKey);
}
public function __destruct(){
openssl_free_key($this->privateKey);
openssl_free_key($this->publicKey);
}
public function getPrivateKey(){
return file_get_contents(dirname(__FILE__).'/'.$this->dir.'/private.pem');
}
}
文件名:SignUtil.php
key = $key;
$this->iv = $iv;
}
/**
* 加密
* @param boolean $status 是否加密
* @return string 处理过的数据
*/
public function encrypt($data,$status=false){
if ($status){
return base64_encode(openssl_encrypt($data, 'des-ede3-cbc', $this->key, OPENSSL_RAW_DATA,$this->iv));
}
return $data;
}
/**
* 解密
* @return string 加密的字符串不是完整的会返回空字符串值
*/
public function decrypt($data,$miv,$status=false){
if ($status){
$k=substr($miv,0,8);
$i=substr($miv,8,8);
return openssl_decrypt(base64_decode($data), 'des-ede3-cbc', $k, OPENSSL_RAW_DATA, $i);
}
return $data;
}
}
?>
控制器文件
host = 'https://testpm.haiercash.com:9002';
$this->loanType = 0;
if(env('APP_ENV') == 'production'){
$this->loanType = 0; // todo 线上地址待完善
$this->host = ''; // todo 线上地址待完善
}
$this->tools = new Tools();
$this->http_clinet = new Client();
require_once dirname(dirname(dirname(__FILE__))) . '/Tools/hai_pay/SignUtil.php';
require_once dirname(dirname(dirname(__FILE__))) . '/Tools/hai_pay/RSAUtils.php';
}
/**
* 贷款申请
* @return \Illuminate\Http\JsonResponse
* @throws LogicException
* @throws \GuzzleHttp\Exception\GuzzleException
* User: https://github.com/WXiangQian
*/
public function hai_consume()
{
$key = rand(10000000, 99999999);
$iv = rand(10000000, 99999999);
$order_id = $this->request->input('order_id',0);
$model = $this->request->input('model','');
// 期数。3、6、9、12
$applyTnr = $this->request->input('applyTnr',0);
if (!in_array($applyTnr,[3,6,9,12])) {
return $this->response->tag('PARAM_ERROR')->response();
}
// 根据订单号查询数据库的实付金额
$payAmt = 0;
if (!isset($payAmt)) {
return $this->response->tag('ORDER_NOT_EXIST')->response();
}
// 小于1w的课程不允许使用海尔金融
if ($payAmt < 10000) {
return $this->response->tag('PARAM_ERROR')->response();
}
$post_data = array(
'uuid' => '交易流水号',
'body' => array(
'orderSn' => '订单号',
'loanType' => '贷款品种编码',
'payAmt' => '贷款金额',
'orderDate' => '下单时间Y-m-d',
'applyTnr' => '期数',
'orderMessage' => array(
'cOrderSn' => time(),
'topLevel' => '',
'model' => '',
'sku' => 0,
'price' => '价格',
'num' => 1,
'cOrderAmt' => '价格',
'cOrderPayAmt' => '价格'
),
)
);
$sign = new SignUtil($key, $iv);
$desData = $sign->encrypt(json_encode($post_data), true);
$rsa = new RSAUtils();
$password_ = $rsa->encryptByPublicKey($key . $iv);
$data = [
'applyNo' => $order_id,
'channelNo' => '', // todo 文档里的渠道编号
'tradeCode' => '', // todo 内部系统使用,文档里有标识
'data' => $desData,
'privatekey' => $rsa->getPrivateKey(),
'key' => $password_
];
$data_string = json_encode($data);
$clinet_data = [
'body' => $data_string,
];
// 这里使用到了guzzle扩展包,可以更换为curl去请求
$result = $this->http_clinet->request('post', $this->host.'/api/payment/gmorder/loanApplication', $clinet_data);
if ($result->getStatusCode() != 200) {
return $this->response->tag('PARAM_ERROR')->response();
}
$result = json_decode($result->getBody(),true);
// 00000为申请成功
if ($result['head']['retFlag'] != '00000') {
throw new LogicException($result['head']['retMsg'],400);
}
$resData = $result['body']['data'];
$resKey = $result['body']['key'];
$decryptByPublicKey = $rsa->decryptByPrivateKey($resKey);
$r = $sign->decrypt($resData, $decryptByPublicKey, true);
$url = '';
if ($r) {
$r = json_decode($r, true);
if (!empty($r['url'])) {
$url = $r['url'];
}
}
return $this->response->data(['url'=>$url])->response();
}
/**
* 贷款回调
* User: https://github.com/WXiangQian
*/
public function hai_callback()
{
$post = file_get_contents('php://input');
$rs = json_decode(stripslashes($post),true);
if(empty($rs['key']) || empty($rs['data'])){
echo json_encode(array('status'=>1,'msg'=>'key值或data值为空'),JSON_UNESCAPED_UNICODE); die;
}
$sign = new SignUtil();
$rsa = new RSAUtils();
$decryptByPublicKey=$rsa->decryptByPrivateKey($rs['key']);
$r = $sign->decrypt($rs['data'],$decryptByPublicKey,true);
if(!$r){
echo json_encode(array('status'=>1,'msg'=>'解密失败'),JSON_UNESCAPED_UNICODE); die;
}
$r = json_decode($r,true);
if(!$r['ordersn']){
echo json_encode(array('status'=>1,'msg'=>'没有订单编号'),JSON_UNESCAPED_UNICODE); die;
}
$out_trade_no = $r['ordersn']; //订单号
$transStatus = $r['body']['outSts']; //订单状态 01审批中02审批通过03审批拒绝04 贷款已取消05 客人以确认提交(订单保存)06 审批退回(客人
$trade_no = $r['body']['orderNo']; //流水号
// $notify_time = time(); //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。
if($transStatus == '02') {
// 调用支付回调回调地址
echo json_encode(array('status'=>1,'msg'=>'02处理成功'),JSON_UNESCAPED_UNICODE); die;
}
echo json_encode(array('status'=>1,'msg'=>'处理成功'),JSON_UNESCAPED_UNICODE); die;
}
}
实战demo地址
https://github.com/WXiangQian/laravel-api
操作流程
结束语
真枪实战php接入海尔消费金融,希望可以得到一个👍哦