开发前准备工作
在开发小程序之前,确保你的小程序开通了微信支付(开通申请要求小程序已发布上线),详情参考微信支付开发文档。、
地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11&index=2
调用统一下单接口
地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
统一下单接口必传参数之小程序ID-appid。
统一下单接口和生成签名必传参数之商户号-mch_id。
统一下单接口必传的参数签名-sign,通过签名算法计算得出的签名值。
签名生成算法:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3
微信支付接口签名校验工具:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
生成签名必传参数key的获取:key设置路径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API安全–>密钥设置
正确生成签名
支付验证签名失败部分原因
参考地址:https://developers.weixin.qq.com/community/develop/doc/000e48bbda4178c903b8085a45b800
代码编写
调用统一下单接口
/**
* 小程序支付 - 统一下单
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/unifiedorder")
public String wechatpayunifiedorder(Integer orderId,HttpServletRequest request) throws Exception {
String openId = "oRUgC5cfq4gvMIeubi4Q-6UDTqws"; // 用户在商户appid下的唯一标识
Map params = new HashMap();
//获得订单
WxOrderEntity order = orderService.getById(Long.valueOf(orderId));
WxCourseEntity courseEntity = wxCourseService.selectByPrimaryKey(order.getCourseId());
String body = courseEntity.getName();
String total_amount = "1";
if (order != null) {
if (order.getSalePrice() != null && order.getSalePrice() > 0)
total_amount = (int) (order.getSalePrice() * 100) + "";
else
return "价格不能为空";
}
String res = null;
Map resp = null;
MiniProgramConfig config = new MiniProgramConfig();
WXPay wxpay = new WXPay(config, "/wechat/order/updateState", false, false);
Map data = new HashMap<>();
data.put("body", body); // 商品简单描述
data.put("out_trade_no", order.getOrderNo() + "_" + new Date().getTime()); //商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一
data.put("fee_type", "CNY"); // 符合ISO 4217标准的三位字母代码,默认人民币:CNY
data.put("total_fee", total_amount); // 订单总金额,单位为分
String ip = getIpAddr(request);
data.put("spbill_create_ip", "127.0.0.1"); // 终端IP
data.put("trade_type", "JSAPI"); // 此处指定为公众号支付
data.put("openid", openId); //用户标识
try {
resp = wxpay.unifiedOrder(data);
String str = resp.get("return_code");
if (str.equals("SUCCESS")){
// 调用成功返回参数
resp.put("signType", WXPayConstants.MD5);
resp.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
Map s = new HashMap<>();
s.put("appId", config.getAppID());
s.put("timeStamp", resp.get("timeStamp"));
s.put("nonceStr", resp.get("nonce_str"));
s.put("package", "prepay_id=" + resp.get("prepay_id")); // 微信生成的预支付会话标识,用于后续接口调用中使用,该值有效期为2小时
s.put("signType", WXPayConstants.MD5);
resp.put("paySign", WXPayUtil.generateSignature(s, config.getKey(), WXPayConstants.SignType.MD5));
logger.debug("paySign:" + resp.get("paySign"));
res = JSON.toJSONString(resp);
System.out.println(res);
}else {
res = resp.get("return_msg");
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
小程序配置类
public class MiniProgramConfig extends WXPayConfig{
private byte[] certData;
public MiniProgramConfig() throws Exception {
}
public String getAppID() {
return "小程序appid";
}
public String getAppSecret() {
return "小程序秘钥secret";
}
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;
}
@Override
IWXPayDomain getWXPayDomain() {
return WXPayDomainSimpleImpl.instance();
}
}
WXPay类是一个封装了请求微信接口的类,用到的工具类比较多,不好截图或者放代码,会将相关的类上传,这里放几个用到的方法。
调用统一下单参数
调用统一下单失败的返回
调用统一下单成功的返回
微信支付完成
微信小程序与公众号支付都是调用统一下单接口,下面是微信公众号支付调用后台统一下单的接口方法。
function unifiedorder(){
var openId = document.getElementById("openId").value;
var orderId = ("${order.id}");
$.ajax({
data:{
"orderId" : orderId,
"openId" : openId
},
dataType:'json',//服务器返回json格式数据
type:'post',//HTTP请求类型
timeout:10000,//超时时间设置为10秒;
url: "${rc.contextPath}/wechat/order/unifiedorder",
success:function(data){
appId = data.appid;
timeStamp = data.timeStamp;
nonceStr = data.nonce_str;
packageStr = data.prepay_id;
signType = data.signType;
paySign = data.paySign;
callpay();
},
error:function(xhr,type,errorThrown){
//异常处理;
}
});
}
function callpay(){
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();
}
}
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : appId, //公众号名称,由商户传入
"timeStamp" : timeStamp, //时间戳,自1970年以来的秒数
"nonceStr" : nonceStr , //随机串
"package" : "prepay_id="+packageStr,
"signType" : signType, //微信签名方式:
"paySign" : paySign //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
updateState(); // 支付成功之后的处理,改变订单状态等
}
if (res.err_msg == "get_brand_wcpay_request:cancel") {
}
if (res.err_msg == "get_brand_wcpay_request:fail") {
}
}
);
}
微信公众号开发需要设置支付目录
地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3
相关的微信支付的工具类(java)
地址:https://download.csdn.net/download/rookieta/11718859