微信建行支付对接

这篇具有很好参考价值的文章主要介绍了微信建行支付对接。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

建行微信支付 代码参考

java实现对接建行支付及其回调
参考链接一 微信小程序使用建行支付
参考链接二 微信小程序,调用建行支付
参开链接三 集成建行聚合支付踩过的坑,有些槽不吐不快
建行支付里三大步骤与坑 验签也有顺序
Java实现建行聚合支付对接及其回调

这里我也得吐槽一下,2022年了 建行的回调验签居然还是把jar自己导入到本次仓库进行依赖添加,居然没有上传自己的pom依赖,jdk还是1.5的。。。还是说有新的,我不知道?

微信支付使用建行流程

微信建行支付对接

链接一

https://ibsbjstar.ccb.com.cn/CCBIS/ccbMainCCB_IBSVersion=V6&MERCHANTID=105320148140002&POSID=100001135&BRANCHID=320000000&ORDERID=88487&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=128.128.80.125&REGINFO=xiaofeixia&PROINFO=digital&REFERER=&SMERID=111&SMERNAME=%u5DE5%u827A%u7F8E%u672F%u5546%u5E97&SMERTYPEID=112&SMERTYPE=%u5BBE%u9986%u9910%u5A31%u7C7B&TRADECODE=001&TRADENAME=%u6D88%u8D39&SMEPROTYPE=1&PRONAME=%u5DE5%u827A%u54C1&TIMEOUT=20161028101226&TRADE_TYPE=MINIPRO&SUB_APPID=wx8888888888888888&SUB_OPENID=oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&WX_CHANNELID=wx902937628837&USERPARAM=1U2xb%2FdMepRIs0KcM53xns%2Chdg2xBh3qwJ%2F%2F%2FHi%2FjMfPcbUYjQdxJKe%2CnoHnBgXppyQqPVPdDf8p%0D%0AEwxoLdkWjvdj2QUXJ5Hb&RETURN_FIELD=10000000000000000000&MAC=b2a1adfc9f9a44b57731440e31710740

链接二

https://ibsbjstar.ccb.com.cn/CCBIS/B2CMainPlat_02?CCB_IBSVersion=V6&MERCHANTID=105320148140002&POSID=100001135&BRANCHID=320000000&ORDERID=88487&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=128.128.80.125&REGINFO=xiaofeixia&PROINFO=digital&REFERER=&SMERID=111&SMERNAME=%u5DE5%u827A%u7F8E%u672F%u5546%u5E97&SMERTYPEID=112&SMERTYPE=%u5BBE%u9986%u9910%u5A31%u7C7B&TRADECODE=001&TRADENAME=%u6D88%u8D39&SMEPROTYPE=1&PRONAME=%u5DE5%u827A%u54C1&TIMEOUT=20161028101226&TRADE_TYPE=MINIPRO&SUB_APPID=wx8888888888888888&SUB_OPENID=oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&MAC=b2a1adfc9f9a44b57731440e31710740&QRCODE=1&CHANNEL=1

支付参数

"appId": "wxad35f06adfdsgre3" 
"errcode": "000000"
"errmsg": ""
"mweb_url": ""
"mypackage": "prepay_id=wx15155254732131244559e3cb82f0000"
"nonceStr": "wYggZEgyfdfdsfasdsaJpPOSw61sG"
"partnerid": "54523121"
"paySign": "Hn/e4XM7gOnfhADoN6ccVh2BnAX09zs2IjlqPs5PfckIkUXFRSwprCd9g94FU4NwoZd58tjtwFjiI/7z2qaXhMwNKlxthjgasavUWhhHd3Nb1JPIORiRXlN/lyElmDj4RQ/6+bheixrQmT7NlIX/gCcpRxJbIw+lmoNMbgJWB8nNZ4YOIkS8B9ybBjluNa4bqePwKxSfLJnDJmlm95IDIVcJ/+uuTED97peHPbEI39t966wFbibXxUi6cbeOtYieW7TkwDIt3LGX6SqvLlMybXDyuKGseyY0wG80UNOFShvOt60iFiFJhAuE0OXHFw=="
"prepayid": ""
"signType": "RSA"
"success": true
"timeStamp": "1605426774"
"txcode": "530590"

链接一、链接二、支付参数 获取方式

  1. 拼接建行链接,链接包括建行参数跟mac(字段MD5信息) post请求
  2. 请求后 建行返回字段中包含 一个链接,再次请求返回支付信息

链接一 通过 POST 方式 第一次请求 字段信息是建行等配置

组装加密字段,拼接MAC,组成完整的请求链接

拼接建行md5加密 字段是有顺序的,不然请求后会返回mac校验失败,PUB(公钥后三十位)字段只参与加密,不参与参数传递

加密字段 加密字段 包含PUB字段
MERCHANTID=0000&POSID=0000&BRANCHID=0000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=2&REMARK2=&TYPE=1&PUB=0000&GATEWAY=0&CLIENTIP=192.168.56.1&REGINFO=&PROINFO=&REFERER=&TRADE_TYPE=JSAPI&SUB_APPID=0000&SUB_OPENID=0000

建行请求链接  建行请求链接  不包含PUB字段
https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6&MERCHANTID=0000&POSID=0000&BRANCHID=0000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=2&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=192.168.56.1&REGINFO=&PROINFO=&REFERER=&TRADE_TYPE=JSAPI&SUB_APPID=0000&SUB_OPENID=0000&MAC=md5加密字信息

请求后 返回信息 这里返回 payUrl是链接二

{
  "SUCCESS": "true",
  "PAYURL": "https://ibsbjstar.ccb.com.cn/CCBIS/B2CMainPlat_02?CCB_IBSVersion=V6&MERCHANTID=105320148140002&POSID=100001135&BRANCHID=320000000&ORDERID=88487&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=128.128.80.125&REGINFO=xiaofeixia&PROINFO=digital&REFERER=&SMERID=111&SMERNAME=%u5DE5%u827A%u7F8E%u672F%u5546%u5E97&SMERTYPEID=112&SMERTYPE=%u5BBE%u9986%u9910%u5A31%u7C7B&TRADECODE=001&TRADENAME=%u6D88%u8D39&SMEPROTYPE=1&PRONAME=%u5DE5%u827A%u54C1&TIMEOUT=20161028101226&TRADE_TYPE=MINIPRO&SUB_APPID=wx8888888888888888&SUB_OPENID=oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&MAC=b2a1adfc9f9a44b57731440e31710740&QRCODE=1&CHANNEL=1"
}

请求 PAYURL字段返回的链接

https://ibsbjstar.ccb.com.cn/CCBIS/B2CMainPlat_02?CCB_IBSVersion=V6&MERCHANTID=105320148140002&POSID=100001135&BRANCHID=320000000&ORDERID=88487&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=128.128.80.125&REGINFO=xiaofeixia&PROINFO=digital&REFERER=&SMERID=111&SMERNAME=%u5DE5%u827A%u7F8E%u672F%u5546%u5E97&SMERTYPEID=112&SMERTYPE=%u5BBE%u9986%u9910%u5A31%u7C7B&TRADECODE=001&TRADENAME=%u6D88%u8D39&SMEPROTYPE=1&PRONAME=%u5DE5%u827A%u54C1&TIMEOUT=20161028101226&TRADE_TYPE=MINIPRO&SUB_APPID=wx8888888888888888&SUB_OPENID=oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&MAC=b2a1adfc9f9a44b57731440e31710740&QRCODE=1&CHANNEL=1

返回支付参数 请求结果就是成功了,将参数返回给前端,调起支付即可

{
"appId": "wxad35f06adfdsgre3" 
"errcode": "000000"
"errmsg": ""
"mweb_url": ""
"mypackage": "prepay_id=wx15155254732131244559e3cb82f0000"
"nonceStr": "wYggZEgyfdfdsfasdsaJpPOSw61sG"
"partnerid": "54523121"
"paySign": "Hn/e4XM7gOnfhADoN6ccVh2BnAX09zs2IjlqPs5PfckIkUXFRSwprCd9g94FU4NwoZd58tjtwFjiI/7z2qaXhMwNKlxthjgasavUWhhHd3Nb1JPIORiRXlN/lyElmDj4RQ/6+bheixrQmT7NlIX/gCcpRxJbIw+lmoNMbgJWB8nNZ4YOIkS8B9ybBjluNa4bqePwKxSfLJnDJmlm95IDIVcJ/+uuTED97peHPbEI39t966wFbibXxUi6cbeOtYieW7TkwDIt3LGX6SqvLlMybXDyuKGseyY0wG80UNOFShvOt60iFiFJhAuE0OXHFw=="
"prepayid": ""
"signType": "RSA"
"success": true
"timeStamp": "1605426774"
"txcode": "530590"
}

参数介绍

字段 名称 说明
SUCCESS 返回状态码 此字段是通信标识,表示通信成功
ERRCODE 错误码 000000表示交易成功,非000000表示交易失败,错误信息可以查看ERRMSG字段
ERRMSG 错误信息 错误信息描述
TXCODE 交易码 530590
appId 微信分配的APPID 参考微信对应的调起支付API
timeStamp 时间戳 参考微信对应的调起支付API
nonceStr 随机串 参考微信对应的调起支付API
package 数据包 参考微信对应的调起支付API
signType 签名方式 参考微信对应的调起支付API
paySign 签名数据 参考微信对应的调起支付API
partnerid 子商户的商户号 参考微信对应的调起支付API
prepayid 预支付交易会话ID 参考微信对应的调起支付API
mweb_url 微信H5支付中间页面URL 参考微信对应的调起支付API

微信建行支付对接

可能会遇到的问题

  1. MAC校验失败, 可能是加密字段顺序不一致
  2. “ERRMSG”:“支付不成功,@@INVALID_REQUEST~~sub_mch_id与sub_appid不匹配@@”, 没有配置商户id绑定

微信建行支付对接
3. 记录支付登记簿异常 escape编码长度超长 。 这里面有的字段中文需要通过escape转码,但是转码长度不能过长

{
	"SUCCESS":"true",
	"ERRCODE":"0130Z1109001",
	"ERRMSG":"记录支付登记簿异常!",
	"TXCODE":"530590",
	"appId":"",
	"timeStamp":"",
	"nonceStr":"",
	"package":"",
	"signType":"",
	"paySign":"",
	"partnerid":"",
	"prepayid":"",
	"mweb_url":""	
}

重点
拼接建行md5加密 字段是有顺序的,不然请求后会返回mac校验失败,PUB(公钥后三十位)字段只参与加密,不参与参数传递

例: 加密字段有PUB字段,请求不需要加 PUB字段, MAC是加密信息md5后的信息

加密字段
MERCHANTID=0000&POSID=0000&BRANCHID=0000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=2&REMARK2=&TYPE=1&PUB=0000&GATEWAY=0&CLIENTIP=192.168.56.1&REGINFO=&PROINFO=&REFERER=&TRADE_TYPE=JSAPI&SUB_APPID=0000&SUB_OPENID=0000

建行请求链接
https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6&MERCHANTID=0000&POSID=0000&BRANCHID=0000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=2&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=192.168.56.1&REGINFO=&PROINFO=&REFERER=&TRADE_TYPE=JSAPI&SUB_APPID=0000&SUB_OPENID=0000&MAC=md5加密字信息

开发前置准备

  1. md5加密使用的是hutool工具集的 SecureUtil.md5() 方法 添加依赖即可 hutool工具集
  2. 建行jar包,以供调用接口回调验签
  3. 配置微信小程序信息 可以使用 wx-java 小程序用小程序的依赖,公众号用公众号的依赖 公众号配置 小程序配置
  4. natapp 配置内网穿透,测试时建议购买一个月的通道,配置到建行的回调地址,方便测试支付后回调

建行验签jar包导入本地 包导入命令

mvn install:install-file "-Dfile=F:\work\java\ccb\netpay.jar" "-DgroupId=CCBSign" "-DartifactId=RSASig" "-Dversion=1.0" "-Dpackaging=jar"

导入到本地仓库后添加到pom文件

<dependency>
   <groupId>CCBSign</groupId>
   <artifactId>RSASig</artifactId>
   <version>1.0</version>
</dependency>

建行开发

mac 加密的字段及顺序

$host = 'https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6&';
$string = 'MERCHANTID=00000&POSID=0000&BRANCHID=000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=&REMARK2=&TYPE=1&PUB=00000000&GATEWAY=0&CLIENTIP=127.0.0.1&REGINFO=&PROINFO=%u94bb%u77f3%u4f1a%u5458%u4f18%u60E0%u5927%u4fC3&REFERER=&TRADE_TYPE=MINIPRO&SUB_APPID=0000&SUB_OPENID=0000';
echo $host.$string."&MAC=".md5($string);

流程看的差不多了,接下来就是对接建行。
如何拼接建行请求字段以及如何拼接生成md5信息,这里提供两种方式

  1. 实体类定义字段,通过反射拼接字符串
  2. 通过map、append拼接字符串

拼接建行请求链接

方式一 利用反射拼接

基础配置

  1. 可以定义在常量类中 直接写死
  2. 我这里写在配置类里进行了读取
    两种方式都可以

yml配置属性

ccb:
  url: https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6
  merchant-id:  你的建行商户id
  pos-id: '你的建行posid'     # 这里使用单引号是因为前面如果是0的话 读取过去会去掉
  branch-id: 你的建行branch-id
  cur-code: '01'
  tx-code: 530590
  gateway: 0
  type: 1
  pub: 公钥后三十位

yml配置类

/**
 * 建行url属性
 *
 * @author Administrator
 * @date 2022/07/28
 */
@Data
@Component
@ConfigurationProperties(prefix = "ccb")
public class CcbProperties {
    /**
     * 建行支付请求连接
     */
    private String url;
    /**
     * 商户代码
     */
    private String merchantId;
    /**
     * 商户柜台代码
     */
    private String posId;
    /**
     * BRANCHID
     */
    private String branchId;
    /**
     * 币种类型 01 人民币
     */
    private String curCode;
    /**
     * 交易码 由建行统一分配为530590
     */
    private String txCode;
    /**
     * 网关 默认0
     */
    private String gateway;
    /**
     * 接口类型 1- 防钓鱼接口
     */
    private String type;
    /**
     * 公钥后三十位
     */
    private String pub;

}

参与加密的字段及顺序 实体类展现

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CcbTakeMacReq {

    /**
     *  商户代码
     */
    private String MERCHANTID;
    /**
     * 商户柜台代码
     */
    private String POSID;
    /**
     * 分行代码
     */
    private String BRANCHID;
    /**
     * 定单号 由商户提供,最长30位
     */
    private String ORDERID;
    /**
     *  付款金额 由商户提供,按实际金额给出
     */
    private String PAYMENT;
    /**
     * 币种 缺省为01-人民币
     * (只支持人民币支付)
     */
    private String CURCODE;
    /**
     *  交易码
     */
    private String TXCODE;

    /**
     *  备注1 一般作为商户自定义备注信息使用,可在对账单中显示。
     */
    private String REMARK1;
    /**
     *  备注2 一般作为商户自定义备注信息使用,可在对账单中显示。
     */
    private String REMARK2;

    /**
     *  接口类型 分行业务人员在P2员工渠道后台设置防钓鱼的开关。
     * 1-	防钓鱼接口
     */
    private String TYPE;
    /**
     *  公钥后30位 商户从建行商户服务平台下载,截取后30位。
     * 仅作为源串参加MD5摘要,不作为参数传递
     */
    private String PUB;
    /**
     *  网关类型 默认送0
     */
    private String GATEWAY;
    /**
     *  客户端IP 客户在商户系统中的IP,即客户登陆(访问)商户系统时使用的ip)
     */
    private String CLIENTIP;
    /**
     *  客户注册信息  客户在商户系统中注册的信息,中文需使用escape编码
     */
    private String REGINFO;
    /**
     * 商品信息 客户购买的商品
     * 中文需使用escape编码
     */
    private String PROINFO;
    /**
     * 商户URL 商户送空值即可;
     * 具体请看REFERER设置说明
     */
    private String REFERER;

    /**
     * 交易类型 JSAPI--公众号支付、APP--app支付、MINIPRO--小程序、H5--H5跳转支付
     * @see WxPayEnum
     */
    private String TRADE_TYPE;
    /**
     * 当前调起支付的小程序APPID
     */
    private String SUB_APPID;
    /**
     * 用户在小程序appid下的唯一标识,小程序通过wx.login获取
     */
    private String SUB_OPENID;

}

参数赋值

package com.kdzt.wxmp.convert;

import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.kdzt.wxmp.config.CcbProperties;
import com.kdzt.wxmp.model.ccb.req.CcbTakeMacReq;
import com.kdzt.wxmp.util.FiledConvertUtils;
import com.kdzt.wxmp.util.IpUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;


/**
 * 建行参数转换
 *
 * @author Administrator
 * @date 2022/08/17
 */
@Component
@RequiredArgsConstructor
public class CcbParamConvert {

    private final CcbProperties ccbProperties;

    public String createCcbParam(String amount, String description, String openId, String orderNo, String zhnum, String appId) {
        // 微信下单 ==》 建行下单
        CcbTakeMacReq ccbTakeReq = new CcbTakeMacReq();
        this.toCcbMacSetting(ccbTakeReq);
        ccbTakeReq.setPAYMENT(amount);
        ccbTakeReq.setORDERID(orderNo);
        ccbTakeReq.setSUB_OPENID(openId);
        ccbTakeReq.setSUB_APPID(appId);
        ccbTakeReq.setREMARK1(“”);
        ccbTakeReq.setREMARK2("");
        ccbTakeReq.setREFERER("");

//        ccbTakeReq.setTIMEOUT("");
        ccbTakeReq.setPROINFO("");
        ccbTakeReq.setREGINFO("");

        // 拼接参数
        String value = FiledConvertUtils.getCcbParam(ccbTakeReq, false);
        ccbTakeReq.setPUB(ccbProperties.getPub());
        // 获取md5加密后的MAC字段
        String md5 = FiledConvertUtils.getCcbParam(ccbTakeReq, true);
        return value + md5;
    }


    private void toCcbMacSetting(CcbTakeMacReq macReq) {
        macReq.setMERCHANTID(ccbProperties.getMerchantId());
        macReq.setPOSID(ccbProperties.getPosId());
        macReq.setBRANCHID(ccbProperties.getBranchId());
        macReq.setCURCODE(ccbProperties.getCurCode());
        macReq.setTXCODE(ccbProperties.getTxCode());
        macReq.setGATEWAY(ccbProperties.getGateway());
        macReq.setTYPE(ccbProperties.getType());
        macReq.setCLIENTIP(IpUtils.getHostIp());
        macReq.setTRADE_TYPE(TradeTypeEnum.JSAPI.name());
        macReq.setREFERER("");
    }
}

反射工具类

package com.kdzt.wxmp.util;

import cn.hutool.crypto.SecureUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 字段转换工具类
 *
 * @author Administrator
 * @date 2022/08/12
 */
@Slf4j
@Component
public class FiledConvertUtils {


    /**
     * 得到建行参数
     *
     * @param object 对象
     * @param md5    md5 是否md5
     * @return {@link String}
     */
    public static String getCcbParam(Object object, boolean md5) {
        List<String> values = Lists.newArrayList();
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                // 判断如果不是算mac MD5 并且字段是PUB 跳过
                if (!md5 && "PUB".equalsIgnoreCase(field.getName())) {
                    continue;
                }
                values.add(String.format("%s=%s", field.getName(), (null == field.get(object)) ? "" : field.get(object)));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("转换建行参数错误 {} {}", md5, e.getMessage());
        }
        String value = String.join("&", values);
        if (md5) {
            System.out.println("加密字符串" + value);
            return String.format("&MAC=%s", SecureUtil.md5(value));
        }
        return String.join("&", values);
    }


}


方式二 直接拼接

拼接工具类


@Component
@RequiredArgsConstructor
public class CcbParamUtils {
    

    private final CcbProperties ccbProperties;

    public String getPayRequestParam(String orderNo, BigDecimal payMoney, String openid, String appId) {
        //md5加密  MD5加密后生成32位(小写字母 + 数字)字符串
        String sb1 = "MERCHANTID=" + ccbProperties.getMerchantId() + "&" +
                "POSID=" + ccbProperties.getPosId() + "&" +
                "BRANCHID=" + ccbProperties.getBranchId() + "&" +
                "ORDERID=" + orderNo.trim() + "&" +
                "PAYMENT=" + payMoney + "&" +
                "CURCODE=" + ccbProperties.getCurCode() + "&" +
                "TXCODE=530590&" +
                "REMARK1=&REMARK2=&" +
                "TYPE=" + ccbProperties.getType() + "&" +
                "PUB=" + ccbProperties.getPub() + "&" +
                "GATEWAY=" + ccbProperties.getGateway() + "&" +
                "CLIENTIP=&REGINFO=&PROINFO=&REFERER=&" +
                "TRADE_TYPE=" + TradeTypeEnum.JSAPI.name() + "&" +
                "SUB_APPID=" + appId + "&" +
                "SUB_OPENID=" + openid;
        String sb2 = "MERCHANTID=" + ccbProperties.getMerchantId() + "&" +
                "POSID=" + ccbProperties.getPosId() + "&" +
                "BRANCHID=" + ccbProperties.getBranchId() + "&" +
                "ORDERID=" + orderNo.trim() + "&" +
                "PAYMENT=" + payMoney + "&" +
                "CURCODE=" + ccbProperties.getCurCode() + "&" +
                "TXCODE=530590&" +
                "REMARK1=&REMARK2=&" +
                "TYPE=" + ccbProperties.getType() + "&" +
                "GATEWAY=" + ccbProperties.getGateway() + "&" +
                "CLIENTIP=&REGINFO=&PROINFO=&REFERER=&" +
                "TRADE_TYPE=" + TradeTypeEnum.JSAPI.name() + "&" +
                "SUB_APPID=" + appId + "&" +
                "SUB_OPENID=" + openid;
        return sb2 + "&MAC=" + SecureUtil.md5(sb1);
    }
}

escape转码工具类

  public static String escape(String src) {  
        int i;  
        char j;  
        StringBuffer tmp = new StringBuffer();  
        tmp.ensureCapacity(src.length() * 6);  
        for (i = 0; i < src.length(); i++) {  
            j = src.charAt(i);  
            if (Character.isDigit(j) || Character.isLowerCase(j)  
                    || Character.isUpperCase(j))  
                tmp.append(j);  
            else if (j < 256) {  
                tmp.append("%");  
                if (j < 16)  
                    tmp.append("0");  
                tmp.append(Integer.toString(j, 16));  
            } else {  
                tmp.append("%u");  
                tmp.append(Integer.toString(j, 16));  
            }  
        }  
        return tmp.toString();  
    }  

    public static String unescape(String src) {  
        StringBuffer tmp = new StringBuffer();  
        tmp.ensureCapacity(src.length());  
        int lastPos = 0, pos = 0;  
        char ch;  
        while (lastPos < src.length()) {  
            pos = src.indexOf("%", lastPos);  
            if (pos == lastPos) {  
                if (src.charAt(pos + 1) == 'u') {  
                    ch = (char) Integer.parseInt(src  
                            .substring(pos + 2, pos + 6), 16);  
                    tmp.append(ch);  
                    lastPos = pos + 6;  
                } else {  
                    ch = (char) Integer.parseInt(src  
                            .substring(pos + 1, pos + 3), 16);  
                    tmp.append(ch);  
                    lastPos = pos + 3;  
                }  
            } else {  
                if (pos == -1) {  
                    tmp.append(src.substring(lastPos));  
                    lastPos = src.length();  
                } else {  
                    tmp.append(src.substring(lastPos, pos));  
                    lastPos = pos;  
                }  
            }  
        }  
        return tmp.toString();  
    }  

请求返回链接 获取返回参数

通过post请求链接到建行,建行返回信息,信息里有微信请求连接,再次通过get方式请求,获取支付调起参数

  1. 请求建行连接https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6&MERCHANTID=0000&POSID=0000&BRANCHID=0000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=2&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=192.168.56.1&REGINFO=&PROINFO=&REFERER=&TRADE_TYPE=JSAPI&SUB_APPID=0000&SUB_OPENID=0000&MAC=md5加密字信息
 // 1 拼接参数请求建行api
String ccbParam = ccbParamConvert.createCcbParam(amountStr, description, openId, orderNo, zhnum);
 // 2 请求建行 返回请求结果
 String result = HttpUtil.post(String.format("%s&%s", ccbProperties.getUrl(), ccbParam), "");
  • 注:ccbParam就是拼接的字符串参数 MERCHANTID=0000&POSID=0000&BRANCHID=0000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=2&REMARK2=&TYPE=1&GATEWAY=0&CLIENTIP=192.168.56.1&REGINFO=&PROINFO=&REFERER=&TRADE_TYPE=JSAPI&SUB_APPID=0000&SUB_OPENID=0000&MAC=md5加密字信息
  • ccbProperties.getUrl() 是 https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6 建行前缀信息
  • HttpUtil hutool的http方法

返回的对象

@Data
public class CcbVo {

    @SerializedName("SUCCESS")
    private String success;

    @SerializedName("PAYURL")
    private String payUrl;
}
  1. 再次请求payUrl 中的连接
   String wxResult = HttpUtil.get(ccbVo.getPayUrl());

返回对象 这里package是关键字, 使用 @JSONField(name = "package") 转一下

@Data
public class CcbWxJsapiResult {

    @SerializedName("SUCCESS")
    private String success;

    @SerializedName("ERRCODE")
    private String errCode;


    @SerializedName("ERRMSG")
    private String errMsg;

    @SerializedName("TXCODE")
    private String txCode;

    private String appId;

    private String timeStamp;

    private String nonceStr;

    @JSONField(name = "package")
    private String packageValue;

    private String signType;

    private String paySign;

    private String partnerid;

    private String prepayid;

    @SerializedName("mweb_url")
    private String mwebUrl;
}

最后将参数传给前端,前端通过参数调起支付

字段 名称 说明
SUCCESS 返回状态码 此字段是通信标识,表示通信成功
ERRCODE 错误码 000000表示交易成功,非000000表示交易失败,错误信息可以查看ERRMSG字段
ERRMSG 错误信息 错误信息描述
TXCODE 交易码 530590
appId 微信分配的APPID 参考微信对应的调起支付API
timeStamp 时间戳 参考微信对应的调起支付API
nonceStr 随机串 参考微信对应的调起支付API
package 数据包 参考微信对应的调起支付API
signType 签名方式 参考微信对应的调起支付API
paySign 签名数据 参考微信对应的调起支付API
partnerid 子商户的商户号 参考微信对应的调起支付API
prepayid 预支付交易会话ID 参考微信对应的调起支付API
mweb_url 微信H5支付中间页面URL 参考微信对应的调起支付API

前端调起支付

小程序
微信H5
APP
公众号

举例:
公众号支付,复制下面方法,将参数改成你返回的参数就可以调起支付了
微信建行支付对接

回调方法

需要在建行配置你的回调地址,域名+请求路径,本地测试的话可以使用内网穿透,通过微信支付调起支付,付款成功后会发起回调
微信建行支付对接
回调方法

/**
     * 建行支付结果通知
     *
     * @param request
     * @return
     */
    @PostMapping("/callBackCcb")
    public ParamMap callBackCcb(HttpServletRequest request) {
        log.debug("callBackCCB start!");
        Map<String, String> map = Maps.newHashMap();
        Enumeration<String> parameterNames = request.getParameterNames();
        StringBuilder data = new StringBuilder();
       // 通过request获取返回信息,构建map
        while (parameterNames.hasMoreElements()) {
            String name = parameterNames.nextElement();
            String value = request.getParameter(name);
            map.put(name, value);
            data.append(name).append("=").append(value).append("&");
        }
        if(log.isDebugEnabled()) {
            log.debug("request 回调信息=====》{} {}", data, map);
        }
        // 验签
        callBackCheck(map);
        return “你的具体实现”;
    }

验签 回调最主要的就是验签,验签成功后才能做具体操作

private void callBackCheck(Map<String, String> map) {
       // 这里顺序必须是这样,不然验签会不成功
        String sb = "POSID=" + map.get("POSID") + "&BRANCHID=" + map.get("BRANCHID") +
                "&ORDERID=" + map.get("ORDERID") + "&PAYMENT=" + map.get("PAYMENT") +
                "&CURCODE=" + map.get("CURCODE") + "&REMARK1=" + map.get("REMARK1") +
                "&REMARK2=" + map.get("REMARK2") + "&ACC_TYPE=" + map.get("ACC_TYPE") +
                "&SUCCESS=" + map.get("SUCCESS") + "&ACCDATE=" + map.get("ACCDATE");
        RSASig rsaSig = new RSASig();
        // 公钥
        rsaSig.setPublicKey(ccbProperties.getPublicKey());

        boolean flag = rsaSig.verifySigature(map.get("SIGN"), sb);
        log.info("callBackCCB Check :[{}]", flag);
        //表示支付成功
        if ("Y".equals(map.get("SUCCESS")) && flag) {
            CallbackResult callbackResult = new CallbackResult();
            callbackResult.setReturnCode("Y");
            callbackResult.setReturnMsg("Ok");
            callbackResult.setOrderNo(map.get("ORDERID"));
        } else {
            throw new MpCcbException("建行回调异常");
        }
    }

之后就可以做具体的操作了,修改订单状态等文章来源地址https://www.toymoban.com/news/detail-403773.html

到了这里,关于微信建行支付对接的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 2023微信支付对接全流程

    简单说一下微信支付的几种类型的应用场景以及前提条件 官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml 前提条件: 1.需要一个载体公众号或者小程序,公众号要是服务号不是订阅号。 2.小程序和公众号支付都要认证,要300rmb。 3.需要一个商户号,绑定公众号或者小程序

    2024年02月05日
    浏览(29)
  • 微信小程序支付-java对接微信

     一共是两个方法: 一个方法后台生成预支付订单,得到预支付交易会话标识prepay_id,传给前端,让前端调起小程序支付; 一个是支付回调 目录 一、生成预支付订单  注意: 二、 支付回调         封装参数向微信发送生成预支付交易单请求,微信会返回一个prepay_id,再将

    2024年02月12日
    浏览(37)
  • 微信小程序对接微信支付详细教程

    小程序 微信支付官方文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11index=2 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml 前提 在进行对接微信支付之前,我们首先需要将以下几点准备好: 申请APPID 申请商户号 小程序开通微信支付,绑定已经申请好的商户号。

    2024年02月09日
    浏览(34)
  • SpringBoot对接小程序微信支付

    目录 前言 一、准备工作 2.1、企业微信小程序开通 2.1.1、获取开发者ID 2.1.2、开通支付功能 2.1.3、关联商户号 2.2、企业商户号的开通 2.2.1、获取商户号mch_id 2.2.2、获取商户API密钥mch_key 二、整体流程 三、后端项目搭建 3.1、统一下单 3.2、支付支付回调 3.3、问题排查 3.4、统一下

    2024年02月04日
    浏览(37)
  • SpringBoot对接微信小程序支付功能开发(二,支付回调功能)

    接着上一篇: SpringBoot对接微信小程序支付功能开发(一,下单功能) 在上一篇下单功能中我们有传支付结果回调地址。 下面是回调接口实现 根据官网给的参数进行业务处理 这就完成了,微信支付回调你的地址,并且把支付的信息传进来,剩下就要根据自己业务进行操作。

    2024年02月11日
    浏览(42)
  • 微信小程序对接微信支付所遇问题合集

    1. 后端使用微信官方sdk会简单很多,可以看看在第五个大标题上。 2. 相关文档汇总:         1、WxJava - MiniApp Java SDK 4.6.0 API         2、wechatpay-java/README.md at main · wechatpay-apiv3/wechatpay-java · GitHub         3、网络 | 微信开放文档         4、开发指引 - JSAPI支付 | 微信支付商

    2024年04月25日
    浏览(40)
  • Java对接微信支付(史上最详细)

    本文将介绍如何使用Java对接微信支付,包括获取支付参数、支付回调处理等步骤。本文适用于已经熟悉微信支付基本原理的读者。 JDK 1.8 Maven Spring Boot 2.x 微信支付开发文档 为了进行支付,我们需要先获取微信支付的参数信息,包括appid、商户id、支付密钥等。 配置文件 我们

    2024年02月15日
    浏览(29)
  • 微信支付-超详细java开发-小程序对接

    本文适用于有一定基础的开发者,简单易通。后台用的的是java,我用的是springBoot,其它框架基本同理,前端就是一个简单的demo。微信官方提供了V2和V3两种方式,本文基于V2版支付开发(后续更新V3)。V2和V3版本区别 1.思路介绍 本次以微信小程序开发为例,如果自己想要玩一

    2024年02月09日
    浏览(39)
  • 记录--H5页面对接微信支付踩坑杂记

    应用背景:vite搭建的vue3项目 需求背景:功能都涉及了支付业务,故需要和外部支付系统对接 外部支付系统:聚合支付、微信小程序支付、微信H5支付 读完本文,你将会对以下几个坑点有所了解: 对接第三方服务商过程踩坑 对接小程序支付踩坑 对接微信H5支付踩坑 关于客户

    2024年02月08日
    浏览(30)
  • 微信native-v3版支付对接流程及demo

    openssl pkcs12 -in apiclient_cert.p12 -out apiclient_cert.pem -nodes 密码是:商户id https://github.com/wechatpay-apiv3/CertificateDownloader 生成证书 https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient

    2024年02月07日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包