微信公众号开发之微信支付
程序员文章站
2023-12-22 15:58:40
...
微信公众号开发之微信支付
1、简要思路图
2、添加支付授权目录
3、页面调用
function onBridgeReady(){
var params={};
params["appId"]=$("#appId").val();
params["timeStamp"]=$("#timeStamp").val();
params["nonceStr"]=$("#nonceStr").val();
params["package"]=$("#package").val();
params["signType"]=$("#signType").val();
params["paySign"]=$("#paySign").val();
WeixinJSBridge.invoke(
'getBrandWCPayRequest', params,
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
var outtradeno = $("#out_trade_no").val();//返回自己的订单号
}
}
);
}
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();
}
4、统一下单
统一下单文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
/**
*
* @description 统一下订单接口(微信公众号)
* @author csh
* @param orderNo 订单号
* @param money 金额
* @param openid 用户 openId
* @param attach 该字段主要用于商户携带订单的自定义数据
* @param request
* @return
* @throws Exception
* @date : 2017-7-3 下午3:21:16
*/
public static Map<String, Object> addDeltaData(String orderNo, String money, String openid,
String attach, HttpServletRequest request)
throws Exception {
String mch_id = IConstants.wxMCHID.trim();//商户id
String body = "福豆工社";
String nonce = create_timestamp();
String ip = IPProject.getIpAddr(request);
String path = "https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单接口
String para = "appid=" + IConstants.wxgzAppID;//公众号ID
para += "&attach=" + attach;//自定义参数
para += "&body=" + body;// 商品描述
para += "&mch_id=" + mch_id;// 商户号
para += "&nonce_str=" + nonce;// 随机字符串
para += "¬ify_url=" + IConstants.wxNotifyUrl;// 接收微信支付异步通知回调地址
para += "&openid=" + openid;// 用户标识
para += "&out_trade_no=" + orderNo;// 商户订单号
para += "&spbill_create_ip=" + ip;// 终端IP
para += "&total_fee=" + money;// 总金额
para += "&trade_type=JSAPI";// 交易类型
para += "&key=" + IConstants.wxMCHSecret;//商户号secret
String signature = MD5WeiXin.encode(para).toUpperCase();
// 组织xml数据
StringBuffer xml = new StringBuffer("<xml>");
xml.append("<appid>").append(IConstants.wxgzAppID).append("</appid>");
xml.append("<attach>").append(attach).append("</attach>");
xml.append("<body>").append(body).append("</body>");
xml.append("<mch_id>").append(mch_id).append("</mch_id>");
xml.append("<nonce_str>").append(nonce).append("</nonce_str>");
xml.append("<notify_url>").append(IConstants.wxNotifyUrl).append("</notify_url>");
xml.append("<openid>").append(openid).append("</openid>");
xml.append("<out_trade_no>").append(orderNo).append("</out_trade_no>");
xml.append("<spbill_create_ip>").append(ip).append("</spbill_create_ip>");
xml.append("<total_fee>").append(money).append("</total_fee>");
xml.append("<trade_type>JSAPI</trade_type>");
xml.append("<sign>").append(signature).append("</sign>");
xml.append("</xml>");
Map<String, Object> maData = new HashMap<String, Object>();
// 请求连接
String str = HttpUtil.request(path, xml.toString());
Document document = DocumentHelper.parseText(str);
Element root = document.getRootElement();
String code = root.elementText("return_code");
if ("SUCCESS".equals(code)) {
// 创建微信订单成功
String resultCode = root.elementText("result_code");
if ("SUCCESS".equals(resultCode)) {
String prepayId = root.elementText("prepay_id");
maData.put("code", "succ");
maData.put("preId", prepayId);
} else {
maData.put("code", "fail");
}
} else {
// 创建微信订单失败
maData.put("code", "fail");
}
return maData;
}
/**
* @description 生成JSSDK支付签名,并生成微信订单
* @param orderNo 订单号
* @param money 金额
* @param openid 用户openid
* @param attach 该字段主要用于商户携带订单的自定义数据
* @param request
* @return
* @throws Exception
*/
public static Map<String, String> ddQm(String orderNo, String money, String openid, String attach, HttpServletRequest request)
throws Exception {
int nwmoney = (int) (Double.valueOf(money) * 100);
// 调用微信统一下单
Map<String, Object> maData = addDeltaData(orderNo, nwmoney + "", openid, "1", request);
String code = (String) maData.get("code");
if ("succ".equals(code)) {
String preId = (String) maData.get("preId");
String times = WeixinJsSdk.create_timestamp();
String nonce = StringCommon.randomCharactersInt(32);
// 进行签名
String para = "appId=" + IConstants.wxgzAppID + "&nonceStr=" + nonce;// 随机字符串
para += "&package=prepay_id=" + preId;
para += "&signType=MD5";
para += "&timeStamp=" + times;
para += "&key=" + IConstants.wxMCHSecret;//商户**
String paySign = MD5WeiXin.encode(para).toUpperCase();
Map<String, String> qmData = new HashMap<String, String>();
qmData.put("appId", IConstants.wxgzAppID);
qmData.put("nonceStr", nonce);
qmData.put("packages", "prepay_id=" + preId);
qmData.put("signType", "MD5");
qmData.put("timeStamp", times);
qmData.put("paySign", paySign);
return qmData;
} else {
return null;
}
}
public static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
/**
* 随机获取字符(字母+数字)
*
* @param size
* 字符位数
* @return
*/
public static String randomCharactersInt(int size) {
StringBuffer sb = new StringBuffer();
Random random = new Random();
for (int i = 0; i < size; i++) {
int j = random.nextInt(35) + 1;// 获得随机数
if (j > 26) {
sb.append(35 - j);
continue;
}
sb.append(getChar(j));
}
return sb.toString();
}
public class MD5WeiXin {
/*
* MD5加密(32位)
*/
public static String encode(String context) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
try {
md.update(context.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] encryContext = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < encryContext.length; offset++) {
i = encryContext[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
return buf.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return context;
}
}
}
public class IPProject {
/**
* 获得IP地址
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0
|| "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0
|| "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0
|| "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")
|| ipAddress.equals("0:0:0:0:0:0:0:1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
return ipAddress;
}
}
public class HttpUtil {
public static String request(String path,String param) {
try {
URL url = new URL(path.toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(10000);
conn.setReadTimeout(60000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
if(param != null && !"".equals(param)){
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.write(param.getBytes("UTF-8"));
out.flush();
out.close();
}
byte[] data = readStream(conn.getResponseCode() == 200 ? conn.getInputStream() : conn.getErrorStream());
String json = new String(data,"UTF-8");
return json;
} catch (Exception e) {
return "";
}
}
public static String GETRequest(String path) {
try {
URL url = new URL(path.toString());
URLConnection conn = url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String l = "";
StringBuilder sb = new StringBuilder();
while ((l = br.readLine()) != null) {
sb.append(l);
}
br.close();
return sb.toString();
} catch (Exception e) {
return "";
}
}
public static byte[] readStream(InputStream inputStream) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
outStream.close();
inputStream.close();
return outStream.toByteArray();
}
/**
* 执行url请求数据
*
* @param urlStr
* @return
* @throws Exception
* @throws IOException
*/
public static String getUrlData(String urlStr) throws Exception {
URL url = new URL(urlStr);
URLConnection connection = url.openConnection();
// 一旦发送成功,用以下方法就可以得到服务器的回应:
String sCurrentLine = "";
StringBuffer sTotalString = new StringBuffer();
InputStream l_urlStream = connection.getInputStream();
// 三层包装
BufferedReader l_reader = new BufferedReader(new InputStreamReader(
l_urlStream, "UTF-8"));
while ((sCurrentLine = l_reader.readLine()) != null) {
sTotalString.append(sCurrentLine);
}
return sTotalString.toString();
}
/**
* 执行url请求数据
*
* @param urlStr
* @return
* @throws Exception
* @throws IOException
*/
public static String postUrlData(String urlStr, String data)
throws Exception {
URL url = new URL(urlStr);
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setRequestMethod("POST");
http.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒28
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒29
// 30
OutputStream os = http.getOutputStream();
os.write(data.getBytes("UTF-8"));// 传入参数
os.flush();
os.close();
// 一旦发送成功,用以下方法就可以得到服务器的回应:
String sCurrentLine = "";
String sTotalString = "";
InputStream l_urlStream = http.getInputStream();
// 传说中的三层包装阿!
BufferedReader l_reader = new BufferedReader(new InputStreamReader(
l_urlStream, "UTF-8"));
while ((sCurrentLine = l_reader.readLine()) != null) {
sTotalString += sCurrentLine;
}
return sTotalString;
}
public static void main(String[] args) {
String url="http://localhost:8080/wap/changeposition.do?coords=114.21892734521,29.575429778924&from=1&to=5&ak=826e806b86676d155282de3d37188137";
try {
System.out.println(getUrlData(url));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}