WechatPay.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * Author: 芸众商城 www.yunzshop.com
  5. * Date: 2017/3/17
  6. * Time: 下午12:00
  7. */
  8. namespace app\common\services;
  9. use app\common\events\payment\ChargeComplatedEvent;
  10. use app\common\exceptions\AppException;
  11. use app\common\exceptions\ShopException;
  12. use app\common\facades\EasyWeChat;
  13. use app\common\helpers\Client;
  14. use app\common\helpers\Url;
  15. use app\common\models\McMappingFans;
  16. use app\common\models\Member;
  17. use app\common\models\OrderPay;
  18. use app\common\models\PayOrder;
  19. use app\common\models\PayType;
  20. use app\common\models\WechatWithdrawLog;
  21. use app\common\services\finance\Withdraw;
  22. use app\common\services\payment\WechatMinPay;
  23. use app\common\services\wechatApiV3\ApiV3Status;
  24. use app\frontend\modules\member\services\factory\MemberFactory;
  25. use app\frontend\modules\order\services\OrderPaySuccessService;
  26. use app\frontend\modules\order\services\OrderService;
  27. use Yunshop\WechatTrade\services\AddOrderService;
  28. class WechatPay extends Pay
  29. {
  30. private $pay_type;
  31. private static $attach_type = 'account';
  32. public function __construct()
  33. {
  34. $this->pay_type = config('app.pay_type');
  35. }
  36. public function doPay($data = [], $payType = 1)
  37. {
  38. $min_client_type = \YunShop::request()->client_type;
  39. if ($min_client_type && $min_client_type == 2) {
  40. return (new WechatMinPay())->doPay($data);
  41. }
  42. $client_type = null;
  43. $text = $data['extra']['type'] == 1 ? '支付' : '充值';
  44. $op = '微信订单' . $text . ' 订单号:' . $data['order_no'];
  45. $pay_type_name = PayType::get_pay_type_name($payType);
  46. $pay_order_model = $this->log($data['extra']['type'], $pay_type_name, $data['amount'], $op, $data['order_no'], Pay::ORDER_STATUS_NON, \YunShop::app()->getMemberId());
  47. if (empty(\YunShop::app()->getMemberId())) {
  48. throw new AppException('无法获取用户ID');
  49. }
  50. if (\YunShop::request()->client_type) {
  51. $client_type = \YunShop::request()->client_type;
  52. } else {
  53. $client_type = $payType;
  54. }
  55. $openid = Member::getOpenIdForType(\YunShop::app()->getMemberId(), $client_type);
  56. \Log::debug('-----pay_member_id-----'. \YunShop::app()->getMemberId());
  57. //不同支付类型选择参数
  58. $pay = $this->payParams($payType);
  59. if (empty($pay['weixin_mchid']) || empty($pay['weixin_apisecret'])
  60. || empty($pay['weixin_appid']) || empty($pay['weixin_secret'])) {
  61. throw new AppException('没有设定支付参数');
  62. }
  63. $notify_url = Url::shopSchemeUrl('payment/wechat/notifyUrl.php');
  64. $payment = $this->getEasyWeChatApp($pay, $notify_url);
  65. //支付方式不等于微信app
  66. if (in_array($payType, [PayFactory::PAY_APP_WEACHAT, PayFactory::WECHAT_CPS_APP_PAY])) {
  67. $data['trade_type'] = 'APP';
  68. } else {
  69. $data['trade_type'] = 'JSAPI';
  70. }
  71. $order = self::getEasyWeChatOrder($data, $openid, $pay_order_model,$payType);
  72. $prepayId = null;
  73. //支付方式不等于微信app
  74. if ($payType == PayFactory::PAY_APP_WEACHAT) {
  75. return true;
  76. } else {
  77. $result = $payment->order->unify($order);
  78. \Log::debug('预下单', $result);
  79. if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
  80. $prepayId = $result['prepay_id'];
  81. $this->changeOrderStatus($pay_order_model, Pay::ORDER_STATUS_WAITPAY,'');
  82. } elseif ($result['return_code'] == 'SUCCESS') {
  83. throw new AppException($result['err_code_des']);
  84. } else {
  85. throw new AppException($result['return_msg']);
  86. }
  87. $config = $payment->jssdk->sdkConfig($prepayId);
  88. $config['appId'] = $pay['weixin_appid'];
  89. $config['prepayId'] = $prepayId;
  90. if($data['trade_type'] == 'APP'){
  91. $config['partnerid'] = $pay['weixin_mchid'] ? : '';
  92. }
  93. $js['appId'] = $config['appId'];
  94. return ['config'=>$config, 'js'=>json_encode($js)];
  95. }
  96. }
  97. /**
  98. * 微信退款
  99. *
  100. * @param 订单号 $out_trade_no
  101. * @param 订单总金额 $totalmoney
  102. * @param 退款金额 $refundmoney
  103. * @return array
  104. */
  105. public function doRefund($out_trade_no, $totalmoney, $refundmoney)
  106. {
  107. $out_refund_no = $this->setUniacidNo(\YunShop::app()->uniacid);
  108. $op = '微信退款 订单号:' . $out_trade_no . '退款单号:' . $out_refund_no . '退款总金额:' . $totalmoney;
  109. if (empty($out_trade_no)) {
  110. throw new AppException('参数错误');
  111. }
  112. $pay_type_id = OrderPay::get_paysn_by_pay_type_id($out_trade_no);
  113. $pay_type_name = PayType::get_pay_type_name($pay_type_id);
  114. $pay_order_model = $this->refundlog(Pay::PAY_TYPE_REFUND, $pay_type_name, $refundmoney, $op, $out_trade_no, Pay::ORDER_STATUS_NON, 0);
  115. //app退款查询app配置中的微信支付信息
  116. if ($pay_type_id == PayFactory::PAY_APP_WEACHAT) {
  117. $pay = \Setting::get('shop_app.pay');
  118. } else {
  119. $pay = $this->payParams($pay_type_id);
  120. }
  121. if (empty($pay['weixin_mchid']) || empty($pay['weixin_apisecret'])) {
  122. throw new AppException('没有设定支付参数');
  123. }
  124. if (empty($pay['weixin_cert']) || empty($pay['weixin_key'])) {
  125. throw new AppException('未上传完整的微信支付证书,请到【系统设置】->【支付方式】中上传!');
  126. }
  127. $notify_url = '';
  128. $payment = $this->getEasyWeChatApp($pay, $notify_url);
  129. try {
  130. $totalmoney = bcmul($totalmoney, 100,0);
  131. $refundmoney = bcmul($refundmoney, 100,0);
  132. $result = $payment->refund->byOutTradeNumber($out_trade_no, $out_refund_no, $totalmoney, $refundmoney);
  133. } catch (\Exception $e) {
  134. \Log::debug('---微信退款接口请求错误---', $e->getMessage());
  135. throw new AppException('微信接口错误:' . $e->getMessage());
  136. }
  137. $this->payResponseDataLog($out_trade_no, '微信退款', json_encode($result));
  138. //微信申请退款失败
  139. if (isset($result['result_code']) && strtoupper($result['result_code']) == 'FAIL') {
  140. \Log::debug('---微信退款申请错误---', $result);
  141. throw new AppException('微信退款申请错误:'.$result['err_code'] . '-' . $result['err_code_des']);
  142. }
  143. $status = $this->queryRefund($payment, $out_trade_no);
  144. \Log::debug('---退款状态---', [$status]);
  145. if ($status == 'PROCESSING' || $status == 'SUCCESS' || ($status == 'fail' && $result->refund_id)){
  146. $this->changeOrderStatus($pay_order_model, Pay::ORDER_STATUS_COMPLETE, $result['transaction_id']);
  147. return true;
  148. } else {
  149. \Log::debug('---微信退款接口返回错误---', $result);
  150. throw new AppException('微信接口错误:'.$result['return_msg'] . '-' . $result['err_code_des'] . '/' . $status);
  151. }
  152. }
  153. /**
  154. * 微信提现
  155. *
  156. * @param 提现者用户ID $member_id
  157. * @param 提现金额 $money
  158. * @param string $desc
  159. * @param int $type
  160. * @param int $withdraw_type 0商城提现1供应商提现
  161. * @return array
  162. */
  163. public function doWithdraw($member_id, $out_trade_no, $money, $desc='', $type=1,$withdraw_type = 0)
  164. {
  165. //判断是否使用新版V3接口
  166. $income_set = \Setting::get('shop.pay');
  167. if ($type == 1 && $income_set['weixin_apiv3']) {//使用新版V3接口并且是打款到钱包
  168. return $this->doWithdrawV3($member_id, $out_trade_no, $money, $desc, $type,$withdraw_type);
  169. }
  170. //$out_trade_no = $this->setUniacidNo(\YunShop::app()->uniacid);
  171. $op = '微信钱包提现 订单号:' . $out_trade_no . '提现金额:' . $money;
  172. $pay_order_model = $this->withdrawlog(Pay::PAY_TYPE_WITHDRAW, $this->pay_type[Pay::PAY_MODE_WECHAT], $money, $op, $out_trade_no, Pay::ORDER_STATUS_NON, $member_id);
  173. $pay = $this->payParams($type);
  174. if (empty($pay['weixin_mchid']) || empty($pay['weixin_apisecret'])) {
  175. throw new AppException('没有设定支付参数');
  176. }
  177. if (empty($pay['weixin_cert']) || empty($pay['weixin_key'])) {
  178. throw new AppException('\'未上传完整的微信支付证书,请到【系统设置】->【支付方式】中上传!\'');
  179. }
  180. if (\YunShop::request()->type) {
  181. $client_type = \YunShop::request()->type;
  182. } else {
  183. $client_type = $type;
  184. }
  185. $openid = Member::getOpenIdForType($member_id, $client_type);
  186. if (empty($openid)) {
  187. throw new AppException('提现用户不存在');
  188. }
  189. // $mc_mapping_fans_model = McMappingFans::getFansById($member_id);
  190. //
  191. // if ($mc_mapping_fans_model) {
  192. // $openid = $mc_mapping_fans_model->openid;
  193. // } else {
  194. // throw new AppException('提现用户不存在');
  195. // }
  196. $notify_url = '';
  197. $app = $this->getEasyWeChatApp($pay, $notify_url);
  198. if ($type == 1) {//钱包
  199. $merchantPay = $app->transfer;
  200. $merchantPayData = [
  201. 'partner_trade_no' => empty($out_trade_no) ? time() . Client::random(4, true) : $out_trade_no,
  202. 'openid' => $openid,
  203. 'check_name' => 'NO_CHECK',
  204. 'amount' => $money * 100,
  205. 'desc' => empty($desc) ? '佣金提现' : $desc,
  206. 'spbill_create_ip' => self::getClientIP(),
  207. ];
  208. //请求数据日志
  209. $this->payRequestDataLog($pay_order_model->id, $pay_order_model->type,
  210. $pay_order_model->type, json_encode($merchantPayData));
  211. $pay_result = $merchantPay->toBalance($merchantPayData);
  212. if (isset($pay_result['partner_trade_no'])) {
  213. $result = $merchantPay->queryBalanceOrder($pay_result['partner_trade_no']);
  214. if ($result['result_code'] == 'FAIL') {
  215. $result = $pay_result;
  216. }
  217. } else {
  218. $result = $pay_result;
  219. }
  220. } else {//红包
  221. $luckyMoney = $app->redpack;
  222. $luckyMoneyData = [
  223. 'mch_billno' => $pay['weixin_mchid'] . date('YmdHis') . rand(1000, 9999),
  224. 'send_name' => \YunShop::app()->account['name'],
  225. 're_openid' => $openid,
  226. 'total_num' => 1,
  227. 'total_amount' => $money * 100,
  228. 'wishing' => empty($desc) ? '佣金提现红包' : $desc,
  229. 'client_ip' => self::getClientIP(),
  230. 'act_name' => empty($act_name) ? '佣金提现红包' : $act_name,
  231. 'remark' => empty($remark) ? '佣金提现红包' : $remark,
  232. ];
  233. //请求数据日志
  234. $this->payRequestDataLog($pay_order_model->id, $pay_order_model->type,
  235. $pay_order_model->type, json_encode($luckyMoneyData));
  236. $pay_result = $luckyMoney->sendNormal($luckyMoneyData);
  237. if (isset($pay_result['mch_billno'])) {
  238. $result = $luckyMoney->info($pay_result['mch_billno']);
  239. if ($result['result_code'] == 'FAIL') {
  240. $result = $pay_result;
  241. }
  242. } else {
  243. $result = $pay_result;
  244. }
  245. }
  246. //响应数据
  247. $this->payResponseDataLog($pay_order_model->out_order_no, $pay_order_model->type, json_encode($result));
  248. \Log::debug('---提现状态---', [$result['status']]);
  249. if (isset($result['status']) && ($result['status'] == 'PROCESSING' || $result['status'] == 'SUCCESS' || $result['status'] == 'SENDING' || $result['status'] == 'SENT')){
  250. \Log::debug('提现返回结果', $result);
  251. $this->changeOrderStatus($pay_order_model, Pay::ORDER_STATUS_COMPLETE, $result['payment_no']);
  252. $this->payResponseDataLog($out_trade_no, '微信提现', json_encode($result));
  253. // Withdraw::paySuccess($result['partner_trade_no']);todo 打款成功之后也会执行,为啥要在这里执行一次?导致重复事件
  254. return ['errno' => 0, 'message' => '微信提现成功'];
  255. } else {
  256. \Log::debug('---微信提现返回接口错误---', $result);
  257. return ['errno' => 1, 'message' => '微信接口错误:' . $result['return_msg'] . '-' . $result['err_code_des']];
  258. }
  259. }
  260. public function doWithdrawV3($member_id, $out_trade_no, $money, $desc='', $type=1,$withdraw_type = 0)
  261. {
  262. try {
  263. $pay = $this->payParams($type);
  264. if (empty($pay['weixin_mchid']) || empty($pay['weixin_apisecret'])) {
  265. // throw new AppException('没有设定支付参数');
  266. }
  267. if (empty($pay['weixin_cert']) || empty($pay['weixin_key'])) {
  268. throw new AppException('\'未上传完整的微信支付证书,请到【系统设置】->【支付方式】中上传!\'');
  269. }
  270. if (empty($pay['weixin_apiv3_secret'])) {
  271. throw new AppException('\'未设置ApiV3密钥!\'');
  272. }
  273. $op = '微信钱包提现 订单号:' . $out_trade_no . '提现金额:' . $money;
  274. $pay_order_model = $this->withdrawlog(Pay::PAY_TYPE_WITHDRAW, $this->pay_type[Pay::PAY_MODE_WECHAT], $money, $op, $out_trade_no, Pay::ORDER_STATUS_NON, $member_id);
  275. $client_type = \YunShop::request()->type ? : $type;
  276. $openid = Member::getOpenIdForType($member_id, $client_type);
  277. if (empty($openid)) {
  278. throw new AppException('提现用户不存在');
  279. }
  280. $notify_url = '';
  281. $app = $this->getEasyWeChatApp($pay, $notify_url);
  282. if (WechatWithdrawLog::uniacid()->search(['withdraw_sn' => $out_trade_no,'type' => $withdraw_type,
  283. 'many_status'=>[1,2]])->count()
  284. ) {
  285. // throw new \Exception('提现正在进行中或已完成');
  286. return ['errno' => 0, 'message' => '提现正在进行中'];
  287. }
  288. //取最后一条发送了请求的数据 todo 判断是否原参数请求
  289. $oldLog = WechatWithdrawLog::uniacid()
  290. ->search(['withdraw_sn' => $out_trade_no])
  291. ->where('status','!=',0)
  292. ->orderBy('id','desc')
  293. ->first();
  294. if ($oldLog && in_array($oldLog->fail_code,['NOT_ENOUGH','FREQUENCY_LIMITED','SYSTEM_ERROR'])) {
  295. $logFill = [
  296. 'uniacid' => $oldLog->uniacid,
  297. 'withdraw_sn' => $oldLog->withdraw_sn,
  298. 'out_batch_no' => $oldLog->out_batch_no,
  299. 'out_detail_no' => $oldLog->out_detail_no,
  300. ];
  301. } else {
  302. $logFill = [
  303. 'uniacid' => \YunShop::app()->uniacid,
  304. 'withdraw_sn' => $out_trade_no,
  305. 'out_batch_no' => WechatWithdrawLog::createOrderSn('WW','out_batch_no'),
  306. 'out_detail_no' => $out_trade_no,
  307. ];
  308. }
  309. $logFill['type'] = $withdraw_type;
  310. $logFill['pay_type'] = 1;
  311. $wechatWithdrawLog = WechatWithdrawLog::saveLog($logFill);
  312. $params = [
  313. 'appid' => $pay['weixin_appid'],
  314. 'out_batch_no' => $wechatWithdrawLog->out_batch_no,
  315. 'batch_name' => empty($desc) ? '佣金提现' : $desc,
  316. 'batch_remark' => empty($desc) ? '佣金提现' : $desc,
  317. 'total_amount' => intval(bcmul($money,100)),
  318. 'total_num' => 1,
  319. 'transfer_detail_list' => [
  320. [
  321. 'out_detail_no' => $wechatWithdrawLog->out_detail_no,
  322. 'transfer_amount' => intval(bcmul($money,100)),
  323. 'transfer_remark' => empty($desc) ? '佣金提现' : $desc,
  324. 'openid' => $openid,
  325. ]
  326. ]
  327. ];
  328. if ($money > 2000) {
  329. $member = Member::find($member_id);
  330. $username = $member->realname;
  331. if (!$username) {
  332. throw new \Exception('提现大于2000元,会员需在会员信息里设置真实姓名,否则微信不予打款!');
  333. }
  334. $params['transfer_detail_list'][0]['user_name'] = $username;
  335. }
  336. $res = $app->transfer_v3->batches($params);
  337. \Log::debug('提现返回结果v3', $res);
  338. $this->payResponseDataLog($pay_order_model->out_order_no, $pay_order_model->type, json_encode($res));
  339. $wechatWithdrawLog->http_code = $res['http_code'];
  340. if ($res['code'] == 0) {//失败了
  341. $wechatWithdrawLog->fail_code = $res['data']['code'] ? : '';//错误码
  342. $wechatWithdrawLog->fail_msg = $res['message'] ? : '';
  343. $wechatWithdrawLog->status = -2;
  344. $wechatWithdrawLog->save();
  345. throw new \Exception($wechatWithdrawLog->fail_msg?:'打款失败');
  346. // return ['errno' => 1, 'message' => '微信接口错误:' . $wechatWithdrawLog->fail_code . '-' . $wechatWithdrawLog->fail_msg];
  347. }
  348. $wechatWithdrawLog->status = 1;
  349. $wechatWithdrawLog->batch_id = $res['data']['batch_id'];
  350. $wechatWithdrawLog->save();
  351. //响应数据
  352. $this->payResponseDataLog($out_trade_no, '微信提现', json_encode($res));
  353. $this->changeOrderStatus($pay_order_model, Pay::ORDER_STATUS_COMPLETE, $res['data']['out_batch_no']);
  354. return ['errno' => 0, 'message' => '微信提现成功'];
  355. } catch (\Exception $e) {//抛出异常会返回代打款状态
  356. \Log::debug('微信支付-商家转账到零钱错误:'.$e->getMessage(),[$member_id, $out_trade_no, $money, $desc, $type,$withdraw_type]);
  357. throw new ShopException($e->getMessage());
  358. }
  359. }
  360. public function doReward($member_id, $out_trade_no, $money, $desc='', $type=1)
  361. {
  362. $op = '微信钱包奖励打款 订单号:' . $out_trade_no . '奖励金额:' . $money;
  363. //访问日志
  364. self::payAccessLog();
  365. //支付日志
  366. self::payLog(Pay::PAY_TYPE_WITHDRAW, $this->pay_type[Pay::PAY_MODE_WECHAT], $money, $op, $member_id);
  367. $pay = $this->payParams($type);
  368. if (empty($pay['weixin_mchid']) || empty($pay['weixin_apisecret'])) {
  369. throw new AppException('没有设定支付参数');
  370. }
  371. if (empty($pay['weixin_cert']) || empty($pay['weixin_key'])) {
  372. throw new AppException('\'未上传完整的微信支付证书,请到【系统设置】->【支付方式】中上传!\'');
  373. }
  374. if (\YunShop::request()->type) {
  375. $client_type = \YunShop::request()->type;
  376. } else {
  377. $client_type = $type;
  378. }
  379. $openid = Member::getOpenIdForType($member_id, $client_type);
  380. if (empty($openid)) {
  381. throw new AppException('奖励用户不存在');
  382. }
  383. $notify_url = '';
  384. $app = $this->getEasyWeChatApp($pay, $notify_url);
  385. if ($type == 1) {//钱包
  386. $merchantPay = $app->transfer;
  387. $merchantPayData = [
  388. 'partner_trade_no' => empty($out_trade_no) ? time() . Client::random(4, true) : $out_trade_no,
  389. 'openid' => $openid,
  390. 'check_name' => 'NO_CHECK',
  391. 'amount' => $money * 100,
  392. 'desc' => empty($desc) ? '用户奖励' : $desc,
  393. 'spbill_create_ip' => self::getClientIP(),
  394. ];
  395. //请求数据日志
  396. $this->payRequestDataLog($out_trade_no, $this->pay_type[Pay::PAY_MODE_WECHAT], $this->pay_type[Pay::PAY_MODE_WECHAT], json_encode($merchantPayData));
  397. $pay_result = $merchantPay->toBalance($merchantPayData);
  398. if (isset($pay_result['partner_trade_no'])) {
  399. $result = $merchantPay->queryBalanceOrder($pay_result['partner_trade_no']);
  400. if ($result['result_code'] == 'FAIL') {
  401. $result = $pay_result;
  402. }
  403. } else {
  404. $result = $pay_result;
  405. }
  406. } else {//红包
  407. $luckyMoney = $app->redpack;
  408. $luckyMoneyData = [
  409. 'mch_billno' => $pay['weixin_mchid'] . date('YmdHis') . rand(1000, 9999),
  410. 'send_name' => \YunShop::app()->account['name'],
  411. 're_openid' => $openid,
  412. 'total_num' => 1,
  413. 'total_amount' => $money * 100,
  414. 'wishing' => empty($desc) ? '用户奖励红包' : $desc,
  415. 'client_ip' => self::getClientIP(),
  416. 'act_name' => empty($act_name) ? '用户奖励红包' : $act_name,
  417. 'remark' => empty($remark) ? '用户奖励红包' : $remark,
  418. ];
  419. //请求数据日志
  420. $this->payRequestDataLog($out_trade_no, $this->pay_type[Pay::PAY_MODE_WECHAT], $this->pay_type[Pay::PAY_MODE_WECHAT], json_encode($luckyMoneyData));
  421. $pay_result = $luckyMoney->sendNormal($luckyMoneyData);
  422. if (isset($pay_result['mch_billno'])) {
  423. $result = $luckyMoney->info($pay_result['mch_billno']);
  424. if ($result['result_code'] == 'FAIL') {
  425. $result = $pay_result;
  426. }
  427. } else {
  428. $result = $pay_result;
  429. }
  430. }
  431. //响应数据
  432. $this->payResponseDataLog($out_trade_no, $this->pay_type[Pay::PAY_MODE_WECHAT], json_encode($result));
  433. \Log::debug('---奖励状态---', [$result['status']]);
  434. if (isset($result['status']) && ($result['status'] == 'PROCESSING' || $result['status'] == 'SUCCESS' || $result['status'] == 'SENDING' || $result['status'] == 'SENT')){
  435. \Log::debug('奖励返回结果', $result);
  436. $this->payResponseDataLog($out_trade_no, $desc, json_encode($result));
  437. return ['errno' => 0, 'message' => '奖励成功'];
  438. } else {
  439. \Log::debug('---奖励返回接口错误---', $result);
  440. return ['errno' => 1, 'message' => '微信接口错误:' . $result['return_msg'] . '-' . $result['err_code_des']];
  441. }
  442. }
  443. /**
  444. * 构造签名
  445. *
  446. * @var void
  447. */
  448. public function buildRequestSign()
  449. {
  450. // TODO: Implement buildRequestSign() method.
  451. }
  452. /**
  453. * 创建支付对象
  454. *
  455. * @param $pay
  456. * @return \EasyWeChat\Payment\Payment
  457. */
  458. public function getEasyWeChatApp($pay, $notify_url)
  459. {
  460. $options = [
  461. 'app_id' => $pay['weixin_appid'],
  462. 'secret' => $pay['weixin_secret'],
  463. 'mch_id' => $pay['weixin_mchid'],
  464. 'key' => $pay['weixin_apisecret'],
  465. 'cert_path' => $pay['weixin_cert'],
  466. 'key_path' => $pay['weixin_key'],
  467. 'key_v3' => $pay['weixin_apiv3_secret'] ? : '',
  468. 'notify_url' => $notify_url
  469. ];
  470. $app = EasyWeChat::payment($options);
  471. return $app;
  472. }
  473. /**
  474. * 创建预下单
  475. *
  476. * @param $data
  477. * @param $openid
  478. * @param $pay_order_model
  479. * @return easyOrder
  480. */
  481. public static function getEasyWeChatOrder($data, $openid, &$pay_order_model,$payType='')
  482. {
  483. $attributes = [
  484. 'trade_type' => $data['trade_type'], // JSAPI,NATIVE,APP...
  485. 'body' => mb_substr($data['subject'], 0, 40),
  486. 'out_trade_no' => $data['order_no'],
  487. 'total_fee' => $data['amount'] * 100, // 单位:分
  488. 'nonce_str' => Client::random(8) . "",
  489. 'device_info' => 'yun_shop',
  490. 'attach' => \YunShop::app()->uniacid . ':' . self::$attach_type,
  491. 'spbill_create_ip' => self::getClientIP(),
  492. 'openid' => $openid
  493. ];
  494. if ($payType){
  495. $attributes['attach'] .= ':'.$payType;
  496. }
  497. //请求数据日志
  498. self::payRequestDataLog($attributes['out_trade_no'], $pay_order_model->type,
  499. $pay_order_model->third_type, json_encode($attributes));
  500. return $attributes;
  501. }
  502. private function changeOrderStatus($model, $status, $trade_no)
  503. {
  504. $model->status = $status;
  505. $model->trade_no = $trade_no;
  506. $model->save();
  507. }
  508. /**
  509. * 支付参数
  510. * @return array|mixed
  511. */
  512. private function payParams($payType = 1)
  513. {
  514. $pay = \Setting::get('shop.pay');
  515. if ($payType == 9){
  516. $pay = \Setting::get('shop_app.pay');
  517. } else{
  518. if (!is_null($event_arr = \app\common\modules\shop\ShopConfig::current()->get('special_wechat_app_pay_config'))) {
  519. foreach ($event_arr as $event){
  520. $class = array_get($event, 'class');
  521. $function = array_get($event, 'function');
  522. $res = $class::$function(['payType'=>$payType]);
  523. if ($res['result']){
  524. $pay = $res['data']['setting'];
  525. }
  526. }
  527. }
  528. }
  529. return $pay;
  530. }
  531. /**
  532. * 订单退款查询
  533. *
  534. * @param $payment
  535. * @param $out_trade_no
  536. * @return mixed
  537. */
  538. public function queryRefund($payment, $out_trade_no)
  539. {
  540. $result = $payment->refund->queryByOutTradeNumber($out_trade_no);
  541. foreach ($result as $key => $value) {
  542. if (preg_match('/refund_status_\d+/', $key)) {
  543. return $value;
  544. }
  545. }
  546. return 'fail';
  547. }
  548. }