@@ -221,6 +221,100 @@ public function validateDomain($attribute, $value,$parameters){
221
221
return preg_match ('/^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,6}$/ ' , $ value ) > 0 ;
222
222
}
223
223
224
+ /**
225
+ * 银行卡验证
226
+ * 16-19 位卡号校验位采用 Luhm 校验方法计算:
227
+ * 1,将未带校验位的 15 位卡号从右依次编号 1 到 15,位于奇数位号上的数字乘以 2
228
+ * 2,将奇位乘积的个十位全部相加,再加上所有偶数位上的数字
229
+ * 3,将加法和加上校验位能被 10 整除。
230
+ * @param $s
231
+ * @return bool
232
+ */
233
+ public function validateBankCard ($ attribute , $ value , $ parameters )
234
+ {
235
+ if (!$ value ) return true ;
236
+ if (!preg_match ("/^[0-9]{1,}$/ " , $ value )){
237
+ return false ;
238
+ }
239
+ $ n = 0 ;
240
+ $ ns = strrev ($ value ); // 倒序
241
+ for ($ i = 0 ; $ i < strlen ($ value ); $ i ++) {
242
+ if ($ i % 2 == 0 ) {
243
+ $ n += $ ns [$ i ]; // 偶数位,包含校验码
244
+ } else {
245
+ $ t = $ ns [$ i ] * 2 ;
246
+ if ($ t >= 10 ) {
247
+ $ t = $ t - 9 ;
248
+ }
249
+ $ n += $ t ;
250
+ }
251
+ }
252
+ $ res = ($ n % 10 ) == 0 ;
253
+ $ bank_code = Arr::get ($ parameters , 0 , '' );
254
+
255
+ if (!$ bank_code || !$ res ) { //不验证所属银行代码
256
+ return $ res ;
257
+ }
258
+ try {
259
+ $ url = 'https://ccdcapi.alipay.com/validateAndCacheCardInfo.json ' ;
260
+ $ response = \App \Facades \Client::request ('get ' , $ url , [
261
+ 'query ' => [
262
+ '_input_charset ' => 'utf-8 ' ,
263
+ 'cardNo ' => $ value ,
264
+ 'cardBinCheck ' => 'true '
265
+ ]
266
+ ]);
267
+ if ($ response ->getStatusCode () == 200 ) {
268
+ $ stringBody = $ response ->getBody ()->getContents ();
269
+ $ result = json_decode ($ stringBody , true );
270
+ $ res_bank_code = array_get ($ result , 'bank ' , '' );
271
+ if (array_get ($ result , 'stat ' ) == 'ok ' && $ res_bank_code ) {
272
+ $ res = array_get ($ result , 'validated ' ) && //有效卡号
273
+ $ bank_code == $ res_bank_code
274
+ //&& //卡号所属银行
275
+ //array_get($result, 'cardType') == 'DC' //DC-储蓄卡,CC-信用卡
276
+ ;
277
+ }
278
+ }
279
+ } catch (\Exception $ e ) {
280
+ }
281
+ return $ res ;
282
+ }
283
+
284
+ /**
285
+ * 社会统一信用码验证
286
+ * @param $code
287
+ * @return bool
288
+ */
289
+ public function validateUnifiedSocialCreditIdentifier ($ attribute , $ code )
290
+ {
291
+ if (is_null ($ code ) || $ code ==='' ) return true ;
292
+ if (!preg_match ('~^[0-9ABCDEFGHJKLMNPQRTUWXY]{18}$~ ' , $ code )) {
293
+ return false ;
294
+ }
295
+ $ code = strtoupper ($ code );
296
+ // 18位统一社会信用代码不使用I、O、Z、S、V这五个英文字母
297
+ $ alphaMap = [
298
+ '0 ' => 0 , '1 ' => 1 , '2 ' => 2 , '3 ' => 3 , '4 ' => 4 ,
299
+ '5 ' => 5 , '6 ' => 6 , '7 ' => 7 , '8 ' => 8 , '9 ' => 9 ,
300
+ 'A ' => 10 , 'B ' => 11 , 'C ' => 12 , 'D ' => 13 , 'E ' => 14 ,
301
+ 'F ' => 15 , 'G ' => 16 , 'H ' => 17 , 'J ' => 18 , 'K ' => 19 ,
302
+ 'L ' => 20 , 'M ' => 21 , 'N ' => 22 , 'P ' => 23 , 'Q ' => 24 ,
303
+ 'R ' => 25 , 'T ' => 26 , 'U ' => 27 , 'W ' => 28 , 'X ' => 29 ,
304
+ 'Y ' => 30 ,
305
+ ];
306
+ $ weight = [1 , 3 , 9 , 27 , 19 , 26 , 16 , 17 , 20 , 29 , 25 , 13 , 8 , 24 , 10 , 30 , 28 ];
307
+ $ chrs = str_split ($ code );
308
+ $ sum = 0 ;
309
+ foreach (array_slice ($ chrs , 0 , 17 ) as $ index => $ chr ) {
310
+ $ sum += $ alphaMap [$ chr ] * $ weight [$ index ];
311
+ }
312
+ $ checkNum = 31 - ($ sum % 31 );
313
+ $ checkNum = $ checkNum == 31 ? 0 : $ checkNum ;
314
+ $ flipAlphaMap = array_flip ($ alphaMap );
315
+ return $ chrs [17 ] === (string ) $ flipAlphaMap [$ checkNum ];
316
+ }
317
+
224
318
225
319
226
320
0 commit comments