CloudWallet.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\library\LianLianPay;
  4. use llianpay\accp\security\LLianPayAccpSignature;
  5. use think\Db;
  6. use llianpay\accp\client\LLianPayClient;
  7. date_default_timezone_set('Asia/Shanghai');
  8. header('Content-type:application/json;charset=utf-8');
  9. require_once env('root_path').'application/common/library/llp/src/cfg.php';
  10. require_once env('root_path').'application/common/library/llp/src/client/LLianPayClient.php';
  11. /**
  12. * @title 云钱包【提现、充值和支付还是用之前接接口】
  13. * @desc 用的是测试环境的用户钱包,测试环境忽略user_id不同接口结果不一致的场景
  14. * @controller CloudWallet
  15. * @package app\api\controller
  16. * @group worker
  17. */
  18. class CloudWallet extends Base
  19. {
  20. protected $env = 0; // 0 测试环境 1正式环境
  21. protected $prefix = 'xl_';
  22. protected $cloud_url = [
  23. //用户申请接入[云钱包申请开户]
  24. 'apply'=>[
  25. 'https://accpgw-ste.lianlianpay-inc.com/v1/acctmgr/openacct-apply',//测试环境
  26. 'https://accpgw.lianlianpay.com/v1/acctmgr/openacct-apply',//生产环境
  27. ],
  28. // 激活云钱包
  29. 'activate'=>[
  30. 'https://accpapi-ste.lianlianpay-inc.com/v1/acctmgr/openacct-activate-apply',//测试环境
  31. 'https://accpapi.lianlianpay.com/v1/acctmgr/openacct-activate-apply',//生产环境
  32. ],
  33. // 随机因子
  34. 'random'=>[
  35. 'https://accpapi-ste.lianlianpay-inc.com/v1/acctmgr/get-random',//测试环境
  36. 'https://accpapi.lianlianpay.com/v1/acctmgr/get-random',//生产环境
  37. ],
  38. // 获取云钱包用户信息
  39. 'userinfo'=>[
  40. 'https://accpapi-ste.lianlianpay-inc.com/v1/acctmgr/query-userinfo',//测试环境
  41. 'https://accpapi.lianlianpay.com/v1/acctmgr/query-userinfo',//生产环境
  42. ],
  43. // 获取云钱包账号信息
  44. 'acctinfo'=>[
  45. 'https://accpapi-ste.lianlianpay-inc.com/v1/acctmgr/query-acctinfo',//测试环境
  46. 'https://accpapi.lianlianpay.com/v1/acctmgr/query-acctinfo',//生产环境
  47. ],
  48. // 云钱包提现
  49. 'withdrawal'=>[
  50. 'https://accpapi-ste.lianlianpay-inc.com/v1/txn/withdrawal',//测试环境
  51. 'https://accpapi.lianlianpay.com/v1/txn/withdrawal',//生产环境
  52. ],
  53. //交易二次短信验证
  54. 'validation'=>[
  55. 'https://accpapi-ste.lianlianpay-inc.com/v1/txn/validation-sms',//测试环境
  56. 'https://accpapi.lianlianpay.com/v1/txn/validation-sms',//生产环境
  57. ],
  58. // 支付
  59. 'cashier'=>[
  60. 'https://accpgw-ste.lianlianpay-inc.com/v1/cashier/paycreate',//测试环境
  61. 'https://accpgw.lianlianpay.com/v1/cashier/paycreate',//生产环境
  62. ],
  63. ];
  64. public function initialize(){
  65. parent::initialize();
  66. //parent::check_login();
  67. }
  68. /**
  69. * @title 申请接入[开户]
  70. * @desc 申请接入[开户]
  71. * @author qc
  72. * @method POST
  73. * @tag 编辑信息
  74. * @url /api/Cloud_wallet/openAcctApply
  75. * @header name:Authorization require:1 desc:Token
  76. * @param name:user_id type:int require:0 default:0 desc:用户id
  77. * @return name:ret_code type:string default:0 desc:0000:成功,其他异常
  78. * @return name:ret_msg type:string default:0 desc:请求结果描述
  79. * @return name:user_status type:string default:0 desc:用户状态【NORMAL:正常,其他异常】
  80. * @return name:bank_open_flag type:int default:0 desc:银行开户标识【0未开户,1已开户,2开户中】
  81. * @return name:bank_account type:string default:0 desc:ACCP合作银行账户
  82. */
  83. public function openAcctApply()
  84. {
  85. $user_id = input('post.user_id');
  86. $user_info = Db::name('store_member')->find($user_id);
  87. //if(empty($user_info)) $user_info = Db::name('store_member')->find(6);
  88. if(empty($user_info)) $this->error('用户信息有误');
  89. if(!$user_info['true_name'] || !$user_info['id_card']) $this->error('请先实名认证');
  90. if(!$user_info['bank_num']) $this->error('请绑定银行卡');
  91. $current = date("YmdHis");
  92. $params = [
  93. 'timestamp' => $current,
  94. 'oid_partner' => OID_PARTNER,
  95. 'user_id' => $this->prefix.$user_id,
  96. 'txn_seqno' => get_order_sn(),
  97. 'txn_time' =>$current,
  98. 'flag_chnl' => "H5",
  99. 'notify_url' => 'https://'.$_SERVER['HTTP_HOST'] . '/api/Notify/openAcctApplyNotify',
  100. 'user_type' => 'INNERUSER',
  101. 'basicInfo'=>[
  102. 'reg_phone' => $user_info['phone'] ,
  103. 'user_name' => $user_info['true_name'] ,
  104. 'id_type' => 'ID_CARD',
  105. 'id_no' => $user_info['id_card'] ,
  106. 'occupation' =>18,
  107. ],
  108. 'accountInfo' => [
  109. //'account_type' => 'PERSONAL_PAYMENT_ACCOUNT'
  110. ],
  111. 'linkedAcctInfo'=>[
  112. //'linked_accttype'=> 'LEGALREPT_BANK_CARD',
  113. //'linked_acctno'=> $user_info['bank_num'] ,
  114. ],
  115. ];
  116. $url = $this->cloud_url['apply'][$this->env];
  117. $result = LLianPayClient::sendRequest($url, json_encode($params,JSON_UNESCAPED_UNICODE));
  118. $this->success('ok',json_decode($result,true));
  119. }
  120. /**
  121. * @title 激活申请
  122. * @desc 激活申请
  123. * @author qc
  124. * @method POST
  125. * @tag 编辑信息
  126. * @url /api/Cloud_wallet/activateApply
  127. * @header name:Authorization require:1 desc:Token
  128. * @param name:user_id type:int require:0 default:0 desc:用户id
  129. * @param name:password type:string require:0 default:0 desc:支付密码。6-12位的字母、数字,不可以是连续或者重复的数字和字母,正则:^[a-zA-Z0-9]{6,12}$。通过密码控件加密成密文传输
  130. * @return name:ret_code type:string default:0 desc:0000:成功,其他异常
  131. * @return name:ret_msg type:string default:0 desc:请求结果描述
  132. * @return name:user_status type:string default:0 desc:用户状态【NORMAL:正常,其他异常】
  133. * @return name:bank_open_flag type:int default:0 desc:银行开户标识【0未开户,1已开户,2开户中】
  134. * @return name:bank_account type:string default:0 desc:ACCP合作银行账户
  135. */
  136. public function activateApply()
  137. {
  138. $user_id = input('post.user_id');
  139. $password = input('post.password');
  140. $current = date("YmdHis");
  141. $rand_arr = self::getRandomKey($this->prefix.$user_id, $this->cloud_url['random'][$this->env],'H5');
  142. if($rand_arr['ret_code'] != '0000') $this->error($rand_arr['ret_msg']);
  143. $params = [
  144. 'timestamp' => $current,
  145. 'oid_partner' => OID_PARTNER,
  146. 'user_id' => $this->prefix.$user_id,
  147. 'txn_seqno' => get_order_sn(),
  148. 'txn_time' =>$current,
  149. 'notify_url' => 'https://'.$_SERVER['HTTP_HOST'] . '/api/Notify/openAcctApplyNotify',
  150. 'password' => $password,
  151. 'random_key' => $rand_arr['random_key'],
  152. 'accountInfo'=>[
  153. //'account_type' => 'PERSONAL_PAYMENT_ACCOUNT'
  154. ]
  155. ];
  156. $url = $this->cloud_url['activate'][$this->env];
  157. $result = LLianPayClient::sendRequest($url, json_encode($params,JSON_UNESCAPED_UNICODE));
  158. $this->success('ok',json_decode($result,true));
  159. }
  160. /**
  161. * @title 获取随机因子
  162. * @desc 获取随机因子
  163. * @author qc
  164. * @method GET
  165. * @tag 编辑信息
  166. * @url /api/Cloud_wallet/getRandomKeys
  167. * @header name:Authorization require:1 desc:Token
  168. * @param name:user_id type:int require:0 default:0 desc:用户id
  169. * @return name:ret_code type:string default:0 desc:0000:成功,其他异常
  170. * @return name:ret_msg type:string default:0 desc:请求结果描述
  171. * @return name:random_key type:string default:0 desc:随机因子key,有效期30分钟
  172. * @return name:random_value type:string default:0 desc:随机因子值,有效期30分钟
  173. */
  174. public function getRandomKeys()
  175. {
  176. $user_id = input('get.user_id');
  177. $res = self::getRandomKey($this->prefix.$user_id, $this->cloud_url['random'][$this->env],'H5');
  178. $this->success('ok',$res);
  179. }
  180. // 获取随机因子
  181. public static function getRandomKey($user_id,$url,$flag_chnl = 'H5')
  182. {
  183. $current = date("YmdHis");
  184. $params = [
  185. 'timestamp' => $current,
  186. 'oid_partner' => OID_PARTNER,
  187. 'user_id' => $user_id,
  188. 'flag_chnl' => $flag_chnl,
  189. ];
  190. $result = LLianPayClient::sendRequest($url, json_encode($params,JSON_UNESCAPED_UNICODE));
  191. return json_decode($result,JSON_UNESCAPED_UNICODE);
  192. }
  193. /**
  194. * @title 获取云钱包用户信息
  195. * @desc 获取云钱包用户信息
  196. * @author qc
  197. * @method GET
  198. * @tag 编辑信息
  199. * @url /api/Cloud_wallet/getUserInfo
  200. * @header name:Authorization require:1 desc:Token
  201. * @param name:user_id type:int require:0 default:0 desc:用户id
  202. * @return name:ret_code type:string default:0 desc:0000:成功,其他异常
  203. * @return name:ret_msg type:string default:0 desc:请求结果描述
  204. * @return name:user_status type:string default:0 desc:用户状态【NORMAL:正常,其他异常】
  205. * @return name:bank_open_flag type:int default:0 desc:银行开户标识【0未开户,1已开户,2开户中】
  206. * @return name:bank_account type:string default:0 desc:ACCP合作银行账户
  207. */
  208. public function getUserInfo()
  209. {
  210. $user_id = input('get.user_id');
  211. $current = date("YmdHis");
  212. $params = [
  213. 'timestamp' => $current,
  214. 'oid_partner' => OID_PARTNER,
  215. 'user_id' => $this->prefix.$user_id,
  216. ];
  217. $url = $url = $this->cloud_url['userinfo'][$this->env];
  218. $result = LLianPayClient::sendRequest($url, json_encode($params,JSON_UNESCAPED_UNICODE));
  219. $this->success('ok',json_decode($result,true));
  220. }
  221. /**
  222. * @title 获取云钱包账户信息
  223. * @desc 获取云钱包账户信息
  224. * @author qc
  225. * @method GET
  226. * @tag 编辑信息
  227. * @url /api/Cloud_wallet/getAcctInfo
  228. * @header name:Authorization require:1 desc:Token
  229. * @param name:user_id type:int require:0 default:0 desc:用户id
  230. * @return name:ret_code type:string default:0 desc:0000:成功,其他异常
  231. * @return name:ret_msg type:string default:0 desc:请求结果描述
  232. * @return name:ret_msg type:string default:0 desc:请求结果描述
  233. * @return name:acctinfo_list type:array default:0 desc:账户列表
  234. * @return name:acctinfo_list.oid_acctno type:string default:0 desc:账户号
  235. * @return name:acctinfo_list.acct_state type:string default:0 desc:账户状态【NORMAL:正常,其他异常】
  236. * @return name:acctinfo_list.amt_balcur type:float default:0 desc:资金余额[单位:元]
  237. * @return name:acctinfo_list.amt_balaval type:float default:0 desc:可用余额[单位:元]
  238. * @return name:acctinfo_list.amt_balfrz type:float default:0 desc:冻结金额[单位:元]
  239. * @return name:acctinfo_list.amt_lastbal type:float default:0 desc:昨日资金余额[单位:元]
  240. * @return name:acctinfo_list.amt_lastaval type:float default:0 desc:昨日可用余额[单位:元]
  241. * @return name:acctinfo_list.amt_lastfrz type:float default:0 desc:昨日冻结金额[单位:元]
  242. *
  243. */
  244. public function getAcctInfo()
  245. {
  246. $user_id = input('get.user_id');
  247. $current = date("YmdHis");
  248. $params = [
  249. 'timestamp' => $current,
  250. 'oid_partner' => OID_PARTNER,
  251. 'user_id' => $this->prefix.$user_id,
  252. 'user_type' => 'INNERUSER',
  253. ];
  254. $url = $url = $this->cloud_url['acctinfo'][$this->env];
  255. var_dump($params);
  256. $result = LLianPayClient::sendRequest($url, json_encode($params,JSON_UNESCAPED_UNICODE));
  257. $this->success('ok',json_decode($result,true));
  258. }
  259. /**
  260. * @title 交易二次短信验证
  261. * @desc 交易二次短信验证
  262. * @author qc
  263. * @method GET
  264. * @tag 编辑信息
  265. * @url /api/Cloud_wallet/validationSms
  266. * @header name:Authorization require:1 desc:Token
  267. * @param name:user_id type:int require:0 default:0 desc:用户id
  268. * @param name:txn_seqno type:int require:0 default:0 desc:订单号
  269. * @param name:total_amount type:int require:0 default:0 desc:订单金额【提现金额】
  270. * @param name:token type:int require:0 default:0 desc:token
  271. * @return name:ret_code type:string default:0 desc:0000:成功,其他异常
  272. * @return name:ret_msg type:string default:0 desc:请求结果描述
  273. */
  274. public function validationSms()
  275. {
  276. $user_id = input('get.user_id');
  277. $token = input('get.token');
  278. $txn_seqno = input('get.txn_seqno');
  279. $total_amount = input('get.total_amount');
  280. $current = date("YmdHis");
  281. $params = [
  282. 'timestamp' => $current,
  283. 'oid_partner' => OID_PARTNER,
  284. 'payer_type'=>"USER",
  285. 'payer_id' => $this->prefix.$user_id,
  286. 'txn_seqno'=>$txn_seqno,
  287. 'total_amount'=>$total_amount,
  288. 'token'=>$token,
  289. 'verify_code'=>rand(000000,999999)
  290. ];
  291. $url = $url = $this->cloud_url['validation'][$this->env];
  292. $result = LLianPayClient::sendRequest($url, json_encode($params,JSON_UNESCAPED_UNICODE));
  293. $this->success('ok',json_decode($result,true));
  294. }
  295. /**
  296. * @title 收银台支付测试【测试用不对接】
  297. * @desc 收银台支付测试
  298. * @author qc
  299. * @method GET
  300. * @tag 编辑信息
  301. * @url /api/Cloud_wallet/cashierPay
  302. */
  303. public function cashierPay()
  304. {
  305. $voucher_order = [];
  306. $voucher_order['order_no'] = get_order_sn();
  307. $money = 10;
  308. $from = input('post.from',1);
  309. $user = Db::name('store_member')->where('id',$this->uid)->find();
  310. $notify_url = 'https://'.$_SERVER['HTTP_HOST'] . '/api/Pay/lianLianNotify';
  311. $return_url ='https://'.$_SERVER['HTTP_HOST']."/h5/pages/mine/mine";//回调地址
  312. $risk_item= risk_item($user,'余额充值',$from == 1 ? 16 : 10);
  313. $res= LianLianPay::cashierPay($voucher_order['order_no'],$money,$this->uid,$notify_url,$return_url,'余额充值',[[
  314. 'payee_id'=>OID_PARTNER,
  315. 'payee_type' => 'MERCHANT',
  316. 'payee_amount' => $money,
  317. ]],$risk_item);
  318. $this->success('ok',$res);
  319. }
  320. /**
  321. * @title 云钱包提现【测试用不对接】
  322. * @desc 云钱包提现
  323. * @author qc
  324. * @method POST
  325. * @tag 编辑信息
  326. * @url /api/Cloud_wallet/withdrawal
  327. * @header name:Authorization require:1 desc:Token
  328. * @param name:user_id type:int require:0 default:0 desc:用户id
  329. * @param name:source type:int require:0 default:10 desc:app传10,h5传16
  330. * @return name:ret_code type:string default:0 desc:0000:成功,其他异常
  331. * @return name:ret_msg type:string default:0 desc:请求结果描述
  332. */
  333. public function withdrawal()
  334. {
  335. $user_id = input('post.user_id');
  336. $money = input('post.money');
  337. $password = input('post.password');
  338. $random_key = self::getRandomKey($this->prefix.$user_id, $this->cloud_url['random'][$this->env],'H5');
  339. $current = date("YmdHis");
  340. $user_info = Db::name('store_member')->where('id',$user_id)->find();
  341. $risk_item = risk_item($user_info,'余额提现',input('post,source',10));
  342. $notify_url = 'https://'.$_SERVER['HTTP_HOST'] . '/api/Pay/withdrawalNotify';
  343. $params = [
  344. 'timestamp' => $current,
  345. 'oid_partner' => OID_PARTNER,
  346. 'notify_url'=> $notify_url,
  347. 'risk_item'=>json_encode($risk_item),
  348. 'linked_acctno'=>$user_info['bank_num'],
  349. 'check_flag'=> 'N',
  350. 'pay_time_type'=> 'TRANS_NORMAL',
  351. 'orderInfo'=>[
  352. 'txn_seqno'=>get_order_sn(),
  353. 'txn_time' => $current,
  354. 'total_amount' => $money,
  355. ],
  356. 'payerInfo'=>[
  357. 'payer_type'=> 'USER',
  358. 'payer_id'=> $this->prefix.$user_id,
  359. 'payer_accttype'=> 'USEROWN',
  360. 'password'=> $password,
  361. 'random_key'=> $random_key['random_key'],
  362. ]
  363. ];
  364. $url = $url = $this->cloud_url['withdrawal'][$this->env];
  365. $result = LLianPayClient::sendRequest($url, json_encode($params,JSON_UNESCAPED_UNICODE));
  366. $this->success('ok',json_decode($result,true));
  367. }
  368. public function payNotifyTest()
  369. {
  370. $result = '{"oid_partner":"2020042200284052","payerInfo":[{"amount":"1.00","method":"BALANCE","payer_type":"USER","payer_id":"1"}],"txn_type":"GENERAL_CONSUME","payeeInfo":[{"amount":"1.00","payee_id":"2020042200284052","payee_type":"MERCHANT"}],"orderInfo":{"total_amount":"1.00","txn_seqno":"202210091020109197255438","txn_time":"20221009102010"},"txn_status":"TRADE_SUCCESS","accounting_date":"20221009","finish_time":"20221009102029","accp_txno":"2022100916760526"}';
  371. $header = '{"accept-encoding":"gzip,deflate","host":"xianglian-api.hdlkeji.com","content-length":"458","signature-type":"RSA","signature-data":"a5BMrkODcWl6FJ2vOEMG\/dnDbHfsBp34yY9ls9KmaWv5zYYO2EoK+DwL9PAFWTFzb0sKKYaOgrO8mFjl4CclTEd5UWvDFTAhv+EijImHTm4rGwbv1k2fpiw5MCSci1JTAE3ROsocgDWbLSsuFbTQ\/d97oR9KJbrjIInlVPEjO04=","correlationid":"2b9369df-ca95-49df-8f25-10fca9854c02","user-agent":"httpcomponents","connection":"Close","content-type":"text\/json;charset=UTF-8"}';
  372. $result = json_decode($result,true);
  373. $header = json_decode($header,true);
  374. // var_dump($result,$header);
  375. $check_sign = LLianPayAccpSignature::checkSign(json_encode($result,JSON_UNESCAPED_UNICODE),$header['signature-data']);
  376. var_dump($check_sign);
  377. $orderNo = $result['orderInfo']['txn_seqno'];
  378. var_dump(['out_trade_no' => $orderNo,'user_id'=> trim($result['payerInfo'][0]['payer_id'],$this->prefix)]);
  379. }
  380. }