Activity.php 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. <?php
  2. namespace app\api\controller;
  3. use app\admin\model\PalmpaySplitAccountLog;
  4. use app\common\controller\Api;
  5. use app\common\library\Ip;
  6. use app\common\library\Redis;
  7. use app\api\library\OrderDeduction;
  8. use app\common\service\KuaifenService;
  9. use app\common\service\OrderService;
  10. use app\common\service\UserVipExtendService;
  11. use app\main\constants\ApiConstants;
  12. use app\main\constants\CacheConstants;
  13. use app\main\constants\KafkaDotConstants;
  14. use app\main\constants\PayConstants;
  15. use app\main\model\object\AnalysisObject;
  16. use app\main\service\ActivityService;
  17. use app\main\service\AdminService;
  18. use app\main\service\JoinPayService;
  19. use app\main\service\KafkaDotService;
  20. use app\main\service\LogService;
  21. use app\main\service\OrderCollectService;
  22. use app\main\service\PalmPayService;
  23. use app\main\service\UrlService;
  24. use app\main\service\UserService;
  25. use app\main\service\MihuaPayService;
  26. use app\main\service\IpaynowPayService;
  27. use app\main\service\WeChatAdService;
  28. use think\Cookie;
  29. use think\Exception;
  30. use think\Log;
  31. use EasyWeChat\Factory;
  32. use think\Config;
  33. use Symfony\Component\Cache\Simple\RedisCache;
  34. use fast\Random;
  35. use GuzzleHttp\Client as Http;
  36. use GuzzleHttp\Exception\GuzzleException;
  37. use app\main\service\UnsPayService;
  38. class Activity extends Api
  39. {
  40. protected $wxNeedLogin = ['pay'];
  41. private function _initPayInfo()
  42. {
  43. Log::info('[ WeChat ] [ PAY ] [ CALLBACK ] GET: ' . json_encode(var_export($this->request->get(), true),
  44. JSON_UNESCAPED_UNICODE));
  45. Log::info('[ WeChat ] [ PAY ] [ CALLBACK ] INPUT: ' . json_encode(var_export($this->request->getInput(), true),
  46. JSON_UNESCAPED_UNICODE));
  47. $rid = $this->request->request('id'); // 资源id
  48. $act_id = $this->request->request('aid'); // 活动ID
  49. $adminId = UserService::instance()->getAdminId()->data; // 渠道商/代理商ID
  50. /**
  51. * 获取渠道商/代理商资料
  52. */
  53. $adminExtend = model('AdminExtend')->getInfo($adminId);
  54. if (!$adminExtend) {
  55. $this->error('管理员信息获取失败');
  56. }
  57. // $channelId = UserService::instance()->getRunTimeObject()->channelId; // 渠道商ID
  58. $channelId = UserService::instance()->getUserChannelId()->data;
  59. // $adminConfig = model('AdminConfig')->getAdminInfoAll($channelId);
  60. if ($adminExtend['distribute'] == '1') {
  61. //代理商配置信息
  62. $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($adminId);
  63. } else {
  64. //渠道商配置信息
  65. $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($channelId);
  66. }
  67. if (!$rid || !$adminId) {
  68. $this->error('缺少参数');
  69. }
  70. $goodsCategory = $this->request->request('category'); //商品分类 nickname
  71. $group = model('AuthGroupAccess')->where('uid', $adminId)->find();
  72. $groupId = $group->group_id;
  73. // $resourceModel = model('resource');
  74. // $goodsInfo = $resourceModel->find($rid);
  75. $goodsInfo = ActivityService::instance()->getResourceForFront($rid);
  76. //渠道自定义活动时,resource的活动ID为空,需要替换
  77. if ($act_id && empty($goodsInfo['activity_id'])) {
  78. $goodsInfo['activity_id'] = $act_id;
  79. }
  80. if (empty($goodsInfo)) {
  81. $this->error('商品不存在');
  82. }
  83. /**
  84. * 未登录的逻辑处理
  85. */
  86. if (!$this->user->isLogin()) {
  87. $this->error('登录信息获取失败');
  88. }
  89. $channelExtend = $adminExtend;
  90. if ($groupId == 4) {
  91. //代理 获取渠道信息
  92. $channelExtend = AdminService::instance()->getAdminExtendModel()->where(['admin_id' => $channelId])->find();
  93. }
  94. return [$goodsCategory, $rid, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend];
  95. }
  96. /**
  97. * 创建订单
  98. * @param $payment 支付方式 0 微信;1 四方平台
  99. * @param $adminId
  100. * @param $adminExtend
  101. * @param $row
  102. * @param $goodsCategory
  103. * @param $pdOrderId
  104. * @param $out_trade_no
  105. * @param $goodsId
  106. * @param $payInfo
  107. * @param $channelId
  108. * @param $prepay_id
  109. * @param $groupId
  110. * @param $pay_json
  111. * @param $kl_admin_info
  112. * @throws \think\db\exception\DataNotFoundException
  113. * @throws \think\db\exception\ModelNotFoundException
  114. * @throws \think\exception\DbException
  115. */
  116. private function _createOrderInfo(
  117. $payment,
  118. $adminId,
  119. $adminExtend,
  120. $row,
  121. $goodsCategory,
  122. $pdOrderId,
  123. $out_trade_no,
  124. $goodsId,
  125. $payInfo,
  126. $channelId,
  127. $prepay_id,
  128. $groupId,
  129. $pay_json,
  130. $kl_admin_info,
  131. $channelExtend
  132. )
  133. {
  134. $user_id = UserService::instance()->getUserInfo()->id;
  135. $insertData = [
  136. 'user_id' => $user_id,
  137. 'admin_id' => $adminId,
  138. 'benefit' => $adminExtend['benefit'],
  139. 'money' => $row['money'],
  140. 'money_benefit' => round($row['money'] * $adminExtend['benefit'], 2),
  141. 'category' => $goodsCategory,
  142. 'payid' => $prepay_id,
  143. 'out_trade_no' => $out_trade_no,
  144. 'ip' => Ip::ip(),
  145. 'referral_id' => UrlService::instance()->getUserReferralId()->data,
  146. 'referral_id_permanent' => UserService::instance()->getUserInfo()->referral_id_permanent,
  147. 'book_id' => $this->request->request('book_id'),
  148. 'chapter_id' => $this->request->request('chapter_id'),
  149. 'goods_id' => $goodsId,
  150. 'kandian' => $row['kandian'],
  151. 'free_kandian' => $row['free_kandian'],
  152. 'day' => $row['day'],
  153. 'type' => $row['type'],
  154. 'state' => 0,
  155. 'pay_json' => $pay_json,
  156. 'activity_id' => $row['activity_id'],
  157. 'payment_method' => $payment,
  158. 'wxpay_id' => $payInfo['id'],
  159. 'ext' => UserService::instance()->getUserInfo()->ext && json_decode(UserService::instance()->getUserInfo()->ext) ? UserService::instance()->getUserInfo()->ext : json_encode(new \stdClass()),
  160. 'createtime' => time(),
  161. 'updatetime' => time(),
  162. 'channel_id' => $channelId,
  163. 'channel_benefit' => $channelExtend['benefit'],
  164. 'group' => $groupId,
  165. ];
  166. if ($payment == ApiConstants::PAYMENT_METHOD_PALM) {
  167. $insertData['pdorderid'] = $pdOrderId; //四方平台订单号
  168. }
  169. try {
  170. if ($kl_admin_info) {
  171. if ($kl_admin_info['admin_id'] != $channelId) {
  172. $insertData['deduct'] = 1;
  173. }
  174. $insertData['benefit'] = $kl_admin_info['benefit'];
  175. $insertData['money_benefit'] = round($row['money'] * $kl_admin_info['benefit'], 2);
  176. $insertData['admin_id'] = $kl_admin_info['admin_id'];
  177. $insertData['resource_id'] = $adminId;
  178. $adminId = $kl_admin_info->admin_id;
  179. $groupId = 3;
  180. $insertData['group'] = $groupId;
  181. }
  182. } catch (\Exception $e) {
  183. Log::error('订单扣量失败, Error:' . $e->getMessage());
  184. }
  185. //转移订单结束
  186. $ordersId = model('Orders')->insertGetId($insertData);
  187. if (empty($insertData['deduct']) && $this->request->request('float_id')) {
  188. Redis::instance()->set(CacheConstants::getFloatTipsOrderId($ordersId), $this->request->request('float_id'));
  189. }
  190. if (!$ordersId) {
  191. $this->error('订单创建失败');
  192. }
  193. #region 快分app订单
  194. KuaifenService::instance()->createKuaifenOrders($ordersId, $insertData['admin_id'], $user_id, 0,
  195. $insertData['money'], $insertData['out_trade_no']);
  196. #endregion
  197. //判断是充值vip还是充值看点
  198. $isVip = false;
  199. if (!empty($row['day'])) {
  200. $isVip = true;
  201. }
  202. $isActivity = !empty($row['activity_id']);
  203. if (empty($insertData['deduct'])) { //如果不是KL
  204. $channel_id = UserService::instance()->getUserChannelId()->data;
  205. OrderCollectService::instance()->addCreateOrderCollect($user_id, $adminId, $isVip, $channel_id, $groupId, PayConstants::BUSINESS_WECHAT, $isActivity);
  206. $oAna = new AnalysisObject();
  207. $oAna->type = KafkaDotConstants::TYPE_ACTIVITY;
  208. $oAna->user_from = [
  209. 'activity_id' => $row['activity_id']
  210. ];
  211. $oAna->data = [
  212. 'stage' => 'start'
  213. ];
  214. KafkaDotService::instance()->sendMsg($user_id, $oAna);
  215. } else {
  216. OrderCollectService::instance()->addCreateOrderCollect($user_id, $kl_admin_info['admin_id'], $isVip, $kl_admin_info['admin_id'], $groupId, PayConstants::BUSINESS_WECHAT, $isActivity);
  217. }
  218. }
  219. /**
  220. * 支付下单总入口
  221. */
  222. public function pay()
  223. {
  224. //默认官方支付
  225. $payment_method = 0;
  226. //根据域名进行匹配
  227. $host = get_host_no_port();
  228. $payHosts = model('Wxpay')->getHosts();
  229. if (in_array($host, $payHosts)) {
  230. //支付域名匹配成功
  231. $pay_hosts = model('Wxpay')->getInfoByHost($host);
  232. $payInfo = model('Wxpay')->getInfo($pay_hosts['platform_id'], $pay_hosts['id']);
  233. if (isset($payInfo['payment_method']) && $payInfo['payment_method'] > 0) {
  234. $payment_method = $payInfo['payment_method'];
  235. }
  236. } else {
  237. //支付域名匹配失败,从Cookie获取渠道默认支付方式
  238. $adminId = UserService::instance()->getAdminId()->data; // 渠道商/代理商ID
  239. $adminConfig = model('AdminConfig')->getAdminInfoAll($adminId);
  240. if (isset($adminConfig['payment_method']) && $adminConfig['payment_method'] > 0) {
  241. $payment_method = $adminConfig['payment_method'];
  242. }
  243. }
  244. switch ($payment_method) {
  245. case ApiConstants::PAYMENT_METHOD_PALM://四方支付
  246. return $this->payPalm();
  247. case ApiConstants::PAYMENT_METHOD_JOIN://汇聚支付
  248. return $this->payJoin();
  249. case ApiConstants::PAYMENT_METHOD_MIHUA://米花支付
  250. return $this->payMihua();
  251. case ApiConstants::PAYMENT_METHOD_UNS://银生宝支付
  252. return $this->payUns();
  253. case ApiConstants::PAYMENT_METHOD_IPAYNOW://现在支付
  254. return $this->payIpaynow();
  255. default://微信官方支付
  256. return $this->payWechat();
  257. }
  258. }
  259. /**
  260. * 微信官方下单
  261. */
  262. public function payWechat()
  263. {
  264. list($goodsCategory, $goodsId, $adminId, $row, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend)
  265. = $this->_initPayInfo();
  266. switch ($goodsCategory) {
  267. case 'wechat': //微信公众号支付
  268. $paymentApplication = Factory::payment(Config::get('wechat'));
  269. $paymentApplication['cache'] = new RedisCache(Redis::instanceCache());
  270. $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15;
  271. $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port());
  272. $userId = UserService::instance()->getUserInfo()->id;
  273. if ($pay_timeout) {
  274. $endTime = time() - intval($pay_timeout) * 60;
  275. $has_orders = model('orders')
  276. ->where([
  277. 'goods_id' => $goodsId,
  278. 'user_id' => $userId,
  279. 'admin_id' => $adminId,
  280. 'state' => 0,
  281. 'payment_method' => ApiConstants::PAYMENT_METHOD_WECHAT
  282. ])
  283. ->where('createtime', '>', $endTime)->where('wxpay_id', $payInfo['id'])
  284. ->find();
  285. } else {
  286. $has_orders = null;
  287. }
  288. if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单
  289. $jssdk = $paymentApplication->jssdk;
  290. $json = $jssdk->bridgeConfig($has_orders['payid']);
  291. } else {
  292. $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [
  293. 'day' => $row['day'],
  294. 'activity_id' => $row['activity_id'],
  295. 'user_id' => Cookie::get('user_id'),
  296. 'book_id' => $this->request->request('book_id'),
  297. ], true)->data;
  298. $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4);
  299. $data = [
  300. 'body' => $row['type'] == 2 ? '充值VIP' : '充值书币',
  301. 'out_trade_no' => $out_trade_no,
  302. 'total_fee' => $row['money'] * 100,
  303. 'spbill_create_ip' => Ip::ip(),
  304. 'notify_url' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/pay',
  305. // 支付结果通知网址,如果不设置则会使用配置里的默认地址
  306. 'trade_type' => 'JSAPI',
  307. 'openid' => Cookie::get('openid'),
  308. ];
  309. $goods_des = Config::get('site.goodsdes');
  310. if ($goods_des) {
  311. $data['body'] = $data['body'] . ' ' . $goods_des;
  312. }
  313. //添加公众号昵称
  314. if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) {
  315. $zfxx = $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $data['body'];
  316. $data['body'] = mb_substr($zfxx, 0, 120, 'utf-8');
  317. }
  318. $palmApiStartTime = microtime(true);
  319. $result = $paymentApplication->order->unify($data);
  320. $palmApiEndTime = microtime(true);
  321. $apiRunTime = round($palmApiEndTime - $palmApiStartTime, 3);
  322. if ($result['return_code'] == 'FAIL') {
  323. Log::error(sprintf('wechatpay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,admin_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,errmessage:%s'
  324. , $payInfo['id'], $payInfo['name'], $payInfo['mcid'], $adminId, $channelId, $userId, $row['money'],
  325. $goodsId, $out_trade_no, $apiRunTime, json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE)));
  326. Log::error('微信订单创建失败!订单内容: ' . json_encode(var_export($data, true),
  327. JSON_UNESCAPED_UNICODE) . " 微信返回内容: " . json_encode(var_export($result, true),
  328. JSON_UNESCAPED_UNICODE));
  329. $this->error('微信订单创建失败');
  330. }
  331. $this->_createOrderInfo(0, $adminId,
  332. $adminExtend,
  333. $row,
  334. $goodsCategory,
  335. 0,
  336. $out_trade_no,
  337. $goodsId,
  338. $payInfo,
  339. $channelId,
  340. $result['prepay_id'],
  341. $groupId,
  342. '',
  343. $kl_admin_info,
  344. $channelExtend
  345. );
  346. $jssdk = $paymentApplication->jssdk;
  347. $json = $jssdk->bridgeConfig($result['prepay_id']);
  348. Log::info(sprintf('wechatpay_create_order_success!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s'
  349. , $payInfo['id'], $payInfo['name'], $payInfo['mcid'], $adminId, $userId,
  350. $row['money'], $goodsId, $out_trade_no, $apiRunTime));
  351. }
  352. //下单订单数据统计
  353. $this->success('订单创建成功', ['json' => $json]);
  354. break;
  355. case 'wechath5': //微信H5支付
  356. break;
  357. case 'alipay': //支付宝支付
  358. break;
  359. }
  360. $this->error('未知充值方式');
  361. }
  362. /**
  363. * 四方支付下单
  364. */
  365. public function payPalm()
  366. {
  367. list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend)
  368. = $this->_initPayInfo();
  369. $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15;
  370. $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port());
  371. $userId = UserService::instance()->getUserInfo()->id;
  372. if ($pay_timeout) {
  373. $endTime = time() - intval($pay_timeout) * 60;
  374. $has_orders = model('orders')
  375. ->where([
  376. 'goods_id' => $goodsId,
  377. 'user_id' => $userId,
  378. 'admin_id' => $adminId,
  379. 'state' => 0,
  380. 'payment_method' => ApiConstants::PAYMENT_METHOD_PALM
  381. ])
  382. ->where('createtime', '>', $endTime)->where('wxpay_id', $payInfo['id'])
  383. ->find();
  384. } else {
  385. $has_orders = null;
  386. }
  387. if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单
  388. $json = $has_orders['pay_json'];
  389. } else {
  390. $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [
  391. 'day' => $goodsInfo['day'],
  392. 'activity_id' => $goodsInfo['activity_id'],
  393. 'user_id' => Cookie::get('user_id'),
  394. 'book_id' => $this->request->request('book_id'),
  395. ], true)->data;
  396. $paymentApplication = Factory::payment(Config::get('wechat'));
  397. $paymentApplication['cache'] = new RedisCache(Redis::instanceCache());
  398. $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4);
  399. $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币';
  400. $data = [
  401. 'mchId' => $payInfo['quartet_merchant_id'],
  402. 'outTradeNo' => $out_trade_no,
  403. 'appid' => $payInfo['quartet_app_id'],
  404. 'version' => ApiConstants::PALM_PAY_VERSION,
  405. 'money' => $goodsInfo['money'] * 100,
  406. 'ip' => Ip::ip(),
  407. 'notifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/palmpay',
  408. // 支付结果通知网址,如果不设置则会使用配置里的默认地址
  409. 'subAppid' => $payInfo['appid'],
  410. 'openid' => Cookie::get('openid'),
  411. ];
  412. if ($payInfo['quartet_is_split'] == ApiConstants::QUARTET_IS_SPLIT) {
  413. if ($kl_admin_info && $kl_admin_info['admin_id'] != $channelId) {
  414. $palmPayCmd = OrderService::instance()->getPalmPayCmd($goodsInfo['money'], 0)->data;
  415. $cmd = $palmPayCmd['cmd'];
  416. $palmPayCmdDefault = $palmPayCmd['default'];
  417. } else {
  418. $palmPayCmd = OrderService::instance()->getPalmPayCmd($goodsInfo['money'], $channelId)->data;
  419. $cmd = $palmPayCmd['cmd'];
  420. $palmPayCmdDefault = $palmPayCmd['default'];
  421. }
  422. if (!$cmd) {
  423. LogService::debug("微信分账设置错误");
  424. $this->success('订单创建失败,请重新下单!');
  425. }
  426. $data['cmd'] = $cmd;
  427. }
  428. $goods_des = Config::get('site.goodsdes');
  429. if ($goods_des) {
  430. $data['productName'] = urlencode($productName . ' ' . $goods_des);
  431. } else {
  432. $data['productName'] = urlencode($productName);
  433. }
  434. if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) {
  435. if (empty($goods_des)) {
  436. $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName;
  437. } else {
  438. $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName . '_' . $goods_des;
  439. }
  440. $data['productDesc'] = mb_substr($zfxx, 0, 120, 'utf-8');
  441. $data['productDesc'] = urlencode($data['productDesc']);
  442. }
  443. $signStr = $payInfo['quartet_app_id'] . 'WECHAT_SUB' . $data['money'] . $data['outTradeNo'] . $payInfo['quartet_app_key'];
  444. $data['sign'] = md5($signStr);
  445. $orderInfo = [
  446. 'goods_id' => $goodsId,
  447. 'out_trade_no' => $out_trade_no,
  448. 'admin_id' => $adminId,
  449. 'user_id' => $userId,
  450. ];
  451. try {
  452. $result = PalmPayService::instance()->payPalmApi($data, $payInfo, $goodsInfo, $orderInfo);
  453. } catch (Exception $e) {
  454. $this->success($e->getMessage());
  455. }
  456. //分账记录日志
  457. if (!empty($palmPayCmdDefault)) {
  458. $channel_palmpay_sub_account_id = $palmPayCmdDefault['channel_palmpay_sub_account_id'];
  459. $channel_amount = $palmPayCmdDefault['channel_amount'];
  460. $dz_palmpay_sub_account_id = $palmPayCmdDefault['dz_palmpay_sub_account_id'];
  461. $dz_amount = $palmPayCmdDefault['dz_amount'];
  462. PalmpaySplitAccountLog::create([
  463. 'order_id' => $out_trade_no,
  464. 'dz_palmpay_sub_account_id' => $dz_palmpay_sub_account_id,
  465. 'dz_amount' => $dz_amount,
  466. 'channel_palmpay_sub_account_id' => $channel_palmpay_sub_account_id,
  467. 'channel_amount' => $channel_amount
  468. ])->insert();
  469. }
  470. $result = $result['result'];
  471. $payInfoArr = json_decode($result['pay_info'], true);
  472. $prepay_id = explode('=', $payInfoArr['package'])[1];
  473. $this->_createOrderInfo(1, $adminId,
  474. $adminExtend,
  475. $goodsInfo,
  476. $goodsCategory,
  477. $result['pdorderid'],
  478. $out_trade_no,
  479. $goodsId,
  480. $payInfo,
  481. $channelId,
  482. $prepay_id,
  483. $groupId,
  484. $result['pay_info'],
  485. $kl_admin_info,
  486. $channelExtend
  487. );
  488. $json = $result['pay_info'];
  489. }
  490. //下单订单数据统计
  491. $this->success('订单创建成功', ['json' => $json]);
  492. }
  493. /**
  494. * 汇聚支付下单
  495. */
  496. public function payJoin()
  497. {
  498. list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend)
  499. = $this->_initPayInfo();
  500. $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15;
  501. $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port());
  502. $userId = Cookie::get('user_id');
  503. if ($pay_timeout) {
  504. $endTime = time() - intval($pay_timeout) * 60;
  505. $has_orders = model('orders')
  506. ->where([
  507. 'goods_id' => $goodsId,
  508. 'user_id' => $userId,
  509. 'admin_id' => $adminId,
  510. 'state' => 0,
  511. 'wxpay_id' => $payInfo['id'],
  512. 'payment_method' => ApiConstants::PAYMENT_METHOD_JOIN
  513. ])
  514. ->where('createtime', '>', $endTime)
  515. ->find();
  516. } else {
  517. $has_orders = null;
  518. }
  519. if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单
  520. $json = $has_orders['pay_json'];
  521. } else {
  522. $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [
  523. 'day' => $goodsInfo['day'],
  524. 'activity_id' => $goodsInfo['activity_id'],
  525. 'user_id' => Cookie::get('user_id'),
  526. 'book_id' => $this->request->request('book_id'),
  527. ], true)->data;
  528. $paymentApplication = Factory::payment(Config::get('wechat'));
  529. $paymentApplication['cache'] = new RedisCache(Redis::instanceCache());
  530. $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4);
  531. $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币';
  532. $data = [
  533. 'p0_Version' => ApiConstants::JOIN_PAY_VERSION,
  534. 'p1_MerchantNo' => $payInfo['quartet_merchant_id'],
  535. 'p2_OrderNo' => $out_trade_no,
  536. 'p3_Amount' => $goodsInfo['money'],
  537. 'p4_Cur' => '1',
  538. 'p9_NotifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/joinpay',
  539. 'q1_FrpCode' => ApiConstants::JOIN_PAY_TYPE,
  540. 'q5_OpenId' => Cookie::get('openid'),
  541. 'q7_AppId' => $payInfo['appid'],
  542. ];
  543. $goods_des = Config::get('site.goodsdes');
  544. if ($goods_des) {
  545. $data['p6_ProductDesc'] = $productName . ' ' . $goods_des;
  546. } else {
  547. $data['p6_ProductDesc'] = $productName;
  548. }
  549. if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) {
  550. if (empty($goods_des)) {
  551. $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName;
  552. } else {
  553. $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName . '_' . $goods_des;
  554. }
  555. } else {
  556. if (empty($goods_des)) {
  557. $zfxx = $userId . '_' . $productName;
  558. } else {
  559. $zfxx = $userId . '_' . $productName . '_' . $goods_des;
  560. }
  561. }
  562. $data['p5_ProductName'] = mb_substr($zfxx, 0, 120, 'utf-8');
  563. $secret = $payInfo['quartet_app_key'];
  564. $signStr = $data['p0_Version'] . $data['p1_MerchantNo'] . $data['p2_OrderNo'] . $data['p3_Amount'] . $data['p4_Cur'] . $data['p5_ProductName'] . $data['p6_ProductDesc'] . $data['p9_NotifyUrl'] . $data['q1_FrpCode'] . $data['q5_OpenId'] . $data['q7_AppId'] . $secret;
  565. $data['hmac'] = md5($signStr);
  566. $orderInfo = [
  567. 'goods_id' => $goodsId,
  568. 'out_trade_no' => $out_trade_no,
  569. 'admin_id' => $adminId,
  570. 'user_id' => $userId,
  571. ];
  572. $joinService = JoinPayService::instance();
  573. try {
  574. $result = $joinService->payJoinApi($data, $payInfo, $goodsInfo, $orderInfo);
  575. } catch (Exception $e) {
  576. $this->success($e->getMessage());
  577. }
  578. $payInfoArr = json_decode($result['rc_Result'], true);
  579. $prepay_id = explode('=', $payInfoArr['package'])[1];
  580. $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_JOIN, $adminId,
  581. $adminExtend,
  582. $goodsInfo,
  583. $goodsCategory,
  584. $result['r7_TrxNo'],
  585. $out_trade_no,
  586. $goodsId,
  587. $payInfo,
  588. $channelId,
  589. $prepay_id,
  590. $groupId,
  591. $result['rc_Result'],
  592. $kl_admin_info,
  593. $channelExtend
  594. );
  595. $json = $result['rc_Result'];
  596. }
  597. //下单订单数据统计
  598. $this->success('订单创建成功', ['json' => $json]);
  599. }
  600. /**
  601. * 米花支付下单
  602. * @throws \think\db\exception\DataNotFoundException
  603. * @throws \think\db\exception\ModelNotFoundException
  604. * @throws \think\exception\DbException
  605. */
  606. public function payMihua()
  607. {
  608. list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend)
  609. = $this->_initPayInfo();
  610. $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15;
  611. $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port());
  612. $userId = Cookie::get('user_id');
  613. if ($pay_timeout) {
  614. $endTime = time() - intval($pay_timeout) * 60;
  615. $has_orders = model('orders')
  616. ->where([
  617. 'goods_id' => $goodsId,
  618. 'user_id' => $userId,
  619. 'admin_id' => $adminId,
  620. 'state' => '0',
  621. 'wxpay_id' => $payInfo['id'],
  622. 'payment_method' => ApiConstants::PAYMENT_METHOD_MIHUA
  623. ])
  624. ->where('createtime', '>', $endTime)
  625. ->find();
  626. } else {
  627. $has_orders = null;
  628. }
  629. if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单
  630. $json = $has_orders['pay_json'];
  631. } else {
  632. $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [
  633. 'day' => $goodsInfo['day'],
  634. 'activity_id' => $goodsInfo['activity_id'],
  635. 'user_id' => Cookie::get('user_id'),
  636. 'book_id' => $this->request->request('book_id'),
  637. ], true)->data;
  638. $paymentApplication = Factory::payment(Config::get('wechat'));
  639. $paymentApplication['cache'] = new RedisCache(Redis::instanceCache());
  640. $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4);
  641. $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币';
  642. $userId = Cookie::get('user_id'); // 用户ID
  643. $user = model('User')->getUserInfo($userId);
  644. $createtimeTs = empty($user) ? time() : $user['createtime'];
  645. $createtimeStr = date('YmdHis', $createtimeTs);
  646. $aRiskItem = [
  647. 'userInfoMerchantNo' => $userId,
  648. 'userInfoDtRegister' => $createtimeStr,
  649. ];
  650. $data = [
  651. 'merAccount' => $payInfo['quartet_app_id'],
  652. 'merNo' => $payInfo['quartet_merchant_id'],
  653. 'orderId' => $out_trade_no,
  654. 'time' => time(),
  655. 'amount' => (int)($goodsInfo['money'] * 100),
  656. 'payWay' => 'WEIXIN',
  657. 'payType' => 'JSAPI_WEIXIN',
  658. 'userIp' => Ip::ip(),
  659. 'openId' => Cookie::get('openid'),
  660. 'returnUrl' => 'http://www.baidu.com',//前端页面回调地址
  661. 'notifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/mihuapay',
  662. 'riskItem' => json_encode($aRiskItem),
  663. ];
  664. $goods_des = Config::get('site.goodsdes');
  665. if ($goods_des) {
  666. $data['productDesc'] = $productName . ' ' . $goods_des;
  667. } else {
  668. $data['productDesc'] = $productName;
  669. }
  670. if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) {
  671. if (empty($goods_des)) {
  672. $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName;
  673. } else {
  674. $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName . '丨' . $goods_des;
  675. }
  676. } else {
  677. if (empty($goods_des)) {
  678. $zfxx = $userId . '丨' . $productName;
  679. } else {
  680. $zfxx = $userId . '丨' . $productName . '丨' . $goods_des;
  681. }
  682. }
  683. $data['product'] = mb_substr($zfxx, 0, 120, 'utf-8');
  684. $mihuaService = MihuaPayService::instance($payInfo['quartet_app_key'],
  685. $payInfo['quartet_app_public_key']);
  686. $data['sign'] = $mihuaService->getSign($data);
  687. Log::info('米花支付请求参数:' . json_encode($data));
  688. $encode_data = $mihuaService->encrypt($data);
  689. $postData = array(
  690. 'merAccount' => $payInfo['quartet_app_id'],//商户标识
  691. 'data' => $encode_data
  692. );
  693. $orderInfo = [
  694. 'goods_id' => $goodsId,
  695. 'out_trade_no' => $out_trade_no,
  696. 'admin_id' => $adminId,
  697. 'user_id' => $userId,
  698. ];
  699. try {
  700. $result = $mihuaService->payMihuaApi($postData, $data, $payInfo, $goodsInfo, $orderInfo);
  701. } catch (Exception $e) {
  702. $this->success($e->getMessage());
  703. }
  704. $prepay_id = $result['data']['mbOrderId'];
  705. $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_MIHUA, $adminId,
  706. $adminExtend,
  707. $goodsInfo,
  708. $goodsCategory,
  709. 0,
  710. $out_trade_no,
  711. $goodsId,
  712. $payInfo,
  713. $channelId,
  714. $prepay_id,
  715. $groupId,
  716. $result['data']['payInfo'],
  717. $kl_admin_info,
  718. $channelExtend
  719. );
  720. $json = $result['data']['payInfo'];
  721. }
  722. $this->success('订单创建成功', ['json' => $json]);
  723. }
  724. public function payUns()
  725. {
  726. list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend)
  727. = $this->_initPayInfo();
  728. $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15;
  729. $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port());
  730. $userId = Cookie::get('user_id');
  731. if ($pay_timeout) {
  732. $endTime = time() - intval($pay_timeout) * 60;
  733. $has_orders = model('orders')
  734. ->where([
  735. 'goods_id' => $goodsId,
  736. 'user_id' => $userId,
  737. 'admin_id' => $adminId,
  738. 'state' => '0',
  739. 'wxpay_id' => $payInfo['id'],
  740. 'payment_method' => ApiConstants::PAYMENT_METHOD_UNS
  741. ])
  742. ->where('createtime', '>', $endTime)
  743. ->find();
  744. } else {
  745. $has_orders = null;
  746. }
  747. if (!empty($has_orders)) { //如果用户已经在该代理商/渠道商下过该单
  748. $json = $has_orders['pay_json'];
  749. } else {
  750. $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [
  751. 'day' => $goodsInfo['day'],
  752. 'activity_id' => $goodsInfo['activity_id'],
  753. 'user_id' => Cookie::get('user_id'),
  754. 'book_id' => $this->request->request('book_id'),
  755. ], true)->data;
  756. $paymentApplication = Factory::payment(Config::get('wechat'));
  757. $paymentApplication['cache'] = new RedisCache(Redis::instanceCache());
  758. $out_trade_no = date('YmdHis') . $userId . Random::build('alnum', 4);
  759. $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币';
  760. $data = [
  761. 'accountId' => $payInfo['quartet_app_id'],
  762. 'orderId' => $out_trade_no,
  763. 'amount' => $goodsInfo['money'],
  764. 'responseUrl' => 'http://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/unspay',
  765. 'openId' => Cookie::get('openid'),
  766. 'version' => '1.0.1',
  767. ];
  768. $goodsDes = Config::get('site.goodsdes');
  769. if ($goodsDes) {
  770. $data['commodity'] = $productName . ' ' . $goodsDes;
  771. } else {
  772. $data['commodity'] = $productName;
  773. }
  774. if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) {
  775. if (empty($goods_des)) {
  776. $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName;
  777. } else {
  778. $zfxx = $userId . '丨' . $adminConfig['json']['authorizer_info']['nick_name'] . '丨' . $productName . '丨' . $goods_des;
  779. }
  780. } else {
  781. if (empty($goods_des)) {
  782. $zfxx = $userId . '丨' . $productName;
  783. } else {
  784. $zfxx = $userId . '丨' . $productName . '丨' . $goods_des;
  785. }
  786. }
  787. $unsPayService = UnsPayService::instance($payInfo['quartet_app_key']);
  788. $data['subject'] = mb_substr($zfxx, 0, 120, 'utf-8');
  789. $data['mac'] = $unsPayService->makeMacParams($data);
  790. $orderInfo = [
  791. 'goods_id' => $goodsId,
  792. 'out_trade_no' => $out_trade_no,
  793. 'admin_id' => $adminId,
  794. 'user_id' => $userId,
  795. ];
  796. try {
  797. $result = $unsPayService->payUnsApi($data, $payInfo, $goodsInfo, $orderInfo);
  798. } catch (Exception $e) {
  799. $this->success($e->getMessage());
  800. }
  801. $strmPackage = $result['mPackage'];
  802. $amPackage = explode('=', $strmPackage);
  803. $prepayId = $amPackage[1];
  804. $payJson = UnsPayService::makeJsJsonParam($result);
  805. $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_UNS, $adminId,
  806. $adminExtend,
  807. $goodsInfo,
  808. $goodsCategory,
  809. 0,
  810. $out_trade_no,
  811. $goodsId,
  812. $payInfo,
  813. $channelId,
  814. $prepayId,
  815. $groupId,
  816. $payJson,
  817. $kl_admin_info,
  818. $channelExtend
  819. );
  820. $json = $payJson;
  821. }
  822. $this->success('订单创建成功', ['json' => $json]);
  823. }
  824. public function payIpaynow()
  825. {
  826. list($goodsCategory, $goodsId, $adminId, $goodsInfo, $adminExtend, $channelId, $adminConfig, $groupId, $channelExtend)
  827. = $this->_initPayInfo();
  828. $pay_timeout = Config::has('site.pay_timeout') ? Config::get('site.pay_timeout') : 15;
  829. $payInfo = model('Wxpay')->getInfoByHost(get_host_no_port());
  830. $userId = Cookie::get('user_id');
  831. if ($pay_timeout) {
  832. $endTime = time() - intval($pay_timeout) * 60;
  833. $has_orders = model('orders')
  834. ->where([
  835. 'goods_id' => $goodsId,
  836. 'user_id' => $userId,
  837. 'admin_id' => $adminId,
  838. 'state' => '0',
  839. 'wxpay_id' => $payInfo['id'],
  840. 'payment_method' => ApiConstants::PAYMENT_METHOD_IPAYNOW
  841. ])
  842. ->where('createtime', '>', $endTime)
  843. ->find();
  844. } else {
  845. $has_orders = null;
  846. }
  847. if (!empty($has_orders)) {//如果用户已经在该代理商/渠道商下过该单
  848. $json = $has_orders['pay_json'];
  849. } else {
  850. $kl_admin_info = OrderService::instance()->getKlAdminInfo($groupId, $adminId, $channelId, [
  851. 'day' => $goodsInfo['day'],
  852. 'activity_id' => $goodsInfo['activity_id'],
  853. 'user_id' => Cookie::get('user_id'),
  854. 'book_id' => $this->request->request('book_id'),
  855. ], true)->data;
  856. $paymentApplication = Factory::payment(Config::get('wechat'));
  857. $paymentApplication['cache'] = new RedisCache(Redis::instanceCache());
  858. $out_trade_no = date('YmdHis') . '_' . $userId . '_' . Random::build('alnum', 4);
  859. $productName = $goodsInfo['type'] == 2 ? '充值VIP' : '充值书币';
  860. $data = [
  861. 'funcode' => 'WP001',
  862. 'version' => '1.0.0',
  863. 'appId' => $payInfo['quartet_app_id'],
  864. 'mhtOrderNo' => $out_trade_no,
  865. 'mhtOrderType' => '01',
  866. 'mhtCurrencyType' => '156',
  867. 'mhtOrderAmt' => $goodsInfo['money'] * 100,
  868. 'mhtOrderStartTime' => date('YmdHis'),
  869. 'notifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/ipaynowpay',
  870. 'frontNotifyUrl' => Config::get('site.scheme') . '://' . Api::PAY_CALLBACK_PREFIX . $payInfo['pay_host'] . '/api/wechat/ipaynowpay',
  871. 'mhtCharset' => 'UTF-8',
  872. 'deviceType' => '0600',
  873. 'payChannelType' => '13',
  874. 'outputType' => '1',
  875. 'mhtSubAppId' => $payInfo['appid'],
  876. 'consumerId' => Cookie::get('openid'),
  877. 'mhtLimitPay' => '0',
  878. 'mhtSignType' => 'MD5',
  879. ];
  880. $goodsDes = Config::get('site.goodsdes');
  881. if ($goodsDes) {
  882. $data['mhtOrderDetail'] = $productName . ' ' . $goodsDes;
  883. } else {
  884. $data['mhtOrderDetail'] = $productName;
  885. }
  886. if (!empty($adminConfig['json']['authorizer_info']['nick_name'])) {
  887. if (empty($goods_des)) {
  888. $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName;
  889. } else {
  890. $zfxx = $userId . '_' . $adminConfig['json']['authorizer_info']['nick_name'] . '_' . $productName . '_' . $goods_des;
  891. }
  892. } else {
  893. if (empty($goods_des)) {
  894. $zfxx = $userId . '_' . $productName;
  895. } else {
  896. $zfxx = $userId . '_' . $productName . '_' . $goods_des;
  897. }
  898. }
  899. $data['mhtOrderName'] = mb_substr($zfxx, 0, 120, 'utf-8');
  900. $privateKey = $payInfo['quartet_app_private_no'];
  901. $data['mhtSignature'] = IpaynowPayService::instance($privateKey)->makeSign($data);
  902. $orderInfo = [
  903. 'goods_id' => $goodsId,
  904. 'out_trade_no' => $out_trade_no,
  905. 'admin_id' => $adminId,
  906. 'user_id' => $userId,
  907. ];
  908. try {
  909. $result = IpaynowPayService::instance($payInfo['quartet_app_key'])->payIpaynowApi($data, $payInfo,
  910. $goodsInfo, $orderInfo);
  911. } catch (Exception $e) {
  912. $this->success($e->getMessage());
  913. }
  914. $tnStr = urldecode($result['tn']);
  915. parse_str($tnStr, $aJson);
  916. $aJson['appId'] = $aJson['wxAppId'];
  917. $aJson['package'] = 'prepay_id=' . $aJson['prepay_id'];
  918. unset($aJson['wxAppId']);
  919. unset($aJson['prepay_id']);
  920. $json = json_encode($aJson);
  921. $this->_createOrderInfo(ApiConstants::PAYMENT_METHOD_IPAYNOW, $adminId,
  922. $adminExtend,
  923. $goodsInfo,
  924. $goodsCategory,
  925. 0,
  926. $out_trade_no,
  927. $goodsId,
  928. $payInfo,
  929. $channelId,
  930. '',
  931. $groupId,
  932. $json,
  933. $kl_admin_info,
  934. $channelExtend
  935. );
  936. }
  937. $this->success('订单创建成功', ['json' => $json]);
  938. }
  939. }