CategoryPHP

IOS App Store 服务端支付接口开发

首先 “苹果禁止在app中提供第三方支付” 所以但凡是做IOS App的,需要充值的地方都会遇到服务端充值的功能需要开发。

 

充值的大体流程是这样的,App内在购买成功后,会得到一个从苹果AppStore服务器得到一个本次交易数据的字符串,即收据(Receipt),Receipt中包含了本次交易的几乎所有信息,前面这部分的内容都是由App内实现,所以服务端不用去管。

 

App拿到Receipt之后,向应用的服务端(即用户自己的服务器)请求发送本次交易的Receipt及当前用户的唯一标识。服务端再从Receipt中获取到交易信息,并发往苹果的AppStore服务器验证交易信息的真伪,验证通过后则修改当前App用户的账户余额信息(为了防止越狱和IAP free等插件造成的欺诈性购买)。之后将增加后的用户余额信息返回给App引用,此时用户看到app上显示充值成功并且自己的账户余额也发生了变化。

 

与服务器端的通信,就是一个RPC的过程,服务器端写好一些供调用的API接口,在客户端联网调用,具体有什么xmlrpc, jsonrpc的,都有开源的框架可以使用。注意:客户端与游戏服务器端通信的时候,必需附带一个标识其身份的代码(UUID或者帐号名称),否则服务器端无法知道是谁进行了充值。
Continue reading

PHP+JS 身份证号码有效性验证

PHP验证身份证号码有效性,可选是否验证用户性别

* 新的18位身份证号码各位的含义:
* 1-2位省、自治区、直辖市代码; 11-65
* 3-4位地级市、盟、自治州代码;
* 5-6位县、县级市、区代码;
* 7-14位出生年月日,比如19670401代表1967年4月1日;
* 15-17位为顺序号,其中17位男为单数,女为双数;
* 18位为校验码,0-9和X,由公式随机产生。
* 举例:
* 130503 19670401 0012这个身份证号的含义: 13为河北,05为邢台,03为桥西区,出生日期为1967年4月1日,顺序号为001,2为验证码。
*
*
* 15位身份证号码各位的含义:
* 1-2位省、自治区、直辖市代码;
* 3-4位地级市、盟、自治州代码;
* 5-6位县、县级市、区代码;
* 7-12位出生年月日,比如670401代表1967年4月1日,这是和18位号码的第一个区别;
* 13-15位为顺序号,其中15位男为单数,女为双数;
* 与18位身份证号的第二个区别:没有最后一位的验证码。
* 举例:
* 130503 670401 001的含义; 13为河北,05为邢台,03为桥西区,出生日期为1967年4月1日,顺序号为001。
Continue reading

根据银行卡号的前几位判断卡号信息

本判断需要依靠一个银行信息的记录,内容如下
bankList 下载下载Bank_list
[code type=php]
$bankList = [
‘621098’ => ‘邮储银行-绿卡通-借记卡’,
‘622150’ => ‘邮储银行-绿卡银联标准卡-借记卡’,
‘622151’ => ‘邮储银行-绿卡银联标准卡-借记卡’,
……
];

$card_8 = substr($card, 0, 8);
if (isset($bankList[$card_8])) {
return $bankList[$card_8];
}
$card_6 = substr($card, 0, 6);
if (isset($bankList[$card_6])) {
return $bankList[$card_6];
}
$card_5 = substr($card, 0, 5);
if (isset($bankList[$card_5])) {
return $bankList[$card_5];
}
$card_4 = substr($card, 0, 4);
if (isset($bankList[$card_4])) {
return $bankList[$card_4];
}[/code]

PHP+JS验证银行卡号

本规则只应对主流的LUHN卡号生成规则的银行卡,需要说明的LUHN规则只能验证卡号是否符合规则,并不能验证是否有这张卡。

关于LUHN卡号的信息:

LUHN算法,主要用来计算信用卡等证件号码的合法性。
1、从卡号最后一位数字开始,偶数位乘以2,如果乘以2的结果是两位数,将两个位上数字相加保存。
2、把所有数字相加,得到总和。
3、如果信用卡号码是合法的,总和可以被10整除。
英文描述:
1.Counting from the check digit, which is the rightmost, and moving left, double the value of every second digit.
2.Sum the digits of the products (e.g., 10: 1 + 0 = 1, 14: 1 + 4 = 5) together with the undoubled digits from the original number.
3.If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the Luhn formula; else it is not valid.

LUHN算法或是LUHN公式,也被称作“模10算法”。它是一种简单的校验公式,一般会被用于身份证号码,IMEI号码,美国供应商识别号码,或是加拿大的社会保险号码的验证。该算法是由IBM的科学家Hans Peter LUHN所创造,于1954年1月6日提出该专利的申请,并于1960年8月23日被授予,在美国的专利号为2950048。
该算法一直都被大家所公用,并且时至今日应用也很广泛。它被指定在ISO/IEC7812-1。它的目的不是成为一种加密安全的哈希函数;它的目的是防止意外出现的错误,而不是恶意攻击。很多信用卡和众多的政府身份识别号码都使用该算法从一系列的随机数字中提取有效的数字。
优点和缺点
LUHN算法会检测到任何单码的错误以及几乎所有的相邻数字换位的错误。但是它不会检测两个数字序列09转90的错误(反之亦然)。它会检测到十分之七的相同双位数错误(不会检测到22和55的互换,33和66的互换,44和77的互换)。其他更复杂的检查数字算法,如费尔赫夫算法,可以检测出更多的转录错误。模N的Luhn算法是Luhn算法的一个扩展,支持非数字字符串。因为该算法采取了从右向左的方式,而且零位会影响计算的结果。只有当零位造成了数位的移动或是用零来填充一串数字的开头时才不会影响计算结果的生成。因此不论在将1234用零填充为0001234之前或是之后,使用LUHN算法得到的结果都是一样的。
该算法在美国专利上是为了给手持或是机械设备计算校验码。所以它必须尽可能的简单。

此代码验证主要为16或者19位。个别特殊位数的不好做处理
PHP代码

if(!$bank_card_number || (strlen($bank_card_number) != 16 && strlen($bank_card_number) != 19)){
echo json_encode(array('success'=>false,'data'=>array('msg'=>'银行卡号长度错误')));
exit;
}
$luhn_check = false;//是否对卡号进行luhn规则校验
if($luhn_check){
//luhn运算 校验卡号
$bank_card_number = (string)$bank_card_number;
$len = strlen($bank_card_number) - 1;
$sum = 0;
for($i = 1; $i <= $len; $i++){
if($i%2==1){
if($bank_card_number[$i-1]<5){ $sum += 2 * $bank_card_number[$i-1]; }else{ $sum += 2 * $bank_card_number[$i-1] - 9; } }else{ $sum += $bank_card_number[$i-1]; } } if( (intval($sum) + intval(substr($bank_card_number,-1,1))) % 10 != 0){ echo json_encode(array('success'=>false,'data'=>array('msg'=>'银行卡号错误')));
exit;
}
}

Javascript代码

/**
* Created by CheungQ on 8/7/2015.
*
* Description: 银行卡号Luhn校验算法
*
* luhn校验规则:16位银行卡号(19位通用):
*
* 1.将未带校验位的 15(或18)位卡号从右依次编号 1 到 15(18),位于奇数位号上的数字乘以 2。
* 2.将奇位乘积的个十位全部相加,再加上所有偶数位上的数字。
* 3.将加法和加上校验位能被 10 整除。
*
* bankno位银行卡号
*/
var Luhn = {
luhnCheck:function(bankno){
if(bankno.length != 16 && bankno.length !=19){
return false;
}

var lastNum=bankno.substr(bankno.length-1,1);//取出最后一位(与luhn进行比较)

var first15Num=bankno.substr(0,bankno.length-1);//前15或18位
var newArr=new Array();
for(var i=first15Num.length-1;i>-1;i--){ //前15或18位倒序存进数组
newArr.push(first15Num.substr(i,1));
}
var arrJiShu=new Array(); //奇数位*2的积 <9 var arrJiShu2=new Array(); //奇数位*2的积 >9

var arrOuShu=new Array(); //偶数位数组
for(var j=0;j<newArr.length;j++){
if((j+1)%2==1){//奇数位
if(parseInt(newArr[j])*2<9) arrJiShu.push(parseInt(newArr[j])*2); else arrJiShu2.push(parseInt(newArr[j])*2); } else //偶数位 arrOuShu.push(newArr[j]); } var jishu_child1=new Array();//奇数位*2 >9 的分割之后的数组个位数
var jishu_child2=new Array();//奇数位*2 >9 的分割之后的数组十位数
for(var h=0;h<arrJiShu2.length;h++){
jishu_child1.push(parseInt(arrJiShu2[h])%10);
jishu_child2.push(parseInt(arrJiShu2[h])/10);
}

var sumJiShu=0; //奇数位*2 < 9 的数组之和 var sumOuShu=0; //偶数位数组之和 var sumJiShuChild1=0; //奇数位*2 >9 的分割之后的数组个位数之和
var sumJiShuChild2=0; //奇数位*2 >9 的分割之后的数组十位数之和
var sumTotal=0;
for(var m=0;m<arrJiShu.length;m++){
sumJiShu=sumJiShu+parseInt(arrJiShu[m]);
}

for(var n=0;n<arrOuShu.length;n++){
sumOuShu=sumOuShu+parseInt(arrOuShu[n]);
}

for(var p=0;p<jishu_child1.length;p++){
sumJiShuChild1=sumJiShuChild1+parseInt(jishu_child1[p]);
sumJiShuChild2=sumJiShuChild2+parseInt(jishu_child2[p]);
}
//计算总和
sumTotal=parseInt(sumJiShu)+parseInt(sumOuShu)+parseInt(sumJiShuChild1)+parseInt(sumJiShuChild2);

//计算luhn值
var k= parseInt(sumTotal)%10==0?10:parseInt(sumTotal)%10;
var luhn= 10-k;

if(lastNum==luhn){
return true;//luhn验证通过
}
else{
return false;//luhn验证不通过
}
}
};

另外并不是所有的银行卡都是遵循LUHN规则生成卡号的,比如:

发行机构 卡号开始 使用 卡号长度 验证方式
American Express 34, 37 Yes 15 Luhn algorithm
Bankcard 5610, 560221-560225 No 16 Luhn algorithm
China UnionPay 62 Yes 16-19 no validation
Diners Club Carte Blanche 300-305 Yes 14 Luhn algorithm
Diners Club enRoute 2014, 2149 No 15 no validation

所以目前主要流行的银行卡验证方法是通过汇款转账一个数额较小的指定金额(如1元5角3分),通过这笔转账交易确认银行卡及持卡人的真实性。

将数组被print_r出的字符串重新转换回PHP数组

和同事一起开发一个页面,因为进度问题,分工我帮写view层和一个稍微有点复杂的JS,同事那边controller层提供一个数组给我所需要的数据。因为同事有急事,当天走的匆忙,所以只给了我一个数组print_r后的字符串,因为数组较大,手动修改工作量很大,所以就google了下
找寻到如下代码,可以完美将字符串重新转换回数组。

特在此分享:

[code type=php]
function print_r_reverse(&$output)
{
$expecting = 0; // 0=nothing in particular, 1=array open paren ‘(‘, 2=array element or close paren ‘)’
$lines = explode(“\n”, $output);
$result = null;
$topArray = null;
$arrayStack = array();
$matches = null;
while (!empty($lines) && $result === null)
{
$line = array_shift($lines);
$trim = trim($line);
if ($trim == ‘Array’)
{
if ($expecting == 0)
{
$topArray = array();
$expecting = 1;
}
else
{
trigger_error(“Unknown array.”);
}
}
else if ($expecting == 1 && $trim == ‘(‘)
{
$expecting = 2;
}
else if ($expecting == 2 && preg_match(‘/^\[(.+?)\] \=\> (.+)$/’, $trim, $matches)) // array element
{
list ($fullMatch, $key, $element) = $matches;
if (trim($element) == ‘Array’)
{
$topArray[$key] = array();
$newTopArray =& $topArray[$key];
$arrayStack[] =& $topArray;
$topArray =& $newTopArray;
$expecting = 1;
}
else
{
$topArray[$key] = $element;
}
}
else if ($expecting == 2 && $trim == ‘)’) // end current array
{
if (empty($arrayStack))
{
$result = $topArray;
}
else // pop into parent array
{
// safe array pop
$keys = array_keys($arrayStack);
$lastKey = array_pop($keys);
$temp =& $arrayStack[$lastKey];
unset($arrayStack[$lastKey]);
$topArray =& $temp;
}
}
// Added this to allow for multi line strings.
else if (!empty($trim) && $expecting == 2)
{
// Expecting close parent or element, but got just a string
$topArray[$key] .= “\n”.$line;
}
else if (!empty($trim))
{
$result = $line;
}
}

$output = implode(n, $lines);
return $result;
}

/**
* @param string $output : The output of a multiple print_r calls, separated by newlines
* @return mixed[] : parseable elements of $output
*/
function print_r_reverse_multiple($output)
{
$result = array();
while (($reverse = print_r_reverse($output)) !== NULL)
{
$result[] = $reverse;
}
return $result;
}
[/code]
[code type=php]
$str = “Array
(
[0] => Array
(
[play_type_id] => 102
[play_type_name] => 三亚+其他
)

[1] => Array
(
[play_type_id] => 172
[play_type_name] => 三亚一地
)

)”;
$arr = print_r_reverse($str);
[/code]

© 2018 CheungQ

Theme by Anders NorénUp ↑