超级细节的订阅号调用服务号接口实现微信支付方案(后端语言Java)
这篇文章适用所有基于微信的H5页面实现微信支付方案
准备条件 1.认证过并且开通商户功能的服务号 2.设置网页授权域名 3.设置支付目录,配置MP_verify_f6Z9lS45bbpAZ8wY.txt
四大参数,重要,重要 1.APPID 2.APPSECRET 3.MCHID 4.KEY
下载官方SDK 我们先别挑了解压后全部丢到你的项目里面,这里有个坑后面解释
sendpix0.jpg
网页授权登录 这个不是这篇文章重点,这一步我们主要是拿到openID,所以建议使用nsapi_base授权方式。
配置MyConfig
import com.github.wxpay.sdk.WXPayConfig;
import java.io.*;
public class MyConfig implements WXPayConfig{
private byte[] certData;
public MyConfig() throws Exception {
//注意这个地方,改成你的路径,保证可以访问到,不然的话一定报错,一定~~~~~
String certPath = "/path/to/apiclient_cert.p12";
File file = new File(certPath);
InputStream certStream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
certStream.read(this.certData);
certStream.close();
}
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 8000;
}
public int getHttpReadTimeoutMs() {
return 10000;
}
}
统一下单(重点来了)
先贴代码,再解释
import com.github.wxpay.sdk.WXPay;
import java.util.HashMap;
import java.util.Map;
public class WXPayExample {
public static void main(String[] args) throws Exception {
MyConfig config = new MyConfig();
WXPay wxpay = new WXPay(config);
Map
data.put("body", "这里你自己随便写,就是付款商品名称");
data.put("out_trade_no", "这个是单号,自己随便生成个当前时间就OK,不要重复,否则会触发支付签名失败错误");
data.put("device_info", "WEB");
data.put("fee_type", "货币类型,人民币就写CNY");
data.put("total_fee", "支付金额,单位是分");
data.put("spbill_create_ip", "这里写你自己服务器IP就可以(47.100.13.44)");
data.put("notify_url", "回调URL,就是用户支付成功后通知你的地址,你要保证这个地址外网可以访问到,千万不要设置权限");
data.put("trade_type", "JSAPI"); // 此处指定为JSPAI
data.put("product_id", "商品编号,随便写");
try {
Map
//在这里我们打印微信服务器的返回结果,其实这里需要处理数据告诉前段去调起支付的,后面讲。
System.out.println(resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
如果你没出意外(没踩新坑),上面打印的结果会是
阶段性总结一下
如果你没有返回上面结果 1.首先检查你四大参数有没有对 2.服务器支付目录有没有配置正确
加工第二步拿到的xml,整出6大参数丢给前端
前端调起微信支付需要的6参数
sendpix1.jpg
实际上你想办法凑够这六个参数丢到前端,你的微信支付基本完成
1.appId 已经有了,就是四大参数里面的APPID
2.timeStamp 当前时间戳,懒得写,下好的SDK里面 WXPayUtil.getCurrentTimestamp()方法
3.nonceStr 随机搞一个,懒得写,下好的SDK里面 WXPayUtil.generateNonceStr()方法
4.signType 签名类型,这里就写MD5
5.package 这个在上一步调用微信统一下单后返回的xml里面,
注意这里你要把他拼成prepay_id=..........的格式
6.paySign
最重要的一个参数,它使用前面5个参数加四大参数里面的KEY生成的,自己懒得实现,下好的SDK里面 WXPayUtil.generateSignature("前面5个参数的map",KEY)
上面过程我贴上示例代码
Map
HashMap
map.put("appId", 你的四大参数APPID);
map.put("timeStamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));
map.put("nonceStr", WXPayUtil.generateNonceStr());
//这里的resp就是上一步里面的返回值
map.put("package", "prepay_id=" + resp.get("prepay_id"));
map.put("signType", "MD5");
map.put("paySign", WXPayUtil.generateSignature(map, 你的四大参数KEY));
OK 最重要步骤完成,先喝口咖啡在往下看 第2,3步连起来
public String payWX(HttpSession session,Integer goodsId) throws Exception {
MyWXPayConfig config = new MyWXPayConfig();
WXPay wxpay = new WXPay(config);
Goods goods = frontService.getGoodsById(goodsId);
Map
data.put("body", goods.getText());
String out_trade_no = String.valueOf(WXPayUtil.getCurrentTimestampMs());
data.put("body", "这里你自己随便写,就是付款商品名称");
data.put("out_trade_no", "这个是单号,自己随便生成个当前时间就OK,不要重复,否则会触发支付签名失败错误");
data.put("device_info", "WEB");
data.put("fee_type", "货币类型,人民币就写CNY");
data.put("total_fee", "支付金额,单位是分");
data.put("spbill_create_ip", "这里写你自己服务器IP就可以(47.100.13.44)");
data.put("notify_url", "回调URL,就是用户支付成功后通知你的地址,你要保证这个地址外网可以访问到,千万不要设置权限");
data.put("trade_type", "JSAPI"); // 此处指定为JSPAI
data.put("product_id", "商品编号,随便写");
try {
Map
HashMap
Map
HashMap
map.put("appId", 你的四大参数APPID);
map.put("timeStamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));
map.put("nonceStr", WXPayUtil.generateNonceStr());
//这里的resp就是上一步里面的返回值
map.put("package", "prepay_id=" + resp.get("prepay_id"));
map.put("signType", "MD5");
map.put("paySign", WXPayUtil.generateSignature(map, 你的四大参数KEY));
frontService.saveOrders(((User) session.getAttribute("User")).getUserId(),goodsId,out_trade_no);
//最后数据丢给前端
return jsonObj.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
这里有个大坑 如果你直接用了官方SDK,那么在WXPay.java里面像我这样改,否则会触发签名验证失败错误,因为它默认没有使用MD5
sendpix0.jpg
微信支付后端的工作阶段性完成,最后上前端
前端接到上一步的数据,直接如下操作
function onBridgeReady(data){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":data[0]["appId"], //公众号名称,由商户传入
"timeStamp":data[0]["timeStamp"], //时间戳,自1970年以来的秒数
"nonceStr":data[0]["nonceStr"], //随机串
"package":data[0]["package"],
"signType":data[0]["signType"], //微信签名方式:
"paySign":data[0]["paySign"] //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
}
});
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady(data);
}
不出意外的话,你会看到下面页面
799EE375B71C93CF165075D8C22361ED.jpg
要是出了意外的话你可能要加班检查你的签名对了没有官方验证工具
我先下班祝你好运