首先普及一下银行卡号组成信息,
银行卡号一般由三部分组成:
- 发卡行标识代码(BIN号)
- 发卡行自定义位
- 校验码。
银行卡号的前6位是BIN号,是bank identification number的缩写,由国际标准化组织(ISO)分配给各从事跨行转接交换的银行卡组织。
一般地:4字头——VISA;5字头——Mastercard;62——中国银联;3字头——运通、JCB等。
发卡行自定义位长度可以是6-12位,一般可能会包含银行内部分行标识,比如第6-7位,01代表北京地区的卡,其余的就是随即生成了。
最后卡号最末位的校验码,具有一定的计算规则,用于防伪。银联标准卡符合中国银联标准,使用中国银联分配的BIN码(目前为622126-622925,共800个),在中国银联支付网络范围和协议网络下使用。
项目添加银行卡信息时,有这样一个需求,要求当用户输入银行卡后自动检测出该银行卡属于哪家银行。
本文实现自定义EditText,根据银行卡号判断该银行卡所归属的银行,格式化银行卡号,每四位增加一个空格。数据来源网络整理,并不及时,只供参考学习。
先看效果图:
使用方式
<com.aikaifa.bankcard.BandCardEditText
android:id="@+id/bankCardEditText"
android:layout_width="match_parent"
android:background="@drawable/bg_edittext"
android:padding="10dp"
android:layout_height="40dp"
android:hint="请输入银行卡号" />
tv_desc = (TextView) findViewById(R.id.tv_desc);
bankCardEditText = (BandCardEditText) findViewById(R.id.bankCardEditText);
bankCardEditText.setBankCardListener(new BandCardEditText.BankCardListener() {
@Override
public void success(String name) {
tv_desc.setText(name);
}
@Override
public void failure() {
tv_desc.setText("没有查到所属银行");
}
});
实现过程:
1、新建类BandCardEditText继承EditText
public class BandCardEditText extends EditText {
private boolean shouldStopChange = false;
private final String space = " ";
private BankCardListener listener;
public BandCardEditText(Context context) {
this(context, null);
}
public BandCardEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BandCardEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
format(getText());
shouldStopChange = false;
setFocusable(true);
setEnabled(true);
setFocusableInTouchMode(true);
addTextChangedListener(new BandCardWatcher());
}
class BandCardWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable editable) {
format(editable);
}
}
private void format(Editable editable) {
if (shouldStopChange) {
shouldStopChange = false;
return;
}
shouldStopChange = true;
String str = editable.toString().trim().replaceAll(space, "");
int len = str.length();
int courPos;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < len; i++) {
builder.append(str.charAt(i));
if (i == 3 || i == 7 || i == 11 || i == 15) {
if (i != len - 1)
builder.append(space);
}
}
courPos = builder.length();
setText(builder.toString());
setSelection(courPos);
if (listener != null) {
if (isBankCard()) {
char[] ss = getBankCardText().toCharArray();
listener.success(BankInfo.getNameOfBank(ss, 0));
} else {
listener.failure();
}
}
}
public String getBankCardText() {
return getText().toString().trim().replaceAll(" ", "");
}
public boolean isBankCard() {
return checkBankCard(getBankCardText());
}
/**
* 校验银行卡卡号
* @param cardId
* @return
*/
public boolean checkBankCard(String cardId) {
if(TextUtils.isEmpty(cardId)) {
return false;
}
char bit = getBankCardCheckCode(cardId.substring(0, cardId.length() - 1));
if (bit == 'N') {
return false;
}
return cardId.charAt(cardId.length() - 1) == bit;
}
/**
*
* @param nonCheckCodeCardId
* @return
*/
public char getBankCardCheckCode(String nonCheckCodeCardId) {
if (TextUtils.isEmpty(nonCheckCodeCardId)
|| !nonCheckCodeCardId.matches("\\d+")
|| nonCheckCodeCardId.length() < 16
|| nonCheckCodeCardId.length() > 19) {
//如果传的不是数据返回N
return 'N';
}
char[] chs = nonCheckCodeCardId.trim().toCharArray();
int sum = 0;
for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
int k = chs[i] - '0';
if (j % 2 == 0) {
k *= 2;
k = k / 10 + k % 10;
}
sum += k;
}
return (sum % 10 == 0) ? '0' : (char) ((10 - sum % 10) + '0');
}
public void setBankCardListener(BankCardListener listener) {
this.listener = listener;
}
public interface BankCardListener {
void success(String name);
void failure();
}
}
源码下载地址 https://pan.baidu.com/s/1qYfJoRy
【END】