李帅

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,
60 - ['json' => ['receipt-data' => $token, 'password' => self::PASSWORD]])->getBody()->getContents();
61 - $resp = json_decode($response,true);
62 - Log::debug($response);
63 - if ($resp['status'] <= 21003) {
64 - $newToken = str_replace('+', ' ', $token);
65 - try{
66 $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,
67 - ['json' => ['receipt-data' => $newToken, 'password' => self::PASSWORD]])->getBody()->getContents(); 60 + ['json' => ['receipt-data' => $token, 'password' => self::PASSWORD]])
68 - Log::debug('======== 替换+ ========'); 61 + ->getBody()->getContents();
62 + $resp = json_decode($response, true);
63 + if ($resp['status'] > 0) {
69 Log::debug($response); 64 Log::debug($response);
70 - }catch (GuzzleException $exception){ 65 + return false;
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,16 +98,21 @@ class ApplePayment implements PaymentInterface ...@@ -93,16 +98,21 @@ 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]);
105 + $signedTransactionInfoString = $responseBodyPayload->data->signedTransactionInfo;
106 + $components = explode('.',$signedTransactionInfoString);
107 + $header = json_decode(base64_decode($components[0]),true);
108 + $signedTransactionInfo = $this->decodeCertificate($signedTransactionInfoString, $header['x5c'][0]);
109 + $responseBodyPayload->data->signedTransactionInfo = $signedTransactionInfo;
110 + $signedRenewalInfoString = $responseBodyPayload->data->signedRenewalInfo;
111 + $components = explode('.',$signedRenewalInfoString);
112 + $header = json_decode(base64_decode($components[0]),true);
113 + $signedRenewalInfo = $this->decodeCertificate($signedRenewalInfoString, $header['x5c'][0]);
114 + $responseBodyPayload->data->signedRenewalInfo = $signedRenewalInfo;
115 +
106 Log::debug(print_r($responseBodyPayload,true)); 116 Log::debug(print_r($responseBodyPayload,true));
107 /**{ 117 /**{
108 "notificationType": "SUBSCRIBED" 118 "notificationType": "SUBSCRIBED"
...@@ -112,26 +122,7 @@ class ApplePayment implements PaymentInterface ...@@ -112,26 +122,7 @@ class ApplePayment implements PaymentInterface
112 "bundleId": "ink.parlando.parlando" 122 "bundleId": "ink.parlando.parlando"
113 "bundleVersion": "13" 123 "bundleVersion": "13"
114 "environment": "Sandbox" 124 "environment": "Sandbox"
115 - "signedTransactionInfo": "xxx" 125 + "signedTransactionInfo": {
116 - "signedRenewalInfo": "xxx"
117 - }
118 - "version": "2.0"
119 - "signedDate": 1671451705697
120 - }
121 - */
122 -
123 - $signedTransactionInfoString = $responseBodyPayload->data->signedTransactionInfo;
124 - $components = explode('.',$signedTransactionInfoString);
125 - $header = json_decode(base64_decode($components[0]),true);
126 - if (count($components) < 3){
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;
134 - /**{
135 "transactionId": "2000000231419425" 126 "transactionId": "2000000231419425"
136 "originalTransactionId": "2000000229164150" 127 "originalTransactionId": "2000000229164150"
137 "webOrderLineItemId": "2000000017115109" 128 "webOrderLineItemId": "2000000017115109"
...@@ -146,18 +137,8 @@ class ApplePayment implements PaymentInterface ...@@ -146,18 +137,8 @@ class ApplePayment implements PaymentInterface
146 "inAppOwnershipType": "PURCHASED" 137 "inAppOwnershipType": "PURCHASED"
147 "signedDate": 1671451705700 138 "signedDate": 1671451705700
148 "environment": "Sandbox" 139 "environment": "Sandbox"
149 - }*/
150 - $signedRenewalInfoString = $responseBodyPayload->data->signedRenewalInfo;
151 - $components = explode('.',$signedRenewalInfoString);
152 - $header = json_decode(base64_decode($components[0]),true);
153 - if (count($components) < 3){
154 - Log::error("jwt错误");
155 - return false;
156 } 140 }
157 - $signedRenewalInfo = $this->decodeCertificate($string, $header['x5c'][0]); 141 + "signedRenewalInfo": {
158 - Log::debug(print_r($signedRenewalInfo,true));
159 - $responseBodyPayload->data->signedRenewalInfo = $signedRenewalInfo;
160 - /**{
161 "originalTransactionId": "2000000229164150" 142 "originalTransactionId": "2000000229164150"
162 "autoRenewProductId": "monthly_yiyan_vip" 143 "autoRenewProductId": "monthly_yiyan_vip"
163 "productId": "monthly_yiyan_vip" 144 "productId": "monthly_yiyan_vip"
...@@ -165,8 +146,79 @@ class ApplePayment implements PaymentInterface ...@@ -165,8 +146,79 @@ class ApplePayment implements PaymentInterface
165 "signedDate": 1671451705673 146 "signedDate": 1671451705673
166 "environment": "Sandbox" 147 "environment": "Sandbox"
167 "recentSubscriptionStartDate": 1671451694000 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)
......