第一次做这个功能,坑有点多(官方坑也有),最终完全了付款到银行卡功能,一一为大家踩坑。文章只讲解关于转账至银行卡的业务逻辑,需要用到的工具类,还有具体做法都会贴,适合第一次开发此功能的人看。

官方文档:

【微信支付】付款开发者文档

一、准备

1.证书

按照文档操作,得到apiclient_cert.p12文件,将他放到项目内的resources/static内,如果要部署jar到云服务器的,可以把证书放在项目同文件。后面访问时需要证书路径。

2.rsa公钥文件

看文档内获取rsa公钥的文档,准备好请求参数,直接用postman请求,参数中随机值(自己生产也好,随便敲也好,跟示例参数一样多位的随机值就行),sign参数(用签名工具类把几个参数签下名)

签名方式和支付功能一样,可以直接用之前开发支付用的工具类,啥?之前没做支付,没有工具类?

那我贴一下吧:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.*;/*** 微信支付要用到的:xml解析工具类*/
public class WXPayUtils {/*** XML格式字符串转换为Map** @param strXML XML字符串* @return XML数据转换后的Map* @throws Exception*/public static Map<String, String> xmlToMap(String strXML) throws Exception {try {Map<String, String> data = new HashMap<String, String>();DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));org.w3c.dom.Document doc = documentBuilder.parse(stream);doc.getDocumentElement().normalize();NodeList nodeList = doc.getDocumentElement().getChildNodes();for (int idx = 0; idx < nodeList.getLength(); ++idx) {Node node = nodeList.item(idx);if (node.getNodeType() == Node.ELEMENT_NODE) {org.w3c.dom.Element element = (org.w3c.dom.Element) node;data.put(element.getNodeName(), element.getTextContent());}}try {stream.close();} catch (Exception ex) {// do nothing}return data;} catch (Exception ex) {WXPayUtils.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);throw ex;}}/*** 将Map转换为XML格式的字符串** @param data Map类型数据* @return XML格式的字符串* @throws Exception*/public static String mapToXml(Map<String, String> data) throws Exception {Document document = WXPayXmlUtil.newDocument();Element root = document.createElement("xml");document.appendChild(root);for (String key: data.keySet()) {String value = data.get(key);if (value == null) {value = "";}value = value.trim();Element filed = document.createElement(key);filed.appendChild(document.createTextNode(value));root.appendChild(filed);}TransformerFactory tf = TransformerFactory.newInstance();Transformer transformer = tf.newTransformer();DOMSource source = new DOMSource(document);transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");transformer.setOutputProperty(OutputKeys.INDENT, "yes");StringWriter writer = new StringWriter();StreamResult result = new StreamResult(writer);transformer.transform(source, result);String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");try {writer.close();}catch (Exception ex) {}return output;}/*** 生成微信支付sign*/public static String createSign(SortedMap<String, String> params, String key){StringBuilder sb = new StringBuilder();Set<Map.Entry<String, String>> es = params.entrySet();Iterator<Map.Entry<String, String>> it = es.iterator();while(it.hasNext()){Map.Entry<String, String> entry = it.next();String k = entry.getKey();String v = entry.getValue();if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)){sb.append(k + "=" + v + "&");}}sb.append("key=").append(key);String sign = CommonUtils.MD5(sb.toString()).toUpperCase();return sign;}/*** 校验签名* @param params* @param key* @return*/public static Boolean isCorrectSign(SortedMap<String, String> params, String key){String sign = createSign(params, key);String wxPaySign = params.get("sign").toUpperCase();return  wxPaySign.equals(sign);}/*** 获取有序map* @param map*/public static SortedMap<String, String> getSortedMap(Map<String, String> map){SortedMap<String, String> sortedMap = new TreeMap<>();Iterator<String> it = map.keySet().iterator();while(it.hasNext()){String key = it.next();String value = map.get(key);String temp = "";if(null != value){temp = value.trim();}sortedMap.put(key, value);}return sortedMap;}/*** 日志* @return*/public static Logger getLogger() {Logger logger = LoggerFactory.getLogger("wxpay java sdk");return logger;}/*** 获取当前时间戳,单位秒* @return*/public static long getCurrentTimestamp() {return System.currentTimeMillis()/1000;}/*** 获取当前时间戳,单位毫秒* @return*/public static long getCurrentTimestampMs() {return System.currentTimeMillis();}/*** 生成UUID(用来表示一笔订单)* @return*/public static String generateUUID(){String uuid = UUID.randomUUID().toString().replaceAll("-","").substring(0,32);return uuid;}
}

——签好名就请求获取rsa公钥接口,拿到了RSA公钥字符串。

——不要高兴得太早,请把这个字符串复制进txt,名字随意英文,然后改后缀名.pem,因为你是Java你需要转pkcs#8

文档内有互转的方法:

openssl rsa -RSAPublicKey_in -in <filename> -pubout

——如果没有openssl,你需要安装并配置openssl,这个可以百度。安装好后配置环境变量,然后在bin路径输入cmd,再跑上面的代码,成功之后,转换结果会直接显示在命令行,请复制这些密钥字符串。

——接下来,删除首尾:-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----

——然后将剩下的字符串放进txt,该后缀名pem,再放进项目的resources/static内。

——截止目前,我们便得到了rsa公钥文件:rsa.pem

3.银行卡开户行代号(付款至银行卡需要微信自己的参数)

这个我觉得不用说那么详细了,我自己用的方式都很业余。我是从百度找到了一个阿里的开发性api,用于获取银行卡开户行,然后再把微信的代号填到对照表里。再整理成工具类,把银行卡号做参数就可以得出代号(有几个小银行没有在对照表里),从优化的角度来看,这种方式需要跨域请求,最好是用一种可以直接识别银行卡号开户行的工具类,然后把微信开户行代号表和工具类的银行名称对齐一下。这里就默认你已经获取了银行卡开户行代号。

二、入参准备

——商户号:自行获取

——商户订单号:在请求这个接口前,你需要先新增一个你目前系统的订单,就是在订单表里插入一条订单,这个订单号就是商户订单号。

——随机值:直接调用我上方的工具类,有个generateUUID()函数直接获取。

——银行卡号:这个就需要用rsa公钥加密了。你已经有了公钥文件,但需要转成PublicKey类才能使用我的加密工具类。下面分步叙述流程(结果将得到PublicKey文件):

1.获取公钥文件的字节输入流

InputStream rsaStream = getClass().getClassLoader().getResourceAsStream(RSA公钥文件的路径字符串);

2.用下面这个工具类转成字符串

import java.io.ByteArrayOutputStream;
import java.io.InputStream;/*IO流工具类*/
public class StreamUtil {/*** 读取 InputStream 到 String字符串中*/public static String readStream(InputStream in) {try {//<1>创建字节数组输出流,用来输出读取到的内容ByteArrayOutputStream baos = new ByteArrayOutputStream();//<2>创建缓存大小byte[] buffer = new byte[1024]; // 1KB//每次读取到内容的长度int len = -1;//<3>开始读取输入流中的内容while ((len = in.read(buffer)) != -1) { //当等于-1说明没有数据可以读取了baos.write(buffer, 0, len);   //把读取到的内容写到输出流中}//<4> 把字节数组转换为字符串String content = baos.toString();//<5>关闭输入流和输出流in.close();baos.close();//<6>返回字符串结果return content;} catch (Exception e) {e.printStackTrace();return  e.getMessage();}}
}

3.再用下面这个工具类getPublicKey(String key)函数将公钥字符串转为PublicKey类(该工具类包含RSA加密方法)

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;
import sun.misc.BASE64Decoder;public class RSAwxUtil {public static byte[] decrypt(byte[] encryptedBytes, PrivateKey privateKey, int keyLength, int reserveSize, String cipherAlgorithm) throws Exception {int keyByteSize = keyLength / 8;int decryptBlockSize = keyByteSize - reserveSize;int nBlock = encryptedBytes.length / keyByteSize;ByteArrayOutputStream outbuf = null;try {Cipher cipher = Cipher.getInstance(cipherAlgorithm);cipher.init(Cipher.DECRYPT_MODE, privateKey);outbuf = new ByteArrayOutputStream(nBlock * decryptBlockSize);for (int offset = 0; offset < encryptedBytes.length; offset += keyByteSize) {int inputLen = encryptedBytes.length - offset;if (inputLen > keyByteSize) {inputLen = keyByteSize;}byte[] decryptedBlock = cipher.doFinal(encryptedBytes, offset, inputLen);outbuf.write(decryptedBlock);}outbuf.flush();return outbuf.toByteArray();} catch (Exception e) {throw new Exception("DEENCRYPT ERROR:", e);} finally {try{if(outbuf != null){outbuf.close();}}catch (Exception e){outbuf = null;throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);}}}public static byte[] encrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm) throws Exception {int keyByteSize = keyLength / 8;int encryptBlockSize = keyByteSize - reserveSize;int nBlock = plainBytes.length / encryptBlockSize;if ((plainBytes.length % encryptBlockSize) != 0) {nBlock += 1;}ByteArrayOutputStream outbuf = null;try {Cipher cipher = Cipher.getInstance(cipherAlgorithm);cipher.init(Cipher.ENCRYPT_MODE, publicKey);outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {int inputLen = plainBytes.length - offset;if (inputLen > encryptBlockSize) {inputLen = encryptBlockSize;}byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);outbuf.write(encryptedBlock);}outbuf.flush();return outbuf.toByteArray();} catch (Exception e) {throw new Exception("ENCRYPT ERROR:", e);} finally {try{if(outbuf != null){outbuf.close();}}catch (Exception e){outbuf = null;throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);}}}public static PrivateKey getPriKey(String privateKeyPath,String keyAlgorithm){PrivateKey privateKey = null;InputStream inputStream = null;try {if(inputStream==null){System.out.println("hahhah1!");}inputStream = new FileInputStream(privateKeyPath);System.out.println("hahhah2!");privateKey = getPrivateKey(inputStream,keyAlgorithm);System.out.println("hahhah3!");} catch (Exception e) {System.out.println("加载私钥出错!");} finally {if (inputStream != null){try {inputStream.close();}catch (Exception e){System.out.println("加载私钥,关闭流时出错!");}}}return privateKey;}public static PublicKey getPubKey(String publicKeyPath,String keyAlgorithm){PublicKey publicKey = null;InputStream inputStream = null;try{System.out.println("getPubkey 1......");inputStream = new FileInputStream(publicKeyPath);System.out.println("getPubkey 2......");publicKey = getPublicKey(inputStream,keyAlgorithm);System.out.println("getPubkey 3......");} catch (Exception e) {e.printStackTrace();//EAD PUBLIC KEY ERRORSystem.out.println("加载公钥出错!");} finally {if (inputStream != null){try {inputStream.close();}catch (Exception e){System.out.println("加载公钥,关闭流时出错!");}}}return publicKey;}public static PublicKey getPublicKey(InputStream inputStream, String keyAlgorithm) throws Exception {try{System.out.println("b1.........");BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));System.out.println("b2.........");StringBuilder sb = new StringBuilder();String readLine = null;System.out.println("b3.........");while ((readLine = br.readLine()) != null) {if (readLine.charAt(0) == '-') {continue;} else {sb.append(readLine);sb.append('\r');}}System.out.println("b4.........");X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(decodeBase64(sb.toString()));System.out.println("b5.........");KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);System.out.println("b6.........");//下行出错  java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=127, too big.PublicKey publicKey = keyFactory.generatePublic(pubX509);System.out.println("b7.........");return publicKey;} catch (Exception e) {e.printStackTrace();System.out.println("b8.........");throw new Exception("1这里报异常了:"+e.getMessage(), e);} finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {inputStream = null;throw new Exception("INPUT STREAM CLOSE ERROR:", e);}}}public static PrivateKey getPrivateKey(InputStream inputStream, String keyAlgorithm) throws Exception {try {BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));StringBuilder sb = new StringBuilder();String readLine = null;while ((readLine = br.readLine()) != null) {if (readLine.charAt(0) == '-') {continue;} else {sb.append(readLine);sb.append('\r');}}System.out.println("hahhah4!"+decodeBase64(sb.toString()));PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(decodeBase64(sb.toString()));System.out.println("hahhah5!");KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);System.out.println("hahhah6!");PrivateKey privateKey = keyFactory.generatePrivate(priPKCS8);System.out.println("hahhah7!");return privateKey;} catch (Exception e) {throw new Exception("READ PRIVATE KEY ERROR:" ,e);}  finally {try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {inputStream = null;throw new Exception("INPUT STREAM CLOSE ERROR:", e);}}}//一下面是base64的编码和解码public static String encodeBase64(byte[]input) throws Exception{Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");Method mainMethod= clazz.getMethod("encode", byte[].class);mainMethod.setAccessible(true);Object retObj=mainMethod.invoke(null, new Object[]{input});return (String)retObj;}/**** decode by Base64*/public static byte[] decodeBase64(String input) throws Exception{Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");Method mainMethod= clazz.getMethod("decode", String.class);mainMethod.setAccessible(true);Object retObj=mainMethod.invoke(null, input);return (byte[])retObj;}public static PublicKey getPublicKey(String key) throws Exception {byte[] keyBytes;keyBytes = (new BASE64Decoder()).decodeBuffer(key);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(keySpec);return publicKey;}public static PrivateKey getPrivateKey(String key) throws Exception {byte[] keyBytes;keyBytes = (new BASE64Decoder()).decodeBuffer(key);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(keySpec);return privateKey;}}

该步骤总代码:

PublicKey pub;
try {pub = RSAwxUtil.getPublicKey(readStream(wxPayAppConfig.getRsaPublicKeyStream()));
} catch (Exception e) {e.printStackTrace();baseEntity.setStatus(2);baseEntity.setMessage("读取RSA公钥时异常:"+e.getMessage());return baseEntity;
}

加密流程(以卡号为例):

1.直接复制(文档要求)

String rsa ="RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";

2.调用encrypt()函数,直接贴我的逻辑代码:

byte[] enc_bank_no_byte;
try {enc_bank_no_byte = RSAwxUtil.encrypt(bank_card.getBytes(),pub,2048,11,rsa);
} catch (Exception e) {e.printStackTrace();baseEntity.setStatus(2);baseEntity.setMessage("对银行卡号进行加密时异常,异常原因:"+e.getMessage());return baseEntity;
}String enc_bank_no;//最终银行卡号参数
try {enc_bank_no = BASE64.encode(enc_bank_no_byte);
} catch (Exception e) {e.printStackTrace();baseEntity.setStatus(2);baseEntity.setMessage("将银行卡号byte转为字符串时异常,异常原因:"+e.getMessage());return baseEntity;
}

——真实姓名:加密过程一致,不赘述。

——银行卡代号:不赘述

——金额:这里要注意,没做过支付的朋友,这个单位是分不是元,用订单金额*100即可。

——签名:上面已经贴了签名工具类,下面会贴我的请求代码。

最终请求代码:

SortedMap<String, String> params = new TreeMap<>();
try{params.put("mch_id",wxPayAppConfig.getMchID());params.put("partner_trade_no",orderNo);           // 商户订单号params.put("nonce_str",WXPayUtils.generateUUID());//随机值params.put("enc_bank_no",enc_bank_no);//加密后的银行卡号params.put("enc_true_name",enc_true_name);//加密后的真实姓名params.put("bank_code",bank_code);//银行卡代号params.put("amount",amount);// 标价金额(单位为分)params.put("desc", "提现");//sign签名String sign = WXPayUtils.createSign(params, wxPayAppConfig.getKey());params.put("sign",sign);
} catch (Exception e){e.printStackTrace();baseEntity.setStatus(2);baseEntity.setMessage("请求前,封装入参时异常,异常原因:"+e.getMessage());return baseEntity;
}

因为入参格式要求xml,请用工具类(上面找)转换:

String payXml;
try{payXml = WXPayUtils.mapToXml(params);
} catch (Exception e){e.printStackTrace();baseEntity.setStatus(2);baseEntity.setMessage("请求接口前,map转xml异常,异常原因:"+e.getMessage());return baseEntity;
}

到此,入参封装好了。

三、请求转账接口

直接调用请求类请求,下面会发,在请求之前,说一说证书路径。如果要将jar部署到云服务器上,可以将你的证书放在云服务器里和项目同一个目录,然后用以下方法直接获取路径:

String path = System.getProperty("user.dir")+"/apiclient_cert.p12";

下面是请求类:

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;import javax.net.ssl.SSLContext;import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;/*** This example demonstrates how to create secure connections with a custom SSL* context.*/
public class ClientCustomSSL {@SuppressWarnings("deprecation")public static String doRefund(String url, String data, String p12_path, String p12_key) throws Exception {KeyStore keyStore = KeyStore.getInstance("PKCS12");FileInputStream instream = new FileInputStream(new File(p12_path));//P12文件目录try {/*** 下载证书时的密码、默认密码是你的MCHID mch_id* */keyStore.load(instream, p12_key.toCharArray());} finally {instream.close();}// Trust own CA and all self-signed certs/*** 下载证书时的密码、默认密码是你的MCHID mch_id* */SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, p12_key.toCharArray())//这里也是写密码的.build();// Allow TLSv1 protocol onlySSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();try {HttpPost httpost = new HttpPost(url); httpost.addHeader("Connection", "keep-alive");httpost.addHeader("Accept", "*/*");httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");httpost.addHeader("Host", "api.mch.weixin.qq.com");httpost.addHeader("X-Requested-With", "XMLHttpRequest");httpost.addHeader("Cache-Control", "max-age=0");httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");httpost.setEntity(new StringEntity(data, "UTF-8"));CloseableHttpResponse response = httpclient.execute(httpost);try {HttpEntity entity = response.getEntity();String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");EntityUtils.consume(entity);return jsonStr;} finally {response.close();}} finally {httpclient.close();}}
}

我的请求代码:(请求类四个参数分别是:付款url,入参xml,证书路径,商户号)

String result;
try{result = ClientCustomSSL.doRefund(url, payXml,path,wxPayAppConfig.getMchID());
} catch (Exception e){e.printStackTrace();baseEntity.setStatus(2);baseEntity.setMessage("请求转账接口时异常,异常原因:"+e.getMessage());return baseEntity;
}

最后需要将xml转为map:

Map<String, String> payBankMap;
try{payBankMap = WXPayUtils.xmlToMap(s);
} catch (Exception e){e.printStackTrace();baseEntity.setStatus(2);baseEntity.setMessage("请求结果xml数据转map时异常,异常原因:"+e.getMessage());return baseEntity;
}

至此,付款请求完成。

根据payBankMap.get("result_code")参数可以知道付款成功或失败。

最后不要忘记更新相关数据库表的业务逻辑,如:付款后,订单改为已付款之类的。

还有,请保证微信支付运营账户余额大于1.5元,因为每一笔打款订单,微信起步手续费1元。也就是说,就算你打款0.01元,将被扣1.01元。

因为文档没有体现手续费起步1元,我浪费了大半天时间百度,就连技术客服都不知道这个规则,还帮我看后台日志,最后问他同事才知道。这种坑实在是不应该,还有请求时突然不支持的协议(该文档已经屏蔽),从开发社区里看到,两年前的文档漏洞,今天还没改...

另外需要注意的是,每个商户最低打款额不同,有些商户是0.01元,也有看到有很多商户是0.03元。

微信支付:springboot企业付款到个人银行卡相关推荐

  1. java 微信转账 ca_error_【微信支付】企业付款开发者文档

    [微信支付]企业付款开发者文档 2018-11-24 简介 企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款 ...

  2. 微信支付(企业付款到个人微信零钱账户)微信公众平台开发教程(6)

    微信支付(企业付款到个人微信零钱账户)微信公众平台开发教程(6 简介 开发步骤 后端代码实现 简介 Senparc.Weixin SDK 是由盛派网络(Senparc)团队自主研发的针对微信各模块的 ...

  3. PHP之 微信支付 查询企业付款银行卡API 或 查询给企业付款是否到账 功能业务处理

    一.情景简述 之前做了微信付款到企业银行卡的功能,但是,给客户打款后,次日才能到账,为及时进行反馈,于是又做了"查询给企业付款是否到账"的功能.这块,我直接写了一个类,进行处理,下 ...

  4. 微信支付之企业付款(提现,理赔,退款)(java)

    /*** 提现操作* @throws Exception */@RequestMapping("doCash")public String doTravelScoreCash(Ht ...

  5. 微信支付(一) - 企业付款到用户零钱

    使用场景介绍 官方说的太绕了, 简单说就是 app运营商(网站/等等)- 代表你,你想给你网站用户打钱: 那么首先你得提交一些列材料去微信申请 申请详细介绍地址参考 https://pay.weixi ...

  6. 微信支付之企业付款--微信商户后台没有“企业付款到零钱”解决方案

    项目需要用到用户提现功能,准备用微信支付提供的企业付款功能,即提供企业向用户付款的功能,支持企业通过API接口付款,或通过微信支付商户平台网页功能操作付款. 登录商户后台准备开通,发现产品中心中并不存 ...

  7. php 微信支付到银行卡号,【微信支付】企业付款开发者文档

    字段名 变量名 必填 类型 说明 返回状态码 return_code 是 String(16) SUCCESS/FAIL 此字段是通信标识,非付款标识,付款是否成功需要查看result_code来判断 ...

  8. 微信接口 java_【微信支付】企业付款开发者文档

    付款方式 ◆ 支持API接口或网页操作,付款至目标用户. 收款用户身份指定 ◆ 通过APPID+OPENID指定收款用户. ◆ APPID需要为申请商户号时的APPID,或者与商户号有绑定关系. ◆ ...

  9. php 微信证书,【微信支付】企业付款开发者文档

    1.签名算法 签名生成的通用步骤如下: 第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=valu ...

最新文章

  1. 网站开发绝不像你看到的那么简单!
  2. c++调用python操作mongo
  3. c++ primer 笔记 (三)
  4. IDEA 断点调试高级玩法 |debug高手必看!
  5. python数据结构实验目的_图的基本操作实现(数据结构实验)
  6. 不要在变量名的旁边加echo和.br;
  7. 凝思系统改时间_大众改原厂盲点监测系统,中山大众原厂改装,途观L改盲点监测...
  8. 关注电子商务网站开发-《网站中常用的Jquery插件》
  9. Kettle增量同步变动数据
  10. 【UVa11178】Morley's Theorem(向量旋转+直线交点)
  11. 启用IIS7配置ASP运行环境的详细方法
  12. 身心灵觉醒视频汇总【建议收藏】
  13. MSDC 4.3 接口规范(25)
  14. Win11系统输入法无法调出问题解决方法
  15. PostGreSQL主从库环境下的从节点故障恢复
  16. 打印机不打印计算机原因,打印机打印不完整?是这10个原因造成的!打印必备...
  17. 合成共轭莫比乌斯索烃研究取得进展
  18. 2020年笔记本电脑计算机专业,适合女生用的笔记本电脑排名2020
  19. Linux 安装AndroidSdk 并使用zipalign对齐工具完成apk的签名
  20. 蓝牙协议栈消息的关联

热门文章

  1. OpenGL置换贴图
  2. 客服对于网店的重要性
  3. springboot 支付宝支付( 花呗分期)
  4. 如何用Python做词云?(基础篇视频教程)
  5. 一位项目管理专家总结的项目职场技巧
  6. ibm cloud属于paas吗_研华成立WISE-Cloud智慧云平台联盟
  7. me shy是什么歌 抖音make_抖音上最火爆的5首英文歌原版!每一首听不腻!都
  8. JS数字转字符串,字符串转数字
  9. 运营商如何创新流量经营模式?
  10. LaTeX-----绘制三线表格