当前位置: 首页 > news >正文

佛山网站建设价格多少郑州网络营销哪个好

佛山网站建设价格多少,郑州网络营销哪个好,中信建设有限责任公司定州,wordpress 糗百文章目录 前言一、对账系统构建二、执行流程三、获取支付渠道数据1.接口形式1.1 后台配置1.2 脚本编写1.2.1 模板1.2.2 解析脚本 2.FTP形式2.1 后台配置2.2 脚本编写2.2.1 模板2.2.2 解析脚本 四、获取支付平台数据五、数据比对1. 比对模型2. 比对器 总结 前言 从《支付系统设…

文章目录

  • 前言
  • 一、对账系统构建
  • 二、执行流程
  • 三、获取支付渠道数据
    • 1.接口形式
      • 1.1 后台配置
      • 1.2 脚本编写
        • 1.2.1 模板
        • 1.2.2 解析脚本
    • 2.FTP形式
      • 2.1 后台配置
      • 2.2 脚本编写
        • 2.2.1 模板
        • 2.2.2 解析脚本
  • 四、获取支付平台数据
  • 五、数据比对
    • 1. 比对模型
    • 2. 比对器
  • 总结


前言

从《支付系统设计一:支付系统产品化》系列中支付网关系统设计我们知道,在对接支付渠道的时候只需要产品经理进行后台渠道相关信息的配置,以及开发人员编写的模板、脚本就能够完成支付渠道的对接了,同样的,通过此模式也可以完成支付系统和支付渠道的对账。


一、对账系统构建

在这里插入图片描述

对账系统构建在网关系统的基础上,将网关应用单独部署几个节点,作为对账系统。

在这里插入图片描述
需要解决的问题有:

  1. 作为对账的网关节点不能向注册中心注册服务,对账节点只是用来完成对账功能。
    项目有两个主启动类包,demo-reconmain依赖demo-main,其中通过demo-reconmain主启动类启动需要配置:
  // 对账节点不注册服务System.setProperty("eureka.client.register-with-eureka", "false");
  1. 作为处理交易的网关节点不能消费对账任务,网关节点只是用来完成交易功能。
  // 对账节点消费对账任务以及刷新任务System.setProperty("paygw.rabbit.flag", buildRabbitFlag(RabbitFlagConsts.ALL, RabbitFlagConsts.RECON));

关于这块,见以前写的篇博客《多机房控制消息消费方实现》

即通过此设计,支付网关系统又可以作为对账系统,可以很巧妙的解决支付渠道侧对账数据获取的问题。

二、执行流程

在这里插入图片描述

三、获取支付渠道数据

不同的支付渠道获取对账文件的方式也各不相同,有的是推送FTP,有的是通过接口下载等,文件类型也有所不同,有的是TEXT,有的是CSV等,文件内容格式也是各不相同,所以我们同样的套路,不同处使用脚本实现,将渠道侧数据解析入临时表。

1.接口形式

1.1 后台配置

如兴业银行的对账文件通过接口下载,那么我们需要配置下载对账文件的通讯信息:

在这里插入图片描述

1.2 脚本编写

1.2.1 模板

cib_depute_recon_main.vm

##单付对账脚本
#set($umask  = "1000")
#set($version =  "1.0.2")##版本号
#set($mchtId=$data.merExtends.merId)##渠道商户号
#set($signType="RSA")##签名类型
#set($serialNo=$DateUtil.getCurrentDateTimeStr()) ##渠道请求流水号使用时间
#set($transTime=$DateUtil.getCurrentDateTimeStr())##交易时间
#set($checkType="1")##D+1对账文件
#set($checkDate= $DateUtil.format($data.reconStartDate,"yyyyMMdd"))##对账日期yyyyMMdd
#set($businessMap =
{"version":"$!version","mchtId":"$!mchtId","signType":"$!signType","serialNo":"$!serialNo","transTime":"$!transTime","checkType":"$!checkType","checkDate":"$!checkDate"
})
#set($certCodePrivate=$data.merExtends.certCodePrivate)##商户自己的私钥
#set($businessStr=$MapUtils.generateParamStr($businessMap))
#set($mac=$certService.sign($certCodePrivate,$businessStr))##获取签名
#set($signMap =
{"mac":"$!mac"
})
$umask$JSON.toJSONString($MapUtils.putAll($businessMap,$signMap))

cib_depute_recon_header.vm

#set($map =
{"Content-Type":"application/json;charset=UTF-8"
})
$map

1.2.2 解析脚本

/*** @author Kkk* @Describe: 兴业银行代付对账解析*/
class CIBDeputeReconParser extends AbstractReconDataFetchParser{def logger = LoggerFactory.getLogger(CIBDeputeReconParser.class)def resp_code_success = ["E0000"]public static final String ALGORITHM = "SHA1PRNG"/** 证书服务*/@AutowiredCertService certService/*** 查询结果处理*/@OverrideReconDataFetchResult parse4ReconData(PayGwContext context, Object message) {Map<String, Object> data = context.getMessageDescription().getDatas()ReconDataFetchResult fetchResult = new ReconDataFetchResult()try {//验证签名(必须)def flag = verifySign(context, message)if (!flag) {//签名通过返回解析后的数据,不包含签名类型和签名数据throw new Exception("[兴业银行-单笔代付对账请求] 返回参数,验签失败!")}Object result = JSON.parse(message)JSONObject jobj = (JSONObject) resultdef respCode= jobj.get("respCode");def respMsg= jobj.get("respMsg");if(!resp_code_success.contains(respCode)){fetchResult.setSuccess(false)fetchResult.setRemark("兴业银行对账失败["+respCode+"]["+respMsg+"]");return fetchResult}String fileContent= jobj.get("fileContent")String aesKey= jobj.get("aesKey")//使用私钥解密aesKeydef certCodePrivate = context.getMessageDescription().getData("merExtends").get("certCodePrivate")def aesK=certService.decryptBase64(certCodePrivate,aesKey)//用解密得到的aesKey解密fileContentbyte[] afterFileContent =this.AESDecode(fileContent,aesK)//将得到的fileContent解码byte[] bb1 = BASE64.decodeCib(new String(afterFileContent,"utf-8").toCharArray())//解压缩byte[] dedata = FileUtils.decompress(bb1)//流读取文件内容并入表保存InputStream is = new ByteArrayInputStream(dedata)BufferedReader bufferedReadertry{def tempStrLoggerUtil.info(logger, "兴业银行-单付对账-文件-开始解析")bufferedReader = new BufferedReader(new InputStreamReader(is,"UTF-8"))//解析第一行def str=bufferedReader.readLine()LoggerUtil.info(logger, "解析第一行str:{}",str)while ((tempStr = bufferedReader.readLine()) != null) {if (StringUtils.isNotBlank(tempStr)) {LoggerUtil.info(logger, "兴业对账文件解析内容:{}",tempStr)String[] transStr = tempStr.split("\\|")ReconTrans reconTrans = convert2ReconTrans(transStr)store(context, reconTrans)}}} catch (Exception e) {logger.error("兴业银行-单笔代付-对账异常", e)fetchResult.setSuccess(false)fetchResult.setRemark(e.getMessage())} finally {if (bufferedReader != null) {try {bufferedReader.close()} catch (IOException e1) {}}}fetchResult.setSuccess(true)data.put(PayGwConstant.PAYGW_TRANS_STATUS, TransStatusEnum.SUCCESS.getCode())fetchResult.setRemark("兴业银行-单笔代付对账成功。")return fetchResult}catch (PayGwException e){LoggerUtil.error(logger, "[兴业银行-单笔代付对账请求失败]",  e);fetchResult.setSuccess(false)fetchResult.setRemark(e.getErrorMsg())return fetchResult}catch (Exception e){LoggerUtil.error(logger,"[兴业银行-单笔代付对账请求失败]:{}--异常信息",e)fetchResult.setSuccess(false)fetchResult.setRemark("兴业银行-单笔代付对账失败,paygw解析数据异常")return fetchResult}}/*** 验签*/boolean verifySign(PayGwContext context, String resData) {def certCodePublic = context.getMessageDescription().getData("merExtends").get("certCodePublic")Map<String,String> resMap=MapUtils.covertToJSON(resData);String mac=resMap.get("mac");//获取签约值resMap.remove("mac");String oriSign=MapUtils.generateParamStr(resMap);boolean  vflag=  certService.checkSign(certCodePublic,mac,oriSign)logger.info("兴业银行-单笔代付对账请求,请求返回签名值({}),验签结果({})",mac,vflag)return vflag}/*** 构建对象*/private ReconTrans convert2ReconTrans(def transStr) {ReconTrans trans = new ReconTrans()trans.setInstReqNo(transStr[0])trans.setAcctNo(transStr[1])trans.setTransCode(TransactionEnum.DEPUTE.code)trans.setTransAmount(new BigDecimal(transStr[4]))String dataStr=transStr[5]if(StringUtils.isNotEmpty(dataStr)){Date d=DateUtil.parseDateTime(dataStr,"yyyyMMddHHmmss")trans.setTransDateTime(d)trans.setTransDate(d)}trans.setTransStatus(TransStatusEnum.SUCCESS.code())return trans}/*** 使用AES解密fileContent*/static byte[] AESDecode(String str,String num) throws Exception{KeyGenerator kg = KeyGenerator.getInstance("AES");SecureRandom sr = SecureRandom.getInstance(ALGORITHM);sr.setSeed(num.getBytes());kg.init(128, sr);SecretKey sk = kg.generateKey();byte[] raw = sk.getEncoded();SecretKey key = new SecretKeySpec(raw,"AES");Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, key);byte[] str_AES = cipher.doFinal(HexConvertorUtil.hex2Bytes(str));return str_AES;}
}

2.FTP形式

2.1 后台配置

如平安银行的对账文件通过FTP下载,那么我们需要配置下载对账文件的通讯信息:
在这里插入图片描述

在这里插入图片描述

2.2 脚本编写

2.2.1 模板

pingan_depute_recon_main.vm

#set($umask  = "1000")
#set($map =
{"fileName":$!data.fileNameCHK
})
$umask$!MapUtils.toJsonStr($map)

2.2.2 解析脚本

/*** @author Kkk* @Describe: 平安银行单付对账文件解析*/
class PANBANKDeputeReconFilesParser extends AbstractReconDataFetchParser {Logger logger = LoggerFactory.getLogger(PANBANKDeputeReconFilesParser.class)def success = true, remark = '平安银行单付对账入库成功。', panbank_success = "0000"@OverrideReconDataFetchResult parse4ReconData(PayGwContext context, Object message) {ReconDataFetchResult fetchResult = new ReconDataFetchResult()Map<String, Object> data = context.getMessageDescription().getDatas()//先设置结果的扩展字段JSONObject extend = JSON.parseObject(StringUtils.valueOf(data.get("extend1")))logger.info("平安银行单付对账解析文件,第四步解析前extend值为:{}",extend)if (StringUtils.isNotBlank(message) && message.length > 0) {//解析文件,并入库parseFile(context, message)extend.put("stepOrder", 6)fetchResult.setExtend1(extend.toString())fetchResult.setSuccess(success)fetchResult.setRemark(remark)logger.info("平安银行单付对账解析文件data:{}",data)data.put(PayGwConstant.PAYGW_TRANS_STATUS, TransStatusEnum.SUCCESS.getCode())logger.info("平安银行单付对账解析文件,并入库fetchResult.setRemark-4:{}--extend:{}",fetchResult.getRemark(),extend)return fetchResult}fetchResult.setSuccess(false)fetchResult.setRemark("平安银行单付对账失败,文件下载失败。")logger.info("平安银行单付对账fetchResult.setRemark-4:{}--extend:{}",fetchResult.getRemark(),extend)return fetchResult}/*** 解析对账文件*/void parseFile(PayGwContext context, byte[] absoluteFilePath) {def line = null//获取对账文件的文件流InputStream is = new ByteArrayInputStream(absoluteFilePath)try {//按行读取对账文件LineReader xline = new LineReader(new InputStreamReader(is, "GBK"))//获取渠道文件集合List<ReconTrans> list = new ArrayList<>()boolean firstLine = truewhile ((line = xline.readLine()) != null) {//按行转换成对账流水记录ReconTrans reconTrans = convert2ReconTrans(line, firstLine)//从此以后再无第一行firstLine = falseif (reconTrans == null) {continue}list.add(reconTrans)}//入库for (ReconTrans trans : list) {store(context, trans)}} catch (PayGwException e) {//更新success = falseremark = '平安银行单付对账失败,原因:' + e.getErrorMsg()LoggerUtil.error(logger, "文件读取异常:", e)} catch (Exception e) {//更新success = falseremark = '平安银行单付对账失败'LoggerUtil.error(logger, "文件读取异常:", e)}finally {IOUtils.closeQuietly(is)}}private ReconTrans convert2ReconTrans(def lineStr, boolean firstLine) {ReconTrans trans = new ReconTrans()def transStatusdef item = lineStr.split("\\|\\:\\:\\|", -1)def transDate = item[0]def instReqNo = item[3]def acctNo = item[5]def transAmt = new BigDecimal(item[6])//0000 成功 其余为失败def errorCode = item[10]//交易状态(平安银行对账文件全为成功数据)if (StringUtils.equals(errorCode, panbank_success)) {transStatus = TransStatusEnum.SUCCESS.code()} else {//其他状态不入库return null}trans.setTransStatus(transStatus)trans.setInstReqNo(instReqNo)trans.setTransCode(TransactionEnum.DEPUTE.code)//用户卡号trans.setAcctNo(acctNo)//交易金额trans.setTransAmount(transAmt)//交易日期trans.setTransDate(DateUtil.parseDate(transDate, "yyyyMMdd"))//交易时间,因对账文件中不存在交易时间,故将交易日期入库trans.setTransDateTime(DateUtil.parseDateTime(transDate, "yyyyMMdd"))return trans}
}

四、获取支付平台数据

直接使用SQL查询出对应支付渠道的对应的交易类型的交易数据。

五、数据比对

拉取两侧数据,构建数据比对模型放到内存中进行数据比对

1. 比对模型

/*** @author Kkk* @Describe: 对账-比对模型*/
public class CompareModel {/*** 唯一索引*/private String uniqueIndex;/*** 值*/private String value;/*** 业务流水ID*/private Long transId;
}

2. 比对器

/*** @author Kkk* @Describe: 对账-比较器定义*/
public interface IComparator {IComparator putOrigins(List<CompareModel> origins);IComparator putTargets(List<CompareModel> targets);CompareResult compare();
}

总结

后文详细展开具体实现。


文章转载自:
http://measles.rywn.cn
http://disamenity.rywn.cn
http://bullhorn.rywn.cn
http://limean.rywn.cn
http://jauntily.rywn.cn
http://turkomen.rywn.cn
http://wintry.rywn.cn
http://fonduta.rywn.cn
http://escabeche.rywn.cn
http://nonius.rywn.cn
http://cooperativize.rywn.cn
http://anecdotage.rywn.cn
http://gadabout.rywn.cn
http://nizamate.rywn.cn
http://sukiyaki.rywn.cn
http://shipbuilder.rywn.cn
http://lipopexia.rywn.cn
http://kraakporselein.rywn.cn
http://midiron.rywn.cn
http://ovibovine.rywn.cn
http://woodprint.rywn.cn
http://rearwards.rywn.cn
http://justification.rywn.cn
http://serpentinize.rywn.cn
http://verity.rywn.cn
http://smokeless.rywn.cn
http://mechanical.rywn.cn
http://haneda.rywn.cn
http://sherry.rywn.cn
http://vagary.rywn.cn
http://dnieper.rywn.cn
http://vertically.rywn.cn
http://stiver.rywn.cn
http://organa.rywn.cn
http://bure.rywn.cn
http://preferences.rywn.cn
http://fastidiousness.rywn.cn
http://athenai.rywn.cn
http://preengage.rywn.cn
http://granddaughter.rywn.cn
http://basaltoid.rywn.cn
http://stockholder.rywn.cn
http://periphyton.rywn.cn
http://paraselene.rywn.cn
http://waterward.rywn.cn
http://lappic.rywn.cn
http://ventriculoperitoneal.rywn.cn
http://lpt.rywn.cn
http://polylith.rywn.cn
http://notaphily.rywn.cn
http://slightness.rywn.cn
http://alumnae.rywn.cn
http://rutherford.rywn.cn
http://veiling.rywn.cn
http://shutdown.rywn.cn
http://idahoan.rywn.cn
http://afdc.rywn.cn
http://cingulotomy.rywn.cn
http://sweetening.rywn.cn
http://formulization.rywn.cn
http://bibliographical.rywn.cn
http://passe.rywn.cn
http://markdown.rywn.cn
http://iatrochemist.rywn.cn
http://esc.rywn.cn
http://swizz.rywn.cn
http://wilmer.rywn.cn
http://blastopore.rywn.cn
http://hydrobomb.rywn.cn
http://overdrawn.rywn.cn
http://monstrance.rywn.cn
http://state.rywn.cn
http://uninquiring.rywn.cn
http://chapped.rywn.cn
http://demystification.rywn.cn
http://hodiernal.rywn.cn
http://halitosis.rywn.cn
http://pentecost.rywn.cn
http://mallenders.rywn.cn
http://gumweed.rywn.cn
http://abruption.rywn.cn
http://hyperglycaemia.rywn.cn
http://weeklong.rywn.cn
http://depressible.rywn.cn
http://unimodular.rywn.cn
http://gynaeceum.rywn.cn
http://undyed.rywn.cn
http://resiliometer.rywn.cn
http://cardcastle.rywn.cn
http://sketchily.rywn.cn
http://grivet.rywn.cn
http://primiparity.rywn.cn
http://grandly.rywn.cn
http://moped.rywn.cn
http://whit.rywn.cn
http://glissando.rywn.cn
http://marvy.rywn.cn
http://dealate.rywn.cn
http://labyrinthectomy.rywn.cn
http://chondroitin.rywn.cn
http://www.15wanjia.com/news/78456.html

相关文章:

  • 网站建设年终总结怎么写互联网广告行业
  • 上传网站到虚拟主机网络推广和网站推广平台
  • 南昌媒体网站建设口碑推荐免费发布活动的平台
  • 佛山低价网站建设郑州网站排名优化外包
  • 南京网站设计建设成都网络营销推广
  • 淘宝店有给网站做优化am百度关键词排名怎么做
  • 网站做微信小程序如何做网站网页
  • 培训建设网站小程序开发文档
  • 电商跟开网店是一样吗广东seo网站设计
  • 杭州建设工程信用平台郑州seo哪家好
  • 专门做日本旅游的网站有哪些关键词列表
  • 建设网站网址是多少seo营销名词解释
  • 案例较少如何做设计公司网站安卓aso优化排名
  • 网站建设预览bilibili官网网页入口
  • 免费html网站代码优化seo哪家好
  • 如何建立公司网站?免费网站推广产品
  • 建设开源社区网站什么意思高州新闻 头条 今天
  • 计算机培训班出来好找工作吗王通seo教程
  • 保定外贸网站制作今日重大新闻头条十条
  • 广州微网站建设机构关键词生成器
  • 深圳seo优化电话seo实战培训视频
  • 营销网站的搭建怎么看app的下载网址
  • 网站动态海报效果怎么做的竞价排名的定义
  • letsencrypt wordpress如何做谷歌优化
  • 网站开发日程表百度怎么联系客服
  • 购物网站seo关键词定位软文广告范文
  • 非响应式网站优点哈市今日头条最新
  • 福州思企互联网站建设公司怎么样站长工具ip查询
  • 专业独立门户网站建设互联网营销是什么
  • 网站风格包括什么百度问答seo