1.Java接入银联支付(chinapay)教程及避坑点

这篇具有很好参考价值的文章主要介绍了1.Java接入银联支付(chinapay)教程及避坑点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、背景及效果展示

现如今,诸多的供应链系统需要使用电子钱包功能,所以接入银联B2B无卡支付,是很多系统应用需要做的事情。银联支付的类型分很多种:网关支付(带token请求实现,下次有空再分享)、B2B无卡支付(带证书秘钥请求实现)分商户和机构入网,具体和更详细的内容可以去看中国银联开放平台,今天这里主要针对于企业中所涉及的的B2B无卡快捷支付做介绍与讲解。

二、B2B快捷支付流程

java对接银联支付,第三方支付,java,前端

此流程图在商户接入手册中有展示,可以在文档中详细查看

2.1 B2B支付流程介绍

java对接银联支付,第三方支付,java,前端

我们正常做的B2B支付对于银联来说,即是前台支付(B2B业务中都是前台支付),后台支付不用管。

整体流程走向:

1.通过后端先将支付请求的参数构建好并返回给到前端,前端请求银联的前台支付地址;

2.前端处理银联的响应信息(银联返回的是页面,可新开页签),后续到支付流程都是银联侧;
java对接银联支付,第三方支付,java,前端

**注:**此处没有进行银行的选择,是在进行支付请求时传递了银行的机构码,银联的网关前置功能会自动跳转至对应的银联支付页面

3.填写银行卡密码等信息,填写完成后点击支付

4.支付完成后,银联会回调我们的后端回调接口或前端页面(前端页面回调地址可不传,采用手动关闭银联的页面)

5.接收到银行的支付回调信息后,主动调 交易查询接口 进行当前订单的支付状态

6.对支付回调信息与交易查询的响应信息进行处理,判断支付状态,进行后续的业务操作

**后续(退款类)**交易接口与支付流程基本一致,不过后续(退款类)交易接口是直接通过后端完成即可

三、前置工作

当接入银联无卡支付的时候,会有银联的对接人给你们申请,通过邮件发送开发所需的文件,如下:
java对接银联支付,第三方支付,java,前端

1、开发文档ChinaPay新一代商户接入手册_20220616.pdf

2、公钥证书 CP.rar,需要解压此rar文件

3、usexxx.zip,私钥和密码压缩包,需解压后,生成私钥xxxxxxxx.sm2和密码

4、插件包,里面提供了Java、.net、C和PHP的插件包,java核心jar包就是chinapaysecure-sm-1.0.jar,通过此jar中的方法进行签名的生成、验签,加密解密
java对接银联支付,第三方支付,java,前端

5、需要联系银联的对接人员开通B2B支付的测试账号

6、让银联方配置测试ip白名单,固定的对外IP

**注:**如果确实需要银联方提供demo参考(不建议),可让对接人员提供,demo本身基于servlet + jsp构建的eclipse项目,注释也很少,有问题建议直接跟银联方沟通,确认好自己的需求,效率会高很多。

四、正式接入

4.1 新建私钥及证书配置文件

在当前项目下,新建security.properties文件,配置好对应的公私钥及密码等信息

#报文中不参与签名的字段名称,多个字段用逗号进行分隔
sign.invalid.fields=Signature,CertId
#报文中签名的字段名称
signature.field=Signature
#是否输出调试日志,true输出,其他只输出错误日志
log.info=false
#私钥算法
secss.privateAlg=SM2
#私钥路径
secss.privatePath=/xxx/xxx.sm2
#私钥密码
secss.privatePwd=a111111
#公钥算法
secss.publicAlg=SM2
#公钥路径
secss.publicPath=/xxx/xxx.cer
#是否排除过期秘钥
secss.excludeExpiredCert=true

注:公私钥路径最好采用文件的绝对路径

4.2 引入chinapaysecure-sm-1.0.jar

项目中使用maven或gradle进行依赖管理时,可先将此jar包解压至本地仓库,后通过maven的gav坐标将其引入(gradle引入依赖与此类似)

<dependency>
	<groupId>com.unionpay</groupId>
	<artifactId>chinapaysecure-sm</artifactId>
	<version>1.0</version>
</dependency>

注:如果maven仓库是采用的私服仓库,上传了这个jar后,如果项目中无法获取,需要检查仓库的更新策略,具体可以联系公司内的相关人员进行处理

4.3 代码接入

4.3.1 核心工具类 SecssUtil 初始化

@Slf4j
@Configuration
public class SecssConfig {

    @Value("${china.pay.securityUrl}")
    private String securityUrl;

    @Bean
    public SecssUtil init(){
        //执行secss初始化
        SecssUtil secssUtil = new SecssUtil();
        boolean bool = secssUtil.init(securityUrl);
        if (bool) {
            log.info("ChinaPay交易证书、验签证书初始化成功!");
        } else {
            log.error("ChinaPay交易证书、验签证书初始化失败:"+secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());
        }
        return secssUtil;
    }

}

4.3.2 构建支付请求参数

@Autowired
private SecssUtil secssUtil;

private TreeMap<String,Object> buildPayParams(SendPayReq payReq){
        TreeMap<String,Object> req = new TreeMap<>();
        req.put(Constants.VERSION,Constants.REQUEST_VERSION);
        req.put(Constants.MER_ID,merId);
        req.put(Constants.MER_ORDER_NO,payReq.getPayOrderId());
        req.put(Constants.TRAN_DATE, TimeUtil.date2String(LocalDate.now()));
        req.put(Constants.TRAN_TIME,TimeUtil.time2String(LocalTime.now()));
        //元转分
        Long orderAmt = payReq.getRemitterAmt().multiply(new BigDecimal(100)).longValue();
        req.put(Constants.ORDER_AMT,orderAmt.toString());
        req.put(Constants.BUSI_TYPE,Constants.BUSINESS_TYPE);
        //req.put("BankInstNo", param.getAccCode()); // 支付机构号-银联在线支付(这个参数必填,如果是无卡支付前端请求,否则会失败)
        //req.put("TranType",Constants.PAY_TRAN_TYPE);
        //支付接口后端回调地址
        req.put(Constants.MER_BG_URL,backPayUrl);
        //付款支付完成后跳转至的系统前台展示地址
        if (StringUtils.isNotEmpty(payReq.getMerPageUrl())){
            req.put("MerPageUrl",payReq.getMerPageUrl());
        }
        req.put(Constants.REMOTE_ADDR,remoteAddr);
        secssUtil.sign(req);
        log.info("支付交易签名响应is {},信息 {}",secssUtil.getErrCode(),secssUtil.getErrMsg());
        String sign = secssUtil.getSign();
        req.put(Constants.SIGNATURE,sign);
        return req;
   }

4.3.3 接收支付回调

支付完成后,银联会回调我们的这个接口,具体内容及接收方法课看下第五大点中的5.3回调接口

4.3.4 构建交易查询接口参数

	/**
     * 构建银联商务交易查询参数
     * @param param
     * @return
     */
    private TreeMap<String,Object> buildQueryPayParams(AccountStorageQueryReq param){
        TreeMap<String,Object> req = new TreeMap<>();
        req.put(Constants.VERSION,Constants.REQUEST_VERSION);
        req.put(Constants.MER_ID,merId);
        req.put(Constants.MER_ORDER_NO,param.getPayOrderId());
        req.put(Constants.TRAN_DATE, param.getOriTranDate());
        req.put(Constants.TRAN_TYPE,Constants.QUERY_TRAN_TYPE);
        req.put(Constants.BUSI_TYPE,Constants.BUSINESS_TYPE);
        secssUtil.sign(req);
        log.info("商务交易签名响应is {},信息 {}",secssUtil.getErrCode(),secssUtil.getErrMsg());
        String sign = secssUtil.getSign();
        req.put(Constants.SIGNATURE,sign);
        return req;
    }

五、注意点

5.1 参数类型

在向银联发起支付、交易查询、退款类等请求时,虽说文档中每个字段类型各异,但实际上所有参数都是string类型

5.2 字段解密

如果需要对银行的返回信息中某个字段需要进行解密时,需要先注意下返回的加密信息是否含有 “%”,如果含有,则需要先通过url解码对字符串解码,去除该特殊符号,然后继续采用解密方法进行解密

import java.net.URLDecoder;

public String getDecData(String encData){
        try {
            //对加密内容进行url解码
            String cardTranData = URLDecoder.decode(encData, Charsets.UTF_8);
            //调用核心类方法进行解密
            secssUtil.decryptData(cardTranData);
            //获取解密后的内容
            String cardData = secssUtil.getDecValue();
            if (StringUtils.isNotEmpty(cardData)){
                Map map = JSONObject.parseObject(cardData, Map.class);
                return (String)map.get("CardNo");
            }else {
                return "";
            }
        }catch (Exception e){
            log.warn("银行账户字段解签错误");
            return "";
        }
  }
5.3 回调接口

我们接收银联回调的接口,地址需要能直接被银联方访问到,(公网地址,并配置银联的白名单)。采用HttpServletRequest接收参数,并用获取paramMap方法拿到所有的响应参数内容

/**
     * 银联支付接口异步回调
     * @return
     */
@PostMapping("/")
public ApiResult<Void> payCallback(HttpServletRequest request){
    Map<String, String[]> parameterMap = request.getParameterMap();
    log.info("4.1支付异步回调响应信息 is {}",parameterMap);
    if (CollectionUtils.isEmpty(parameterMap)){
        return ApiResult.fail("4.1支付异步回调响应信息为空");
    }
    return ApiResult.ok();
}
5.4 请求参数签名

银联构建的所有参数都需要进行签名(签名字段本身除外),然后一起组装到请求参数中,发送至银联的对应接口文章来源地址https://www.toymoban.com/news/detail-657672.html

public String getSign(TreeMap<String,Object> req){
        secssUtil.sign(req);
        log.info("待签名信息is {},签名响应: {}",secssUtil.getErrCode(),secssUtil.getErrMsg());
        String sign = secssUtil.getSign();
        return sign;
  }
联的对应接口

```java
public String getSign(TreeMap<String,Object> req){
        secssUtil.sign(req);
        log.info("待签名信息is {},签名响应: {}",secssUtil.getErrCode(),secssUtil.getErrMsg());
        String sign = secssUtil.getSign();
        return sign;
  }

到了这里,关于1.Java接入银联支付(chinapay)教程及避坑点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一文搞定Windows11+WSL+Pycharm开发环境及避坑

    众所周知,虽然Windows和Linux都可以运行Python,但是对很多Python扩展包的支持是不一样的。 比如 深度学习相关的pytorch 比如 自动化运维相关的ansible 小编本人也尝试将Ubuntu作为自己的主系统,并且为了逼自己适应,硬是将自己三台电脑(家里台式、笔记本、公司台式)全部装上

    2024年02月11日
    浏览(65)
  • iOS 微信、支付宝、银联支付组件的进一步设计

    原文地址:https://zhanglei.blog.csdn.net/article/details/121376500 有段时间没写技术文章了,一是因为工作太忙,再者因为本人文笔实在一般。最近终于闲下来,本着分享的目的将一些组件设计上的心得与大家分享。 本篇文章是基于原有一篇关于支付文章的进一步优化设计,所以在阅读

    2024年02月10日
    浏览(46)
  • Flyway详解(使用说明及避坑指南、一文搞懂flyway)

    Flyway是一款开源的数据库版本管理工具,可以实现管理并跟踪数据库变更,支持数据库版本自动升级,而且不需要复杂的配置,能够帮助团队更加方便、合理的管理数据库变更。 例:创建两个sql变更文件,项目启动后会将两个文件中的sql语句全部执行。 简单举个例子:开发

    2023年04月22日
    浏览(45)
  • 银联在线支付、第三方快捷支付三种快捷支付模式有何区别?

    银联在线支付是中国银联联合各家商业银行共同打造的银行卡转接清算平台,涵盖四种支付方式:认证支付、快捷支付、储值卡支付和网银支付,无需开通网银; 代扣是用户通过线上或线下柜台方式签署“用户-授权商户-银行”的三方协议,在协议期内,授权商户可以直接从

    2024年02月11日
    浏览(49)
  • 小程序表单校验uni-forms正确使用方式及避坑指南

    小程序上使用表单理应是很常用,也很必须的功能,因为系统实用了uni-app,所以这时候会用到uni-forms,但使用过程中遇到不少问题。 这边的需求有3个: 即时校验(输入框失焦立即校验值) 需自定义校验规则 需要异步校验 满足这3个需求,就能实现绝大部分表单校验,然而

    2024年01月18日
    浏览(54)
  • 小程序地理位置接口wx.getLocation申请审核解决方法(详细说明及避坑)

    本人申请了三次才最终通过,简单说一下坑 前几天想实现定位功能改了一天代码手机上也不行。 晚上登上小程序管理界面才发现那个功能要申请。。。那就申请呗 申请路径 :小程序页面-开发-开发管理-接口设置-地理位置 之后就提交申请,两次都不过就不理解了。特地去问

    2024年01月16日
    浏览(56)
  • React18.x + i18next + antd 国际化正确使用姿势及避坑指南

    如果你使用这个教程还不能够解决你的问题的话,直接私信我,免费一对一给你解决。 具体的创建方法大家参考vite官方文档,大概的操作如下,如果需要更详细的,大家去自行搜索即可 因为我这里使用的是ts版本,所以,你自己看着办吧。 其中 i18next-browser-languagedetector i1

    2024年02月05日
    浏览(57)
  • 使用logstash将项目的日志存储到Elasticsearch中(详细!新手避坑点!)

    1.环境准备 我这里默认你们这个logstash和Elasticsearch已经安装好了。 我使用的是logstash版本7.4.0 Elasticsearch版本7.4.0。 使用其他版本 注意版本一定要一致,版本不一致大概率会出现logstash启动报Failed to install template.异常 ,已经踩坑了。 logstash的配置文件: 接下来 以配置文件启

    2024年02月04日
    浏览(87)
  • 【ES6】js 中class的extends、super关键字用法和避坑点

    在JavaScript中,使用class可以实现面向对象编程。其中,extends和super是两个非常重要的,它们分别用于实现类的继承和调用父类的方法。 一、extends extends用于实现类的继承,它可以让一个子类继承父类的属性和方法。使用extends时,需要指定要

    2024年02月09日
    浏览(33)
  • JAVA接入小程序微信支付

    1、在 微信公众平台 注册应用,并保存好appId和appSecret 2、在微信支付商户平台 注册一个商户,保存好mchId(商户id)、api_key(支付密钥)、以及商户证书序列号。还需要将支付商户密钥文件下载放到项目resources目录中 (结构中包含的其他内容与支付无关) 1、导入jar包 2、在y

    2024年04月14日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包