**
近期要做支付,查了很多资料,所以把一些东西分享给大家
首先要去申请一个公众号,是服务类型的,完成企业认证。
如图所示,申请支付,通过后会把商户号相关信息发送到预留的邮箱
这里查看公众号的AppId,设置开发者密码。
我们用申请支付通过后,发给我们的商户号登陆商户平台> 设置API密钥
API密钥用于接口调用时候,必填参数签名sign的生成,签名算法
准备工作差不多已经完成,接下来准备开始开发
官方开发文档地址
由于近期工作时间比较紧张,这里只说一个下单的接口使用方法,其余的类似。
大概就是利用HTTP方式请求接口,然后拿到响应的内容。请求参数,响应参数文档都有写,照着填就行。需要注意的是,请求接口的参数必须是xml格式的,不是json!
首先得写一个http请求的工具类,网上一大堆,我这里帖出一个:
public class HttpUtils extends WXPayConfig {
public enum RequestMethod {
POST, GET
}
/**
* 发送https请求
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return 返回微信服务器响应的信息
*/
public static String httpsRequest(String requestUrl, RequestMethod requestMethod, String outputStr) {
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
X509TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod.toString());
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
log.error("连接超时:{}", ce);
} catch (Exception e) {
log.error("https请求异常:{}", e);
}
return null;
}
}
下面是生成sign的方法,data就是请求的参数,放进一个Map中,键就是官方文档里给的参数名
/**
* 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
*
* @param data 待签名数据
* @param key API密钥
* @param signType 签名方式
* @return 签名
*/
public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
sb.append("key=").append(key);
if (SignType.MD5.equals(signType)) {
return MD5(sb.toString()).toUpperCase();
}
else if (SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
下来我们用main方法测试(当然你也可以用postman等工具)
public static void main(String[] args) throws Exception {
Map map = new HashMap();
map.put("appid", WXPayConfig.pcAppId);//公众号APPId
map.put("mch_id",WXPayConfig.mch_id);//商户号ID
map.put("nonce_str", WXPayUtil.generateNonceStr());//随机数,方式有很多种。
map.put("body","测试");//商品描述
map.put("notify_url","https://www.baidu.com");//通知地址,我这里乱填的
map.put("out_trade_no","11111111111");//商品订单号,根据实际情况自己生成
map.put("spbill_create_ip","127.0.0.1");//客户端IP
map.put("total_fee","1");//订单金额,注意单位是分
map.put("trade_type",WXPayConfig.NATIVE);//交易类型,这里填NATIVE
//生成签名sign
String sign = WXPayUtil.generateSignature(map,WXPayConfig.key,SignType.MD5);
//把签名继续装进map
map.put("sign",sign);
//把map类型的参数转换成xml
String xmlParam = WXPayUtil.mapToXml(map);
//下单接口地址(参考官方接口文档)
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
String result =HttpUtils.httpsRequest(url, HttpUtils.RequestMethod.POST,xmlParam);
log.info(result);
}
这里返回的也是xml格式,具体看官方。其中有一个标签是code_url,里面就存着我们需要的二维码链接,把这个链接发给前端,用插件生成二维码图片,或者直接在后端生成图片存到某一路径下,让前端直接显示。
我们需要做的就是把这个xml格式的字符串给他转换出我们想要的类型,map也好,对象也行,总之这里xml之间的转换,网上也有一大堆,这里就不贴出代码了,因为每个人的方式不同。
最后感谢看完这篇我都看不下去的大佬们 ,这也只是我小小的记录而已,并没有多少实质上的技术含量,还望大牛们海涵,哪里有不对的地方,请大佬们指出。