注意:乐百分是分测试与正式帐号的 3,注意事项: 1.交易金额范围(600—50000)元。 2.交易测试账号:接口使用(商户名称、商户编号、接口密码)乐百分管理后台使用(商户登录账号
注意:乐百分是分测试与正式帐号的
3,注意事项:
1.交易金额范围(600—50000)元。
2.交易测试账号:接口使用(商户名称、商户编号、接口密码)乐百分管理后台使用(商户登录账号、登录密码、退款密码、PC端登陆地址)。
3.测试环境只能使用测试卡信息表中的卡号、cvn、有效期等信息做测试交易,身份证号可以填写真实个人身份证,若填写真实的卡号等信息是无法做交易的。
4.测试时需要接收短信验证码,因此手机号要为真实有效的手机号码。若无法接收短信,切勿多次触发短信验证码,可检查是否手机网络问题,或同一手机号测试交易过多,换其他手机号测试。
5.为了测试方便测试环境的扣款间隔为两天一期,若需测试退款请在交易第二天(清算后)操作。
6.测试完成,要接到乐百分生产环境时需更换商户编号、商户名称、商户简称、接口密码、生产环境域名,证书不用更换。
两个文件放到 \extend\lfqpay php文件
LebaifenPay.php
参数都在缓存取得
<?phpnamespace lfqpay;
/**
* 乐百分 支付
*
* Created by .
* User: going1000
* Date: 9/19/16
* Time: 4:34 PM
*/
class LebaifenPay
{
// private $version = '1.0.0';
// private $encoding = 'utf-8';
const VS = '1.0.0';//$version
const ED = 'utf-8';//$encoding
public $lbfpay_conf;
public $cert_addr;
public $lfqpay_cert_password;
public $create_api;
public $cancel_api;
public $query_api;
public $front_url;
public $back_url;
public function __construct()
{
//初始化,取得微信支付参数
$system_cofing=system_cofing();
$this->lbfpay_conf = $system_cofing;
$lfqpay_cert_addr=explode('/uploads/',$system_cofing['lfqpay_cert_addr']);//http://www.cg.com/uploads/file/20191230\e675796c651a74dd9272a8705dbb22e3.pfx
$this->cert_addr='./uploads/'.$lfqpay_cert_addr[1];//证书绝对路径
$this->lfqpay_cert_password=$system_cofing['lfqpay_cert_password'];
$system_website=$this->lbfpay_conf['system_website'];
$this->front_url=$system_website.'/pay/index/lfqpay_notify_url';//交易完成或失败通过此地址同步返回交易结果到商户页面 同步回调 http://www.1.com/lbf_pay/frontUrl.php
$this->back_url=$system_website.'/pay/index/lfqpay_notify';//异步通知交易结果以及后期 异步回调 http://www.1.com/lbf_pay/backUrl.php
if($system_cofing['lfqpay_test_is']){//1=正式环境(正式上线支付)
$this->create_api='https://interface.lfqpay.com/lfq-pay/gateway/api/frontTransRequest.do';
$this->cancel_api='https://interface.lfqpay.com/lfq-pay/gateway/api/backCancelRequest.do';
$this->query_api='https://interface.lfqpay.com/lfq-pay/gateway/api/singleQueryRequest.do';
}else{//0=测试环境
$this->create_api='https://tt.lfqpay.com/lfq-pay/gateway/api/frontTransRequest.do';
$this->cancel_api='https://tt.lfqpay.com/lfq-pay/gateway/api/backCancelRequest.do';
$this->query_api='https://tt.lfqpay.com/lfq-pay/gateway/api/singleQueryRequest.do';
}
//分期数
$this->choose_installments_num=$system_cofing['lfqpay_txnTerms'];
// dump($data['choose_installments_num']);exit;
}
/**
* 创建-pc
*
* @param $data
* @return string
* @throws ErrorException
*/
public function buildRequestForm($data)
{
// 分期数
if($data['choose_installments_num']){
$choose_installments_num=$data['choose_installments_num'];
}else{
$choose_installments_num=$this->choose_installments_num;
}
$rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
$certdata = openssl_x509_parse($cert['cert']);
if(empty($certdata) || !$this->front_url || !$this->back_url || !$this->lbfpay_conf['lfqpay_merId'] || !$this->lbfpay_conf['lfqpay_merName'] || !$this->lbfpay_conf['lfqpay_merPwd']){
$sHtml='缺少必要参数!';
}else{//正确
$param =array(
'certId' => $certdata['serialNumber'],
'version' => self::VS,
'txnType' => '01', // 创建
'frontUrl' => $this->front_url, // 同步回调
'backUrl' => $this->back_url, // 异步回调
'encoding' => self::ED,
'merId' => $this->lbfpay_conf['lfqpay_merId'],
'merName' => $this->lbfpay_conf['lfqpay_merName'],//商户名称
'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],//商户简称
'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
'orderId' => $data['out_trade_no'], // 订单号
'txnTime' => date('YmdHis'), // 发送时间
'txnAmt' => round($data['total_fee'] * 100), // 订单总额 (单位分)
'txnTerms' => $choose_installments_num?$choose_installments_num:6, // 分期数
'txnTermsList' => 15, // 前台交易时可通过此参数控制页面显示的分期数列表。不同分期之间用逗号分开,如“3,6”。
'merNote' => $data['body'], // 物品信息
'userMac' => ',',
//'monthAmount' => round($data['price_per_installments_without_lbf_price'] * 100),
//'discount' => round($data['ahs_subsidies'] * 100),
'validTime' => date('YmdHis')+ 60*60*24*3 // 超时时间 yyyyMMddHHmmss
);
// dump($param);die;
$sign = $this->_sign($param);
$param['signature'] = $sign;
$sHtml = "<form name='xxform' action='{$this->create_api}' method='get'>";
foreach ($param as $key => $val) {
$sHtml .= " <input type='hidden' name='" . $key . "' value='" . $val . "'/> ";
}
$sHtml = $sHtml . "</form>";
$sHtml = $sHtml . "<script>document.forms['xxform'].submit();</script>";
}
// dump($sHtml);exit;
return $sHtml;
}
/**
* 创建-移动app
*
* @param $data
* @return string
* @throws ErrorException
*/
public function buildRequestFormApp($data)
{
// 分期数
if($data['choose_installments_num']){
$choose_installments_num=$data['choose_installments_num'];
}else{
$choose_installments_num=$this->choose_installments_num;
}
$choose_installments_num=$choose_installments_num?$choose_installments_num:6;
$rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
$certdata = openssl_x509_parse($cert['cert']);
if(empty($certdata) || !$this->front_url || !$this->back_url || !$this->lbfpay_conf['lfqpay_merId'] || !$this->lbfpay_conf['lfqpay_merName'] || !$this->lbfpay_conf['lfqpay_merPwd']){
$param=[];
}else{//正确
$txnTime=date('YmdHis');
$validTime=$txnTime + 60*60*24*3;
//用于签名
$param_sign =array(
'certId' => $certdata['serialNumber'],
'version' => self::VS,
'txnType' => '01', // 创建
'frontUrl' => $this->front_url, // 同步回调
'backUrl' => $this->back_url, // 异步回调
'encoding' => self::ED,
'merId' => $this->lbfpay_conf['lfqpay_merId'],
'merName' => $this->lbfpay_conf['lfqpay_merName'],//商户名称
'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],//商户简称
'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
'orderId' => $data['out_trade_no'], // 订单号
'txnTime' => $txnTime, // 发送时间
'txnAmt' => round($data['total_fee'] * 100), // 订单总额 (单位分)
'txnTerms' => $choose_installments_num, // 分期数
'txnTermsList' => 15, // 前台交易时可通过此参数控制页面显示的分期数列表。不同分期之间用逗号分开,如“3,6”。
'merNote' => $data['body'], // 物品信息
'userMac' => ',',
//'monthAmount' => round($data['price_per_installments_without_lbf_price'] * 100),
//'discount' => round($data['ahs_subsidies'] * 100),
'validTime' => $validTime // 超时时间 yyyyMMddHHmmss
);
// dump($param_sign);
$param =array(
'certId' => 'certId='.$certdata['serialNumber'],
'version' => '&version='.self::VS,
'txnType' => '&txnType='.'01', // 创建
'frontUrl' => '&frontUrl='.$this->front_url, // 同步回调
'backUrl' => '&backUrl='.$this->back_url, // 异步回调
'encoding' => '&encoding='.self::ED,
'merId' => '&merId='.$this->lbfpay_conf['lfqpay_merId'],
'merName' => '&merName='.$this->lbfpay_conf['lfqpay_merName'],//商户名称
'merAbbr' => '&merAbbr='.$this->lbfpay_conf['lfqpay_merName'],//商户简称
'merPwd' => '&merPwd='.$this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
'orderId' => '&orderId='.$data['out_trade_no'], // 订单号
'txnTime' => '&txnTime='.$txnTime, // 发送时间
'txnAmt' => '&txnAmt='.round($data['total_fee'] * 100), // 订单总额 (单位分)
'txnTerms' => '&txnTerms='.$choose_installments_num, // 分期数
'txnTermsList' => '&txnTermsList=15', // 前台交易时可通过此参数控制页面显示的分期数列表。不同分期之间用逗号分开,如“3,6”。
'merNote' => '&merNote='.$data['body'], // 物品信息
'userMac' => '&userMac=,',
//'monthAmount' => round($data['price_per_installments_without_lbf_price'] * 100),
//'discount' => round($data['ahs_subsidies'] * 100),
'validTime' => '&validTime='.$validTime // 超时时间 yyyyMMddHHmmss
);
// dump($param);exit;
$sign = $this->_sign($param_sign);
$param['signature'] = '&signature='.urlencode($sign);
$param['url'] = $this->create_api.'?';
}
return $param;
}
/**
* 取消订单
*
* @param $contractsCode
* @return bool
* @throws ErrorException
* @throws UserException
*/
public function cancel($contractsCode) {
// $lbfpay_conf = Config::get('onlinepay.lbfpay');
// $rs = openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
$rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
$certdata = openssl_x509_parse($cert['cert']);
$param=array(
'certId' => $certdata['serialNumber'],
'version' => self::VS,
'encoding' => self::ED,
'txnType' => '04', // 退款
'txnTime' => date('YmdHis'), // 发送时间
'merId' => $this->lbfpay_conf['lfqpay_merId'],
'merName' => $this->lbfpay_conf['lfqpay_merName'],
'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],
'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
'backUrl' => $this->back_url,
'contractsCode' => $contractsCode
);
$sign = $this->_sign($param);
$param['signature'] = $sign;
$rs = CurlHandler::post($this->cancel_api, $param);
$arr = json_decode($rs, true);
if($arr['respCode'] === '0000' && $contractsCode == $arr['contractsCode'] && $arr['state'] === '1') {
return true;
} else {
throw new UserException($rs);
}
}
/**
* 确认收货
*
* @param $contractsCode
* @return bool
* @throws ErrorException
* @throws UserException
*/
public function confirm($data) {
// $lbfpay_conf = Config::get('onlinepay.lbfpay');
//
// $rs = openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
$rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
$certdata = openssl_x509_parse($cert['cert']);
$param = array(
'certId' => $certdata['serialNumber'],
'version' => self::VS,
'encoding' => self::ED,
'txnType' => '91', // 确认收货
'txnTime' => date('YmdHis'), // 发送时间
'merId' => $this->lbfpay_conf['lfqpay_merId'],
'merName' => $this->lbfpay_conf['lfqpay_merName'],
'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],
'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
'backUrl' => $this->back_url,
'contractsCode' => $contractsCode
);
$sign = $this->_sign($param);
$param['signature'] = $sign;
$rs = CurlHandler::post($lbfpay_conf['confirm_api'], $param);
$arr = json_decode($rs, true);
if($arr['respCode'] === '0000' && $contractsCode == $arr['contractsCode']) {
return true;
} else {
// throw new UserException($arr['respMsg']);
// throw new \Exception($arr['respMsg']);
return false;
}
}
/**
* 查询定单
*
* @param $data
* @return bool
*/
public function query($data) {
$rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
$certdata = openssl_x509_parse($cert['cert']);
$param = array(
'certId' => $certdata['serialNumber'],
'version' => self::VS,
'encoding' => self::ED,
'txnType' => '73', // 订单查询
'txnTime' => date('YmdHis'), // 发送时间
'orderId' => $data['out_trade_no'], // 订单号
'merId' => $this->lbfpay_conf['lfqpay_merId'],
'merName' => $this->lbfpay_conf['lfqpay_merName'],
'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],
'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
);
$sign = $this->_sign($param);
$param['signature'] = $sign;
// dump($param);
// dump($this->query_api);
$returndata=postCurl($this->query_api,$param);
// dump($returndata);
return $returndata;
}
/**
* 签名数据
*
* @param $data
* @return string
* @throws ErrorException
*/
function _sign($data)
{
// $lbfpay_conf = Config::get('onlinepay.lbfpay');
// $rs = openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
// dump($this->cert_addr);
$rs = openssl_pkcs12_read(file_get_contents($this->cert_addr), $cert, $this->lfqpay_cert_password);
// dump($rs);
if($rs) {
$a= new OpensslAuth ;
$sign = $a ->generate_signature($this->_sha1_from_param($data), $cert['pkey']);
} else {
// throw new ErrorException('证书获取失败');
throw new \Exception('证书获取失败');
}
return $sign;
}
/**
* 验签
*
* @param $data
* @return bool
*/
function _vertify_sign($data)
{
// $lbfpay_conf = Config::get('onlinepay.lbfpay');
// 过滤 signature
$sign = $data['signature'];
unset($data['signature']);
// openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
$rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
$a=new OpensslAuth;
$verify_rs = $a->vertify_signature($this->_sha1_from_param($data), $cert['cert'], $sign);
return $verify_rs;
}
/**
* 从参数中提取 sha1 摘要
*
* @param $data
* @return string
*/
private function _sha1_from_param($data) {
// 排序
ksort($data);
// 签名
$tmp_str = '';
foreach ($data as $k => $v) {
$tmp_str .= $k . '=' . $v . '&';
}
$tmp_str = trim($tmp_str, '&');
// sha1 摘要
$tmp_str = sha1($tmp_str);
return $tmp_str;
}
}
OpensslAuth.php
<?phpnamespace lfqpay;
class OpensslAuth
{
private $_private_key;
private $_public_key;
function set_private_key($key)
{
$this->_private_key = $key;
}
function get_private_key()
{
return $this->_private_key;
}
function set_public_key($key)
{
$this->_public_key = $key;
}
function get_public_key()
{
return $this->_public_key;
}
/**
* 生成签名
*
* @param $salt
* @param $private_key
* @return string
* @throws \Exception
*/
function generate_signature($salt, $private_key)
{
$res = openssl_pkey_get_private($private_key);
if (!openssl_sign($salt, $signature, $res)) {
throw new ErrorException('open ssl error');
}
return base64_encode($signature);
}
/**
* 验证签名是否正确
*
* @param $salt
* @param $public_key
* @param $signature
* @return bool
*/
function vertify_signature($salt, $public_key, $signature)
{
$signature = base64_decode($signature);
$res = openssl_pkey_get_public($public_key);
if (openssl_verify($salt, $signature, $res) === 1) {
return true;
} else {
return false;
}
}
}
1.PC控制器方法
$params = ['choose_installments_num' => $choose_installments_num,//分期数
'body' => $body,//订单名称 商品简单描述
'out_trade_no' => $out_trade_no,//订单号
'total_fee' => $price,//总价格 如果购买多个商品,就是多个商品的总价 ,
];
$returnDa = new \lfqpay\LebaifenPay;
$result=$returnDa->buildRequestForm($params);
2.移动方法(API接口方式)
参数组成一个网址形式返回给前端网页,收到网址就是打开一个外部连接网址
https://tt.lfqpay.com/lfq-pay/gateway/api/frontTransRequest.do?certId=&version=&txnType=&frontUrl=&backUrl=&encoding=&merId=&merName=&merAbbr=&orderId=&txnTime=&txnAmt=&txnTerms=txnTermsList&merNote=&userMac=&validTime=&signature=
$params = ['choose_installments_num' => $choose_installments_num,//分期数
'body' => $body,//订单名称 商品简单描述
'out_trade_no' => $out_trade_no,//订单号
'total_fee' => $price,//总价格 如果购买多个商品,就是多个商品的总价 ,
];
$returnDa = new \lfqpay\LebaifenPay;
$result=$returnDa->buildRequestFormApp($params);
if(empty($result)){
throw new \Exception(json_encode(array('code'=>7001,'msg'=>'缺少必要参数','out_trade_no'=>$out_trade_no)));
}
$returnArr['url']=$result['url'].$result['certId'].$result['version'].$result['txnType'].$result['frontUrl'].$result['backUrl'].$result['encoding'].$result['merId'].$result['merName'].$result['merAbbr'].$result['merPwd'].$result['orderId'].$result['txnTime'].$result['txnAmt'].$result['txnTerms'].$result['txnTermsList'].$result['merNote'].$result['userMac'].$result['validTime'].$result['signature'];
重点:签名那里要urlencode($sign),不然网址带+空变是空格的,会验证失败
3.回调
//同步调回接口 乐百分分期 支付public function lfqpay_notify_url(){
$postStr=input('get.');
if($postStr['respCode']=='0000'){//成功
$this->lfqpayNotify($postStr);
}else{
if($postStr['respCode']=='0140'){//单笔交易金额不在规定范围内
$msg=',金额在600-50000元之间';
}
$respMsg=$postStr['respMsg'].$msg;
$this->error($respMsg,'index/user/order');
}
}
//异步调回接口 乐百分分期 支付
public function lfqpay_notify(){
$data=input('post.');
$orderId=input('post.orderId');
$respMsg=input('post.respMsg');
$respCode=input('post.respCode');
//收到支付成功通知变更订单状态
if($orderId&&$respMsg=='成功'&&$respCode=='0000'){
//收到支付成功通知变更订单状态
$this->lfqpayNotify($data);
//处理完所有订单状态等信息后输出success
echo "success";
}
}
//乐百分分期支付成功后回调共同的操作
public function lfqpayNotify($data){
//判断合法性
$returnDa = new \lfqpay\LebaifenPay;
$sign_is=$returnDa->_vertify_sign($data);
if(!empty($sign_is)){
//成功
}
}
php原生demo我放个到个人百度网盘中,就不分享出来了,,有些证书不适合。。。。