微信小程序使用建行支付
微信小程序使用建行支付
- IT
- JAVA
- 支付
- 小程序
- java
一、交易流程说明
正在上传…重新上传取消
二、接口说明
字段 | 说明 | 类型 | 必传 |
---|---|---|---|
MERCHANTID | 商户代码,由建行统一分配 | CHAR(15) | 是 |
POSID | 商户柜台代码,由建行统一分配 | CHAR(9) | 是 |
BRANCHID | 分行代码,由建行统一分配 | CHAR(9) | 是 |
ORDERID | 订单号,由商户提供,最长30位(数字) | CHAR(30) | 是 |
PAYMENT | 付款金额,由商户提供,按实际金额给出。支付完成后,请商户与收到的商户通知中的付款金额比对,确认两者金额一致; | NUMBER(16,2) | 是 |
CURCODE | 币种,缺省为01-人民币(目前只支持人民币支付) | CHAR(2) | 是 |
REMARK1 | 备注1,一般作为商户自定义备注信息使用,可在对账单中显示。集团主商户代理发起子商户交易时,需将集团主商户信息填入该字段,格式如下:JTSH:主商户号+主柜台例如:JTSH:105000000000000123456789其中105000000000000为主商户号,123456789为主柜台 | CHAR(30) | 否 |
REMARK2 | 备注2,一般作为商户自定义备注信息使用,可在对账单中显示。 | CHAR(30) | 否 |
TXCODE | 交易码,由建行统一分配 ,为530590 | CHAR(6) | 是 |
MAC | MAC校验域,采用标准MD5算法,由商户实现 | CHAR(32) | 是 |
TYPE | 接口类型,分行业务人员在P2员工渠道后台设置防钓鱼的开关。1-防钓鱼接口 | CHAR(1) | 是 |
PUB | 公钥后30位,商户从建行商户服务平台下载,截取后30位。仅作为源串参加MD5摘要,不作为参数传递 | CHAR(30) | 是 |
GATEWAY | 网关类型,默认为0 | VARCHAR(100) | 是 |
CLIENTIP | 客户端IP,客户在商户系统中的IP,即客户登陆(访问)商户系统时使用的ip) | CHAR(40) | 否 |
REGINFO | 客户注册信息,客户在商户系统中注册的信息,中文需使用escape编码 | CHAR(256) | 否 |
PROINFO | 商品信息,客户购买的商品中文需使用escape编码 | CHAR(256) | 否 |
REFERER | 商户URL,商户送空值即可;具体请看REFERER设置说明 | CHAR(100) | 否 |
TIMEOUT | 订单超时时间,格式:YYYYMMDDHHMMSS如:20120214143005银行系统时间> TIMEOUT时拒绝交易,若送空值则不判断超时。当该字段有值时参与MAC校验,否则不参与MAC校验。 | CHAR(14) | 否 |
TRADE_TYPE | 交易类型,JSAPI–公众号支付、MINIPRO–小程序 | CHAR(16) | 是 |
SUB_APPID | 小程序/公众号的APPID,当前调起支付的小程序/公众号APPID | CHAR(32) | 是 |
SUB_OPENID | 用户子标识用户在小程序/公众号appid下的唯一标识,小程序通过wx.login获取,接口文档地址:https://developers.weixin.qq.com/miniprogram/dev/api/api-login.html?t=20161122 | CHAR(128) | 是 |
WX_CHANNELID | 渠道商号,对于商户自定义的渠道商号当该字段有值时参与MAC校验,否则不参与MAC校验。 | CHAR(20) | 否 |
RETURN_FIELD | 返回信息位图,共20位,商户通知是否返回某个字段的位图,0或空-不返回,1-返回。第1位:是否返回OPENID和SUB_OPENID第2位:保留位,默认送0第3位:保留位,默认送0 第4位:是否返回支付详细信息字段示例:10000000000000000000 | CHAR(20) | 否 |
USERPARAM | 实名支付,实名支付功能,包含类型、证件号、姓名三个子域(如果本字段出现,那么本字段包含的三个子域均需出现。详见下文说明5)USERPARAM字段说明)。当该字段有值时参与MAC校验,否则不参与MAC校验。暂未上线,请忽略 | VARCHAR(2000) | 否 |
二级商户信息
若上送二级商户信息则八个二级商户信息字段必须都送值,当该字段有值时参与MAC校验,否则不参与MAC校验。
字段 | 说明 | 类型 | 必传 |
---|---|---|---|
SMERID | 二级商户代码,由建行统一分配 | CHAR(15) | 否 |
SMERNAME | 二级商户名称,中文需使用escape编码 | 中文(33)、英文CHAR(100) | 否 |
SMERTYPEID | 二级商户类别代码 | CHAR(15) | 否 |
SMERTYPE | 二级商户类别名称,汉字最长27个,中文需使用escape编码 | 中文(27)、英文CHAR(81) | 否 |
TRADECODE | 交易类型代码 | CHAR(15) | 否 |
TRADENAME | 交易类型名称,如消费、投资理财、信用卡还款等,中文需使用escape编码 | 中文(10),英文CHAR(30) | 否 |
SMEPROTYPE | 商品类别代码 | CHAR(24) | 否 |
PRONAME | 商品类别名称,中文需使用escape编码 | 中文(15)英文CHAR(50) | 否 |
注:字符串中变量名必须是大写字母。
1)参与摘要运算的字符串及其顺序如下:
请注意:加粗的字段请根据需要上送,有值时才参与MAC,否则无需参与MAC。
MERCHANTID=123456789&POSID=000000000&BRANCHID=110000000&ORDERID=19991101234&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=&REMARK2=&TYPE=1&PUB=30819d300d06092a864886f70d0108&GATEWAY=0&CLIENTIP=172.0.0.1®INFO=%u5C0F%u98DE%u4FA0&PROINFO=%u5145%u503C%u5361&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
2)使用js的escape()方法对“客户注册信息”和“商品信息”进行转码,数字字母信息不需转码。
例:escape(小飞侠)= %u5C0F%u98DE%u4FA0
escape(充值卡)= %u5145%u503C%u5361
3)使用js的escape()方法对“二级商户名称”、“二级商户类别名称”、“交易类型名称”、“商品类别名称”进行转码,数字字母信息不需转码。
例: escape (工艺美术商店)=%u5DE5%u827A%u7F8E%u672F%u5546%u5E97
escape (宾馆餐娱类)= %u5BBE%u9986%u9910%u5A31%u7C7B
escape (消费)= %u6D88%u8D39
escape (工艺品)= %u5DE5%u827A%u54C1
4)完整的URL:
第三方商户提交给网银的网关地址:注意用post方式提交参数。
https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6
请注意:加粗的字段请根据需要上送
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®INFO=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
5)访问上述请求后,获得数据
{“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®INFO=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” }
6)使用GET请求,直接访问PAYURL中的地址
7)获得JSON数据,
{"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 |
三、微信相关调起API链接
小程序:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_sl_api.php?chapter=7_7&index=5
公众号:https://pay.weixin.qq.com/wiki/doc/api/jsapi_sl.php?chapter=7_7&index=6
四、支付反馈地址设置(回调地址)
说明:反馈地址,就是支付完成后,建行会向你设置的反馈地址发送信息,类似纯微信支付的反馈地址。
信息里面会有ORDERID(订单号)与PAYMENT(字符金额),当然还有其他的信息。一般会在反馈的处理方法里面进行金额校验与修改订状态的操作
方法1:商户后台设置
正在上传…重新上传取消
方法2:访问开发接口
查阅接口文档
建行开放接口文档
项目中遇到的有关反馈的问题
反馈地址这一块相对来说是比较难调试,也会遇到很多问题。我就说一下我遇到的问题以及我是如何解决的。
在测试版本(测试版本使用的反馈地址的协议是http)测试时,可正常接收到建行发送过来的反馈信息。但是切换到正式版本(正式版本使用的反馈地址的协议是https)后,发现支付完成后怎么都接收不到建行的反馈信息,建行那边查询原因后说是向反馈地址发送请求后返回的是403(服务器禁止访问),尝试了很多种方法,最后是通过开启springboot项目的双协议配置,即项目可同时通过http协议与https协议进行访问(不同协议端口不一致),回调地址使用的是http协议的。这是退而求其次的方法,这个问题并没有完全解决,今后如果找到解决方法,会更新博客。哪位大佬彻底解决了这个问题,也欢迎分享。
springboot开启双协议的配置
五、访问建行开发接口
建行开放接口文档
1. 商户反馈地址查询(示例,其他的接口都类似)
1)请求地址:http://120.77.236.53:9999
2)请求参数
<TX> <REQUEST_SN>请求序列号REQUEST_SN> <CUST_ID>商户号CUST_ID> <USER_ID>操作员号USER_ID> <PASSWORD>操作员号密码PASSWORD> <TX_CODE>5W1019TX_CODE> <LANGUAGE>CNLANGUAGE> <TX_INFO> <POS_ID>终端编号POS_ID> TX_INFO>
TX>
3)响应信息
<TX> <REQUEST_SN>请求序列码REQUEST_SN> <CUST_ID>商户号CUST_ID> <TX_CODE>5W1019TX_CODE> <RETURN_CODE>响应码RETURN_CODE> <RETURN_MSG>响应信息RETURN_MSG> <LANGUAGE>CNLANGUAGE> <TX_INFO> <POS_ACCDATE_FLAG>是否返回记账日期POS_ACCDATE_FLAG> <LIST> <EC_CgyCd>电子渠道类别代码EC_CgyCd> <Rsrv_Fld_1>网页反馈地址Rsrv_Fld_1> <Rsrv_Fld_2>服务器反馈地址Rsrv_Fld_2> <Rsrv_Fld_3>实时反馈标志Rsrv_Fld_3> LIST> <NOTICE>提示信息NOTICE> TX_INFO> TX>
正在上传…重新上传取消
4)Springboot使用RestTemplate请求实例
public Response test(){RestTemplate restTemplate = new RestTemplateBuilder().build();String urlXML ="" +"" +"" + KeyUtil.uniqueKey() + "" +"" + "" + "" +"" + "" + "" +"" + "" + "" +"" + "5W1019" + "" +"" + "CN"+ "" +"" +"" + "" + "" +"" +"";String params = null;params = "requestXml=" + urlXML;String parameter = params;HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);HttpEntity<String> requestEntity = new HttpEntity<String>(parameter, headers);ResponseEntity<String> response = restTemplate.exchange("http://120.77.236.53:9999", HttpMethod.POST, requestEntity, String.class);return Response.success(response.getBody());}
六、Demo项目代码
1.服务层接口
import java.math.BigDecimal;/*** 建行支付服务类*/
public interface JHPayService {/*** 发起支付* @param orderNo 订单号* @param payMoney 支付金额* @param openid 微信用户openid* @param appId 微信小程序appId* @return*/JHPayResult JHPay(String orderNo, BigDecimal payMoney, String openid, String appId);/*** 发起退款* @param orderNo 订单号* @param refundMoney 退款金额* @param payMoney 支付金额* @return*/JHRefundResponse JHRefund(String orderNo, BigDecimal refundMoney, BigDecimal payMoney);
}
2.服务层实现
import com.google.gson.Gson;
import com.zengmi.config.JHPayProperties;
import com.zengmi.enums.ErrorEnum;
import com.zengmi.exception.MyException;
import com.zengmi.utils.KeyUtil;
import com.zengmi.utils.MD5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.math.BigDecimal;
import java.util.Date;/*** 建行支付退款服务层* @author IT00ZYQ* @Date 2020/10/22 19:14**/
@Service
@Slf4j
public class JHPayServiceImpl implements JHPayService{private static final String successCode = "000000";@Autowiredprivate JHPayProperties jhPayProperties;@Autowiredprivate RestTemplate restTemplate;@Overridepublic JHPayResult JHPay(String orderNo, BigDecimal payMoney, String openid, String appId) {HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);HttpEntity<String> requestEntity = new HttpEntity<>(getPayRequestParam(orderNo, payMoney, openid, appId), headers);//POST方式访问网银获取PAYURLResponseEntity<String> response = restTemplate.exchange(jhPayProperties.getURL(), HttpMethod.POST, requestEntity, String.class);HttpEntity<String> requestEntity2 = new HttpEntity<>("", headers);JHPayDTO dto = new Gson().fromJson(response.getBody(), JHPayDTO.class);//GET方式访问PAYURL获取唤起微信支付的参数ResponseEntity<String> response2 = restTemplate.exchange(dto.getPayUrl(), HttpMethod.GET, requestEntity2, String.class);//将json字符串转化为WxPayment对象JHPayResult result = new Gson().fromJson(response2.getBody(), JHPayResult.class);result.setOrderNo(orderNo);return result;}@Overridepublic JHRefundResponse JHRefund(String orderNo, BigDecimal refundMoney, BigDecimal payMoney) {if (refundMoney.compareTo(payMoney) > 0 ){throw new MyException(ErrorEnum.REFUND_MONEY_HAVE_ERROR);}log.info("【进入建行退款】订单号:{}, 退款金额:{}, 时间:{}", orderNo, refundMoney, new Date());//请求外联HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);HttpEntity<String> requestEntity = new HttpEntity<String>(getRefundRequestXml(orderNo, refundMoney), headers);System.out.println(requestEntity);ResponseEntity<String> response = this.restTemplate.exchange(jhPayProperties.getREFUND_URL(),HttpMethod.POST,requestEntity,String.class);if (ObjectUtils.isEmpty(response) || ObjectUtils.isEmpty(response.getBody())){throw new MyException(ErrorEnum.REFUND_REQUEST_ERROR);}String str = response.getBody();log.info("【建行退款返回信息】:{}", str);//分割得到返回信息String code = str.substring(str.indexOf("")+13, str.lastIndexOf(""));if (successCode.equals(code)){return JHRefundResponse.builder().orderNo(str.substring(str.indexOf("") + 11, str.lastIndexOf(""))).payMoney(new BigDecimal(str.substring(str.indexOf("") + 12, str.lastIndexOf("")))).refundMoney(new BigDecimal(str.substring(str.indexOf("") + 8, str.lastIndexOf("")))).success(true).build();}else {throw new MyException(ErrorEnum.REFUND_ERROR);}}/*** 建行支付请求参数处理* @param orderNo* @param payMoney* @param openid* @param appId* @return*/private String getPayRequestParam(String orderNo, BigDecimal payMoney, String openid, String appId) {//md5加密 MD5加密后生成32位(小写字母 + 数字)字符串String sb1 = "MERCHANTID=" + jhPayProperties.getMERCHANTID() + "&" +"POSID=" + jhPayProperties.getPOSID() + "&" +"BRANCHID=" + jhPayProperties.getBRANCHID() + "&" +"ORDERID=" + orderNo.trim() + "&" +"PAYMENT=" + payMoney + "&" +"CURCODE=" + jhPayProperties.getCURCODE() + "&" +"TXCODE=530590&" +"REMARK1=&REMARK2=&" +"TYPE=" + jhPayProperties.getTYPE() + "&" +"PUB=" + jhPayProperties.getPUB() + "&" +"GATEWAY=" + jhPayProperties.getGATEWAY() + "&" +"CLIENTIP=®INFO=&PROINFO=&REFERER=&" +"TRADE_TYPE=" + jhPayProperties.getTRADE_TYPE() + "&" +"SUB_APPID=" + appId + "&" +"SUB_OPENID=" + openid;String sb2 = "MERCHANTID=" + jhPayProperties.getMERCHANTID() + "&" +"POSID=" + jhPayProperties.getPOSID() + "&" +"BRANCHID=" + jhPayProperties.getBRANCHID() + "&" +"ORDERID=" + orderNo.trim() + "&" +"PAYMENT=" + payMoney + "&" +"CURCODE=" + jhPayProperties.getCURCODE() + "&" +"TXCODE=530590&" +"REMARK1=&REMARK2=&" +"TYPE=" + jhPayProperties.getTYPE() + "&" +"GATEWAY=" + jhPayProperties.getGATEWAY() + "&" +"CLIENTIP=®INFO=&PROINFO=&REFERER=&" +"TRADE_TYPE=" + jhPayProperties.getTRADE_TYPE() + "&" +"SUB_APPID=" + appId + "&" +"SUB_OPENID=" + openid;return sb2 + "&MAC=" + MD5Util.MD5Lower(sb1);}/*** 建行退款请求参数处理* @param orderNo* @param refundMoney* @return*/private String getRefundRequestXml(String orderNo, BigDecimal refundMoney){//请求序列号String requestSN = KeyUtil.uniqueKey();StringBuffer sb = new StringBuffer();sb.append("requestXml=").append("").append("").append("").append(requestSN).append("").append("").append(jhPayProperties.getCUST_ID()).append("").append("").append(jhPayProperties.getUSER_ID()).append("").append("").append(jhPayProperties.getPASSWORD()).append("").append("").append("5W1004").append("").append("").append(jhPayProperties.getLANGUAGE()).append("").append("").append("").append(refundMoney).append("").append("").append(orderNo).append("").append("").append("").append("").append("").append("");return sb.toString();}
}
3.MD5工具类
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;public class MD5Util {static final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};static final char[] hexDigitsLower = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};public static String makeMD5(String password) {String result = null;MessageDigest messageDigest;try {messageDigest = MessageDigest.getInstance("MD5");messageDigest.update(password.getBytes());result = new BigInteger(1, messageDigest.digest()).toString(16);} catch (Exception e) {e.printStackTrace();}return result;}/*** 对字符串 MD5 无盐值加密** @param plainText 传入要加密的字符串* @return MD5加密后生成32位(小写字母 + 数字)字符串*/public static String MD5Lower(String plainText) {try {// 获得MD5摘要算法的 MessageDigest 对象MessageDigest md = MessageDigest.getInstance("MD5");// 使用指定的字节更新摘要md.update(plainText.getBytes());// digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值。1 固定值return new BigInteger(1, md.digest()).toString(16);} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}}/*** 对字符串 MD5 加密** @param plainText 传入要加密的字符串* @return MD5加密后生成32位(大写字母 + 数字)字符串*/public static String MD5Upper(String plainText) {try {// 获得MD5摘要算法的 MessageDigest 对象MessageDigest md = MessageDigest.getInstance("MD5");// 使用指定的字节更新摘要md.update(plainText.getBytes());// 获得密文byte[] mdResult = md.digest();// 把密文转换成十六进制的字符串形式int j = mdResult.length;char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = mdResult[i];str[k++] = hexDigits[byte0 >>> 4 & 0xf];// 取字节中高 4 位的数字转换, >>> 为逻辑右移,将符号位一起右移str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换}return new String(str);} catch (Exception e) {e.printStackTrace();return null;}}/*** 对字符串 MD5 加盐值加密** @param plainText 传入要加密的字符串* @param saltValue 传入要加的盐值* @return MD5加密后生成32位(小写字母 + 数字)字符串*/public static String MD5Lower(String plainText, String saltValue) {try {// 获得MD5摘要算法的 MessageDigest 对象MessageDigest md = MessageDigest.getInstance("MD5");// 使用指定的字节更新摘要md.update(plainText.getBytes());md.update(saltValue.getBytes());// digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值。1 固定值return new BigInteger(1, md.digest()).toString(16);} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}}/*** 对字符串 MD5 加盐值加密** @param plainText 传入要加密的字符串* @param saltValue 传入要加的盐值* @return MD5加密后生成32位(大写字母 + 数字)字符串*/public static String MD5Upper(String plainText, String saltValue) {try {// 获得MD5摘要算法的 MessageDigest 对象MessageDigest md = MessageDigest.getInstance("MD5");// 使用指定的字节更新摘要md.update(plainText.getBytes());md.update(saltValue.getBytes());// 获得密文byte[] mdResult = md.digest();// 把密文转换成十六进制的字符串形式int j = mdResult.length;char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = mdResult[i];str[k++] = hexDigits[byte0 >>> 4 & 0xf];str[k++] = hexDigits[byte0 & 0xf];}return new String(str);} catch (Exception e) {e.printStackTrace();return null;}}/*** MD5加密后生成32位(小写字母+数字)字符串* 同 MD5Lower() 一样*/public static String MD5(String plainText) {try {MessageDigest mdTemp = MessageDigest.getInstance("MD5");mdTemp.update(plainText.getBytes("UTF-8"));byte[] md = mdTemp.digest();int j = md.length;char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = md[i];str[k++] = hexDigitsLower[byte0 >>> 4 & 0xf];str[k++] = hexDigitsLower[byte0 & 0xf];}return new String(str);} catch (Exception e) {return null;}}/*** 校验MD5码** @param text 要校验的字符串* @param md5 md5值* @return 校验结果*/public static boolean valid(String text, String md5) {return md5.equals(MD5(text)) || md5.equals(Objects.requireNonNull(MD5(text)).toUpperCase());}}
4.参数封装类
1)访问网银接口返回封装类
import com.google.gson.annotations.SerializedName;
import lombok.Data;/*** @author IT00ZYQ* @Date 2020/11/13 10:36* PARURL封装类**/
@Data
public class JHPayDTO {@SerializedName("SUCCESS")private String success;@SerializedName("PAYURL")private String payUrl;}
2)建行返回封装对象
import com.google.gson.annotations.SerializedName;
import lombok.Data;import java.io.Serializable;/*** 建行返回参数封装对象*/
@Data
public class JHPayResult implements Serializable {/*** 此字段是通信标识,表示通信成功*/@SerializedName("SUCCESS")private boolean success;/*** 000000表示交易成功,非000000表示交易失败,错误信息可以查看ERRMSG字段*/@SerializedName("ERRCODE")private String errcode;/**** 错误信息描述*/@SerializedName("ERRMSG")private String errmsg;/*** 交易码*/@SerializedName("TXCODE")private String txcode;/***微信分配的APPID*/private String appId;/*** 时间戳*/private String timeStamp;/*** 随机串*/private String nonceStr;/*** 数据包*/@SerializedName("package")private String Mypackage;/*** 签名方式*/private String signType;/*** 签名数据*/private String paySign;/*** 子商户的商户号*/private String partnerid;/*** 预支付交易会话ID 建行没有*/private String prepayid ;/*** 微信H5支付中间页面URL*/private String mweb_url;/*** 订单号*/private String orderNo;}
3)建行退款返回封装类
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;/*** @author IT00ZYQ* @Date 2020/11/13 12:48* 建行退款返回封装类**/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class JHRefundResponse {/*** 是否成功退款,成功true,失败false*/private Boolean success;/*** 订单号*/private String orderNo;/*** 订单支付金额,单位元*/private BigDecimal payMoney;/*** 退款金额,单位元*/private BigDecimal refundMoney;}
5.获取唯一随机序列工具类
import java.util.Random;/*** @author IT00ZYQ* @Date 2020/5/25 18:02* 获取唯一序列工具类**/
public class KeyUtil {/*唯一键,当前毫秒数+三位随机数*/public static synchronized String uniqueKey(){Random random = new Random();Integer number = random.nextInt(900)+100;return System.currentTimeMillis()+String.valueOf(number);}/*唯一键,当前毫秒数后9位+三位随机数*/public static synchronized String uniqueKey2(){Random random = new Random();Integer number = random.nextInt(900)+100;return String.valueOf(System.currentTimeMillis()).substring(6)+String.valueOf(number);}
}
你可能感兴趣的
微信小程序使用建行支付相关推荐
- 微信小程序 openid及支付的若干问题解决方案
微信小程序 openid及支付的若干问题解决方案 参考文章: (1)微信小程序 openid及支付的若干问题解决方案 (2)https://www.cnblogs.com/jhlqab/p/78500 ...
- 【SpringBoot学习】39、SpringBoot 集成 wxJava 微信小程序:订单支付
文章目录 SpringBoot 集成 wxJava 微信小程序:订单支付 1.整合 wxJava 小程序 2.支付配置类 3.application.yml 配置 4.授权登录流程 5.uniapp ...
- 老板提了个需求:微信小程序调用支付宝支付!然后群里炸锅了
大前天,我们头戴菊花手拿红包的小编同学在社群里发出了灵魂提问: (声明一下:小编同学只是在我这里兼职运营社群,人家正经工作还是产品狗.所以这个老板不是我) 这个问题简单说,就是在微信小程序里调用支付宝 ...
- 微信小程序怎么开通支付功能?
对于一些想通过小程序卖货的企业商家来说,在申请小程序后需要同时开通微信支付功能,才能在小程序上进行交易.那么关于微信小程序怎么开通支付功能,下面给大家说一说. 一.注册非个人主体的小程序账号 不管你是 ...
- 微信小程序php后台支付,微信小程序 支付功能实现PHP实例详解
微信小程序 支付功能实现PHP实例详解 前端代码: wx.request({ url: 'https://www.yourhost.com/weixin/WeiActivity/payJoinfee' ...
- 微信小程序开发笔记 支付篇③——微信支付JSAPI下单和微信小程序调起支付(V2版本)
文章目录 一.前文 二.流程图 三.SpringBoot接口实现 2.1 微信调起支付所需数据 2.2 下单接口 2.3 支付回调接口 三.微信小程序实现 3.1 JSAP统一下单 3.2 小程序调起 ...
- 微信小程序订单生成支付二维码接口 code
手机的小程序订单是直接拉起支付界面的,有些朋友需要生成支付二维码 这边就需要去调用微信的支付二维码接口了 需要的参数是 session_id, timeStamp, nonceStr, package ...
- 微信小程序如何开通支付功能?
微信小程序商城支付方式有哪些,如何开通小程序商城的支付功能,商家开通小程序支付功能的条件有哪些,小程序支付和微商城支付有冲突吗,小程序商城支付方式下商家如何提现,手续费多少? 微信小程序商城支付方式 ...
- 微信小程序服务商模式支付巨坑解决!
今日有个在同一个小程序支付 款项需要付到不同的银行卡里去??? 于是找了下微信小程序支付文档,只有个requestPayment方法 emmm 去看看小程序后台吧 ok 有个微信支付 但是只能绑定一 ...
- 微信小程序云开发支付
微信小程序的云开发支付先看下微信官方给出的流程图: 这张图里,开发者只需要关注的是小程序和云函数端即可:云函数做了很多参数的处理,所以我们不需要关注证书,签名等,只需要调用相应的函数即可:接下来大致说 ...
最新文章
- 航天智慧物流创意组-技术培训
- System Center 2012 R2 CM系列之安装Configuration Manager
- iOS - Quartz 2D 画板绘制
- mapreduce编程实例(4)-求中位数和标准差
- wsgiserver python 漏洞_简单的WSGI server
- 一步一步学习iOS 5编程(第三版)-PDF中文版-正式发布!
- android dp sp px_规范|iOS与Android设计规范解析(一)
- linux下的C语言开发(gdb调试)
- Caused by: org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, mil_id)
- 阿里图标库的基本使用
- 转android gralloc流程分析for msm8960
- 华为手机什么时候更新鸿蒙系统_华为鸿蒙2.0系统什么时候可以用 华为鸿蒙2.0系统升级方法介绍[多图]...
- 2018美国大学计算机科学,美国大学计算机2018最新排名
- GooglePlay上架流程
- 计算机信息检索技术实质上是逻辑运算,在信息检索的实际过程中,如需要扩大检索范围时,如何调整检索策略...
- 贵州:科技创新促高质量发展
- java smb删除指定文件,java 利用SMB向远道机器写文件
- 掘安杯原题复现---Web签到题
- 移动端 简易的table表格
- 判断两个向量是否平行
热门文章
- 中芯国际公布最新人事调整(5张数据表揭开公司真实情况)
- 腾讯社交广告大赛 —— 特征与模型介绍
- 若依ruoyi框架整合magic-api快速开发
- 友盟推送:测试模式推送完成,但却收不到推送信息
- 微机原理笔记day01 计算机发展史,和计算机组成部分
- php自动生成word目录,word目录自动生成,word如何自动生成目录
- java mis_关于使用java开发Mis系统的相关内容。
- iPhone真机测试Crash信息分析
- 计算机模拟超光速,超光速十代笔记本电脑怎么样-电脑测评
- matlab设置图片背景透明_MATLAB设置图片背景透明,和设定大小,适合论文中使用...