1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<?php
namespace App\Http\Service;
use App\Http\Dao\GameDao;
use App\Http\Dao\GameUserDao;
use App\Http\Dao\OrderDao;
use App\Http\Manager\SdkManager;
use App\Utils\Rsa;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use RuntimeException;
use WpOrg\Requests\Requests;
class PayService
{
private $orderDao;
public function __construct()
{
$this->orderDao = new OrderDao();
}
/**
* 创建订单,返回订单号
* @param array $params
* @return array
*/
public function createOrder(array $params): array
{
$model = DB::table("app_order");
// 查询cp订单号是否有重复情况
$orderInfo = $model->where(['cp_order_id' => $params['cp_order_id'], 'appid' => $params['app_id']])->first();
if ($orderInfo) {
return error("禁止重复下单");
}
// 检查参数
if (!is_numeric($params['money']) || $params['money'] < 1) {
return error("订单金额的格式类型不正确");
}
if (empty($params['app_id']) || empty($params['money']) || empty($params['uid'])) {
return error("提交参数异常!");
}
//获取游戏表配置
$gameInfo = DB::table("app_games_config")
->where(['app_id' => $params['app_id']])->first();
if (is_null($gameInfo)) {
return error('该游戏配置不存在,app_id:' . $params['app_id']);
}
// 获取渠道表配置
$verInfo = DB::table("app_ver_game as avg")
->leftJoin('app_ver as av', 'avg.ver', '=', 'av.ver_class')
->where(['app_id' => $params['app_id']])->first();
if (is_null($verInfo)) {
return error('该游戏渠道没配置,app_id:' . $params['app_id']);
}
// 查找融合用户信息
$userInfo = DB::table('app_member')->where(['uid' => $params['uid']])->first();
// 入库
$orderId = $this->createOrderId();
$insertData = [
'uid' => $params['uid'],
'order_id' => $orderId,
'cp_order_id' => $params['cp_order_id'],
'veruniqid' => $userInfo->veruniqid,
'ver' => $verInfo->ver_code,
'appid' => $params['app_id'],
'server_id' => $params['server_id'],
'server_name' => $params['server_name'],
'role_id' => $params['role_id'],
'money' => $params['money'],
'role_name' => htmlspecialchars($params['role_name']),
'role_level' => $params['role_level'],
'subject' => $params['pname'],
'extra_info' => $params['extend'] ?? '',
'currency_type' => $params['currency_type'] ?? 'CNY',
'create_time' => date('Y-m-d H:i:s')
];
$model->insert($insertData);
// 走一下渠道的下单接口,如果部分渠道没有,则返回空
$sdkManager = new SdkManager();
$channel_order_id = $sdkManager->createOrder($verInfo, $gameInfo, $params);
if($channel_order_id){
$model->where(['order_id'=>$orderId])->update(['channel_order_id'=>$channel_order_id]);
}
return success('success',['order_id' => $channel_order_id ?: $orderId]);
}
/**
* 生成订单号
* @return int
*/
private function createOrderId(): string
{
$datestr = date('YmdHis');
list($usec, $sec) = explode(" ", microtime());
$ustr = (float)$usec*1000000;
$ustr = (string)$ustr;
$datestr .= $ustr;
$pfix = env('APIORDER_FIX','');
return $pfix.$datestr;
}
/**
* 二次确认订单,通过则返回订单状态
* @param array $params
* @return array
*/
public function confirmOrder(array $params)
{
$orderInfo = DB::table('app_order')->where(['order_id' => $params['order_id'], 'status' => 0])->first();
if (is_null($orderInfo)) {
return error('订单状态异常,请重新下单!');
}
// 参数校验
if ($orderInfo->money != $params['money'] || $orderInfo->uid != $params['uid']) {
return error('订单金额异常!');
}
return success('success',['order_id' => $orderInfo->order_id,'status'=>$orderInfo->status]);
}
/**
* 渠道回调,带 appid + 渠道号 参数
* @param array $params
* @return array
*/
public function verBack(array $params)
{
//获取游戏表配置
$gameInfo = DB::table("app_games_config")
->where(['app_id' => $params['app_id']])->first();
if (is_null($gameInfo)) {
return error('该游戏配置不存在,app_id:' . $params['app_id']);
}
// 获取渠道表配置
$verInfo = DB::table("app_ver_game as avg")
->leftJoin('app_ver as av', 'avg.ver', '=', 'av.ver_class')
->where(['app_id' => $params['app_id'], 'ver_code' => $params['ver']])->first();
if (is_null($verInfo)) {
return error('该游戏渠道没配置,ver_code:' . $params['ver']);
}
// 渠道标识就是类名称
$sdkManager = new SdkManager();
// 返回渠道订单号+订单金额[单位元]
$payInfo = $sdkManager->pay($verInfo, $gameInfo, $params);
if (!isset($payInfo['order_id']) && !isset($payInfo['money'])) {
return $payInfo['result'];
}
$orderModel = DB::table('app_order');
// 更新回调时间+金额
$orderModel->where(['order_id' => $payInfo['order_id']])->update(['status' => 1, 'amount'=>$payInfo['money'],'channel_order_id'=>$payInfo['channel_order_id'],'dateline' => time()]);
// 保存回调日志
DB::table('app_callback_log')->insert([
'order_id' => $payInfo['order_id'],
'requrl' => request()->fullUrl(),
'reqparams' => var_export(request()->post(),true),
'reqresult' => var_export($payInfo,true),
'reqtime' => time(),
]);
// 获取订单信息
$orderInfo = $orderModel->where(['order_id' => $payInfo['order_id']])->first();
// 通知CP发货,组装post参数,并签名
$post_params = [
'order_id' => $orderInfo->order_id,
'good_name' => $orderInfo->subject,
'cp_order_id' => $orderInfo->cp_order_id,
'uid' => $orderInfo->uid,
'money' => $orderInfo->money,
'app_id' => $orderInfo->appid,
'service_id' => $orderInfo->server_id,
'service_name' => $orderInfo->server_name,
'role_id' => $orderInfo->role_id,
'role_name' => $orderInfo->role_name,
'time' => time(),
'pay_status' => $orderInfo->status,
'extend' => $orderInfo->extra_info,
];
ksort($params);
$signStr = http_build_query($params)."&paykey=".$gameInfo->paykey;
$params['sign'] = md5($signStr);
$response = Requests::post($gameInfo->send_url,['Accept' => 'application/json'],$post_params)->body;
$response_arr = json_decode($response,true);
if($response_arr['code'] === 200) {
$orderModel->where(['order_id' => $payInfo['order_id']])->update(['gstatus' => 1]);
}
// 返回渠道要求返回的提示 成功|失败
return $payInfo['result'];
}
}