在软件开发中,我们会经常遇到微信支付功能的需求,本文将介绍如何实现微信的退付款功能。包括:“客户端扫描二维码发起微信支付”、“客户端请求服务器,进行微信支付”、“服务器收到客户端的微信支付请求,进行微信支付”、“服务器端返回微信支付结果给客户端”、“客户端收到服务器返回的微信支付结果”、“客户端向服务器发起微信退款请求”、“服务器收到客户端微信退款申请,进行微信退款”、“将微信退款结果返回给客户端”。

1、客户端扫描二维码发起微信支付。

客户端首先对支付金额进行格式化:

String dPaymentMoney = WXPayUtil.formatAmountToPayViaWX(payAmount);/*** 当amount非常大时,为了不让传递给WX的金额因为科学记数法出现较大误差,要使用本接口而非formatAmount(double amount)*/
public static String formatAmountToPayViaWX(double amount) {BigDecimal fen = new BigDecimal(100);BigDecimal yuan = new BigDecimal(amount);//DecimalFormat df = new DecimalFormat("0.00");df.setMaximumFractionDigits(2); // 四舍五入到小数点两位return df.format(fen.multiply(yuan).doubleValue()).replaceAll(",", "");
}

新建WXPayInfo类的实例,设置微信支付金额支付授权码,授权码为扫描二维码后得到的微信付款授权码:

WXPayInfo wxPayInfo = new WXPayInfo();
wxPayInfo.setAuth_code(wxPayAuthCode);
wxPayInfo.setTotal_fee(dPaymentMoney);

WXPayInfo主要封装了微信支付需要的字段:

public class WXPayInfo extends BaseModel {public static final WXPayInfoField field = new WXPayInfoField();public static final String HTTP_WXPayInfo_MicroPay = "wxpay/microPayEx.bx";public static final String HTTP_WXPayInfo_Reverse = "wxpay/reverseEx.bx";public static final String HTTP_WXPayInfo_Refund = "wxpay/refundEx.bx";@Transientprotected String sub_mch_id; // 子商户号@Transientprotected String nonce_str; // 随机字符串@Transientprotected String sign; // 签名@Transientprotected String body; // 商品描述@Transientprotected String out_trade_no; // 随机字符串@Transientprotected String total_fee; // 总金额@Transientprotected String spbill_create_ip; // 终端IP@Transientprotected String auth_code; // 授权码@Transientprotected String transaction_id; // 微信支付订单号@Transientprotected String refund_desc; // 退款原因@Transientprotected String out_refund_no; // 商户退款单号@Transientprotected String refund_fee; // 申请退款金额@Transientprotected String refund_id; // 微信退款单号protected String couponCode; //微信支付时使用的优惠券码@Transientprotected int bonusIsChanged; // 是否进行积分变动@Transientprotected int vipID;@Transientprotected int wxVipID;@Transientprotected int wxVipCardDetailID;……

微信支付需要联网,所以需要设备连接了网络:

//结算时选择了微信支付,然后断网,在这里进行判断。支付一次失败后(短暂断网),不会将session设置为null,下次支付仍然可以使用微信支付
if (!NetworkUtils.isNetworkAvalible(getActivity())) {wxPayHttpEvent.setLastErrorCode(ErrorInfo.EnumErrorCode.EC_InvalidSession);hm.setErrorCode(EC_InvalidSession);return false;
}//判断网络是否连接
public static boolean isNetworkAvalible(Context context) {// 获得网络状态管理器ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);if (connectivityManager != null) {// 建立网络数组NetworkInfo[] net_info = connectivityManager.getAllNetworkInfo();if (net_info != null) {for (int i = 0; i < net_info.length; i++) {// 判断获得的网络状态是否是处于连接状态if (net_info[i].getState() == NetworkInfo.State.CONNECTED) {return true;} else {log.info("网络不可用!");}}}}return false;
}

2、客户端请求服务器,进行微信支付。

public boolean microPayAsync(BaseModel bm) {//TODO 暂没有指定sessionlog.info("正在执行WXPayHttpBO的microPayAsync");// 判断session是否为空,是否为断网情况if (GlobalController.getInstance().getSessionID() == null) {httpEvent.setLastErrorCode(ErrorInfo.EnumErrorCode.EC_InvalidSession);return false;}WXPayInfo wxPayInfo = (WXPayInfo) bm;RequestBody body = new FormBody.Builder().add(WXPayInfo.field.getFIELD_NAME_auth_code(), wxPayInfo.getAuth_code()) //.add(WXPayInfo.field.getFIELD_NAME_total_fee(), wxPayInfo.getTotal_fee()) //.add(WXPayInfo.field.getFIELD_NAME_couponCode(), (wxPayInfo.getCouponCode()) == null ? "" : wxPayInfo.getCouponCode()) //.add(WXPayInfo.field.getFIELD_NAME_bonusIsChanged(), String.valueOf(wxPayInfo.getBonusIsChanged())) //.add(WXPayInfo.field.getFIELD_NAME_vipID(),  String.valueOf(wxPayInfo.getVipID())) //.add(WXPayInfo.field.getFIELD_NAME_wxVipID(),  String.valueOf(wxPayInfo.getWxVipID())) //.add(WXPayInfo.field.getFIELD_NAME_wxVipCardDetailID(),  String.valueOf(wxPayInfo.getWxVipCardDetailID())) //.build();Request req = new Request.Builder().url(Configuration.HTTP_IP + WXPayInfo.HTTP_WXPayInfo_MicroPay).addHeader(BaseHttpBO.COOKIE, GlobalController.getInstance().getSessionID()).post(body).build();HttpRequestUnit hru = new RequestWXPayMicroPay();hru.setRequest(req);hru.setTimeout(TIME_OUT);hru.setbPostEventToUI(true);httpEvent.setEventProcessed(false);httpEvent.setStatus(BaseEvent.EnumEventStatus.EES_Http_ToDo);hru.setEvent(httpEvent);HttpRequestManager.getCache(HttpRequestManager.EnumDomainType.EDT_Communication).pushHttpRequest(hru);return true;
}

3、服务器收到客户端的微信支付请求,进行微信支付。

服务器收到微信支付请求,首先对支付金额的格式和大小做检查:

Double mount = BaseModel.TOLERANCE;do {try {mount = Double.parseDouble(wxPayInfo.getTotal_fee());logger.debug("App传递的金额=" + mount);if (wxPayInfo.getTotal_fee().length() - wxPayInfo.getTotal_fee().indexOf(".") == 3) { // App传递的金额一定有2位小数break;}} catch (Exception ex) {}logger.info("订单金额格式错误");return null;} while (false);if (mount <= BaseModel.TOLERANCE) {if (!StringUtils.isEmpty(wxPayInfo.getCouponCode())) {// 商家创建满10-10的优惠券,顾客有此优惠券,并且购买商品的金额为10元,那么优惠后则为0元,微信不支持支付0元params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_BusinessLogicNotDefined.toString());params.put(BaseAction.KEY_HTMLTable_Parameter_msg, "此单优惠后价格为 0 元,不支持微信支付");return JSONObject.fromObject(params, JsonUtil.jsonConfig).toString();} else {return "";}}

根据公众号appid、商户号mchid,密钥secret和证书cert创建WXPayConfigImpl实例:

WXPayConfigImpl config = new WXPayConfigImpl(appid, mchid, secret, cert);

Appid、mchid、secret、cert在配置文件中获取,cert要放在一个安全地地方:

env.properties配置文件
#运行环境
env=
#支付服务商公众号APPID
env.appid=
#服务商商户号
env.mchid=
#服务商API密钥
env.secret=
#服务商证书路径
env.cert=

使用@Value获取配置文件信息:

@Value("${env.appid}")private String appid;@Value("${env.mchid}")private String mchid;@Value("${env.secret}")private String secret;@Value("${env.cert}")private String cert;

WXPayConfigImpl类继承了WXPayConfig:

查看代码
public class WXPayConfigImpl implements WXPayConfig {private static Log logger = LogFactory.getLog(WXPayConfigImpl.class);// 支付服务商/** 服务商 公众号APPID 防止泄露 */private static String AppID = null;/** 服务商 商户号 防止泄露 */private static String MchID = null;/** 服务商 API 密钥 防止泄露 */private static String KEY = null;private byte[] certData;/** 初始化配置* * @param env* @param appid* @param mchid* @param secret*/public WXPayConfigImpl(final String appid, final String mchid, final String secret, final String cert) {try {if (StringUtils.isEmpty(BaseAction.ENV.getName()) || StringUtils.isEmpty(appid) || StringUtils.isEmpty(mchid) || StringUtils.isEmpty(secret) || StringUtils.isEmpty(cert)) {logger.info("微信支付初始化配置错误,请检查env.properties文件配置是否正确!!");logger.info("env=" + BaseAction.ENV);logger.info("appid=" + appid);logger.info("mchid=" + mchid);logger.info("secret=" + secret);logger.info("cert=" + cert);return;}// 必须放在KEY前面AppID = appid;MchID = mchid;if (EnumEnv.DEV.getName().equals(BaseAction.ENV.getName())) {if (BaseAction.UseSandBox) {KEY = getSandboxSignKey(secret);// 沙箱环境下让其每次请求微信时休眠5秒,不要频繁请求,否则可能发生意外情况Thread.sleep(5000);} else {KEY = secret;}} else if (EnumEnv.SIT.getName().equals(BaseAction.ENV.getName()) || EnumEnv.UAT.getName().equals(BaseAction.ENV.getName()) || EnumEnv.PROD.getName().equals(BaseAction.ENV.getName())) {KEY = secret;BaseAction.UseSandBox = false;} else {logger.info("env=" + BaseAction.ENV);logger.info("运行环境配置错误,请检查env.properties配置是否正确!!");return;}File file = new File(cert); // TODO 证书需要放在安全的地方!!InputStream certStream = new FileInputStream(file);this.certData = new byte[(int) file.length()];certStream.read(this.certData);certStream.close();} catch (Exception e) {logger.info("微信支付初始化配置异常:" + e.getMessage());}}public String getAppID() {return AppID;}public String getMchID() {return MchID;}public String getKey() {return KEY;}public InputStream getCertStream() {ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);return certBis;}public int getHttpConnectTimeoutMs() {return 10000;}public int getHttpReadTimeoutMs() {return 10000;}/** @param secret*            真实环境的key <br>*            根据真实环境的key获取沙箱环境下的KEY */public String getSandboxSignKey(String secret) {WXPay wxPay = new WXPay(this);try {Map<String, String> params = new HashMap<String, String>();params.put("mch_id", this.getMchID());params.put("nonce_str", WXPayUtil.generateNonceStr());params.put("sign", WXPayUtil.generateSignature(params, secret));String strXML = wxPay.requestWithoutCert("https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey", params, this.getHttpConnectTimeoutMs(), this.getHttpReadTimeoutMs());Map<String, String> result = WXPayUtil.xmlToMap(strXML);logger.info("沙箱KEY:" + result);if ("SUCCESS".equals(result.get(BaseWxModel.WXPay_RETURN))) {return result.get("sandbox_signkey");}return null;} catch (Exception e) {System.out.println("获取沙箱KEY异常:" + e.getMessage());return null;}}
}

根据WXPayConfigImpl的实例创建WXPay的实例:

WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5, UseSandBox);

获取交易单号:

String nonce_str = WXPayUtil.generateNonceStr();// String sign = WXPayUtil.generateSignature(microPayData, config.getKey(),// WXPayConstants.SignType.MD5);String out_trade_no = String.valueOf(System.currentTimeMillis() % 1000000) + nonce_str.substring(6);

将子商户好、商品描述、交易单号、终端IP、订单总金额、授权码放进hashmap容器中:

Company company = getCompanyFromSession(session);microPayData.put(WXPayInfo.field.getFIELD_NAME_sub_mch_id(), company.getSubmchid());microPayData.put(WXPayInfo.field.getFIELD_NAME_body(), "博昕-微信付款码支付-测试"); // 商品描述microPayData.put(WXPayInfo.field.getFIELD_NAME_out_trade_no(), out_trade_no); // 交易单号microPayData.put(WXPayInfo.field.getFIELD_NAME_spbill_create_ip(), "127.0.0.1"); // 终端IPif (BaseAction.UseSandBox) {microPayData.put(WXPayInfo.field.getFIELD_NAME_total_fee(), "1"); // 订单总金额,单位为分,只能为整数microPayData.put(WXPayInfo.field.getFIELD_NAME_auth_code(), "134526050509995238"); // 沙箱环境下的支付授权码} else {String amount = wxPayInfo.getTotal_fee().substring(0, wxPayInfo.getTotal_fee().indexOf("."));microPayData.put(WXPayInfo.field.getFIELD_NAME_total_fee(), amount); // 订单总金额,单位为分,只能为整数microPayData.put(WXPayInfo.field.getFIELD_NAME_auth_code(), wxPayInfo.getAuth_code()); // 授权码}

请求微信服务器进行微信支付:

Map<String, String> resp1 = wxpay.microPay(microPayData);

根据微信支付返回信息,判断是否支付成功:

if (resp1.get(BaseWxModel.WXPay_RETURN).equals(BaseWxModel.WXPay_SUCCESS) && resp1.get(BaseWxModel.WXPay_RESULT).equals(BaseWxModel.WXPay_SUCCESS)) {logger.info("付款码支付成功!!!");params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_NoError.toString());} else if (resp1.get(BaseWxModel.WXPay_RETURN).equals(BaseWxModel.WXPay_SUCCESS) && resp1.get(BaseWxModel.WXPay_RESULT).equals(BaseWxModel.WXPay_FAIL) && resp1.get("err_code").equals("USERPAYING")) {// 用户支付中,等待10秒,然后调用被扫订单结果查询API,查询当前订单的不同状态,决定下一步的操作Thread.sleep(10 * 1000);// 从公司的缓存拿到子商户号// 查询订单Map<String, String> orderQueryData = new HashMap<String, String>();orderQueryData.put(WXPayInfo.field.getFIELD_NAME_sub_mch_id(), company.getSubmchid());// orderQueryData.put(WXPayInfo.field.getFIELD_NAME_nonce_str(), nonce_str);// orderQueryData.put(WXPayInfo.field.getFIELD_NAME_sign(), sign);orderQueryData.put(WXPayInfo.field.getFIELD_NAME_out_trade_no(), out_trade_no);//int timeOut = 30; // 官方建议30秒Map<String, String> resp2 = wxpay.orderQuery(orderQueryData);logger.info("orderQueryData : " + resp2);while (resp2.get(BaseWxModel.WXPay_RETURN).equals(BaseWxModel.WXPay_SUCCESS) && resp2.get(BaseWxModel.WXPay_RESULT).equals(BaseWxModel.WXPay_SUCCESS) && resp2.get("trade_state").equals("USERPAYING") && timeOut-- > 0) {int timespan = 5;Thread.sleep(timespan * 1000);timeOut -= timespan;if (timeOut <= 0) {break;}resp2 = wxpay.orderQuery(orderQueryData);logger.info("orderQuerOyData : " + resp2);}params.putAll(resp2);if (resp2.get(BaseWxModel.WXPay_RETURN).equals(BaseWxModel.WXPay_SUCCESS) && resp2.get(BaseWxModel.WXPay_RESULT).equals(BaseWxModel.WXPay_SUCCESS) && resp2.get("trade_state").equals(BaseWxModel.WXPay_SUCCESS)) {logger.info("查询订单 --> 付款码支付成功!!!");params.put(KEY_HTMLTable_Parameter_msg, resp2.get(BaseWxModel.WXPAY_ERR_CODE_DES));params.put(JSON_ERROR_KEY, EnumErrorCode.EC_NoError.toString());} else {logger.info("查询订单 --> 付款码支付失败!!!");logger.info("用户支付未完成,请撤销订单!!!");params.put(JSON_ERROR_KEY, EnumErrorCode.EC_OtherError.toString());params.put(KEY_HTMLTable_Parameter_msg, resp2.get(BaseWxModel.WXPAY_ERR_CODE_DES));}} else {logger.info("付款码支付失败!!!");params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_OtherError.toString());params.put(KEY_HTMLTable_Parameter_msg, "服务器异常");}

4、服务器端返回微信支付结果给客户端。

return JSONObject.fromObject(params, JsonUtil.jsonConfig).toString();

5、客户端收到服务器返回的微信支付结果。

if (wxPayHttpEvent.getStatus() != BaseEvent.EnumEventStatus.EES_Http_Done) {log.info("微信支付超时....");hm.setErrorCode(ErrorInfo.EnumErrorCode.EC_Timeout);return false;}if (wxPayHttpEvent.getLastErrorCode() != ErrorInfo.EnumErrorCode.EC_NoError) { // 支付失败后,不会将session设置为null,下次支付仍然可以使用微信支付log.info("微信支付失败....");hm.setErrorCode(EC_WechatServerError);hm.setMsg(wxPayHttpEvent.getLastErrorMessage());return false;}

支付成功后,客户端设置零售单的相关字段:

paymentCode = paymentCode | wechatPayCode;BaseActivity.retailTrade.setPaymentType(paymentCode);//// TODO 这里etWechatPayingAmount是文本框输入的金额wetchatAmount = Double.valueOf(etWechatPayingAmount.getText().toString());
//        wetchatAmount = GeneralUtil.sum(Double.valueOf(etWechatPayingAmount.getText().toString()), payAmount);BaseActivity.retailTrade.setAmountWeChat(wetchatAmount);//microPayResponse = wxPayHttpEvent.getMicroPayResponse();BaseActivity.retailTrade.setWxOrderSN(microPayResponse.get("transaction_id") == null ? "" : microPayResponse.get("transaction_id"));BaseActivity.retailTrade.setWxTradeNO(microPayResponse.get("out_trade_no") == null ? "" : microPayResponse.get("out_trade_no"));BaseActivity.retailTrade.setWxRefundSubMchID(microPayResponse.get("sub_mch_id") == null ? "" : microPayResponse.get("sub_mch_id"));BaseActivity.retailTrade.setWxRefundDesc(microPayResponse.get("refund_desc") == null ? "" : microPayResponse.get("refund_desc"));

6、客户端向服务器发起微信退款请求。

客户端请求服务器,进行微信退款:

public boolean refundAsync(BaseModel bm) {log.info("正在执行WXPayHttpBO的refundAsync,bm=" + (bm == null ? null : bm.toString()));RetailTrade rt = (RetailTrade) bm;//RequestBody body = new FormBody.Builder().add(rt.field.getFIELD_NAME_amount(), String.valueOf(rt.getAmount())) //退款金额...
//                .add(rt.getFIELD_NAME_int1(), "1") //....add(rt.getFIELD_NAME_wxOrderSN(), rt.getWxOrderSN() == null ? "" : rt.getWxOrderSN()).add(rt.getFIELD_NAME_wxTradeNO(), rt.getWxTradeNO() == null ? "" : rt.getWxTradeNO())//TODO 沙箱环境可能不会返回sub_mch_id,所以如果为空就先写死;真实环境必定会返回sub_mch_id。.add(rt.getFIELD_NAME_wxRefundSubMchID(), rt.getWxRefundSubMchID() == null ? Constants.submchid : rt.getWxRefundSubMchID()).add(rt.getFIELD_NAME_wxRefundDesc(), rt.getWxRefundDesc() == null ? "" : rt.getWxRefundDesc()).build();Request req = new Request.Builder().url(Configuration.HTTP_IP + WXPayInfo.HTTP_WXPayInfo_Refund).addHeader(BaseHttpBO.COOKIE, GlobalController.getInstance().getSessionID()).post(body).build();HttpRequestUnit hru = new RequestWXPayRefund();hru.setRequest(req);hru.setTimeout(TIME_OUT);hru.setbPostEventToUI(true);httpEvent.setEventProcessed(false);httpEvent.setStatus(BaseEvent.EnumEventStatus.EES_Http_ToDo);hru.setEvent(httpEvent);HttpRequestManager.getCache(HttpRequestManager.EnumDomainType.EDT_Communication).pushHttpRequest(hru);return true;}

7、服务器收到客户端微信退款申请,进行微信退款。

创建WXPayConfigImpl的实例,获取退款单号,签名sign:

WXPayConfigImpl config = new WXPayConfigImpl(appid, mchid, secret, cert);WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5, UseSandBox);Map<String, Object> params = new HashMap<>();Map<String, String> refundData = new HashMap<String, String>();String nonce_str = WXPayUtil.generateNonceStr();String sign = WXPayUtil.generateSignature(refundData, config.getKey(), WXPayConstants.SignType.MD5);String out_refund_no = String.valueOf(System.currentTimeMillis() % 1000000) + nonce_str.substring(12);

将退款信息放到hahmap容器中:

Company company = getCompanyFromSession(session);refundData.put(WXPayInfo.field.getFIELD_NAME_sub_mch_id(), company.getSubmchid());// refundData.put(WXPayInfo.field.getFIELD_NAME_sub_mch_id(),// rt.getWxRefundSubMchID());// 子商户号refundData.put(WXPayInfo.field.getFIELD_NAME_nonce_str(), nonce_str); // 随机字符串refundData.put(WXPayInfo.field.getFIELD_NAME_sign(), sign); // 签名refundData.put(WXPayInfo.field.getFIELD_NAME_transaction_id(), rt.getWxOrderSN()); // 微信订单号refundData.put(WXPayInfo.field.getFIELD_NAME_out_trade_no(), rt.getWxTradeNO()); // 商户订单号refundData.put(WXPayInfo.field.getFIELD_NAME_refund_desc(), rt.getWxRefundDesc() == null ? "" : rt.getWxRefundDesc()); // 退款原因 非必填refundData.put(WXPayInfo.field.getFIELD_NAME_out_refund_no(), out_refund_no); // 商户退款单号 自定义//if (UseSandBox) {refundData.put(WXPayInfo.field.getFIELD_NAME_total_fee(), "502"); // 订单金额refundData.put(WXPayInfo.field.getFIELD_NAME_refund_fee(), "502"); // 申请退款金额} else {// 需要对金额进行转换。String amount = String.valueOf(rt.getAmount()).substring(0, String.valueOf(rt.getAmount()).indexOf("."));refundData.put(WXPayInfo.field.getFIELD_NAME_total_fee(), amount); // 订单金额refundData.put(WXPayInfo.field.getFIELD_NAME_refund_fee(), amount); // 申请退款金额}

进行微信退款:

//Map<String, String> resp = wxpay.refund(refundData);logger.info("refundData:" + resp);Thread.sleep(1000);if (resp.get(BaseWxModel.WXPay_RETURN).equals(BaseWxModel.WXPay_SUCCESS) && resp.get(BaseWxModel.WXPay_RESULT).equals(BaseWxModel.WXPay_SUCCESS)) {logger.info("退款成功!!!");params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_NoError.toString());} else {logger.info("退款失败!!!");params.put(KEY_HTMLTable_Parameter_msg, resp.get(BaseWxModel.WXPAY_ERR_CODE_DES)); // 微信返回的错误信息params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_OtherError.toString());}params.putAll(resp);

8、将微信退款结果返回给客户端。

return JSONObject.fromObject(params, JsonUtil.jsonConfig).toString();

Java实现微信退付款相关推荐

  1. java实现微信企业付款到个人账户

    微信官方提供了微信企业账户付款到微信个人零钱接口,提供企业向用户付款的功能,支持企业通过API接口付款,或通过微信支付商户平台网页功能操作付款.该接口并不是直接所有的商户都拥有,企业要开启必须满足以下 ...

  2. java实现微信企业付款到个人零钱(微信红包)

    今天公司打算做一个活动,就是可以让用户领取平台发送的红包,根据微信官方文档实现微信企业付款到零钱(因为商户号不满足一些条件无法使用红包,红包跟零钱实现方法基本一样),然后又加入了一些简单的红包算法.微 ...

  3. java实现微信企业付款到银行卡_微信企业付款到银行卡实现方式 - 黎明互联-官方博客 - 黎明互联 - 区块链培训,PHP培训,IT培训,职业技能培训,追求极致!改变您的职业生涯!...

    首先说一下微信支付已上线企业付款至银行卡功能.商户可以将商户号余额付款至指定的收款银行账户.通过指定收款银行账户户名.卡号,以及收款银行信息即可实现付款.但是功能目前为灰度开放,已灰度新资金流直连普通 ...

  4. 【Java】微信企业付款报错:java.io.IOException: toDerInputStream rejects tag type 45

    原因是证书格式问题,之前用PHP做一直用.pem格式的证书,看了官方文档才知道,其他语言大多用.p12格式的证书: 更换为.p12格式证书,不报错了.

  5. java 企业付款_java实现微信企业付款到个人功能

    微信官方提供了微信企业账户付款到微信个人零钱接口,提供企业向用户付款的功能,支持企业通过API接口付款,或通过微信支付商户平台网页功能操作付款.该接口并不是直接所有的商户都拥有,企业要开启必须满足以下 ...

  6. Java 微信企业付款到个人钱包

    Java 微信企业付款到个人钱包 希望可以帮助到你 文章目录 **Java 微信企业付款到个人钱包** 前言 一.需要准备的配置 二.开发 总结 前言 微信企业付款到个人钱包,此功能模块需要提前在微信 ...

  7. JAVA微信企业付款到零钱(十分钟搞定),附完整DEMO下载

    最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信提现功能开发的流程, 主要就是按规则封装好请求参数调用微信接口,涉及一些签名校验: A.接口流程 获取用户OPENI ...

  8. java零钱换整程序_JAVA微信企业付款到零钱(十分钟搞定),

    JAVA微信企业付款到零钱(十分钟搞定), 最近帮朋友做了一个简单的微分销系统,实现从企业付款到零钱分润的功能,简单记录一下微信企业付款到零钱的开发过程, 主要就是按规则封装好请求参数调用微信接口,涉 ...

  9. 基于java后台微信图书商城小程序系统 开题报告

      本科生毕业论文 基于JAVA后台微信小程序图书商城系统 开题报告 学    院: 专    业: 年    级: 学生姓名: 指导教师:   XXXX大学本科生毕业论文(设计)开题报告书 姓   ...

  10. java对接微信支付收不到支付通知问题(亲身实践)

    问题描述: 用java对接微信支付时,统一下单接口正常.但是用户扫码付款成功后,设置用于回调的notify_url对应的接口并没有收到请求(这个url测试过,是正常的且外网能访问的). 由于官方文档没 ...

最新文章

  1. IO系统性能之一:衡量性能的几个指标
  2. php 类的数组对象,javascript、php数组对象互转类
  3. FPGA进阶篇--SPI控制双通道16bit串行DAC8532
  4. Xampp修改默认端口号
  5. java stream Interface BiFunction<T,U,R>
  6. Leetcode每日一题:121.best-time-to-buy-and-sell-stock(买股票的最佳时机)
  7. 智能一代云平台(四十):Maven项目如何将lib下依赖的包打印在manifest文件中
  8. mac更新之后vmware fusion下vmware tools报错
  9. Visio常用快捷键
  10. 怎么获取php内的参数,php如何获取方法内的所有参数
  11. AIDE手机编程初级教程(零基础向) 1.1 认识我的第一个应用
  12. python 遗传算法_Python实现遗传算法的代码
  13. c语言json数据转换成字符串,C语言将字符串转json
  14. npm install 报错 this command with --force, or --legacy-peer-deps
  15. 理论小知识:字符串mset命令
  16. 10个MongoDB GUI工具概述
  17. pythonpath环境变量pth_使用pth文件添加Python环境变量方式
  18. 【NLP】第 1 章 语言处理和 Python
  19. TF_REPEATED_DATA ignoring data with redundant timestamp for frame left_wheel at time
  20. 几本关于用户体验的书籍

热门文章

  1. 怎样快速将pdf在线转换成word免费版
  2. 排序算法——梳排序 Comb sort
  3. wind10 使用Hyper-V安装centos7遇到的问题及解决方案
  4. android配置jni cmake,Android JNI之青春期 Cmake(android studio)
  5. 流量、电量、弱网环境怎么测?
  6. mybatis源码解析(二)解析SqlSession下的四大对象(Executor、StatementHandler、ParameterHandler和ResultSetHandler)和插件使用
  7. 使用lettuce和redisTemplate操作redis cluster踩坑日记
  8. 服务器限制网页只能跳转过来,限制网页只能在微信打开
  9. pytorch转onnx报错的可能原因traced region did not have observable data dependence
  10. 学习笔记1——常用的注意力机制(即插即用)