adyen[apionly]直连接入card

1.[2022-03-07]cvv/cvc除了amex是4,其余都按3位处理

2.[2022-03-07]cardbin验证规则

nf.cards.push({cardType:"mc",startingRules:[51,52,53,54,55,22,23,24,25,26,27],permittedLengths:[16],pattern:/^(5[1-5][0-9]{0,14}|2[2-7][0-9]{0,14})$/,securityCode:"CVC"}),
nf.cards.push({cardType:"visadankort",startingRules:[4571],permittedLengths:[16],pattern:/^(4571)[0-9]{0,12}$/}),
nf.cards.push({cardType:"visa",startingRules:[4],permittedLengths:[13,16,19],pattern:/^4[0-9]{0,18}$/,securityCode:"CVV"}),
nf.cards.push({cardType:"amex",startingRules:[34,37],permittedLengths:[15],pattern:/^3[47][0-9]{0,13}$/,securityCode:"CID"}),
nf.cards.push({cardType:"diners",startingRules:[36],permittedLengths:[14],pattern:/^(36)[0-9]{0,12}$/}),
nf.cards.push({cardType:"maestrouk",startingRules:[6759],permittedLengths:[16,18,19],pattern:/^(6759)[0-9]{0,15}$/}),
nf.cards.push({cardType:"solo",startingRules:[6767],permittedLengths:[16,18,19],pattern:/^(6767)[0-9]{0,15}$/}),
nf.cards.push({cardType:"laser",startingRules:[6304,6706,677117,677120],permittedLengths:[16,17,18,19],pattern:/^(6304|6706|6709|6771)[0-9]{0,15}$/,cvcPolicy:"optional"}),
nf.cards.push({cardType:"discover",startingRules:[6011,644,645,646,647,648,649,65],permittedLengths:[16],pattern:/^(6011[0-9]{0,12}|(644|645|646|647|648|649)[0-9]{0,13}|65[0-9]{0,14})$/}),
nf.cards.push({cardType:"jcb",startingRules:[3528,3529,353,354,355,356,357,358],permittedLengths:[16,19],pattern:/^(352[8,9]{1}[0-9]{0,15}|35[4-8]{1}[0-9]{0,16})$/,securityCode:"CAV"}),
nf.cards.push({cardType:"bcmc",startingRules:[6703,479658,606005],permittedLengths:[16,17,18,19],pattern:/^((6703)[0-9]{0,15}|(479658|606005)[0-9]{0,13})$/,cvcPolicy:"hidden"}),
nf.cards.push({cardType:"bijcard",startingRules:[5100081],permittedLengths:[16],pattern:/^(5100081)[0-9]{0,9}$/}),
nf.cards.push({cardType:"dankort",startingRules:[5019],permittedLengths:[16],pattern:/^(5019)[0-9]{0,12}$/}),
nf.cards.push({cardType:"hipercard",startingRules:[606282],permittedLengths:[16],pattern:/^(606282)[0-9]{0,10}$/}),
nf.cards.push({cardType:"cup",startingRules:[62,81],permittedLengths:[14,15,16,17,18,19],pattern:/^(62|81)[0-9]{0,17}$/}),
nf.cards.push({cardType:"maestro",startingRules:[50,56,57,58,6],permittedLengths:[16,17,18,19],pattern:/^(5[0|6-8][0-9]{0,17}|6[0-9]{0,18})$/,cvcPolicy:"optional"}),
nf.cards.push({cardType:"elo",startingRules:[506699,50670,50671,50672,50673,50674,50675,50676,506770,506771,506772,506773,506774,506775,506776,506777,506778,401178,438935,451416,457631,457632,504175,627780,636297,636368],permittedLengths:[16],pattern:/^((((506699)|(506770)|(506771)|(506772)|(506773)|(506774)|(506775)|(506776)|(506777)|(506778)|(401178)|(438935)|(451416)|(457631)|(457632)|(504175)|(627780)|(636368)|(636297))[0-9]{0,10})|((50676)|(50675)|(50674)|(50673)|(50672)|(50671)|(50670))[0-9]{0,11})$/}),
nf.cards.push({cardType:"uatp",startingRules:[1],permittedLengths:[15],pattern:/^1[0-9]{0,14}$/,cvcPolicy:"optional"}),
nf.cards.push({cardType:"cartebancaire",startingRules:[4,5,6],permittedLengths:[16],pattern:/^[4-6][0-9]{0,15}$/}),
nf.cards.push({cardType:"visaalphabankbonus",startingRules:[450903],permittedLengths:[16],pattern:/^(450903)[0-9]{0,10}$/}),
nf.cards.push({cardType:"mcalphabankbonus",startingRules:[510099],permittedLengths:[16],pattern:/^(510099)[0-9]{0,10}$/}),
nf.cards.push({cardType:"hiper",startingRules:[637095,637568,637599,637609,637612],permittedLengths:[16],pattern:/^(637095|637568|637599|637609|637612)[0-9]{0,10}$/}),
nf.cards.push({cardType:"oasis",startingRules:[982616],permittedLengths:[16],pattern:/^(982616)[0-9]{0,10}$/,cvcPolicy:"optional"}),
nf.cards.push({cardType:"karenmillen",startingRules:[98261465],permittedLengths:[16],pattern:/^(98261465)[0-9]{0,8}$/,cvcPolicy:"optional"}),
nf.cards.push({cardType:"warehouse",startingRules:[982633],permittedLengths:[16],pattern:/^(982633)[0-9]{0,10}$/,cvcPolicy:"optional"}),
nf.cards.push({cardType:"mir",startingRules:[220],permittedLengths:[16,17,18,19],pattern:/^(220)[0-9]{0,16}$/}),
nf.cards.push({cardType:"codensa",startingRules:[590712],permittedLengths:[16],pattern:/^(590712)[0-9]{0,10}$/}),
nf.cards.push({cardType:"naranja",startingRules:[377798,377799,402917,402918,527571,527572,589562],permittedLengths:[16,17,18,19],pattern:/^(37|40|5[28])([279])\d$/}),
nf.cards.push({cardType:"cabal",startingRules:[589657,600691,603522,6042,6043,636908],permittedLengths:[16,17,18,19],pattern:/^(58|6[03])([03469])\d$/}),
nf.cards.push({cardType:"shopping",startingRules:[2799,589407,603488],permittedLengths:[16,17,18,19],pattern:/^(27|58|60)([39])\d$/}),
nf.cards.push({cardType:"argencard",startingRules:[501],permittedLengths:[16,17,18,19],pattern:/^(50)(1)\d$/}),
nf.cards.push({cardType:"troy",startingRules:[9792],permittedLengths:[16],pattern:/^(97)(9)\d$/}),
nf.cards.push({cardType:"forbrugsforeningen",startingRules:[600722],permittedLengths:[16],pattern:/^(60)(0)\d$/}),
nf.cards.push({cardType:"vpay",startingRules:[401,408,413,434,435,437,439,441,442,443,444,446,447,455,458,460,461,463,466,471,479,482,483,487],permittedLengths:[13,14,15,16,17,18,19],pattern:/^(40[1,8]|413|43[4,5]|44[1,2,3,4,6,7]|45[5,8]|46[0,1,3,6]|47[1,9]|48[2,3,7])[0-9]{0,16}$/}),
nf.cards.push({cardType:"rupay",startingRules:[508528],permittedLengths:[16],pattern:/^(100003|508(2|[5-9])|60(69|[7-8])|652(1[5-9]|[2-5][0-9]|8[5-9])|65300[3-4]|8172([0-1]|[3-5]|7|9)|817(3[3-8]|40[6-9]|410)|35380([0-2]|[5-6]|9))[0-9]{0,12}$/})

cardType 卡组
startingRules 卡号开头匹配
permittedLengths 总长度
pattern 完整卡号正则

securityCode:"CVV"
securityCode:"CID"
securityCode:"CVC"
securityCode:"CAV"
这些只是对cvv的不同叫法而已

3.[2022-03-07]建议:

传输:用户输入的信息要加密后(eg:RSA)在传输.
存储:
cvc/cvv不可以持久化存储, 也不可以写日志,
完整卡号不持久化存储(除非有特殊需求在做pci的时候就要完整保存,有单独的整改项),不写日志
前6后4可以持久化存储,可以写日志
日期:可以加密持久化存储,不写日志
持卡人姓名:可以加密持久化存储,不写日志

4.[2022-03-16].双标卡的话,可以做成让用户选择走哪个卡组,如果简化的话那就自己写逻辑选择走哪个卡组[见第五条]

效果大致


image.png

image.png

5.[2022-03-16]双标卡的话可能会出现一个卡多个卡组,如果涉及支付路由的话要自己考虑这种情况然后按照自己的偏好来选择走哪个卡组的路由

6.[2022-03-26]3ds的适配页面可以通过challenge的一个参数来指定

const cReqData = {threeDSServerTransID : pResp.additionalData['threeDSServerTransID'],
    acsTransID : pResp.additionalData['acsTransID'],
    messageVersion : pResp.additionalData['.messageVersion'],
    challengeWindowSize : '05',
    messageType : 'CReq'
}

identifier           size
    01          250px x 400px
    02          390px x 400px
    03          500px x 600px
    04          600px x 400px
    05          100% x 100%

7.[2022-03-26]如果一个卡号可以同时命中多个规则,可以调用接口/cardBinDetails来确定是哪个卡组,如果还是能拿到多个卡组信息就说明是双标卡,可以按双标卡的逻辑走

即使luhncheck检查过了只要cardBinDetails查询不到或者报错
{"status":422,"errorCode":"193","message":"Bin Details not found for the given card number","errorType":"validation"}
可以认为当前卡不支持则不需要在继续了

8.[2022-04-17]使用adyen token 绑的卡如果过期了,绑定关系不会自动解除,会返回卡过期的报错,如果要自动更新过期时间可以参考这2个产品

1.account updater: https://docs.adyen.com/online-payments/account-updater
2.network token:https://docs.adyen.com/online-payments/network-tokenization

adyentoken都是有network_token对应的.如果银行不支持network_ token的话那么adyen_token也是与明文卡号关联的
理论上绑卡的3ds只会在第一次绑卡时才会需要验证信息后续的绑卡交易都不需要3ds验证了

9.[2022-04-17]3ds相关

3ds2
https://docs.adyen.com/checkout-build-your-own-3ds2
3ds1
https://docs.adyen.com/online-payments/3d-secure/redirect-3ds2-3ds1
https://docs.adyen.com/online-payments/api-only/handling-redirects
自己实现3ds接入的方式
1.web形式的3ds,适用于web与app
要实现web形式的3ds是需要一个中间页来处理3ds第二步第三步的交互
2.app based
需要拿到EMVCO的证书

参考https://www.emvco.com/processes-forms/certification/

10.[2022-04-17]一笔交易发起后到底是走3ds1还是3ds2是卡组的服务器、银行端[acs服务器]、用户端[卡是否已注册3ds1/3ds2]等因素有关

11.[2022-04-17]Amex支持的币种是与公司主体有关的不可随意扩充

12.[2022-04-17]adyen是支持0元绑卡的,可以用户先绑卡后续在支付,绑卡的好处不用多说了1.体验很好2.成功率会比较高

13.[2022-04-17]0元绑卡的话有一些点需要注意1.用户账单会有个记录体现2.如果有一些银行不支持0元绑卡则adyen会将金额会变为非0授权后在取消授权来实现绑卡,首次绑卡也有可能要做一次3ds

14.[2022-04-17]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,174评论 11 349
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,687评论 2 59
  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,599评论 1 180
  • 2021-08-09: POJO类中布尔类型的变量,命名时不要加is,否则部分框架解析时会引起序列化错误。(因为在...
    windUtterance阅读 1,055评论 0 3
  • 我印象里,身边的老人们,总喜欢把一句话挂在嘴边:“生活不如意事,十之八九!人嘛,总得,自己学会适应生活!”...
    cf96731e55b0阅读 1,749评论 0 4