代码基于IJPay-0.8.jar开发,主要是比较省事
JAVA代码:
package com.fh.controller.wx;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fh.entity.system.PageData;
import com.fh.kit.ApiResponse;
import com.fh.plugins.util.HttpClientUtils;
import com.fh.plugins.util.JsonUtils;
import com.fh.service.app.JFSService;
import com.jpay.ext.kit.HttpKit;
import com.jpay.ext.kit.IpKit;
import com.jpay.ext.kit.PaymentKit;
import com.jpay.weixin.api.WxPayApi;
import com.jpay.weixin.api.WxPayApiConfig;
import com.jpay.weixin.api.WxPayApiConfigKit;
@Controller
@RequestMapping("/wc")
public class WxPayController {
private Logger log = Logger.getLogger(WxPayController.class);
// 小程序的appID
private static final String appID = "";
private static final String appSecret = "";
// 支付的ID
private static final String mchID = "1486736012";// 商户号ID
private static final String partnerKey = "";// 微信支付商户密钥
private String notify_url = "https://xxx/jfs/wc/pay_notify.do";//支付回调。
@Resource(name = "jfsServices")
private JFSService jfsServices;
public static WxPayApiConfig getApiConfig() {
return WxPayApiConfig.New()
.setAppId(appID)
.setMchId(mchID)
.setPaternerKey(partnerKey)
.setPayModel(WxPayApiConfig.PayModel.BUSINESSMODEL);
}
//组装支付参数
@ResponseBody
@RequestMapping(value = "/xcxpay.do", method = { RequestMethod.GET, RequestMethod.POST })
public ApiResponse xcxpay(HttpServletRequest request, HttpServletResponse response, String code, String orderid, String serviceorderid, String type) {
try {
String out_trade_no = "JFS" + String.valueOf(System.currentTimeMillis());
String openId = accessToken(request, appID, appSecret, code);
if (StringUtils.hasText(openId)) {
String ip = IpKit.getRealIp(request);
WxPayApiConfigKit.putApiConfig(getApiConfig());
String payType = "道路救援";
String totalFee = "1";//1表示一分钱(单位为分)
// 商家数据包
Map<String, String> maps = new HashMap<String, String>();
maps.put("orderid", orderid);
maps.put("serviceorderid", serviceorderid);
maps.put("type", type);
maps.put("out_trade_no", out_trade_no);
String attach = JsonUtils.toJson(maps);
Map<String, String> params = WxPayApiConfigKit
.getWxPayApiConfig()
.setOpenId(openId)
.setAttach(attach)//设置附加数据,在查询API和支付通知中原样返回
.setBody(payType)
.setSpbillCreateIp(ip)
.setTotalFee(getMoney(totalFee))
.setTradeType(WxPayApi.TradeType.JSAPI)
.setNotifyUrl(notify_url)
.setOutTradeNo(out_trade_no)// 商户订单号
.build();
log.info("params-->" + params);
String xmlResult = WxPayApi.pushOrder(false, params);
log.info("xmlResult - - - - -- " + xmlResult);
Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
String return_code = result.get("return_code");
if (!PaymentKit.codeIsOK(return_code)) {
log.info("return_code is null");
return new ApiResponse(ApiResponse.Status.ERROR.getCode(), "return_code is null", null);
}
String result_code = result.get("result_code");
if (!PaymentKit.codeIsOK(result_code)) {
log.info("result_code is null");
return new ApiResponse(ApiResponse.Status.ERROR.getCode(), "result_code is null", null);
}
// 以下字段在return_code 和result_code都为SUCCESS的时候有返回
String prepay_id = result.get("prepay_id");
// 封装调起微信支付的参数https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=5
Map<String, String> packageParams = new HashMap<String, String>();
packageParams.put("appId", WxPayApiConfigKit.getWxPayApiConfig().getAppId());
packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
packageParams.put("nonceStr", System.currentTimeMillis() + "");
packageParams.put("package", "prepay_id=" + prepay_id);
packageParams.put("signType", "MD5");
String packageSign = PaymentKit.createSign(packageParams, WxPayApiConfigKit.getWxPayApiConfig().getPaternerKey());
packageParams.put("sign", packageSign);
// 更新订单表信息,状态为待付款,并保存商户订单号
// jfsServices.paySuccess("1", out_trade_no, orderid);
log.info("小程序支付的参数:-->" + packageParams);
return new ApiResponse(ApiResponse.Status.SUCCESS.getCode(), "success", packageParams);
} else {
log.info("参数为空:-->payType:" + payType + "\ttotalFee:" + totalFee);
}
} catch (Exception e) {
e.printStackTrace();
}
return new ApiResponse(ApiResponse.Status.ERROR.getCode(), "error", null);
}
/**
* 微信支付跟支付回调是分开的。支付回调通常是微信收款成功后,让你处理支付成功后的业务逻辑,微信会访问这个地址8次,直到notify_url返回个SUCCESS。
* @param request
* @param orderid
* @param serviceorderid
* @return
*/
@RequestMapping(value = "/pay_notify.do", method = { RequestMethod.POST, RequestMethod.GET })
public void pay_notify(HttpServletRequest req, HttpServletResponse resp) {
try {
// 支付结果通用通知文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
String xmlMsg = HttpKit.readData(req);
log.info("pay notice 支付成功后回调---------" + xmlMsg);
Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);
String result_code = params.get("result_code");
WxPayApiConfigKit.setThreadLocalWxPayApiConfig(getApiConfig());
// 保存订单支付回调信息
//String out_trade_no = params.get("out_trade_no");
//String transaction_id = params.get("transaction_id");
// jfsServices.saveWxPayInfo(out_trade_no, transaction_id, xmlMsg);
// 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态
// 避免已经成功、关闭、退款的订单被再次更新
if (PaymentKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPaternerKey())) {
if ("SUCCESS".equals(result_code)) {
// 更新订单信息
String attach = params.get("attach");
log.info("商家数据包:" + attach);
Map<String, Object> maps = JsonUtils.parseJson(attach, Map.class);
String orderid = "" + maps.get("orderid");
jfsServices.paySuccess("2", out_trade_no, orderid);// 支付成功
String result = HttpClientUtils.sendPost("https://xxxx/jfs/JFSUser/paySuccess", maps);
log.info("result:" + result);
// 发送通知(必须严格按照微信的格式返回,必须按下面用流的形式返回按此不会多次回调)
try {
PrintWriter out = resp.getWriter();
out.write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// return "";
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过微信用户的code换取网页授权access_token
* @return
* @throws IOException
* @throwsS
*/
@SuppressWarnings("unchecked")
public String accessToken(HttpServletRequest request, String appID, String secret, String code) {
try {
String openid = (String) request.getSession().getAttribute("openid");
if (StringUtils.hasText(openid)) {
return openid;
} else {
String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appID + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
HttpResponse res = client.execute(post);
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = res.getEntity();
String str = EntityUtils.toString(entity, "utf-8");
log.info("jscode2session:" + str);
Map<String, String> jsonOb = JsonUtils.parseJson(str, Map.class);
openid = (String) jsonOb.get("openid");
if (StringUtils.hasText(openid)) {
request.getSession().setAttribute("openid", openid);
return openid;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 元转换成分
* @param amount
* @return
*/
public static String getMoney(String amount) {
if (StringUtils.isEmpty(amount)) {
return "";
}
// 金额转化为分为单位
// 处理包含, ¥ 或者$的金额
String currency = amount.replaceAll("\\$|\\¥|\\,", "");
int index = currency.indexOf(".");
int length = currency.length();
Long amLong = 0l;
if (index == -1) {
amLong = Long.valueOf(currency + "00");
} else if (length - index >= 3) {
amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
} else if (length - index == 2) {
amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
} else {
amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
}
return amLong.toString();
}
}
小程序代码(嵌套的H5代码)
Page({
data: {
url: ''
},
onLoad: function (options) {
//初始化页面
if (options.ptype=='pay'){//H5页面调起微信小程序页面,根据传过来的参数ptype判断是否为支付。
wx.login({
success: function (res) {
console.log(res);
//登录成功
if (res.code) {
//调取后台支付参数
wx.request({
url: "https://xxx/jfs/wc/xcxpay.do",
data: {
type: options.type,
code: res.code,
orderid: options.orderid,
serviceorderid: options.serviceorderid,
},
method: 'GET',
success: function (res1) {
console.log(res1.data.code);
if (res1.data.code == 0) {
var ret = res1.data.data;
console.log(ret.timeStamp);
wx.requestPayment({
"timeStamp": ret.timeStamp,
"package": ret.package,
"paySign": ret.sign,
"signType": ret.signType,
"nonceStr": ret.nonceStr,
"paySign": ret.sign,
'success': function (r) {//支付成功
console.log('success:' + JSON.stringify(r));
//跳转到成功页面
wx.navigateTo({
url: '/pages/index/index?url=https://xxx/success.html',
success: function () {
console.log('success')
}
});
},
'fail': function (r) { //支付失败
console.log('fail:' + JSON.stringify(r));
//提示支付失败
wx.showToast({
title: '支付失败:' + JSON.stringify(r),
icon: 'none',
});
//返回付款页面
wx.navigateBack({
delta: 1
});
},
'complete': function (r) {
console.log('complete:' + JSON.stringify(r));
}
});
} else {
console.log('获取支付信息失败!' + res1.message)
}
}
});
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
});
}else{
var url = options.url ? decodeURIComponent(options.url) : 'https://xxx/index.html'
this.setData({ url: url });
}
},
onShareAppMessage: (res) => {//分享页面
return {
title: '聚福社',
path: 'pages/index/index?url=' + encodeURIComponent(res.webViewUrl),
success: (res) => {
console.log("转发成功");
},
fail: (res) => {
console.log("转发失败");
}
}
}
})
<view class="page-body">
<view class="page-section page-section-gap">
<web-view src="{{url}}"></web-view>
</view>
</view>
H5页面调起微信小程序支付代码
if(window.__wxjs_environment === 'miniprogram') {
wx.miniProgram.navigateTo({
url:"/pages/index/index?orderid=" + orderid + "&serviceorderid=" + rid + "&type=rescures&ptype=pay"
});
} else {
console.log("请在小程序中打开");
}