在做有关于微信支付之前,首先你需要让三方平台知道有一个这样的小程序,也就是在微信开发平台上注册一个开发者账号。并在里面创一个程序。我今天想要写下来的支付方式是关于小程序的,并且只有三种:免密支付,企业付款以及申请退款。获取到以下数值:
/**
* 微信支付参数配置
*/
public class WXpayConfig {
/**
* appid
*/
public static String APP_ID = "XXXXXXXXXXXXX";
public static String APP_SECRET = "XXXXXXXXXXXXXXXXX";
/**
* 商户号
*/
public static String MCH_ID = "XXXXXXXXXXXX";
/**
* API密钥,在商户平台设置
*/
public static String API_KEY = "XXXXXXXXXXXXXXXX";
/**
*模板id
*/
public static String PLAN_ID="122396";
/**
* 免密支付请求地址
*/
public static String FREE_PAY_URL="https://api.mch.weixin.qq.com/pay/pappayapply";
/**
* 企业退款
*/
public static String COMPANY_PAY="https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
/**
* 申请退款
*/
public static String RE_BACK_PAY="https://api.mch.weixin.qq.com/secapi/pay/refund";
}
免密支付:
开通免密:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_14&index=2
申请扣款:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_3&index=7
企业退款:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
申请退款:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=9_4&index=11
签名(sign)的生成:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=4_3
请求方法:
public static String postData(String urlStr, String data) {
return postData(urlStr, data, null);
}
public static String postData(String urlStr, String data, String contentType) {
BufferedReader reader = null;
try {
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(CONNECT_TIMEOUT);
if (contentType != null)
conn.setRequestProperty("content-type", contentType);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
if (data == null)
data = "";
writer.write(data);
writer.flush();
writer.close();
reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append("\r\n");
}
return sb.toString();
} catch (IOException e) {
// ((Object) logger).error("Error connecting to " + urlStr + ": " + e.getMessage());
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
}
}
return null;
}
//获取用户信息
String authenticationid=(String)request.getAttribute(APIPrincipal.PORPERTITY_AUTHENTICATION);
APIPrincipal principal=redisService.get(APIPrincipal.getCacheKey(authenticationid),APIPrincipal.class);
HashMap<String,String> map=new HashMap<>();
String contractCode=WeixinUtils.createContractCode();
map.put("appid", WXpayConfig.APP_ID);
//随机生成商户的签约协议号
map.put("contract_code",contractCode);
//随机生成请求序列号
map.put("request_serial",(WeixinUtils.createRequestSerial()+"").trim());
//回调地址(签约或者解约)
map.put("notify_url",server+"/api/wallet/signOrTerminationFreePayment.json");
//用户手机号
map.put("contract_display_account",principal.getPhone());
//商户号
map.put("mch_id",WXpayConfig.MCH_ID);
//模板id
map.put("plan_id", WXpayConfig.PLAN_ID);
//时间戳
map.put("timestamp", WeixinUtils.getTimeStamp());
//签名
map.put("sign",WeixinUtils.sign( WeixinUtils.FormatBizQueryParaMapXCX(map, false),WXpayConfig.API_KEY));
HashMap<String,Object> pay=new HashMap<>();
//获取小数点后几位数值
Double fee=totalFee.multiply(new BigDecimal(100)).doubleValue();
pay.put("appid", WXpayConfig.APP_ID);
//信息提示
pay.put("body","XXXXXXXX");
//委托代扣协议id
pay.put("contract_id",contractId);
pay.put("mch_id",WXpayConfig.MCH_ID);
//随机生成字符串
pay.put("nonce_str", WeixinUtils.createNoncestr());
//回调地址
pay.put("notify_url",server+"/api/wallet/freePayment.json");
//订单号
pay.put("out_trade_no",Sn);
//终端IP
pay.put("spbill_create_ip",host);
//支付金额
pay.put("total_fee",String.valueOf(fee.intValue()));
pay.put("trade_type","PAP");
//签名
pay.put("sign",WeixinUtils.sign( WeixinUtils.FormatBizQueryMap(pay, false),WXpayConfig.API_KEY));
HttpUtil.postData(WXpayConfig.FREE_PAY_URL,WeixinUtils.getXML(pay));
申请退款与企业付款两者之间最大的相同之处就在于都需要证书。因此,在发起支付接口的时候,需要考虑到证书,也就是说,要读取证书里面的内容。我在网上查找到很多有关于这一方面的文章,其链接具体如下:
参考文章:
- https://blog.csdn.net/uknowzxt/article/details/80694609
- https://blog.csdn.net/qq_31482599/article/details/79131680
- https://blog.csdn.net/jrainbow/article/details/50266391
我的代码:
//企业付款到微信零钱
public static String sendSSL(String url,String data){
StringBuffer message=new StringBuffer();
try{
KeyStore keyStore=KeyStore.getInstance("PKCS12","SunJSSE");
//这里需要注意的是,文件所放置的位置
FileInputStream fileInputStream=new FileInputStream(new File("/opt/certs/apiclient_cert.p12"));
keyStore.load(fileInputStream, WXpayConfig.MCH_ID.toCharArray());
SSLContext sslContext= SSLContexts.custom()
.loadKeyMaterial(keyStore,WXpayConfig.MCH_ID.toCharArray())
.build();
SSLConnectionSocketFactory sslConnectionSocketFactory=new SSLConnectionSocketFactory(
sslContext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpClient= HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.build();
HttpPost httpPost=new HttpPost(url);
httpPost.addHeader("Connection","keep-alive");
httpPost.addHeader("Accept", "*/*");
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
httpPost.addHeader("Host", "api.mch.weixin.qq.com");
httpPost.addHeader("X-Requested-With", "XMLHttpRequest");
httpPost.addHeader("Cache-Control", "max-age=0");
httpPost.addHeader("Connection","keep-alive");
httpPost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpPost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpResponse response=httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (entity != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
String text;
while ((text = bufferedReader.readLine()) != null) {
message.append(text);
}
}
EntityUtils.consume(entity);
}catch (IOException e){
e.getStackTrace();
} catch (CertificateException e1) {
e1.printStackTrace();
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
} catch (UnrecoverableKeyException e1) {
e1.printStackTrace();
} catch (KeyStoreException e1) {
e1.printStackTrace();
} catch (KeyManagementException e1) {
e1.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
return message.toString();
}
这个方法是我从网上参考了其他博主的代码,但是实现原理都是一致的
public static String Refunds(String server,String Sn,BigDecimal money){
//获取小数点后几位数值
Double fee=money.multiply(new BigDecimal(100)).doubleValue();
HashMap<String,Object> pay=new HashMap<>();
pay.put("appid", WXpayConfig.APP_ID);
pay.put("mch_id",WXpayConfig.MCH_ID);
pay.put("nonce_str", WeixinUtils.createNoncestr());
pay.put("notify_url",server+"/api/wallet/getBackMsg.json");
pay.put("out_trade_no",Sn);
pay.put("out_refund_no",Sn);
pay.put("total_fee",String.valueOf(fee.intValue()));
pay.put("refund_fee",String.valueOf(fee.intValue()));
pay.put("refund_desc","退款");
pay.put("sign",WeixinUtils.sign( WeixinUtils.FormatBizQueryMap(pay, false),WXpayConfig.API_KEY));
return HttpUtil.sendSSL(WXpayConfig.RE_BACK_PAY,WeixinUtils.getXML(pay));
}
public static String resultCompany(APIPrincipal principal, String Sn, BigDecimal profit,String host){
//获取小数点后几位数值
Double fee=profit.multiply(new BigDecimal(100)).doubleValue();
HashMap<String,Object> pay=new HashMap<>();
pay.put("mch_appid", WXpayConfig.APP_ID);
pay.put("mchid",WXpayConfig.MCH_ID);
pay.put("nonce_str", WeixinUtils.createNoncestr());
pay.put("partner_trade_no",Sn);
pay.put("openid",principal.getOpenId());
pay.put("check_name","FORCE_CHECK");
pay.put("re_user_name",principal.getUsername());
pay.put("spbill_create_ip",host);
pay.put("amount",String.valueOf(fee.intValue()));
pay.put("desc","收益提现");
pay.put("sign",WeixinUtils.sign( WeixinUtils.FormatBizQueryMap(pay, false),WXpayConfig.API_KEY));
return HttpUtil.sendSSL(WXpayConfig.COMPANY_PAY,WeixinUtils.getXML(pay));
}