123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- <?php
- namespace app\expand\controller;
- use app\common\service\HelperService;
- use app\common\service\OpensslService;
- use think\Validate;
- use think\Cache;
- /**
- * 京东支付接口
- * Class Alipay
- * @package app\expand\controller
- */
- class JdPay extends BaseAuth
- {
- private $_Account = null;
- private $_merchant = null;
- private $_notifyUrl = null;//异步通知地址
- private $_notifyUrlArr = [];//通知给调用方的地址
- private $_notifyApiCode = null;
- public function __construct(){
-
- parent::__construct();
-
- if($this->_inWhiteList){
- return true;
- }
-
- $this->_notifyUrl = "http://{$_SERVER['HTTP_HOST']}/v1/notifyJdPay";
- $this->_Account = $this->getKey($this->_apiCode);
- //验证是否具有访问这个接口的权限
- if(!isset($this->_Account['jdMerchant'])
- || !isset($this->_Account['jdDesKey'])
- || !isset($this->_Account['jdNotifyUrlArr']) ){
-
- HelperService::returnJson(['code'=>400,'msg'=>'jdPay interface unauthorized access','data'=>[]]);
- }
- $this->_merchant = $this->_Account['jdMerchant'];
- }
- /**
- * 平台版京东支付
- */
- public function platformJdPay(){
- $params = $this->_sysParams;
- $rule = [
- //'showPayStoreName|收银台展示收款商户'=>'require',
- 'orderNo|订单号'=>'require',
- 'tradeName|订单商品名'=>'require',
- 'amount|支付金额(分)'=>'require|number',
- 'orderType|支付类型(0、实物;1、虚拟)订单'=>'require|number|between:0,1',
- 'callbackUrl|同步回调地址'=>'require',
- 'userId|用户id(保证唯一即可/免登)'=>'require'
- ];
-
- $validate = new Validate($rule);
- if(!$validate->check($params)){
- HelperService::returnJson(['code'=>400,'msg'=>$validate->getError()]);
- }
-
- $requestArr = [
- //'payMerchant'=>"{$params['showPayStoreName']}",//收银台展示的收款商户,默认为商户号对应的商户,
- 'tradeNum'=>"{$params['orderNo']}",//交易流水号
- 'tradeName'=>"{$params['tradeName']}",//商户订单的标题/商品名称/关键字等
- 'tradeTime'=>date('YmdHis'),//订单生成时间。格式:“yyyyMMddHHmmss”
- 'amount'=>"{$params['amount']}",//金额(分),大于0
- 'orderType'=>"{$params['orderType']}",//订单类型,0实物;1虚拟
- 'currency'=>'CNY',//货币种类
- 'callbackUrl'=>"{$params['callbackUrl']}",//同步通知url
- 'notifyUrl'=>$this->_notifyUrl,//异步通知url
- 'userId'=>"{$params['userId']}"
- ];
-
- $signArr=[
- 'version'=>'V2.0',
- 'merchant'=>$this->_merchant//商户号
- ];
-
- $createSignArr = array_merge($signArr,$requestArr);
-
- $sign = $this->getSign($createSignArr);
-
- $signArr['sign'] = $sign;
-
- $encryRequestArr = $this->encryptQuery($requestArr);
- $url = 'https://h5pay.jd.com/jdpay/saveOrder';//统一下单支付
-
- $html = $this->_createHtml($url, array_merge($encryRequestArr,$signArr));
-
- HelperService::addLog($createSignArr, $url, 'JDPAY');
- $this->assign('html',$html);
- return $this->fetch('jdpay/pay');
- }
-
- private function _createHtml($url,$postParams){
- $html = "<form action='$url' id='postFrom' method='post'>";
- foreach($postParams as $key=>$val){
- $html .="<input name='{$key}' type='hidden' value='{$val}' />";
- }
- $html .= "</form>";
- return $html;
- }
- public function notifyJdPay(){
-
- $oldParams = $this->_oldParams;
- $url = HelperService::getHttpHeader().$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
- try{
-
- $resData = $this->decryptResXml($oldParams);
-
- if($resData['result']['code']=='000000'){
-
- $tradeNum = isset($resData['tradeNum'])?$resData['tradeNum']:"";
- //一年之内,同一笔订单不能复现,否则屏蔽
- if(Cache::has("JD{$tradeNum}")){
- HelperService::addLog(['resData'=>$resData,'return'=>'success'], $url, 'JDPAY');
- die('success');
- }
-
- foreach($this->_notifyUrlArr as $notifyUrl){
- $isSsl = strpos($notifyUrl, 'https://')!==false?true:false;
-
- $postData = json_encode($resData);
- $times = 3;
- while ($times--){
- $res = HelperService::httpPost($notifyUrl,$postData, $isSsl);
- HelperService::addLog(['request'=>$postData,'res'=>$res,'times'=>$times], $notifyUrl, "JDPAY_DETAIL");
- if($res !== false){
- break;
- }
- }
- }
-
- Cache::set("JD{$tradeNum}",time(),365*86400);
-
- HelperService::addLog(['resData'=>$resData,'return'=>'success'], $url, 'JDPAY');
- die('success');
- }
-
- HelperService::addLog(['resData'=>$resData,'return'=>'fail'], $url, 'JDPAY');
- die('fail');
-
- } catch (\Exception $ex){
-
- HelperService::addLog(['resData'=>$oldParams,'return'=>$ex->getMessage()], $url, 'JDPAY');
- die('fail');
- }
- }
- private function getSign($param){
-
- ksort($param);
- $queryStr = $this->httpBuildQuery($param);
-
- $sha256SourceSignString = hash("sha256", $queryStr);
- $sign = OpensslService::encryptByPrivateKey($this->_apiCode, $sha256SourceSignString);
- return $sign;
- }
-
- private function httpBuildQuery($arr=[]){
- $queryStr = '';
- foreach($arr as $key=>$val){
- if($val===""){
- continue;
- }
- if(!empty($queryStr)){
- $queryStr.='&';
- }
- $queryStr .= "$key=$val";
- }
-
- return $queryStr;
- }
-
- private function encryptQuery($param){
-
- $desKey = $this->_Account['jdDesKey'];
- $keys = base64_decode($desKey);
-
- foreach($param as &$val){
- $val = OpensslService::encrypt2HexStr($keys, $val);
- }
-
- return $param;
- }
-
- private function decryptResXml($resultData){
-
- $resultXml = simplexml_load_string($resultData);
-
- $resultObj = json_decode(json_encode($resultXml),TRUE);
- if(!isset($resultObj["encrypt"])){
- die($resultXml);
- }
- $encryptXml = $resultObj["encrypt"];
- $encryptStr=base64_decode($encryptXml);
-
- $desKey = $this->_getJdDesKeyByMerchant($resultObj['merchant']);
-
- $keys = base64_decode($desKey);
- $reqBody = OpensslService::decrypt4HexStr($keys, $encryptStr);
- //echo "请求返回encrypt Des解密后:".$reqBody."\n";
- $bodyXml = simplexml_load_string($reqBody);
- //echo "请求返回encrypt Des解密后:".$bodyXml->saveXML()."\n";
- $resData = json_decode(json_encode($bodyXml),TRUE);
-
- return $resData;
- }
-
- /**
- * 遍历目录下该jd商户号是否等于回传的商户号
- * @param type $merchant
- * @return type
- */
- private function _getJdDesKeyByMerchant($merchant){
-
- $fileList = scandir("COMPANY_LIST");
- foreach($fileList as $fileName){
- $authFileName = "COMPANY_LIST/$fileName/auth.php";
-
- if(strpos($fileName,'.')===false && file_exists($authFileName)){
- $fileContent = require_once($authFileName);
- if(isset($fileContent['jdMerchant']) &&$fileContent['jdMerchant'] == $merchant){
- //将异步通知接口回传
- $this->_notifyUrlArr = $fileContent['jdNotifyUrlArr'];
- $this->_notifyApiCode = $fileName;
- return $fileContent['jdDesKey'];
- }
- }
- }
-
- HelperService::returnJson(['code'=>200,'msg'=>'desKey is error','data'=>[]]);
- }
- }
|