李帅

1.打印苹果日志

...@@ -43,12 +43,15 @@ class PayController extends Controller ...@@ -43,12 +43,15 @@ class PayController extends Controller
43 $order_sn = $request->post('order_sn'); 43 $order_sn = $request->post('order_sn');
44 $pay_type = $request->post('pay_type'); 44 $pay_type = $request->post('pay_type');
45 $token = $request->post('token'); 45 $token = $request->post('token');
46 + $others = $request->post('others',[]);
47 + $transactionId = $others['apple']['transactionIdentifier'];
48 + $originalTransactionId = $others['apple']['originalTransactionIdentifier'];
46 49
47 $order = Order::query()->where('order_sn', $order_sn)->first(); 50 $order = Order::query()->where('order_sn', $order_sn)->first();
48 51
49 if ($order->status != Order::UNPAID) return Response::fail('订单错误!'); 52 if ($order->status != Order::UNPAID) return Response::fail('订单错误!');
50 53
51 - $payment = $factory->init($pay_type)->verify($order, $token); 54 + $payment = $factory->init($pay_type)->verify($order, $token, $transactionId, $originalTransactionId);
52 55
53 if ($payment) return Response::success(['order_sn' => $order_sn], '支付成功'); 56 if ($payment) return Response::success(['order_sn' => $order_sn], '支付成功');
54 else return Response::fail('订单错误!'); 57 else return Response::fail('订单错误!');
......
...@@ -14,6 +14,12 @@ class UserProfile extends Model ...@@ -14,6 +14,12 @@ class UserProfile extends Model
14 14
15 protected $fillable = ['user_id','unionid']; 15 protected $fillable = ['user_id','unionid'];
16 16
17 + const IS_VIP = 1;
18 +
19 + const NO_VIP = 0;
20 +
21 + const WAIT_VIP = 2; // 已付款,等待处理(回调不及时,需要等待)
22 +
17 public function user() 23 public function user()
18 { 24 {
19 return $this->belongsTo('App\Models\User', 'id', 'user_id'); 25 return $this->belongsTo('App\Models\User', 'id', 'user_id');
......
...@@ -55,23 +55,28 @@ class ApplePayment implements PaymentInterface ...@@ -55,23 +55,28 @@ class ApplePayment implements PaymentInterface
55 // 4. 验证成功,返回true 55 // 4. 验证成功,返回true
56 56
57 $client = new Client(['headers' => ['Content-Type' => 'application/json']]); 57 $client = new Client(['headers' => ['Content-Type' => 'application/json']]);
58 - try{ 58 + try {
59 $response = $client->post(self::IS_SANDBOX ? self::SANDBOX_URL : self::VERIFY_URL, 59 $response = $client->post(self::IS_SANDBOX ? self::SANDBOX_URL : self::VERIFY_URL,
60 - ['json' => ['receipt-data' => $token, 'password' => self::PASSWORD]])->getBody()->getContents(); 60 + ['json' => ['receipt-data' => $token, 'password' => self::PASSWORD]])
61 - $resp = json_decode($response,true); 61 + ->getBody()->getContents();
62 - Log::debug($response); 62 + $resp = json_decode($response, true);
63 - if ($resp['status'] <= 21003) { 63 + if ($resp['status'] > 0) {
64 - $newToken = str_replace('+', ' ', $token); 64 + Log::debug($response);
65 - try{ 65 + return false;
66 - $response = $client->post(self::IS_SANDBOX ? self::SANDBOX_URL : self::VERIFY_URL,
67 - ['json' => ['receipt-data' => $newToken, 'password' => self::PASSWORD]])->getBody()->getContents();
68 - Log::debug('======== 替换+ ========');
69 - Log::debug($response);
70 - }catch (GuzzleException $exception){
71 - Log::error($exception->getMessage() . 'Line:' . $exception->getLine());
72 - }
73 } 66 }
74 - }catch (GuzzleException $exception){ 67 + $originalTransactionId = $resp['receipt']['pending_renewal_info']['originalTransactionId'];
68 +
69 + // 绑定order 和 originalTransactionId
70 + $order->pay_number = $originalTransactionId;
71 + $order->status = Order::PAID;
72 + $order->save();
73 +
74 + // 修改用户状态
75 + $profile = UserProfile::query()->find($order->user_id);
76 + $profile->is_vip = UserProfile::WAIT_VIP;
77 + $profile->save();
78 + return true;
79 + } catch (GuzzleException $exception) {
75 Log::error($exception->getMessage() . 'Line:' . $exception->getLine()); 80 Log::error($exception->getMessage() . 'Line:' . $exception->getLine());
76 } 81 }
77 82
...@@ -93,80 +98,127 @@ class ApplePayment implements PaymentInterface ...@@ -93,80 +98,127 @@ class ApplePayment implements PaymentInterface
93 Log::debug('sandbox返回的数据:===================='); 98 Log::debug('sandbox返回的数据:====================');
94 99
95 $components = explode('.',$string); 100 $components = explode('.',$string);
96 - if (count($components) < 3){
97 - Log::error("jwt错误");
98 - return false;
99 - }
100 -
101 $header = json_decode(base64_decode($components[0]),true); 101 $header = json_decode(base64_decode($components[0]),true);
102 -
103 // 这一步可以省略,不需要验证根证书 102 // 这一步可以省略,不需要验证根证书
104 - $this->validateAppleRootCa($header); 103 +// $this->validateAppleRootCa($header);
105 $responseBodyPayload = $this->decodeCertificate($string, $header['x5c'][0]); 104 $responseBodyPayload = $this->decodeCertificate($string, $header['x5c'][0]);
106 - Log::debug(print_r($responseBodyPayload,true));
107 - /**{
108 - "notificationType": "SUBSCRIBED"
109 - "subtype": "RESUBSCRIBE"
110 - "notificationUUID": "99e65e59-c178-4f49-8b83-ea7d916cb568"
111 - "data": {
112 - "bundleId": "ink.parlando.parlando"
113 - "bundleVersion": "13"
114 - "environment": "Sandbox"
115 - "signedTransactionInfo": "xxx"
116 - "signedRenewalInfo": "xxx"
117 - }
118 - "version": "2.0"
119 - "signedDate": 1671451705697
120 - }
121 - */
122 -
123 $signedTransactionInfoString = $responseBodyPayload->data->signedTransactionInfo; 105 $signedTransactionInfoString = $responseBodyPayload->data->signedTransactionInfo;
124 $components = explode('.',$signedTransactionInfoString); 106 $components = explode('.',$signedTransactionInfoString);
125 $header = json_decode(base64_decode($components[0]),true); 107 $header = json_decode(base64_decode($components[0]),true);
126 - if (count($components) < 3){ 108 + $signedTransactionInfo = $this->decodeCertificate($signedTransactionInfoString, $header['x5c'][0]);
127 - Log::error("jwt错误");
128 - return false;
129 - }
130 - $signedTransactionInfo = $this->decodeCertificate($string, $header['x5c'][0]);
131 - Log::debug(print_r($signedTransactionInfo,true));
132 -
133 $responseBodyPayload->data->signedTransactionInfo = $signedTransactionInfo; 109 $responseBodyPayload->data->signedTransactionInfo = $signedTransactionInfo;
134 - /**{
135 - "transactionId": "2000000231419425"
136 - "originalTransactionId": "2000000229164150"
137 - "webOrderLineItemId": "2000000017115109"
138 - "bundleId": "ink.parlando.parlando"
139 - "productId": "monthly_yiyan_vip"
140 - "subscriptionGroupIdentifier": "21080623"
141 - "purchaseDate": 1671451694000
142 - "originalPurchaseDate": 1671123372000
143 - "expiresDate": 1671451994000
144 - "quantity": 1
145 - "type": "Auto-Renewable Subscription"
146 - "inAppOwnershipType": "PURCHASED"
147 - "signedDate": 1671451705700
148 - "environment": "Sandbox"
149 - }*/
150 $signedRenewalInfoString = $responseBodyPayload->data->signedRenewalInfo; 110 $signedRenewalInfoString = $responseBodyPayload->data->signedRenewalInfo;
151 $components = explode('.',$signedRenewalInfoString); 111 $components = explode('.',$signedRenewalInfoString);
152 $header = json_decode(base64_decode($components[0]),true); 112 $header = json_decode(base64_decode($components[0]),true);
153 - if (count($components) < 3){ 113 + $signedRenewalInfo = $this->decodeCertificate($signedRenewalInfoString, $header['x5c'][0]);
154 - Log::error("jwt错误");
155 - return false;
156 - }
157 - $signedRenewalInfo = $this->decodeCertificate($string, $header['x5c'][0]);
158 - Log::debug(print_r($signedRenewalInfo,true));
159 $responseBodyPayload->data->signedRenewalInfo = $signedRenewalInfo; 114 $responseBodyPayload->data->signedRenewalInfo = $signedRenewalInfo;
115 +
116 + Log::debug(print_r($responseBodyPayload,true));
160 /**{ 117 /**{
161 - "originalTransactionId": "2000000229164150" 118 + "notificationType": "SUBSCRIBED"
162 - "autoRenewProductId": "monthly_yiyan_vip" 119 + "subtype": "RESUBSCRIBE"
163 - "productId": "monthly_yiyan_vip" 120 + "notificationUUID": "99e65e59-c178-4f49-8b83-ea7d916cb568"
164 - "autoRenewStatus": 1 121 + "data": {
165 - "signedDate": 1671451705673 122 + "bundleId": "ink.parlando.parlando"
166 - "environment": "Sandbox" 123 + "bundleVersion": "13"
167 - "recentSubscriptionStartDate": 1671451694000 124 + "environment": "Sandbox"
125 + "signedTransactionInfo": {
126 + "transactionId": "2000000231419425"
127 + "originalTransactionId": "2000000229164150"
128 + "webOrderLineItemId": "2000000017115109"
129 + "bundleId": "ink.parlando.parlando"
130 + "productId": "monthly_yiyan_vip"
131 + "subscriptionGroupIdentifier": "21080623"
132 + "purchaseDate": 1671451694000
133 + "originalPurchaseDate": 1671123372000
134 + "expiresDate": 1671451994000
135 + "quantity": 1
136 + "type": "Auto-Renewable Subscription"
137 + "inAppOwnershipType": "PURCHASED"
138 + "signedDate": 1671451705700
139 + "environment": "Sandbox"
140 + }
141 + "signedRenewalInfo": {
142 + "originalTransactionId": "2000000229164150"
143 + "autoRenewProductId": "monthly_yiyan_vip"
144 + "productId": "monthly_yiyan_vip"
145 + "autoRenewStatus": 1
146 + "signedDate": 1671451705673
147 + "environment": "Sandbox"
148 + "recentSubscriptionStartDate": 1671451694000
149 + }
150 + }
151 + "version": "2.0"
152 + "signedDate": 1671451705697
168 }*/ 153 }*/
169 - Log::debug(print_r($responseBodyPayload,true)); 154 +
155 + switch ($responseBodyPayload->notificationType){
156 + case "SUBSCRIBED":
157 + if ($responseBodyPayload->subtype == 'INITIAL_BUY'){ //首次购买
158 +
159 + }
160 +
161 + if ($responseBodyPayload->subtype == 'RESUBSCRIBE'){ //重新订阅
162 + // 应该再创建一个订单。。。
163 + }
164 +
165 + $originalTransactionId = $responseBodyPayload->data->signedTransactionInfo->originalTransactionId;
166 +
167 + $order = Order::query()->where('pay_number', $originalTransactionId)->first();
168 + if(!$order) {
169 + Log::error('没有找到对应的订单,说明apple服务端比客户端的回调快!');
170 + return;
171 + }
172 +
173 + /** 修改订单状态*/
174 + $order->pay_time = Carbon::now();
175 + $order->pay_type = $responseBodyPayload->data->signedTransactionInfo->type;
176 + $order->save();
177 + /** 给用户加会员*/
178 + $user = UserProfile::query()->find($order->user_id);
179 + $user->is_vip = 1;
180 + $user->create_vip_time = Carbon::createFromTimestampMs($responseBodyPayload->data->signedTransactionInfo->purchaseDate);
181 + $user->expire_vip_time = Carbon::createFromTimestampMs($responseBodyPayload->data->signedTransactionInfo->expiresDate);
182 + $user->buy_number += 1;
183 + $user->buy_amount += $order->pay_amount;
184 + $user->last_buy_time = Carbon::now();
185 + $user->save();
186 + break;
187 + case "DID_RENEW":
188 + // 应该再创建一个订单。。。
189 + $originalTransactionId = $responseBodyPayload->data->signedTransactionInfo->originalTransactionId;
190 + $order = Order::query()->where('pay_number', $originalTransactionId)->first();
191 + if(!$order) {
192 + Log::error('没有找到对应的订单,说明apple服务端比客户端的回调快!');
193 + return;
194 + }
195 + /** 给用户加会员*/
196 + $user = UserProfile::query()->find($order->user_id);
197 + $user->is_vip = 1;
198 + $user->expire_vip_time = Carbon::createFromTimestampMs($responseBodyPayload->data->signedTransactionInfo->expiresDate);
199 + $user->buy_number += 1;
200 + $user->buy_amount += $order->pay_amount;
201 + $user->last_buy_time = Carbon::now();
202 + $user->save();
203 + break;
204 + case "EXPIRED":
205 + // 应该再创建一个订单。。。
206 + $originalTransactionId = $responseBodyPayload->data->signedTransactionInfo->originalTransactionId;
207 + $order = Order::query()->where('pay_number', $originalTransactionId)->first();
208 + if(!$order) {
209 + Log::error('没有找到对应的订单,说明apple服务端比客户端的回调快!');
210 + return;
211 + }
212 + /** 给用户取消会员*/
213 + $user = UserProfile::query()->find($order->user_id);
214 + $user->is_vip = 0;
215 + $user->expire_vip_time = Carbon::createFromTimestampMs($responseBodyPayload->data->signedTransactionInfo->expiresDate);
216 + $user->save();
217 + break;
218 + default:
219 + Log::debug('特殊通知类型:'.$responseBodyPayload->notificationType.' ====================');
220 + Log::debug(var_export($responseBodyPayload,true));
221 + }
170 } 222 }
171 223
172 private function validateAppleRootCa($header) 224 private function validateAppleRootCa($header)
......