WeiXinPayNotify.Class.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <?php
  2. /**
  3. * 微信支付通知类
  4. * Created by PhpStorm.
  5. * User: phperstar
  6. * Date: 2019/11/28
  7. * Time: 5:00 PM
  8. */
  9. namespace JinDouYun\Controller\Common;
  10. use JinDouYun\Dao\Finance\DAccountType;
  11. use JinDouYun\Dao\Finance\DExpenseSingle;
  12. use JinDouYun\Dao\Market\DVipCardOrder;
  13. use JinDouYun\Model\Finance\MAccount;
  14. use JinDouYun\Model\Finance\MExpenseSingle;
  15. use JinDouYun\Model\Shop\MShopCardOrder;
  16. use JinDouYun\Model\Shop\MShopSubscribe;
  17. use Mall\Framework\Core\ErrorCode;
  18. use Mall\Framework\Core\ResultWrapper;
  19. use Mall\Framework\Factory;
  20. use Mall\Framework\Core\StatusCode;
  21. use JinDouYun\Controller\BaseController;
  22. use JinDouYun\Model\Order\MOrder;
  23. use JinDouYun\Model\Market\MVipCard;
  24. use JinDouYun\Model\System\MPaymentSetting;
  25. class WeiXinPayNotify extends BaseController
  26. {
  27. /**
  28. * 商户支付密钥
  29. */
  30. private $partnerKey = '45c87Fa0352211e78D40d4977a9Ea871';
  31. public function __construct($isCheckAcl = false, $isMustLogin = false, $checkToken = false)
  32. {
  33. parent::__construct($isCheckAcl, $isMustLogin, $checkToken);
  34. }
  35. /**
  36. * 微信回调处理方法
  37. */
  38. public function notify()
  39. {
  40. $postStr = file_get_contents('php://input');// 将整个文件读入字符串
  41. file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinpay.log',date('Y-m-d H:i:s').'回调数据'.var_export($postStr,true).PHP_EOL,FILE_APPEND);
  42. /*
  43. $postStr = '<xml><appid><![CDATA[wxb2198cca99031de1]]></appid>
  44. <attach><![CDATA[64|80|27]]></attach>
  45. <bank_type><![CDATA[OTHERS]]></bank_type>
  46. <cash_fee><![CDATA[1]]></cash_fee>
  47. <fee_type><![CDATA[CNY]]></fee_type>
  48. <is_subscribe><![CDATA[N]]></is_subscribe>
  49. <mch_id><![CDATA[1565202181]]></mch_id>
  50. <nonce_str><![CDATA[9dbae1af7e660f5a5dde2174060f47d9]]></nonce_str>
  51. <openid><![CDATA[oEDnY5VI3HIbLQCxLOc88qFun3JQ]]></openid>
  52. <out_trade_no><![CDATA[vip_tmp322202106228039826320]]></out_trade_no>
  53. <result_code><![CDATA[SUCCESS]]></result_code>
  54. <return_code><![CDATA[SUCCESS]]></return_code>
  55. <sign><![CDATA[4E3D79E8E38A2B35E47BF836589A53FD]]></sign>
  56. <time_end><![CDATA[20210622184532]]></time_end>
  57. <total_fee>1</total_fee>
  58. <trade_type><![CDATA[JSAPI]]></trade_type>
  59. <transaction_id><![CDATA[4200001172202106224897300202]]></transaction_id>
  60. </xml>';
  61. */
  62. if (!empty($postStr)) {
  63. libxml_disable_entity_loader(true);// 禁用加载外部实体的功能
  64. // 先做签名校验
  65. $data = json_decode(json_encode(simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
  66. ksort($data);//根据下标进行排序
  67. $buff = '';
  68. foreach ($data as $k => $v){
  69. if($k != 'sign'){
  70. $buff .= $k . '=' . $v . '&';
  71. }
  72. }
  73. if(empty($data['attach'])){
  74. $this->weixinErrorEcho('附加数据为空');
  75. }
  76. $attach = explode('|', $data['attach']);
  77. $enterpriseId = $attach[0];
  78. unset($attach[0]);
  79. $userCentId = $attach[1];
  80. unset($attach[1]);
  81. //获取支付配置
  82. $objMPaymentSetting = new MPaymentSetting($userCentId, $enterpriseId);
  83. $result = $objMPaymentSetting->getPayData(StatusCode::$payType['wxPay']);
  84. if (!$result->isSuccess() || empty($result->getData())) {
  85. $this->weixinErrorEcho('获取微信配置错误');
  86. }
  87. $payment = $result->getData();
  88. /*
  89. $weixinPayConfigData = Factory::config()->getAppoint('weixin', 'pay');
  90. if(empty($weixinPayConfigData)){
  91. $this->weixinErrorEcho('微信配置错误');
  92. }
  93. $stringSignTemp = $buff . 'key='.$weixinPayConfigData['apiPartnerKey'];*/
  94. $stringSignTemp = $buff . 'key='.$payment['apiPartnerKey'];
  95. $sign = strtoupper(md5($stringSignTemp)); //加密后将所有字母转换成大写
  96. if($sign !== $data['sign']){
  97. $this->weixinErrorEcho('签名错误');
  98. }
  99. // 函数转换形式良好的 XML 字符串为 SimpleXMLElement 对象。
  100. $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
  101. //通信标识
  102. if ($postObj->return_code == 'SUCCESS') {
  103. //业务结果
  104. if ($postObj->result_code == 'SUCCESS') {
  105. $response_content = (array)$postObj;
  106. $data = array(
  107. 'attach' => $response_content['attach'], // 附加数据
  108. 'transaction_id' => $response_content['transaction_id'], // 微信支付订单号
  109. 'out_trade_no' => $response_content['out_trade_no'], // 商户订单号
  110. 'time_end' => $response_content['time_end'], // 支付完成时间
  111. 'total_fel' => $response_content['total_fee'] / 100, //支付金额(转化为元)
  112. );
  113. if(empty($data['attach'])){
  114. $this->weixinErrorEcho('附加数据为空');
  115. }
  116. $attach = explode('|', $data['attach']);
  117. $enterpriseId = $attach[0];
  118. unset($attach[0]);
  119. $userCentId = $attach[1];
  120. unset($attach[1]);
  121. $allOrdersId = array_values($attach);
  122. //处理销售订单
  123. if (strpos( $data['out_trade_no'],'tmp') === false || substr($data['out_trade_no'],0,3) == 'tmp') {
  124. $updateOrderData = [
  125. 'outerTradeNo' => $data['transaction_id'],
  126. 'payType' => StatusCode::$payType['wxPay'],
  127. 'payStatus' => StatusCode::$standard,
  128. 'orderStatus' => StatusCode::$orderStatus['waitDelivery'],
  129. 'payTime' => strtotime($data['time_end']),
  130. 'total_fel'=> $data['total_fel'],
  131. 'pay_way'=>StatusCode::$payType['wxPay']
  132. ];
  133. $objMOrder = new MOrder($userCentId, $enterpriseId);
  134. if(strpos( $data['out_trade_no'],'tmp') === false){
  135. $result = $objMOrder->updateOrderPayData($updateOrderData, ['id'=>$allOrdersId,'no'=>$data['out_trade_no']],true);// 修改订单的支付状态
  136. }else{
  137. $result = $objMOrder->updateOrderPayData($updateOrderData, ['id'=>$allOrdersId,'outerTradeNo'=>$data['out_trade_no']],true);// 修改订单的支付状态
  138. }
  139. if($result->isSuccess()){
  140. $result = array(
  141. 'return_code' => 'SUCCESS',
  142. 'return_msg' => 'OK',
  143. );
  144. echo arrayToWeiXinXml($result);// 数组转xml
  145. exit();
  146. }else{
  147. $this->weixinErrorEcho($result->getData());
  148. }
  149. }
  150. //处理会员卡订单
  151. if (strpos( $data['out_trade_no'],'tmp') !== false && substr($data['out_trade_no'],0,3) == 'vip') {
  152. $vipOrderData = [
  153. 'outerTradeNo' => $data['transaction_id'],
  154. 'payType' => StatusCode::$payType['wxPay'],
  155. 'payStatus' => StatusCode::$standard,
  156. 'payTime' => strtotime($data['time_end']),
  157. ];
  158. $objMVipCard = new MVipCard($enterpriseId, $userCentId);
  159. // 修改订单支付状态,支付成功后赠送对应优惠券
  160. $result = $objMVipCard->updateVipOrderPayData($vipOrderData, ['id'=>$allOrdersId,'outerTradeNo'=>$data['out_trade_no']],true);
  161. // 会员卡订单表
  162. $objDVipCard = new DVipCardOrder();
  163. $objDVipCard->setTable('qianniao_vip_card_order_'.$enterpriseId);
  164. // 费用类型
  165. $objDAccountType = new DAccountType('finance');
  166. $objDAccountType->setTable('qianniao_account_type');
  167. if($result->isSuccess()){
  168. //微信回调方法,新增一条已审核的费用单
  169. //判断有无会员卡消费费用类型
  170. $accountTypeResult = $objDAccountType->query('select * from qianniao_account_type where type = '.StatusCode::$standard.' and name like "%会员卡%"');
  171. if($accountTypeResult === false){
  172. $this->weixinErrorEcho($objDAccountType->error());
  173. }
  174. if(empty($accountTypeResult)){ //没有创建一个收入的会员卡消费类型
  175. $accountTypeDate = [
  176. 'enterpriseId' => $enterpriseId,
  177. 'name' => '会员卡',
  178. 'type' => StatusCode::$standard,
  179. 'remarks' => '购买会员卡',
  180. 'createTime' => time()
  181. ];
  182. $accountTypeInsert = $objDAccountType->insert($accountTypeDate);
  183. if($accountTypeInsert === false){
  184. $this->weixinErrorEcho($objDAccountType->error());
  185. }
  186. }
  187. //查询当前会员卡订单信息
  188. foreach ($allOrdersId as $cardOrderId) {
  189. $vipCardResult = $objDVipCard->get($cardOrderId);
  190. if($vipCardResult === false){
  191. $this->weixinErrorEcho($objDVipCard->error());
  192. }
  193. //获取微信默认账户信息
  194. $objMAccount = new MAccount($enterpriseId, $userCentId);
  195. $defaultAccountResult = $objMAccount->getDefaultAccount($vipCardResult['payType']);
  196. if ($defaultAccountResult->isSuccess() == false) {
  197. $this->weixinErrorEcho($defaultAccountResult->getData());
  198. }
  199. $defaultAccount = $defaultAccountResult->getData();
  200. if(empty($defaultAccount)){
  201. $this->weixinErrorEcho('支付方式对应的银行账户为空');
  202. }
  203. //组装费用单信息
  204. $expenseSingleData = [
  205. 'currentUnitId' => $vipCardResult['customerId'],
  206. 'currentUnit' => $vipCardResult['customerName'],
  207. 'type' => StatusCode::$delete,
  208. 'billTime' => time(),
  209. 'manager' => '',
  210. 'shopId' => $vipCardResult['shopId'],
  211. 'shopName' => '',
  212. 'consumeTypeId' => !empty($accountTypeResult)? $accountTypeResult[0]['id'] : $accountTypeInsert,
  213. 'consumeTypeName' => !empty($accountTypeResult)? $accountTypeResult[0]['name'] : $accountTypeDate['name'],
  214. 'totalCollectionAmount' => $vipCardResult['payAmount'],
  215. 'totalPreferentialAmount' => 0,
  216. 'totalActualAmount' => $vipCardResult['payAmount'],
  217. 'payType' => StatusCode::$standard,
  218. 'auditStatus' => StatusCode::$auditStatus['auditing'],
  219. 'deleteStatus' => StatusCode::$standard,
  220. 'expenseSingleAccountDate'=> [
  221. [
  222. 'expenseName' => 'vip会员卡收入',
  223. 'amount' => $vipCardResult['payAmount'],
  224. 'settlementMethodId' => StatusCode::$payType['wxPay'],
  225. 'settlementAccount' => StatusCode::$payType[1],
  226. 'accountId' => $defaultAccount['id'],
  227. 'preferentialAmount' => 0
  228. ]
  229. ]
  230. ];
  231. // 添加一条费用单
  232. $objMExpenseSingle = new MExpenseSingle($enterpriseId, $userCentId);
  233. $expenseSingleResult = $objMExpenseSingle->addExpenseSingle($expenseSingleData);
  234. if ($expenseSingleResult->isSuccess() == false) {
  235. $this->weixinErrorEcho($expenseSingleResult->getData());
  236. }
  237. //审核
  238. $updateExpenseSingle = $objMExpenseSingle->updateExpenseStatus(['id'=>$expenseSingleResult->getData(),'createTime'=>time()]);
  239. if ($updateExpenseSingle->isSuccess() == false) {
  240. $this->weixinErrorEcho($updateExpenseSingle->getData());
  241. }
  242. }
  243. $result = array(
  244. 'return_code' => 'SUCCESS',
  245. 'return_msg' => 'OK',
  246. );
  247. echo arrayToXml($result); // 数组转xml内容
  248. exit();
  249. }else{
  250. $this->weixinErrorEcho($result->getData());
  251. }
  252. }
  253. //处理预约项目订单
  254. if (substr($data['out_trade_no'],0,2) == 'wx') {
  255. $Msub = new MShopSubscribe($enterpriseId);
  256. $subOrder = $Msub->details(['order_id' => $data['out_trade_no']]);
  257. $subOrder = $subOrder->getData();
  258. if ($subOrder['paid'] == 1){
  259. //已支付
  260. $result = array(
  261. 'return_code' => 'SUCCESS',
  262. 'return_msg' => 'OK',
  263. );
  264. echo arrayToXml($result); // 数组转xml内容
  265. exit();
  266. }
  267. $res = $Msub->paySuccess($data['out_trade_no']);
  268. if ($res){
  269. $result = array(
  270. 'return_code' => 'SUCCESS',
  271. 'return_msg' => 'OK',
  272. );
  273. echo arrayToXml($result); // 数组转xml内容
  274. exit();
  275. }else{
  276. $this->weixinErrorEcho('失败');
  277. }
  278. }
  279. //处理优惠卡订单
  280. if (substr($data['out_trade_no'],0,2) == 'car') {
  281. $Mcard = new MShopCardOrder($enterpriseId);
  282. $order = $Mcard->details(['order_id' => $data['out_trade_no']]);
  283. $order = $order->getData();
  284. if ($order['paid'] == 1){
  285. //已支付
  286. $result = array(
  287. 'return_code' => 'SUCCESS',
  288. 'return_msg' => 'OK',
  289. );
  290. echo arrayToXml($result); // 数组转xml内容
  291. exit();
  292. }
  293. $res = $Mcard->paySuccess($data['out_trade_no']);
  294. if ($res){
  295. $result = array(
  296. 'return_code' => 'SUCCESS',
  297. 'return_msg' => 'OK',
  298. );
  299. echo arrayToXml($result); // 数组转xml内容
  300. exit();
  301. }else{
  302. $this->weixinErrorEcho('失败');
  303. }
  304. }
  305. $this->weixinErrorEcho('out_trade_no错误');
  306. } else {
  307. $this->weixinErrorEcho($postObj->err_code.':'.$postObj->err_code_des);
  308. }
  309. } else {
  310. $this->weixinErrorEcho($postObj->return_msg);
  311. }
  312. }else{
  313. $this->weixinErrorEcho('微信回调数据为空');
  314. }
  315. }
  316. /**
  317. * 统一错误输出
  318. */
  319. public function weixinErrorEcho($errorMsg){
  320. $result = array(
  321. 'return_code' => 'FAIL',
  322. 'return_msg' => $errorMsg,
  323. );
  324. echo arrayToWeiXinXml($result);
  325. exit();
  326. }
  327. }