|
@@ -0,0 +1,387 @@
|
|
|
|
+<?php
|
|
|
|
+
|
|
|
|
+namespace App\Http\Controllers\Api\V1;
|
|
|
|
+
|
|
|
|
+use App\Http\HelperTraits\LogHelper;
|
|
|
|
+use App\Http\HelperTraits\PayHelper;
|
|
|
|
+use App\Http\HelperTraits\JpushHelper;
|
|
|
|
+use Omnipay\Omnipay;
|
|
|
|
+use App\User;
|
|
|
|
+use App\Models\MerchantMemberService;
|
|
|
|
+use App\Models\Order;
|
|
|
|
+use App\Models\AccountLog;
|
|
|
|
+use Request, Config, DB;
|
|
|
|
+
|
|
|
|
+class PayController extends Controller
|
|
|
|
+{
|
|
|
|
+ use PayHelper, LogHelper,JpushHelper;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * p++ webhooks通知
|
|
|
|
+ */
|
|
|
|
+// public function pppNotify() {
|
|
|
|
+// $sig = Request::header('x-pingplusplus-signature');
|
|
|
|
+// $request = Request::instance();
|
|
|
|
+// $data = $request->getContent();
|
|
|
|
+//
|
|
|
|
+// if (!$this->checkPppSignature($data, $sig)) {//验签失败
|
|
|
|
+// header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
|
|
|
|
+// exit("fail");
|
|
|
|
+// }
|
|
|
|
+//
|
|
|
|
+// $event = json_decode($data);
|
|
|
|
+// if (!isset($event->type)) {
|
|
|
|
+//// return Response::make('fail', 400);
|
|
|
|
+// header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
|
|
|
|
+// exit("fail");
|
|
|
|
+// }
|
|
|
|
+// switch ($event->type) {
|
|
|
|
+// case "charge.succeeded":
|
|
|
|
+// // 开发者在此处加入对支付异步通知的处理代码
|
|
|
|
+// header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
|
|
|
|
+// break;
|
|
|
|
+// case "refund.succeeded":
|
|
|
|
+// // 开发者在此处加入对退款异步通知的处理代码
|
|
|
|
+// header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
|
|
|
|
+// break;
|
|
|
|
+// default:
|
|
|
|
+// header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
|
|
|
|
+// break;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ public function alipayNotify() {
|
|
|
|
+ $rawInfo = Request::all();
|
|
|
|
+ \Log::info('aliplay callback');
|
|
|
|
+ \Log::info($rawInfo);
|
|
|
|
+
|
|
|
|
+ $config = Config::get('laravel-omnipay.gateways.alipay');
|
|
|
|
+
|
|
|
|
+ $gateway = Omnipay::create($config['driver']);
|
|
|
|
+ $gateway->setEnvironment($config['options']['environment']);
|
|
|
|
+ $gateway->setAppId($config['options']['appid']);
|
|
|
|
+ $gateway->setEncryptKey($config['options']['encrypt_key']);
|
|
|
|
+ $gateway->setPrivateKey($config['options']['prikey']);
|
|
|
|
+ $gateway->setAlipayPublicKey($config['options']['ali_pubkey']);
|
|
|
|
+ $gateway->setNotifyUrl($config['options']['notify_url']);
|
|
|
|
+
|
|
|
|
+ $request = $gateway->completePurchase();
|
|
|
|
+ $request->setParams($rawInfo);//Optional
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ $response = $request->send();
|
|
|
|
+
|
|
|
|
+ if($response->isPaid()){
|
|
|
|
+ \Log::info('支付成功');
|
|
|
|
+
|
|
|
|
+ $out_trade_no = $rawInfo['out_trade_no'];
|
|
|
|
+ $order = Order::where('transaction_id', '=', $out_trade_no)->first();
|
|
|
|
+ if (!$order) {
|
|
|
|
+ \Log::error('找不到订单' . $out_trade_no);
|
|
|
|
+ return 'fail';
|
|
|
|
+ }
|
|
|
|
+ $master_amount = $order->number;
|
|
|
|
+ $slave_amount = 0;
|
|
|
|
+ if (!empty($order->ext_info)) {
|
|
|
|
+ $extInfo = json_decode($order->ext_info, true);
|
|
|
|
+ if ($extInfo !== null) {
|
|
|
|
+ $cc = $extInfo['cc_bonus'];
|
|
|
|
+ $master_amount = round(($cc / 100) * $order->number);
|
|
|
|
+ $slave_amount = $order->number - $master_amount;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ $tp = '';
|
|
|
|
+// $u = null;
|
|
|
|
+ if ($order->user_type == Order::USER_TYPE_MERCHANT) {
|
|
|
|
+ $tp = 'Merchant';
|
|
|
|
+// $u = Merchant::find($order->user_id);
|
|
|
|
+ } elseif ($order->user_type == Order::USER_TYPE_MEMBER) {
|
|
|
|
+ $tp = 'Member';
|
|
|
|
+ //Not handled here
|
|
|
|
+ }
|
|
|
|
+ $u = User::find($order->user_id);
|
|
|
|
+ if (!$u) {
|
|
|
|
+ \Log::error('用户不存在' . $order->user_type . ', ' . $order->user_id);
|
|
|
|
+ return 'success';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DB::beginTransaction();
|
|
|
|
+
|
|
|
|
+ if ($order->goods_type == Order::GOODS_TYPE_BALANCE||$order->goods_type == Order::GOODS_TYPE_COSUME) {
|
|
|
|
+ $cType = AccountLog::TYPE_BALANCE;
|
|
|
|
+// $u->account_balance += $order->number;
|
|
|
|
+ $u->balance += $master_amount;
|
|
|
|
+ } elseif ($order->goods_type == Order::GOODS_TYPE_CREDIT) {
|
|
|
|
+ $cType = AccountLog::TYPE_CREDIT;
|
|
|
|
+// $u->credit_balance += $order->number;
|
|
|
|
+ $u->credit += $master_amount;
|
|
|
|
+ } else {
|
|
|
|
+ \Log::error('商品不存在' . $order->goods_type);
|
|
|
|
+ return 'success';
|
|
|
|
+ }
|
|
|
|
+ \Log::info('支付金额 '.$master_amount);
|
|
|
|
+ if ($u->save()) {
|
|
|
|
+
|
|
|
|
+ //更新订单状态
|
|
|
|
+ $order->status = Order::STATUS_FINISHED;
|
|
|
|
+ $order->save();
|
|
|
|
+
|
|
|
|
+ //记日志
|
|
|
|
+ $amount = $rawInfo['total_amount'] * 100;
|
|
|
|
+ if (empty($extInfo)) {
|
|
|
|
+ $this->logAccount($tp, $u->id, $u->name,
|
|
|
|
+ AccountLog::OP_CHARGE, $cType, $master_amount,
|
|
|
|
+ AccountLog::DIRECTION_INC, $cType == AccountLog::TYPE_BALANCE ? $u->balance : $u->credit, AccountLog::CHANNEL_ALIPAY);
|
|
|
|
+ } else {
|
|
|
|
+ //续消费
|
|
|
|
+ $this->continue_consume($order);
|
|
|
|
+
|
|
|
|
+ $this->logAccount($tp, $u->id, $u->name,
|
|
|
|
+ AccountLog::OP_CC, $cType, $master_amount,
|
|
|
|
+ AccountLog::DIRECTION_INC, $cType == AccountLog::TYPE_BALANCE ? $u->balance : $u->credit, AccountLog::CHANNEL_ALIPAY);
|
|
|
|
+ }
|
|
|
|
+ \Log::info('支付完成');
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ DB::rollBack();
|
|
|
|
+ \Log::error('保存数据失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ DB::commit();
|
|
|
|
+
|
|
|
|
+ return 'success';
|
|
|
|
+ }else{
|
|
|
|
+ \Log::error('支付失败');
|
|
|
|
+
|
|
|
|
+ return 'fail';
|
|
|
|
+ }
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
+ \Log::error('支付异常' . $e->getMessage());
|
|
|
|
+
|
|
|
|
+ return 'fail';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public function wechatpayNotify() {
|
|
|
|
+ \Log::debug('wechatpay callback');
|
|
|
|
+// \Log::debug(Request::all());
|
|
|
|
+
|
|
|
|
+ $config = Config::get('laravel-omnipay.gateways.wechatpay');
|
|
|
|
+
|
|
|
|
+ $gateway = Omnipay::create("WechatPay");
|
|
|
|
+// $gateway->setEnvironment('sandbox');
|
|
|
|
+ $gateway->setAppId($config['options']['appid']);
|
|
|
|
+ $gateway->setMchId($config['options']['merchant_id']);
|
|
|
|
+ $gateway->setApiKey($config['options']['apikey']);
|
|
|
|
+
|
|
|
|
+ $response = $gateway->completePurchase([
|
|
|
|
+ 'request_params' => file_get_contents('php://input')
|
|
|
|
+ ])->send();
|
|
|
|
+ try {
|
|
|
|
+ if ($response->isPaid()) {
|
|
|
|
+ //pay success
|
|
|
|
+ $rawInfo = $response->getRequestData();
|
|
|
|
+ \Log::debug($rawInfo);
|
|
|
|
+ \Log::info('支付成功');
|
|
|
|
+
|
|
|
|
+ $out_trade_no = $rawInfo['out_trade_no'];
|
|
|
|
+ $order = Order::where('transaction_id', '=', $out_trade_no)->first();
|
|
|
|
+ if (!$order) {
|
|
|
|
+ \Log::error('找不到订单' . $out_trade_no);
|
|
|
|
+ return 'fail';
|
|
|
|
+ }
|
|
|
|
+ $master_amount = $order->number;
|
|
|
|
+ $slave_amount = 0;
|
|
|
|
+ if (!empty($order->ext_info)) {
|
|
|
|
+ $extInfo = json_decode($order->ext_info, true);
|
|
|
|
+ if ($extInfo !== null) {
|
|
|
|
+ $cc = $extInfo['cc_bonus'];
|
|
|
|
+ $master_amount = round(($cc / 100) * $order->number);
|
|
|
|
+ $slave_amount = $order->number - $master_amount;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ $tp = '';
|
|
|
|
+// $u = null;
|
|
|
|
+ if ($order->user_type == Order::USER_TYPE_MERCHANT) {
|
|
|
|
+ $tp = 'Merchant';
|
|
|
|
+// $u = Merchant::find($order->user_id);
|
|
|
|
+ } elseif ($order->user_type == Order::USER_TYPE_MEMBER) {
|
|
|
|
+ $tp = 'Member';
|
|
|
|
+ //Not handled here
|
|
|
|
+ }
|
|
|
|
+ $u = User::find($order->user_id);
|
|
|
|
+ if (!$u) {
|
|
|
|
+ \Log::error('用户不存在' . $order->user_type . ', ' . $order->user_id);
|
|
|
|
+ return 'success';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DB::beginTransaction();
|
|
|
|
+
|
|
|
|
+ if ($order->goods_type == Order::GOODS_TYPE_BALANCE||$order->goods_type == Order::GOODS_TYPE_COSUME) {
|
|
|
|
+ $cType = AccountLog::TYPE_BALANCE;
|
|
|
|
+// $u->account_balance += $order->number;
|
|
|
|
+ $u->balance += $master_amount;
|
|
|
|
+ } elseif ($order->goods_type == Order::GOODS_TYPE_CREDIT) {
|
|
|
|
+ $cType = AccountLog::TYPE_CREDIT;
|
|
|
|
+// $u->credit_balance += $order->number;
|
|
|
|
+ $u->credit += $master_amount;
|
|
|
|
+ } else {
|
|
|
|
+ \Log::error('商品不存在' . $order->goods_type);
|
|
|
|
+ return 'success';
|
|
|
|
+ }
|
|
|
|
+ //测试
|
|
|
|
+ \Log::info('支付金额 '.$master_amount);
|
|
|
|
+ if ($u->save()) {
|
|
|
|
+
|
|
|
|
+ //更新订单状态
|
|
|
|
+ $order->status = Order::STATUS_FINISHED;
|
|
|
|
+ $order->save();
|
|
|
|
+
|
|
|
|
+ //记日志
|
|
|
|
+ $amount = $rawInfo['total_fee'] * 100;
|
|
|
|
+ if (empty($extInfo)) {
|
|
|
|
+ $this->logAccount($tp, $u->id, $u->name,
|
|
|
|
+ AccountLog::OP_CHARGE, $cType, $master_amount,
|
|
|
|
+ AccountLog::DIRECTION_INC, $cType == AccountLog::TYPE_BALANCE ? $u->balance : $u->credit, AccountLog::CHANNEL_WECHATPAY);
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ $this->logAccount($tp, $u->id, $u->name,
|
|
|
|
+ AccountLog::OP_CC, $cType, $master_amount,
|
|
|
|
+ AccountLog::DIRECTION_INC, $cType == AccountLog::TYPE_BALANCE ? $u->balance : $u->credit, AccountLog::CHANNEL_WECHATPAY);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ \Log::info('支付完成');
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ DB::rollBack();
|
|
|
|
+ \Log::error('保存数据失败');
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DB::commit();
|
|
|
|
+
|
|
|
|
+ return 'success';
|
|
|
|
+ }else{
|
|
|
|
+ //pay fail
|
|
|
|
+ \Log::error($response->getData());
|
|
|
|
+ return 'fail';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
+ \Log::error('支付异常' . $e->getMessage());
|
|
|
|
+
|
|
|
|
+ return 'fail';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function continue_consume($order){
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * @api {post} /api/pay/charge 充值
|
|
|
|
+ * @apiDescription 充值(向平台充值)
|
|
|
|
+ * @apiGroup Merchant
|
|
|
|
+ * @apiPermission Passport
|
|
|
|
+ * @apiVersion 0.1.0
|
|
|
|
+ * @apiParam {int} [goods=1] 充值商品(1:余额,2:卡金)
|
|
|
|
+ * @apiParam {int} number 充值数量,人民币,以分表示
|
|
|
|
+ * @apiParam {int} type 支付类型(1:支付宝,2:微信支付)
|
|
|
|
+ * @apiSuccessExample {json} Success-Response:
|
|
|
|
+ * HTTP/1.1 200 OK
|
|
|
|
+ * {
|
|
|
|
+ * "state": true,
|
|
|
|
+ * "code": 0,
|
|
|
|
+ * "message": "",
|
|
|
|
+ * "data": {
|
|
|
|
+ * "id": 2,
|
|
|
|
+ * "code": "ALIPAY_201610231314145719",
|
|
|
|
+ * "transaction_id": "201610231314145719",
|
|
|
|
+ * "user_type": 2,
|
|
|
|
+ * "user_id": 1,
|
|
|
|
+ * "goods_type": 1,
|
|
|
|
+ * "price": 1,
|
|
|
|
+ * "number": 1,
|
|
|
|
+ * "amount": 1,
|
|
|
|
+ * "pay_type": 1,
|
|
|
|
+ * "status": 0,
|
|
|
|
+ * "created_at": "2016-10-23 13:14:14",
|
|
|
|
+ * "updated_at": "2016-10-23 13:14:14",
|
|
|
|
+ * "orderString": "alipay_sdk=lokielse%2Fomnipay-alipay&app_id=2016091201894867&biz_content=%7B%22subject%22%3A%22%5Cu7532%5Cu8c61%5Cu8054%5Cu5408-%5Cu4f59%5Cu989d%5Cu5145%5Cu503c%22%2C%22out_trade_no%22%3A%22201610231314145719%22%2C%22total_amount%22%3A0.01%2C%22product_code%22%3A1%7D&charset=UTF-8&format=JSON&method=alipay.trade.app.pay¬ify_url=http%3A%2F%2Fweb%2Fapi%2Fpay%2Falipay%2Fnotify&sign_type=RSA×tamp=2016-10-23+13%3A14%3A14&version=1.0&sign=oxKM0qGMHLWDlMrXHIiy9%2Fk2BXJq3rC3RKdmcfFwkBJVRXvtG6cBoAYPll6VxJYOMQWeu78Ibfov%2FxIVCuN9yUfzEiokfQrzBoptc94bCQ5k0pNyJcSdgezOUKHB12P5Zmm3Hd6AAbGRDV9UCaLVz0wYkFJPrCyUv1ZfhrM%2BBqc%3D"
|
|
|
|
+ * }
|
|
|
|
+ * }
|
|
|
|
+ * @apiErrorExample {json} Error-Response:
|
|
|
|
+ * HTTP/1.1 400 Bad Request
|
|
|
|
+ * {
|
|
|
|
+ * "state": false,
|
|
|
|
+ * "code": 1000,
|
|
|
|
+ * "message": "传入参数不正确",
|
|
|
|
+ * "data": null or []
|
|
|
|
+ * }
|
|
|
|
+ * 可能出现的错误代码:
|
|
|
|
+ * 1000 CLIENT_WRONG_PARAMS 传入参数不正确
|
|
|
|
+ * 1300 MERCHANT_NOT_EXIST 商户不存在
|
|
|
|
+ */
|
|
|
|
+ public function charge(Request $request)
|
|
|
|
+ {
|
|
|
|
+ $goodsTypes = Order::getAllGoodsTypes();
|
|
|
|
+ $gTypes = array_keys($goodsTypes);
|
|
|
|
+ $payTypes = Order::getAllPayTypes();
|
|
|
|
+ $pTypes = array_keys($payTypes);
|
|
|
|
+ $validator = Validator::make($data = $request->input(),
|
|
|
|
+ [
|
|
|
|
+ 'number' => 'required|integer|min:1',
|
|
|
|
+ 'type' => 'required|in:' . join(',', $pTypes),
|
|
|
|
+ 'goods' => 'in:' . join(',', $gTypes),
|
|
|
|
+ ],
|
|
|
|
+ [
|
|
|
|
+ 'number.required' => '充值金额必填',
|
|
|
|
+ 'number.integer' => '金额必须为整数',
|
|
|
|
+ 'number.min' => '充值金额至少为1',
|
|
|
|
+ 'type.required' => '支付类型必填',
|
|
|
|
+ 'type.in' => '支付类型非法',
|
|
|
|
+ 'goods.in' => '充值商品非法',
|
|
|
|
+ ]
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ if ($validator->fails()) {
|
|
|
|
+ return $this->validatorError($validator->messages()->all(), ErrorCode::CLIENT_WRONG_PARAMS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $user = Auth::user();
|
|
|
|
+ $merchant = Merchant::where('user_id', '=', $user->id)->first();//模型支持单用户多商户,业务只设计单商户
|
|
|
|
+ if (!$merchant) {
|
|
|
|
+ return $this->error(ErrorCode::MERCHANT_NOT_EXIST);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $data['goods_id'] = 0;
|
|
|
|
+ if (!isset($data['goods'])) {//默认充余额
|
|
|
|
+ $data['goods'] = Order::GOODS_TYPE_BALANCE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $data['user_type'] = Order::USER_TYPE_MERCHANT;
|
|
|
|
+ $data['user_id'] = $user->id;//$merchant->id;
|
|
|
|
+ if ($data['type'] == Order::PAY_TYPE_ALIPAY) {
|
|
|
|
+ $result = $this->createAlipayCharge($data);
|
|
|
|
+ } else {
|
|
|
|
+ $result = $this->createWechatpayCharge($data);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ($result === false) {
|
|
|
|
+ return $this->error(ErrorCode::ORDER_GENERATE_FAILED);
|
|
|
|
+ }
|
|
|
|
+ //log
|
|
|
|
+// $data['amount'] = $data['number'];
|
|
|
|
+// $this->chargeLog('Merchant', $merchant->id, $merchant->name,
|
|
|
|
+// 'balance', $data['amount'], 'balance', $data['amount'],
|
|
|
|
+// 'Merchant', $user->id, $merchant->name);
|
|
|
|
+
|
|
|
|
+ return $this->api($result);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|