123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- <?php
- namespace App\Http\Controllers\Api;
- use App\Jobs\Shop\ShopOrderDeliverInfoManage;
- use App\Jobs\System\CheckBatchCahceDataLossJob;
- use App\Lib\ApplePay\ApplePay;
- use App\Lib\WeApp\WeApp;
- use App\Models\Shop\WxShopGoods;
- use App\Models\Shop\WxShopGoodsProduct;
- use App\Models\Shop\WxShopOrderGoods;
- use App\Models\Used\WxUsedGood;
- use App\Models\WxRefund;
- use App\Wen\Utils\FieldUtils;
- use App\Wen\Utils\OrderUtils;
- use App\Wen\Utils\Settings;
- use App\Wen\Utils\ShopUtils;
- use App\Wen\Utils\UserUtils;
- use App\Wen\Utils\Utils;
- use App\Lib\Pay\EPay;
- use App\Models\Shop\WxShopOrder;
- use App\Models\WxOrder;
- use Carbon\Carbon;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\DB;
- use Yansongda\Pay\Pay;
- class NotifyController extends BaseController
- {
- /**
- * @param $event_type 退款状态 REFUND.SUCCESS 退款成功通知 REFUND.ABNORMAL 退款异常通知 REFUND.CLOSED 退款关闭通知
- * @param $out_refund_no 自己的退款单号
- * @param $transaction_id 退款的流水号
- * @param $refund_time 推荐完成时间
- * @param $refund_amount 退款金额
- * @param $refund_account 退款账号说明
- * @param $refund_from 0:微信 1:支付宝
- */
- private function _refund($event_type, $out_refund_no, $transaction_id, $refund_time, $refund_amount, $refund_account, $refund_from){
- $order_good = WxShopOrderGoods::where('refund_no', $out_refund_no)->first();
- if($order_good){
- if($order_good->state == 3){
- // 已退款
- return true;
- }
- if($order_good->recharge > 0){
- DB::beginTransaction();
- try {
- // todo:
- $shop_order = WxShopOrder::where('id', $order_good->order_id)->first();
- $updated_at = Carbon::now();
- $nr = '您购买的:「' . $order_good->name . '(规格:' . $order_good->product . ')」×' . $order_good->quantity . '件的退款申请已处理完毕';
- // 退款记录
- $refund_record = new WxRefund();
- $refund_record->user_id = $order_good->buyer_user_id;
- $refund_record->order_good_id = $order_good->id;
- $refund_record->order_id = $order_good->order_id;
- $refund_record->goods_id = $order_good->goods_id;
- $refund_record->product_id = $order_good->product_id;
- $refund_record->amount = $order_good->recharge;
- $refund_record->goods_type = $order_good->goods_type;
- $refund_record->save();
- if($event_type == 'REFUND.SUCCESS'){
- WxShopOrderGoods::where('id', $order_good->id)->update([
- 'refund_no' => $out_refund_no,
- 'state' => 3,
- 'refund_from' => $refund_from,
- 'refund_amount' => $refund_amount,
- 'refund_time' => $refund_time,
- 'refund_account' => $refund_account
- ]);
- }else if($event_type == 'REFUND.ABNORMAL' || $event_type == 'REFUND.CLOSED'){
- WxShopOrderGoods::where('id', $order_good->id)->update([
- 'state' => 3,
- 'updated_at' => $updated_at
- ]);
- $financial_type = 3;
- if($order_good->goods_type == 7){
- $financial_type = 29;
- }
- if($shop_order->serial_number){
- UserUtils::update_user_financial($order_good->buyer_user_id,$financial_type, $order_good->recharge,
- '您收到了一笔来自「' . $order_good->name . '(规格:' . $order_good->product . ')」×' . $order_good->quantity . '件的退款,退款金额¥' . $order_good->recharge
- );
- }
- }else{
- return false;
- }
- UserUtils::add_user_notice(6002, $order_good->buyer_user_id, '商品退款通知', $nr, 100);
- $result_ = DB::table('wx_shop_order_goods as wg')
- ->select(DB::raw('COUNT(*) as total_count, SUM(CASE WHEN state = 3 THEN 1 ELSE 0 END) as state_3_count'))
- ->where('wg.order_id', $order_good->id)
- ->first();
- if ($result_->total_count == $result_->state_3_count) {
- WxShopOrder::where('id', $order_good->order_id)->update([
- 'pay_status' => 3,
- 'status' => 4,
- 'updated_at' => $updated_at
- ]);
- }
- if(in_array($order_good->goods_type, FieldUtils::getShopGoodTypes())){
- WxShopGoods::where('id', $order_good->goods_id)->decrement('buys', (int)($order_good->quantity));
- WxShopGoodsProduct::where('id', $order_good->product_id)->increment('stock', (int)($order_good->quantity));
- }else{
- if($order_good->goods_type == 6){
- WxUsedGood::where('id', $order_good->goods_id)->update([
- 'status' => 6
- ]);
- }
- }
- DB::commit();
- return true;
- } catch (\Exception $e) {
- DB::rollBack();
- _logger_(__file__, __line__, $e->getMessage());
- return false;
- }
- }
- }
- }
- /**
- * 所有支付的 处理支付通知 函数
- * @param $out_trade_no
- * @param $transaction_id
- * @param $payment_time
- * @param $payed
- * @param $which_pay 0:微信 1:支付宝 2:易支付 3:苹果
- */
- private function _notify($out_trade_no, $transaction_id, $payment_time, $payed, $which_pay = 0){
- try {
- // 判断订单是 来自商品 还是 来自充电或者开通会员。
- $WxOrder = WxOrder::where('order_number', $out_trade_no)->first();
- if ($WxOrder) {
- // 处理重复通知
- if(in_array($WxOrder->order_state, [1, 3, 4, 5, 6])){
- return true;
- }
- // 先检查是否需要微信发货管理
- $is_need_deliver_info_manage = false;
- if($WxOrder->order_serial_platform === 0 && $WxOrder->order_serial_platform_type == 'mini'){
- if(Settings::get('need_mini_deliver_info_manage', 0) == 1){
- $is_need_deliver_info_manage = true;
- }
- }
- if($is_need_deliver_info_manage){
- if($which_pay != $WxOrder->order_serial_platform){
- _logger_(__file__, __line__, '理论上不应出现这种情况,order_id:'.$WxOrder->id);
- }
- WxOrder::where('order_number', $out_trade_no)->update(['order_state' => 3, 'order_serial_number' => $transaction_id]);
- $WxOrder->order_serial_number = $transaction_id;
- // 尝试通知
- $weapp = new WeApp('mini');
- $manage = $weapp->getDeliverInfoManage();
- $manage->virtualDeliverOrder($WxOrder);
- }else{
- WxOrder::where('order_number', $out_trade_no)->update(['order_state' => 1, 'order_serial_number' => $transaction_id, 'order_serial_platform'=>$which_pay]);
- OrderUtils::order_obtains($WxOrder, $which_pay);
- }
- } else {
- // 处理重复通知
- if(WxShopOrder::where('order_id', $out_trade_no)->whereIn('pay_status', [2])->exists()){
- return true;
- }
- $WxShopOrder = WxShopOrder::where('order_id', $out_trade_no)->first();
- if($WxShopOrder){
- //SHOP
- $discounts_amount = $WxShopOrder->discounts_amount;
- $pay_way = ShopUtils::generate_payway_text($discounts_amount,0, $which_pay === 0 ? $payed : 0,
- $which_pay === 1 ? $payed : 0, 0, $WxShopOrder->coins_num, $which_pay === 3 ? $payed : 0,
- $which_pay === 2 ? $payed : 0);
- WxShopOrder::where('id', $WxShopOrder->id)
- ->update(['pay_status' => 2, 'status' => 1, 'serial_number' => $transaction_id, 'serial_platform'=>$which_pay, 'payment_time' => $payment_time, 'payed' => $payed, 'pay_way'=>$pay_way]);
- $this->usedGoodPaied($WxShopOrder->id);
- $is_need_deliver_info_manage = false;
- if($WxShopOrder->serial_platform === 0 && $WxShopOrder->serial_platform_type == 'mini'){
- if(Settings::get('need_mini_deliver_info_manage', 0) == 1){
- if(WxShopOrderGoods::where('order_id', $WxShopOrder->id)->whereIn('goods_type', [2,3,4])->where('state', 0)->exists()){
- $is_need_deliver_info_manage = true;
- }
- }
- }
- if(!$is_need_deliver_info_manage){
- ShopUtils::paied_content_process($WxShopOrder->id);
- }
- ShopUtils::split_shop_order_by_seller($WxShopOrder->id);
- ShopUtils::split_shop_order_by_type($WxShopOrder->id);
- ShopUtils::order_buys_and_stock($WxShopOrder->id);
- if($is_need_deliver_info_manage){
- WxShopOrder::withTrashed()->where('id', $WxShopOrder->id)->orWhere('parent_order_id', $WxShopOrder->id)->update([
- 'status' => 9
- ]);
- ShopOrderDeliverInfoManage::dispatch('virtual-upload', $WxShopOrder->id, null);
- }
- UserUtils::assistant_notice('admin', '您的商城有新的订单。');
- }else{
- return false;
- }
- }
- return true;
- } catch (\Exception $e) {
- _logger_(__file__, __line__, $e->getMessage());
- return false;
- }
- }
- public function usedGoodPaied($order_id){
- $goods_ids = [];
- WxShopOrderGoods::where('order_id', $order_id)->where('goods_type', 6)->get(['goods_id'])->map(function ($v) use (&$goods_ids){
- $goods_ids[] = $v->goods_id;
- return $v;
- });
- if($goods_ids){
- foreach ($goods_ids as $used_id){
- WxUsedGood::where('id', $used_id)->update([
- 'status' => 5
- ]);
- }
- }
- }
- /**
- * 微信app支付通知
- */
- public function wechat_app(){
- $config = json_decode(Cache::get('app_pay_config'), true);
- if(_empty_($config)){
- CheckBatchCahceDataLossJob::dispatch();
- }
- Pay::config($config);
- $result = Pay::wechat()->callback();
- if($result){
- if($result->event_type == 'TRANSACTION.SUCCESS'){
- $out_trade_no = $result->resource['ciphertext']['out_trade_no'];
- $transaction_id = $result->resource['ciphertext']['transaction_id'];
- $payment_time = Utils::strTimeFormat($result->resource['ciphertext']['success_time']);//支付回调支付时间
- $total_fee = $result->resource['ciphertext']['amount']['total'];
- $payed = $total_fee / 100;
- if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 0)){
- return Pay::wechat()->success();
- }
- }else if($result->event_type == 'REFUND.SUCCESS' || $result->event_type == 'REFUND.ABNORMAL' || $result->event_type == 'REFUND.CLOSED'){
- $event_type = $result->event_type;
- $out_refund_no = $result->resource['ciphertext']['out_refund_no'];
- $transaction_id = $result->resource['ciphertext']['transaction_id'];
- $refund_time = Utils::strTimeFormat($result->resource['ciphertext']['success_time']);//支付回调支付时间
- $user_received_account = $result->resource['ciphertext']['user_received_account'];
- $refund_fee = $result->resource['ciphertext']['amount']['refund'];
- $refund = $refund_fee / 100;
- if($this->_refund($event_type, $out_refund_no, $transaction_id, $refund_time, $refund, $user_received_account, 0)){
- return Pay::wechat()->success();
- }
- }
- }
- }
- /**
- * 苹果支付 通知url
- * @param Request $request
- * @return \Illuminate\Http\JsonResponse
- */
- public function apple_app(Request $request){
- $orderId = $request->orderId;
- $productId = $request->productid;
- $user_id = $request->username;
- $transaction = $request->transaction;
- $restore = (int)($request->restore ?? 0);
- _logger_(__file__, __line__, $transaction);
- if($restore == 1){
- if(_empty_($transaction)){
- return $this->fail(200001);
- }
- }else{
- if(_empty_($orderId) || _empty_($productId) || _empty_($user_id) || _empty_($transaction)){
- return $this->fail(200001);
- }
- }
- if( _empty_(_array_key($transaction, 'transactionDate', '')) ||
- _empty_(_array_key($transaction, 'transactionIdentifier', '')) ||
- _empty_(_array_key($transaction, 'transactionState', '')) ||
- _empty_(_array_key($transaction, 'transactionReceipt', ''))
- ){
- return $this->fail(200001);
- }
- if($restore === 0){
- Cache::put('transactionIdentifier:'._array_key($transaction, 'transactionIdentifier', ''), json_encode(['orderId'=>$orderId, 'user_id'=>$user_id, 'productid'=>$productId]), 3600 * 24);
- }else{
- if(Cache::has('transactionIdentifier:'._array_key($transaction, 'transactionIdentifier', ''))){
- $cache_data = Cache::get('transactionIdentifier:'._array_key($transaction, 'transactionIdentifier', '') );
- if($cache_data){
- $cache_data = json_decode($cache_data, true);
- $orderId = $cache_data['orderId'];
- $productId = $cache_data['productid'];
- $user_id = $cache_data['user_id'];
- }
- }
- if(_empty_($orderId) || _empty_($productId)){
- return $this->fail(200001);
- }
- }
- $is_shop_order = false;
- $order = null;
- $notify_data = [
- ];
- if(strpos($productId, 'apple_pay_product_recharge') === 0){
- $productid_num = (int)(str_replace('apple_pay_product_recharge_', '', $productId));
- $order = WxOrder::find($orderId);
- $notify_data['type'] = 3;
- $notify_data['num'] = $productid_num;
- }else if(strpos($productId, 'apple_pay_product_vip') === 0){
- $product_price = (int)(str_replace('apple_pay_product_vip_', '', $productId));
- $order = WxOrder::find($orderId);
- $notify_data['type'] = 1;
- $notify_data['price'] = $product_price;
- }
- if(_empty_($order)){
- return $this->fail(200004, [], '没有与此orderId对应的订单');
- }
- // 已经处理过的订单
- if($is_shop_order){
- if($order->pay_status != 1){
- return $this->fail(200010, [], '该订单已经通知过');
- }
- }else{
- if($order->order_state != 0){
- return $this->fail(200010, [], '该订单已经通知过');
- }
- }
- $is_sand_box = false;
- $applePay = new ApplePay(_array_key($transaction, 'transactionReceipt', ''), Settings::get('apple_pay_password', ''));
- if ($applePay->verifyReceipt($is_sand_box)) {
- $result = $applePay->query($productId, function ($tradeNo, $returnData) use ($order, $is_shop_order, $notify_data) {
- // _logger_(__file__, __line__, $returnData);
- if($is_shop_order){
- }else{
- if($notify_data['type'] == 1){
- return $this->_notify($order->order_number, $tradeNo, current_time(), 0, 3);
- }else if($notify_data['type'] == 3){
- return $this->_notify($order->order_number, $tradeNo, current_time(), 0, 3);
- }
- }
- });
- if ($result) {
- return $this->success();
- } else {
- return $this->fail(200004, [], $applePay->getError());
- }
- } else {
- return $this->fail(200004, [], $applePay->getError());
- }
- }
- public function alipay_app(){
- $config = json_decode(Cache::get('app_pay_config'), true);
- if(_empty_($config)){
- CheckBatchCahceDataLossJob::dispatch();
- }
- Pay::config($config);
- $result = Pay::alipay()->callback();
- // 否则当支付处理
- if($result->alipay_trade_app_pay_response){
- $result = $result->alipay_trade_app_pay_response;
- }
- if($result->trade_status == 'TRADE_SUCCESS' || $result->code == 10000){
- $out_trade_no = $result->out_trade_no;
- $transaction_id = $result->trade_no;
- $payment_time = $result->timestamp;//支付回调支付时间
- $payed = $result->total_amount;
- if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 1)){
- return Pay::alipay()->success();
- }
- }
- }
- public function alipay_wap(){
- $config = json_decode(Cache::get('app_pay_config'), true);
- if(_empty_($config)){
- CheckBatchCahceDataLossJob::dispatch();
- }
- Pay::config($config);
- $result = Pay::alipay()->callback();
- _logger_(__file__, __line__, $result);
- if($result->alipay_trade_wap_pay_response){
- $result = $result->alipay_trade_wap_pay_response;
- }
- if($result->trade_status == 'TRADE_SUCCESS' || $result->code == 10000){
- $out_trade_no = $result->out_trade_no;
- $transaction_id = $result->trade_no;
- $payment_time = $result->timestamp;//支付回调支付时间
- $payed = $result->total_amount;
- if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 1)){
- return Pay::alipay()->success();
- }
- }
- }
- public function yi_app(Request $request){
- if(_empty_($request->out_trade_no) || _empty_($request->sign)){
- return '';
- }
- $epay_config = json_decode(Cache::get('yi_pay_config'), true);
- if(_empty_($epay_config)){
- CheckBatchCahceDataLossJob::dispatch();
- }
- $epay = new EPay();
- $epay->key($epay_config['app_secret']);
- //签名验证
- $data = $request->input();
- if(!$epay->signVerify($data)){
- exit();
- }
- // 交易状态## 交易成功
- if($data['trade_status']=='TRADE_SUCCESS'){
- $out_trade_no=$data['out_trade_no'];//网站自己生成的订单号
- $transaction_id=$data['trade_no'];//第三方平台产生的订单号
- $total_fee=$data['money'];//金额
- $payment_time = date('Y-m-d H:i:s', time());
- $payed=(float)$total_fee;
- if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 2)){
- echo "success";
- }
- }
- return '';
- }
- /** 微信支付v2版本通知url
- * @return string
- */
- public function index()
- {
- $xml = file_get_contents('php://input');
- libxml_disable_entity_loader(true);
- $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
- $valArr = json_decode(json_encode($xmlstring), true);
- $out_trade_no = $valArr['out_trade_no'];//支付回调订单号
- $transaction_id = $valArr['transaction_id'];//支付回调支付号
- $time_end = $valArr['time_end'];//支付回调支付时间
- $payment_time = date('Y-m-d H:i:s', strtotime($time_end));
- $total_fee = $valArr['total_fee'];//支付回调支付金额
- $payed = $total_fee / 100;
- if (_empty_($out_trade_no)) {
- die('错误');
- }
- _logger_(__file__, __line__, $out_trade_no.'开始处理微信小程序支付通知');
- if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 0)){
- return $this->successXml();
- }
- }
- private function successXml()
- {
- $arr = ['return_code' => 'SUCCESS', 'return_msg' => 'OK'];
- $xml = "<xml>";
- foreach ($arr as $key => $val) {
- if (is_array($val)) {
- $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
- } else {
- $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
- }
- }
- $xml .= "</xml>";
- return $xml;
- }
- }
|