关键词搜索

源码搜索 ×
×

tp5.1 乐百分支付(分期)

发布2019-12-31浏览1023次

详情内容

注意:乐百分是分测试与正式帐号

3,注意事项:
1.交易金额范围(600—50000)元。

2.交易测试账号:接口使用(商户名称、商户编号、接口密码)乐百分管理后台使用(商户登录账号、登录密码、退款密码、PC端登陆地址)。

3.测试环境只能使用测试卡信息表中的卡号、cvn、有效期等信息做测试交易,身份证号可以填写真实个人身份证,若填写真实的卡号等信息是无法做交易的。

4.测试时需要接收短信验证码,因此手机号要为真实有效的手机号码。若无法接收短信,切勿多次触发短信验证码,可检查是否手机网络问题,或同一手机号测试交易过多,换其他手机号测试。

5.为了测试方便测试环境的扣款间隔为两天一期,若需测试退款请在交易第二天(清算后)操作。

6.测试完成,要接到乐百分生产环境时需更换商户编号、商户名称、商户简称、接口密码、生产环境域名,证书不用更换。

 

 

两个文件放到 \extend\lfqpay  php文件

LebaifenPay.php

参数都在缓存取得

  1. <?php
  2. namespace lfqpay;
  3. /**
  4. * 乐百分 支付
  5. *
  6. * Created by .
  7. * User: going1000
  8. * Date: 9/19/16
  9. * Time: 4:34 PM
  10. */
  11. class LebaifenPay
  12. {
  13. // private $version = '1.0.0';
  14. // private $encoding = 'utf-8';
  15. const VS = '1.0.0';//$version
  16. const ED = 'utf-8';//$encoding
  17. public $lbfpay_conf;
  18. public $cert_addr;
  19. public $lfqpay_cert_password;
  20. public $create_api;
  21. public $cancel_api;
  22. public $query_api;
  23. public $front_url;
  24. public $back_url;
  25. public function __construct()
  26. {
  27. //初始化,取得微信支付参数
  28. $system_cofing=system_cofing();
  29. $this->lbfpay_conf = $system_cofing;
  30. $lfqpay_cert_addr=explode('/uploads/',$system_cofing['lfqpay_cert_addr']);//http://www.cg.com/uploads/file/20191230\e675796c651a74dd9272a8705dbb22e3.pfx
  31. $this->cert_addr='./uploads/'.$lfqpay_cert_addr[1];//证书绝对路径
  32. $this->lfqpay_cert_password=$system_cofing['lfqpay_cert_password'];
  33. $system_website=$this->lbfpay_conf['system_website'];
  34. $this->front_url=$system_website.'/pay/index/lfqpay_notify_url';//交易完成或失败通过此地址同步返回交易结果到商户页面 同步回调 http://www.1.com/lbf_pay/frontUrl.php
  35. $this->back_url=$system_website.'/pay/index/lfqpay_notify';//异步通知交易结果以及后期 异步回调 http://www.1.com/lbf_pay/backUrl.php
  36. if($system_cofing['lfqpay_test_is']){//1=正式环境(正式上线支付)
  37. $this->create_api='https://interface.lfqpay.com/lfq-pay/gateway/api/frontTransRequest.do';
  38. $this->cancel_api='https://interface.lfqpay.com/lfq-pay/gateway/api/backCancelRequest.do';
  39. $this->query_api='https://interface.lfqpay.com/lfq-pay/gateway/api/singleQueryRequest.do';
  40. }else{//0=测试环境
  41. $this->create_api='https://tt.lfqpay.com/lfq-pay/gateway/api/frontTransRequest.do';
  42. $this->cancel_api='https://tt.lfqpay.com/lfq-pay/gateway/api/backCancelRequest.do';
  43. $this->query_api='https://tt.lfqpay.com/lfq-pay/gateway/api/singleQueryRequest.do';
  44. }
  45. //分期数
  46. $this->choose_installments_num=$system_cofing['lfqpay_txnTerms'];
  47. // dump($data['choose_installments_num']);exit;
  48. }
  49. /**
  50. * 创建-pc
  51. *
  52. * @param $data
  53. * @return string
  54. * @throws ErrorException
  55. */
  56. public function buildRequestForm($data)
  57. {
  58. // 分期数
  59. if($data['choose_installments_num']){
  60. $choose_installments_num=$data['choose_installments_num'];
  61. }else{
  62. $choose_installments_num=$this->choose_installments_num;
  63. }
  64. $rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
  65. $certdata = openssl_x509_parse($cert['cert']);
  66. if(empty($certdata) || !$this->front_url || !$this->back_url || !$this->lbfpay_conf['lfqpay_merId'] || !$this->lbfpay_conf['lfqpay_merName'] || !$this->lbfpay_conf['lfqpay_merPwd']){
  67. $sHtml='缺少必要参数!';
  68. }else{//正确
  69. $param =array(
  70. 'certId' => $certdata['serialNumber'],
  71. 'version' => self::VS,
  72. 'txnType' => '01', // 创建
  73. 'frontUrl' => $this->front_url, // 同步回调
  74. 'backUrl' => $this->back_url, // 异步回调
  75. 'encoding' => self::ED,
  76. 'merId' => $this->lbfpay_conf['lfqpay_merId'],
  77. 'merName' => $this->lbfpay_conf['lfqpay_merName'],//商户名称
  78. 'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],//商户简称
  79. 'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
  80. 'orderId' => $data['out_trade_no'], // 订单号
  81. 'txnTime' => date('YmdHis'), // 发送时间
  82. 'txnAmt' => round($data['total_fee'] * 100), // 订单总额 (单位分)
  83. 'txnTerms' => $choose_installments_num?$choose_installments_num:6, // 分期数
  84. 'txnTermsList' => 15, // 前台交易时可通过此参数控制页面显示的分期数列表。不同分期之间用逗号分开,如“3,6”。
  85. 'merNote' => $data['body'], // 物品信息
  86. 'userMac' => ',',
  87. //'monthAmount' => round($data['price_per_installments_without_lbf_price'] * 100),
  88. //'discount' => round($data['ahs_subsidies'] * 100),
  89. 'validTime' => date('YmdHis')+ 60*60*24*3 // 超时时间 yyyyMMddHHmmss
  90. );
  91. // dump($param);die;
  92. $sign = $this->_sign($param);
  93. $param['signature'] = $sign;
  94. $sHtml = "<form name='xxform' action='{$this->create_api}' method='get'>";
  95. foreach ($param as $key => $val) {
  96. $sHtml .= " <input type='hidden' name='" . $key . "' value='" . $val . "'/> ";
  97. }
  98. $sHtml = $sHtml . "</form>";
  99. $sHtml = $sHtml . "<script>document.forms['xxform'].submit();</script>";
  100. }
  101. // dump($sHtml);exit;
  102. return $sHtml;
  103. }
  104. /**
  105. * 创建-移动app
  106. *
  107. * @param $data
  108. * @return string
  109. * @throws ErrorException
  110. */
  111. public function buildRequestFormApp($data)
  112. {
  113. // 分期数
  114. if($data['choose_installments_num']){
  115. $choose_installments_num=$data['choose_installments_num'];
  116. }else{
  117. $choose_installments_num=$this->choose_installments_num;
  118. }
  119. $choose_installments_num=$choose_installments_num?$choose_installments_num:6;
  120. $rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
  121. $certdata = openssl_x509_parse($cert['cert']);
  122. if(empty($certdata) || !$this->front_url || !$this->back_url || !$this->lbfpay_conf['lfqpay_merId'] || !$this->lbfpay_conf['lfqpay_merName'] || !$this->lbfpay_conf['lfqpay_merPwd']){
  123. $param=[];
  124. }else{//正确
  125. $txnTime=date('YmdHis');
  126. $validTime=$txnTime + 60*60*24*3;
  127. //用于签名
  128. $param_sign =array(
  129. 'certId' => $certdata['serialNumber'],
  130. 'version' => self::VS,
  131. 'txnType' => '01', // 创建
  132. 'frontUrl' => $this->front_url, // 同步回调
  133. 'backUrl' => $this->back_url, // 异步回调
  134. 'encoding' => self::ED,
  135. 'merId' => $this->lbfpay_conf['lfqpay_merId'],
  136. 'merName' => $this->lbfpay_conf['lfqpay_merName'],//商户名称
  137. 'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],//商户简称
  138. 'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
  139. 'orderId' => $data['out_trade_no'], // 订单号
  140. 'txnTime' => $txnTime, // 发送时间
  141. 'txnAmt' => round($data['total_fee'] * 100), // 订单总额 (单位分)
  142. 'txnTerms' => $choose_installments_num, // 分期数
  143. 'txnTermsList' => 15, // 前台交易时可通过此参数控制页面显示的分期数列表。不同分期之间用逗号分开,如“3,6”。
  144. 'merNote' => $data['body'], // 物品信息
  145. 'userMac' => ',',
  146. //'monthAmount' => round($data['price_per_installments_without_lbf_price'] * 100),
  147. //'discount' => round($data['ahs_subsidies'] * 100),
  148. 'validTime' => $validTime // 超时时间 yyyyMMddHHmmss
  149. );
  150. // dump($param_sign);
  151. $param =array(
  152. 'certId' => 'certId='.$certdata['serialNumber'],
  153. 'version' => '&version='.self::VS,
  154. 'txnType' => '&txnType='.'01', // 创建
  155. 'frontUrl' => '&frontUrl='.$this->front_url, // 同步回调
  156. 'backUrl' => '&backUrl='.$this->back_url, // 异步回调
  157. 'encoding' => '&encoding='.self::ED,
  158. 'merId' => '&merId='.$this->lbfpay_conf['lfqpay_merId'],
  159. 'merName' => '&merName='.$this->lbfpay_conf['lfqpay_merName'],//商户名称
  160. 'merAbbr' => '&merAbbr='.$this->lbfpay_conf['lfqpay_merName'],//商户简称
  161. 'merPwd' => '&merPwd='.$this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
  162. 'orderId' => '&orderId='.$data['out_trade_no'], // 订单号
  163. 'txnTime' => '&txnTime='.$txnTime, // 发送时间
  164. 'txnAmt' => '&txnAmt='.round($data['total_fee'] * 100), // 订单总额 (单位分)
  165. 'txnTerms' => '&txnTerms='.$choose_installments_num, // 分期数
  166. 'txnTermsList' => '&txnTermsList=15', // 前台交易时可通过此参数控制页面显示的分期数列表。不同分期之间用逗号分开,如“3,6”。
  167. 'merNote' => '&merNote='.$data['body'], // 物品信息
  168. 'userMac' => '&userMac=,',
  169. //'monthAmount' => round($data['price_per_installments_without_lbf_price'] * 100),
  170. //'discount' => round($data['ahs_subsidies'] * 100),
  171. 'validTime' => '&validTime='.$validTime // 超时时间 yyyyMMddHHmmss
  172. );
  173. // dump($param);exit;
  174. $sign = $this->_sign($param_sign);
  175. $param['signature'] = '&signature='.urlencode($sign);
  176. $param['url'] = $this->create_api.'?';
  177. }
  178. return $param;
  179. }
  180. /**
  181. * 取消订单
  182. *
  183. * @param $contractsCode
  184. * @return bool
  185. * @throws ErrorException
  186. * @throws UserException
  187. */
  188. public function cancel($contractsCode) {
  189. // $lbfpay_conf = Config::get('onlinepay.lbfpay');
  190. // $rs = openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
  191. $rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
  192. $certdata = openssl_x509_parse($cert['cert']);
  193. $param=array(
  194. 'certId' => $certdata['serialNumber'],
  195. 'version' => self::VS,
  196. 'encoding' => self::ED,
  197. 'txnType' => '04', // 退款
  198. 'txnTime' => date('YmdHis'), // 发送时间
  199. 'merId' => $this->lbfpay_conf['lfqpay_merId'],
  200. 'merName' => $this->lbfpay_conf['lfqpay_merName'],
  201. 'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],
  202. 'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
  203. 'backUrl' => $this->back_url,
  204. 'contractsCode' => $contractsCode
  205. );
  206. $sign = $this->_sign($param);
  207. $param['signature'] = $sign;
  208. $rs = CurlHandler::post($this->cancel_api, $param);
  209. $arr = json_decode($rs, true);
  210. if($arr['respCode'] === '0000' && $contractsCode == $arr['contractsCode'] && $arr['state'] === '1') {
  211. return true;
  212. } else {
  213. throw new UserException($rs);
  214. }
  215. }
  216. /**
  217. * 确认收货
  218. *
  219. * @param $contractsCode
  220. * @return bool
  221. * @throws ErrorException
  222. * @throws UserException
  223. */
  224. public function confirm($data) {
  225. // $lbfpay_conf = Config::get('onlinepay.lbfpay');
  226. //
  227. // $rs = openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
  228. $rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
  229. $certdata = openssl_x509_parse($cert['cert']);
  230. $param = array(
  231. 'certId' => $certdata['serialNumber'],
  232. 'version' => self::VS,
  233. 'encoding' => self::ED,
  234. 'txnType' => '91', // 确认收货
  235. 'txnTime' => date('YmdHis'), // 发送时间
  236. 'merId' => $this->lbfpay_conf['lfqpay_merId'],
  237. 'merName' => $this->lbfpay_conf['lfqpay_merName'],
  238. 'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],
  239. 'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
  240. 'backUrl' => $this->back_url,
  241. 'contractsCode' => $contractsCode
  242. );
  243. $sign = $this->_sign($param);
  244. $param['signature'] = $sign;
  245. $rs = CurlHandler::post($lbfpay_conf['confirm_api'], $param);
  246. $arr = json_decode($rs, true);
  247. if($arr['respCode'] === '0000' && $contractsCode == $arr['contractsCode']) {
  248. return true;
  249. } else {
  250. // throw new UserException($arr['respMsg']);
  251. // throw new \Exception($arr['respMsg']);
  252. return false;
  253. }
  254. }
  255. /**
  256. * 查询定单
  257. *
  258. * @param $data
  259. * @return bool
  260. */
  261. public function query($data) {
  262. $rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
  263. $certdata = openssl_x509_parse($cert['cert']);
  264. $param = array(
  265. 'certId' => $certdata['serialNumber'],
  266. 'version' => self::VS,
  267. 'encoding' => self::ED,
  268. 'txnType' => '73', // 订单查询
  269. 'txnTime' => date('YmdHis'), // 发送时间
  270. 'orderId' => $data['out_trade_no'], // 订单号
  271. 'merId' => $this->lbfpay_conf['lfqpay_merId'],
  272. 'merName' => $this->lbfpay_conf['lfqpay_merName'],
  273. 'merAbbr' => $this->lbfpay_conf['lfqpay_merName'],
  274. 'merPwd' => $this->lbfpay_conf['lfqpay_merPwd'], // 商户密码,必送
  275. );
  276. $sign = $this->_sign($param);
  277. $param['signature'] = $sign;
  278. // dump($param);
  279. // dump($this->query_api);
  280. $returndata=postCurl($this->query_api,$param);
  281. // dump($returndata);
  282. return $returndata;
  283. }
  284. /**
  285. * 签名数据
  286. *
  287. * @param $data
  288. * @return string
  289. * @throws ErrorException
  290. */
  291. function _sign($data)
  292. {
  293. // $lbfpay_conf = Config::get('onlinepay.lbfpay');
  294. // $rs = openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
  295. // dump($this->cert_addr);
  296. $rs = openssl_pkcs12_read(file_get_contents($this->cert_addr), $cert, $this->lfqpay_cert_password);
  297. // dump($rs);
  298. if($rs) {
  299. $a= new OpensslAuth ;
  300. $sign = $a ->generate_signature($this->_sha1_from_param($data), $cert['pkey']);
  301. } else {
  302. // throw new ErrorException('证书获取失败');
  303. throw new \Exception('证书获取失败');
  304. }
  305. return $sign;
  306. }
  307. /**
  308. * 验签
  309. *
  310. * @param $data
  311. * @return bool
  312. */
  313. function _vertify_sign($data)
  314. {
  315. // $lbfpay_conf = Config::get('onlinepay.lbfpay');
  316. // 过滤 signature
  317. $sign = $data['signature'];
  318. unset($data['signature']);
  319. // openssl_pkcs12_read(file_get_contents(__DIR__ . $lbfpay_conf['cert_addr']), $cert, $lbfpay_conf['cert_password']);
  320. $rs = openssl_pkcs12_read(file_get_contents( $this->cert_addr), $cert, $this->lfqpay_cert_password);
  321. $a=new OpensslAuth;
  322. $verify_rs = $a->vertify_signature($this->_sha1_from_param($data), $cert['cert'], $sign);
  323. return $verify_rs;
  324. }
  325. /**
  326. * 从参数中提取 sha1 摘要
  327. *
  328. * @param $data
  329. * @return string
  330. */
  331. private function _sha1_from_param($data) {
  332. // 排序
  333. ksort($data);
  334. // 签名
  335. $tmp_str = '';
  336. foreach ($data as $k => $v) {
  337. $tmp_str .= $k . '=' . $v . '&';
  338. }
  339. $tmp_str = trim($tmp_str, '&');
  340. // sha1 摘要
  341. $tmp_str = sha1($tmp_str);
  342. return $tmp_str;
  343. }
  344. }

OpensslAuth.php

  1. <?php
  2. namespace lfqpay;
  3. class OpensslAuth
  4. {
  5. private $_private_key;
  6. private $_public_key;
  7. function set_private_key($key)
  8. {
  9. $this->_private_key = $key;
  10. }
  11. function get_private_key()
  12. {
  13. return $this->_private_key;
  14. }
  15. function set_public_key($key)
  16. {
  17. $this->_public_key = $key;
  18. }
  19. function get_public_key()
  20. {
  21. return $this->_public_key;
  22. }
  23. /**
  24. * 生成签名
  25. *
  26. * @param $salt
  27. * @param $private_key
  28. * @return string
  29. * @throws \Exception
  30. */
  31. function generate_signature($salt, $private_key)
  32. {
  33. $res = openssl_pkey_get_private($private_key);
  34. if (!openssl_sign($salt, $signature, $res)) {
  35. throw new ErrorException('open ssl error');
  36. }
  37. return base64_encode($signature);
  38. }
  39. /**
  40. * 验证签名是否正确
  41. *
  42. * @param $salt
  43. * @param $public_key
  44. * @param $signature
  45. * @return bool
  46. */
  47. function vertify_signature($salt, $public_key, $signature)
  48. {
  49. $signature = base64_decode($signature);
  50. $res = openssl_pkey_get_public($public_key);
  51. if (openssl_verify($salt, $signature, $res) === 1) {
  52. return true;
  53. } else {
  54. return false;
  55. }
  56. }
  57. }

1.PC控制器方法

  1. $params = [
  2. 'choose_installments_num' => $choose_installments_num,//分期数
  3. 'body' => $body,//订单名称 商品简单描述
  4. 'out_trade_no' => $out_trade_no,//订单号
  5. 'total_fee' => $price,//总价格 如果购买多个商品,就是多个商品的总价 ,
  6. ];
  7. $returnDa = new \lfqpay\LebaifenPay;
  8. $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=

  1. $params = [
  2. 'choose_installments_num' => $choose_installments_num,//分期数
  3. 'body' => $body,//订单名称 商品简单描述
  4. 'out_trade_no' => $out_trade_no,//订单号
  5. 'total_fee' => $price,//总价格 如果购买多个商品,就是多个商品的总价 ,
  6. ];
  7. $returnDa = new \lfqpay\LebaifenPay;
  8. $result=$returnDa->buildRequestFormApp($params);
  9. if(empty($result)){
  10. throw new \Exception(json_encode(array('code'=>7001,'msg'=>'缺少必要参数','out_trade_no'=>$out_trade_no)));
  11. }
  12. $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.回调

  1. //同步调回接口 乐百分分期 支付
  2. public function lfqpay_notify_url(){
  3. $postStr=input('get.');
  4. if($postStr['respCode']=='0000'){//成功
  5. $this->lfqpayNotify($postStr);
  6. }else{
  7. if($postStr['respCode']=='0140'){//单笔交易金额不在规定范围内
  8. $msg=',金额在600-50000元之间';
  9. }
  10. $respMsg=$postStr['respMsg'].$msg;
  11. $this->error($respMsg,'index/user/order');
  12. }
  13. }
  14. //异步调回接口 乐百分分期 支付
  15. public function lfqpay_notify(){
  16. $data=input('post.');
  17. $orderId=input('post.orderId');
  18. $respMsg=input('post.respMsg');
  19. $respCode=input('post.respCode');
  20. //收到支付成功通知变更订单状态
  21. if($orderId&&$respMsg=='成功'&&$respCode=='0000'){
  22. //收到支付成功通知变更订单状态
  23. $this->lfqpayNotify($data);
  24. //处理完所有订单状态等信息后输出success
  25. echo "success";
  26. }
  27. }
  28. //乐百分分期支付成功后回调共同的操作
  29. public function lfqpayNotify($data){
  30. //判断合法性
  31. $returnDa = new \lfqpay\LebaifenPay;
  32. $sign_is=$returnDa->_vertify_sign($data);
  33. if(!empty($sign_is)){
  34. //成功
  35. }
  36. }

php原生demo我放个到个人百度网盘中,就不分享出来了,,有些证书不适合。。。。

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载