怎么建立网站 个人

怎么建立网站 个人:微信公众号之调起h5支付(代码详解)

微信公众号支付

最近公司项目做了微信公众号支付 也在网上看了其他网友写的关于微信公众号支付的博客 首先很感谢他们把代码贡献出来 由于微信公众号支付API文档的变化 有些博客上的代码不能复用 近期贡献出来的代码 虽新但是代码不全 所以我把自己的代码整理一下 没有大神们封装的那么好 但是简单可用 供网友参考 如有疑惑或更好的方法请留言 后期会有微信其他的支付代码贡献给大家
- 第一部分 引入pom文件 我们用的是springboot框架 只需要引这一个依赖就行了

 dependency groupId jdom /groupId artifactId jdom /artifactId version 1.1 /version /dependency 
第二部分 前端js页面

第一次用markdown编辑器 不熟悉 前端js页面代码不全 仅供参考

$(function(){ var url ******** //路径 var orderId; $.ajax({ type: post , url:url 这里添具体路径 , dataType: json , async:false, xhrFields: { withCredentials:true }, crossDomain: true, success:function(data){ orderId data.data.orderId; var content; content div class outer data.data.orderDesc /div div class inner data.data.orderMoney /div $( #content ).append(content) } }) var appId; var timeStamp; var nonceStr; var package; var signType; var paySign; $.ajax({ type: post , url:url 这里添具体路径 , dataType: json , async:false, data:{ orderId :orderId}, xhrFields: { withCredentials:true }, crossDomain: true, success:function(data){ console.log(data) appId data.data.appId timeStamp data.data.timeStamp nonceStr data.data.nonceStr package data.data.package signType data.data.signType paySign data.data.paySign } }) function onBridgeReady(){ WeixinJSBridge.invoke( getBrandWCPayRequest , { appId :appId, //公众号名称 由商户传入 timeStamp :timeStamp, //时间戳 自1970年以来的秒数 nonceStr :nonceStr, //随机串 package :package, signType :signType, //微信签名方式: paySign :paySign //微信签名 },function(res){ if(res.err_msg get_brand_wcpay_request:ok ){ window.location.replace( user_index.html ) }else if(res.err_msg get_brand_wcpay_request:cancel ){ alert( 取消支付! }else{ alert( 支付失败! } }); } function pay(){ 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(); } } $( #yajin ).click(function(){ pay() })})

第三部分后端代码

如果在用户登陆微信公众号时 就获取了openId,不用再用tookie获取了 拿来直接用就行了
package yangxiaosong.yangweixin;
import com.alibaba.fastjson.JSONObject;
import yangxiaosong.controller.wxpayutils.WXConfig;
import yangxiaosong.dataobject.user.User;
import yangxiaosong.dataobject.wxpay.WXPayOrder;
import yangxiaosong.enums.PayStatusEnum;
import yangxiaosong.service.ReturnRecordService;
import yangxiaosong.service.UserService;
import yangxiaosong.service.WXPayOrderService;
import yangxiaosong.utils.CookieUtil;
import yangxiaosong.utils.RedisUtil;
import yangxiaosong.utils.ResultVOUtil;
import yangxiaosong.viewobject.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;

RestController
RequestMapping(“/wxpay”)
Slf4j
CrossOrigin
public class WCPay {

 Autowiredprivate WXPayOrderService wxPayOrderService; Autowiredprivate StringRedisTemplate redisTemplate; Autowiredprivate UserService userService; Autowiredprivate ReturnRecordService returnRecordService; RequestMapping(value toPay ,method RequestMethod.POST)public ResultVO dopay(HttpServletRequest request, String orderId) throws JDOMException, IOException { //获取user User user (User) getUserFromRedis(request).getData(); //判断orderId if (orderId null) { return ResultVOUtil.error(1, 订单号为空 } WXPayOrder wXPayOrder wxPayOrderService.findById(orderId); //判断订单是否为空 if (wXPayOrder null) { ResultVOUtil.error(1, 微信订单不存在 } log.info(wXPayOrder.toString()); /** * 商品描述 */ String body wXPayOrder.getOrderDesc(); /** * 商户订单号 */ String out_trade_no wXPayOrder.getOrderId(); /** * 标价金额 把元转化成分 千万不要转化成string类型 要转化成int类型 要不然会报错 一定要跟着文档走 要不然会报total_fee不正确的错误 */ int total_fee (wXPayOrder.getOrderMoney().multiply(new BigDecimal( 100 ))).intValue(); /** * 终端IP(订单生成的机器IP) */ String spbill_create_ip request.getRemoteAddr(); /** * openId */ String openid user.getUserOpenId(); SortedMap Object, Object packageParams new TreeMap Object, Object packageParams.put( appid , WXConfig.appid);//微信公众号id packageParams.put( mch_id , WXConfig.mch_id);//商户号 packageParams.put( nonce_str , WXConfig.nonce_str);//随机字符串 packageParams.put( body , body);//商品描述 packageParams.put( out_trade_no , out_trade_no);//商户订单号 packageParams.put( total_fee , total_fee);//订单金额 packageParams.put( spbill_create_ip ,spbill_create_ip);//用户的终端IP packageParams.put( notify_url , WXConfig.notify_url);//通知地址 packageParams.put( openid , openid);//用户的openid packageParams.put( trade_type , WXConfig.trade_type); //获取签名 String sign PayCommonUtil.createSign( UTF-8 , packageParams, WXConfig.paternerKey); log.info( sign sign); packageParams.put( sign ,sign);//签名 String requestXML PayCommonUtil.getRequestXml(packageParams); log.info(requestXML); String resXml HttpUtil.postData(WXConfig.url, requestXML); Map xmlMap XMLUtil.doXMLParse(resXml); log.info( xmlMap xmlMap); String returnCode (String) xmlMap.get( return_code String returnMsg (String) xmlMap.get( return_msg if( SUCCESS .equals(returnCode)){ String resultCode (String) xmlMap.get( result_code String errCodeDes (String) xmlMap.get( err_code_des if( SUCCESS .equals(resultCode)){ //获取预支付交易会话标识 String prepay_id (String) xmlMap.get( prepay_id log.info( prepay_id prepay_id); //把prepay_id保存到订单中,这一步 根据的自己的业务需求 是否需要保存到数据库中 wxPayOrderService.updateById(prepay_id, wXPayOrder.getOrderId()); //下面是公众号内调起的h5支付 看清楚和上边获取prepay_id的时候 注意单词的大小写 //字符串 String nonceStr packageParams.get( nonce_str ).toString(); // 订单详情扩展字符串 String packages prepay_id prepay_id; SortedMap Object, Object finalpackage new TreeMap Object, Object finalpackage.put( appId , WXConfig.appid); finalpackage.put( timeStamp , WXConfig.timeStamp); finalpackage.put( nonceStr ,nonceStr); finalpackage.put( package ,packages); finalpackage.put( signType , WXConfig.signType); sign PayCommonUtil.createSign( UTF-8 , finalpackage, WXConfig.paternerKey); finalpackage.put( paySign ,sign); finalpackage.put( orderNo ,out_trade_no); finalpackage.put( totalFee ,total_fee); log.info( finalpackage finalpackage); return ResultVOUtil.success(finalpackage); } } return null;}/** * 手机支付完成回调,这个方法主要是完成支付后 项目后台业务需要 * param request * param response *这个方法是用流传递的 *这个方法是用流传递的 *这个方法是用流传递的 */ RequestMapping(value /weixinNotify ,method RequestMethod.POST)public void WXPayBack(HttpServletRequest request, HttpServletResponse response) throws IOException, JDOMException { // 读取参数 InputStream inputStream request.getInputStream(); StringBuffer sb new StringBuffer(); String s; BufferedReader in new BufferedReader(new InputStreamReader(inputStream, UTF-8 log.info( in.toString() in.toString()); while ((s in.readLine()) ! null) { sb.append(s); } in.close(); inputStream.close(); // 解析xml成map Map String, String m new HashMap String, String m XMLUtil.doXMLParse(sb.toString()); Iterator it m.keySet().iterator(); log.info( it it); // 过滤空 设置 TreeMap SortedMap Object, Object packageParams new TreeMap Object, Object while (it.hasNext()) { String parameter (String) it.next(); String parameterValue m.get(parameter); String v if (null ! parameterValue) { v parameterValue.trim(); } packageParams.put(parameter, v); } // 账号信息 String key WXConfig.paternerKey; // key // 判断签名是否正确 if (PayCommonUtil.isTenpaySign( UTF-8 , packageParams, key)) { log.info( 微信支付成功回调 // ------------------------------ // 处理业务开始 // ------------------------------ String resXml if ( SUCCESS .equals((String) packageParams.get( result_code ))) { // 这里是支付成功 String orderNo (String) packageParams.get( out_trade_no log.info( 微信订单号{}付款成功 ,orderNo); //这里 根据实际业务场景 做相应的操作 // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了. resXml xml return_code ![CDATA[SUCCESS]] /return_code return_msg ![CDATA[OK]] /return_msg /xml //这一步开始就是写公司业务需要的代码了 不用参考我的 没有价值 //处理业务:修改状态码 保存微信支付订单号, Integer payStatus PayStatusEnum.SUCCESS_PAY.getCode(); //微信支付订单号 String transactionId (String) packageParams.get( transaction_id wxPayOrderService.updatePayStatus(payStatus,transactionId, orderNo); //用订单id把押金充值到user对象中 WXPayOrder payOrder wxPayOrderService.findById(orderNo); if(payOrder.getLendId() null payOrder.getOrderMoney().equals(new BigDecimal( 0.01 ))){ Integer integer2 userService.userCashUpdate(payOrder.getUserId()); log.info( 充值成功{} ,integer2); }else { Integer integer1 returnRecordService.updateById(payOrder.getLendId()); log.info( 逾期付款成功后改变归还的状态码{}付款成功 ,integer1); } } else { log.info( 支付失败,错误信息 {} ,packageParams.get( err_code resXml xml return_code ![CDATA[FAIL]] /return_code return_msg ![CDATA[报文为空]] /return_msg /xml } // ------------------------------ // 处理业务完毕 // ------------------------------ BufferedOutputStream out new BufferedOutputStream(response.getOutputStream()); out.write(resXml.getBytes()); out.flush(); out.close(); } else { log.info( 通知签名验证失败 }}//自己封装的获取user对象的方法 不一定适合你 //获取user对象方法private ResultVO getUserFromRedis(HttpServletRequest request){ //获取user Cookie token CookieUtil.get(request, openId if (token null) { log.error( token.getValue() token.getValue()); return ResultVOUtil.error(4, cookie是空! } log.error(token.getValue()); String tokenValue RedisUtil.get(token.getValue()) User user JSONObject.parseObject(tokenValue, User.class); log.info( user user.toString()); //对user进行判断 if(user null){ return ResultVOUtil.error(1, 用户还没登陆 请登陆 } return ResultVOUtil.success(user);}

}

第四部分 配置文件
package yangxiaosong.controller.wxpayutils;

import java.util.Random;

public class WXConfig{

/** * 公众号id 公司提供 */public static final String appid /** * 公众号密钥 公司提供 */public static final String appSecret /** * 商户号 公司提供 */public static final String mch_id /** * 商户号密钥 公司提供 */public static final String paternerKey /** * 随机字符串 */public static final String nonce_str MD5.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());/** * 时间戳 */public static final String timeStamp Long.toString(System.currentTimeMillis()/1000);/** * 签名方式 */public static final String signType MD5 /** * 通知地址 */public static final String notify_url 在微信公众号里面设置的网址 外网可以访问的 如果不能访问 加8080端口号试试 /wxpay/weixinNotify /** * 交易类型 */public static final String trade_type JSAPI /** * 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder */public static final String url https://api.mch.weixin.qq.com/pay/unifiedorder 

}

第五部分 就是工具类的使用了HttpUtil

package yangxiaosong.yangweixin;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;

public class HttpUtil {

private final static int CONNECT_TIMEOUT 5000; // in millisecondsprivate final static String DEFAULT_ENCODING UTF-8 public static String postData(String urlStr, String data) { return postData(urlStr, data, null);}public static String postData(String urlStr, String data, String contentType) { BufferedReader reader null; try { URL url new URL(urlStr); URLConnection conn url.openConnection(); conn.setDoOutput(true); conn.setConnectTimeout(CONNECT_TIMEOUT); conn.setReadTimeout(CONNECT_TIMEOUT); if (contentType ! null) conn.setRequestProperty( content-type , contentType); OutputStreamWriter writer new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING); if (data null) data writer.write(data); writer.flush(); writer.close(); reader new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING)); StringBuilder sb new StringBuilder(); String line null; while ((line reader.readLine()) ! null) { sb.append(line); sb.append( \r\n } return sb.toString(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader ! null) reader.close(); } catch (IOException e) { } } return null;}

}

PayCommonUtil

package yangxiaosong.yangweixin;
import yangxiaosong.wxpayutils.MD5Util;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;

public class PayCommonUtil {

/** * sign签名 * Author yangxiaosong * param characterEncoding * param packageParams * param API_KEY * return String * */ SuppressWarnings({ rawtypes })public static String createSign(String characterEncoding, SortedMap Object, Object packageParams, String API_KEY) { StringBuffer sb new StringBuffer(); Set es packageParams.entrySet(); Iterator it es.iterator(); while (it.hasNext()) { Map.Entry entry (Map.Entry) it.next(); String k (String) entry.getKey(); if( total_fee .equals(k)){ String v String.valueOf(entry.getValue()); if (null ! v ! .equals(v) ! sign .equals(k) ! key .equals(k)) { sb.append(k v } }else { String v (String) entry.getValue(); if (null ! v ! .equals(v) ! sign .equals(k) ! key .equals(k)) { sb.append(k v } } } sb.append( key API_KEY); String sign MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign;}/** * 将请求参数转换为xml格式的string * param parameters * return String * */ SuppressWarnings({ rawtypes })public static String getRequestXml(SortedMap Object, Object parameters) { StringBuffer sb new StringBuffer(); sb.append( xml Set es parameters.entrySet(); Iterator it es.iterator(); while (it.hasNext()) { Map.Entry entry (Map.Entry) it.next(); String k (String) entry.getKey(); if( total_fee .equals(k)){ String v String.valueOf(entry.getValue()); sb.append( k v / k }else { String v (String) entry.getValue(); sb.append( k v / k } } sb.append( /xml return sb.toString();}/** * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 * *///方法一 map的键值对是object类型 SuppressWarnings({ rawtypes })public static boolean isTenpaySign(String characterEncoding, SortedMap Object, Object packageParams, String API_KEY) { StringBuffer sb new StringBuffer(); Set es packageParams.entrySet(); Iterator it es.iterator(); while(it.hasNext()) { Map.Entry entry (Map.Entry)it.next(); String k (String)entry.getKey(); String v (String)entry.getValue(); if(! sign .equals(k) null ! v ! .equals(v)) { sb.append(k v } } sb.append( key API_KEY); //算出摘要 String mysign MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); String tenpaySign ((String)packageParams.get( sign )).toLowerCase(); return tenpaySign.equals(mysign);}//方法一 map的键值对是object类型 SuppressWarnings({ rawtypes })public static boolean isTenpaySignB(String characterEncoding, Map String, String packageParams, String API_KEY) { StringBuffer sb new StringBuffer(); Set es packageParams.entrySet(); Iterator it es.iterator(); while(it.hasNext()) { Map.Entry entry (Map.Entry)it.next(); String k (String)entry.getKey(); String v (String)entry.getValue(); if(! sign .equals(k) null ! v ! .equals(v)) { sb.append(k v } } sb.append( key API_KEY); //算出摘要 String mysign MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); String tenpaySign ((String)packageParams.get( sign )).toLowerCase(); return tenpaySign.equals(mysign);}

}

XMLUtil

package yangxiaosong.yangweixin;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class XMLUtil {

/** * 解析xml,返回第一级元素键值对。如果第一级元素有子节点 则此节点的值是子节点的xml数据。 * * param strxml * return * throws JDOMException * throws IOException */ SuppressWarnings({ rawtypes , unchecked })public static Map doXMLParse(String strxml) throws JDOMException, IOException { strxml strxml.replaceFirst( encoding \ .*\ , encoding \ UTF-8\ if (null strxml || .equals(strxml)) { return null; } Map m new HashMap(); InputStream in new ByteArrayInputStream(strxml.getBytes( UTF-8 SAXBuilder builder new SAXBuilder(); Document doc builder.build(in); Element root doc.getRootElement(); List list root.getChildren(); Iterator it list.iterator(); while (it.hasNext()) { Element e (Element) it.next(); String k e.getName(); String v List children e.getChildren(); if (children.isEmpty()) { v e.getTextNormalize(); } else { v XMLUtil.getChildrenText(children); } m.put(k, v); } // 关闭流 in.close(); return m;}/** * 获取子结点的xml * * param children * return String */ SuppressWarnings({ rawtypes })public static String getChildrenText(List children) { StringBuffer sb new StringBuffer(); if (!children.isEmpty()) { Iterator it children.iterator(); while (it.hasNext()) { Element e (Element) it.next(); String name e.getName(); String value e.getTextNormalize(); List list e.getChildren(); sb.append( name if (!list.isEmpty()) { sb.append(XMLUtil.getChildrenText(list)); } sb.append(value); sb.append( / name } } return sb.toString();}

}

点赞 2 评论 6
(十一)Linux实操篇之定时任务调度crond、crontab -e、crontab -l、crontab-r 4620
centos7在VM15中使用vmtools来设置文件共享遇到的问题和解决办法 565

分享到

更多案例

怎么建立网站 个人

怎么建立网站 个人:微信公众号之调起h5支付(代码详解) 微信公众号支付 最近公司项目做了微信公众号支付 也在网上看了其他网友写的关于微信公众号...

网站建设的创新激励方法

伴随着互连网和经济发展的持续发展趋势,越来越越大的事儿被干了,网站也是有了非常大的提高。假如网站很有特点,便会给网站产生丰厚的盈利。这也...

案例展示9

中英文版本...


区域站点: 南丰县h5和小程序有什么区别   南宫市h5微信   囊谦县h5免费   南和县h5抽奖大转盘制作   南华县h5和小程序有什么区别   南江县h5微信   南京市h5免费   南靖县h5抽奖大转盘制作   南康市h5和小程序有什么区别   南乐县h5微信   南陵县h5免费   南宁市h5抽奖大转盘制作   南平市h5和小程序有什么区别   南皮县h5微信   南市区h5免费   南通市h5抽奖大转盘制作   南投县h5和小程序有什么区别   南雄市h5微信   南溪县h5免费   南阳市h5抽奖大转盘制作   南漳县h5和小程序有什么区别   南召县h5微信   南郑县h5免费   那坡县h5抽奖大转盘制作   那曲县h5和小程序有什么区别   纳雍县h5微信   讷河市h5免费   内黄县h5抽奖大转盘制作   内江市h5和小程序有什么区别   内丘县h5微信   内乡县h5免费   嫩江市h5抽奖大转盘制作   聂荣县h5和小程序有什么区别   尼玛县h5微信   尼木县h5免费   宁安市h5抽奖大转盘制作   宁波市h5和小程序有什么区别   宁城县h5微信   宁德市h5免费   宁都县h5抽奖大转盘制作   宁国市h5和小程序有什么区别   宁海县h5微信   宁化县h5免费   宁晋县h5抽奖大转盘制作   宁陵县h5和小程序有什么区别   宁明县h5微信   宁南县h5免费   宁强县h5抽奖大转盘制作   宁陕县h5和小程序有什么区别   宁武县h5微信   宁乡市h5免费   宁阳县h5抽奖大转盘制作   宁远县h5和小程序有什么区别   农安县h5微信   磐安县h5免费   盘锦市h5抽奖大转盘制作   盘山县h5和小程序有什么区别   磐石市h5微信   盘州市h5免费   蓬安县h5抽奖大转盘制作   澎湖县h5和小程序有什么区别   蓬莱市h5微信   彭山县h5免费   蓬溪县h5抽奖大转盘制作   彭阳县h5和小程序有什么区别   彭泽县h5微信   彭州市h5免费   偏关县h5抽奖大转盘制作   平安县h5和小程序有什么区别   平昌县h5微信   平定县h5免费   屏东县h5抽奖大转盘制作   平度市h5和小程序有什么区别   平果县h5微信   平和县h5免费   平湖市h5抽奖大转盘制作   平江县h5和小程序有什么区别   平乐县h5微信   平凉市h5免费   平利县h5抽奖大转盘制作   平罗县h5和小程序有什么区别   平陆县h5微信   屏南县h5免费   平泉市h5抽奖大转盘制作   屏山县h5和小程序有什么区别   平顺县h5微信   平塘县h5免费   平潭县h5抽奖大转盘制作   平武县h5和小程序有什么区别   萍乡市h5微信   平乡县h5免费   平阳县h5抽奖大转盘制作   平遥县h5和小程序有什么区别   平阴县h5微信   平邑县h5免费   平远县h5抽奖大转盘制作   平舆县h5和小程序有什么区别   皮山县h5微信   普安县h5免费   浦北县h5抽奖大转盘制作   浦城县h5和小程序有什么区别   普洱市h5微信   普格县h5免费   浦江县h5抽奖大转盘制作   普兰县h5和小程序有什么区别   普宁市h5微信   莆田市h5免费   迁安市h5抽奖大转盘制作   乾安县h5和小程序有什么区别   潜江市h5微信   潜山市h5免费  

友情链接: 月福步宜 超恒鑫电子

Copyright © 2002-2020 h5免费_h5抽奖大转盘制作_h5和小程序有什么区别_h5微信_手机抽奖小程序 版权所有 (网站地图) 备案号:粤ICP备10235580号