uni-app中微信支付之微信公众号支付的实现【下】

相信大家已在网上找了各种资料,也看过了各种文档,对于整个流程我就不再重复啦,有疑惑的小伙伴可以移步微信开放平台查看详情,网页地址:https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=2_2

废话不多说,直接上代码:

uni-app前端代码:





我这里后端使用的SpringBoot,Maven项目,代码如下:



	com.github.binarywang
	weixin-java-mp
	2.7.0



	com.github.binarywang
	weixin-java-pay
	3.0.0

在application.properties中配置相关信息

微信APP支付这块是需要证书,大家自行去微信开放平台配置下载后放入resources目录下,可直接用classpath:xxxxxx.p12引入

#微信支付
wx.pay.appId=XXXXXXXXXXXXXXXXXXXXX
wx.pay.appSecret=XXXXXXXXXXXXXXXXXXXXX
wx.pay.mchId=XXXXXXXXXXXXXXXXXXXXX
wx.pay.mchKey=XXXXXXXXXXXXXXXXXXXXX
wx.pay.keyPath=classpath:apiclient_cert.p12
wx.pay.tradeType=XXXXXXXXXXX
#微信公众号
wx.mp.appId=XXXXXXXXXXXXXXXXXXXXX
wx.mp.appSecret=XXXXXXXXXXXXXXXXXXXXX

需要先获得用户授权,后端拿到openId存入session中,待调起支付时再从session中获取openId

let openId=uni.getStorageSync('openId');
if(openId){
    //若有openId直接进行下一步操作
	uni.navigateTo({
		url: '../member/membercenter'
	});
}else{
    //若没有openId就请求后端授权
    window.location.href = getApp().globalData.BaseUrl + "/thirdPartLogin/jswx/wxlogin?state=1";
	return;
}

在配置文件内添加以下内容:

#你的前端接受地址
wx.mp.oauth2RdmUri=https://XXXXXXXXXXXXXXXXXXXXXXX

创建控制层

package com.ltf.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
import com.ltf.common.CacheConstans;
import com.ltf.config.SinaWebProperties;
import com.ltf.config.WeChatAppletProperties;
import com.ltf.config.WeChatMpProperties;
import com.ltf.entity.UserProfile;
import com.ltf.service.UserProfileService;
import com.ltf.utils.HttpRequestUtil;
import com.ltf.utils.WebUtils;
import com.qq.connect.QQConnectException;
import com.qq.connect.api.OpenID;
import com.qq.connect.api.qzone.UserInfo;
import com.qq.connect.javabeans.qzone.UserInfoBean;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import weibo4j.Oauth;
import weibo4j.Users;
import weibo4j.http.AccessToken;
import weibo4j.model.User;
import weibo4j.model.WeiboException;

/**
 * 第三方登录控制层
 * @author xhz
 *
 */
@Controller
@RequestMapping("/thirdPartLogin")
public class ThirdPartLoginController extends BaseController {

	private static final Logger logger = LoggerFactory
			.getLogger(ThirdPartLoginController.class);
	@Autowired
	private UserProfileService userProfileService;

	@Autowired
	private WeChatAppletProperties weChatAppletProperties;

	@Autowired
	private  WxMpService wxJsMpService;
	@Autowired
	private WeChatMpProperties wxMpProperties;
	@Autowired
	private SinaWebProperties sinaWebProperties;

	/**
	 * jswx 请求授权地址转发
	 * @param response
	 * @throws IOException 
	 */
	@RequestMapping(path="/jswx/wxlogin", method=RequestMethod.GET)
	@ResponseBody
	public void wxRdLogin(HttpServletRequest request,HttpServletResponse response,
			@RequestParam("state") String state) throws IOException {
		if(state!=null&&state.equals("1")) {
			String redirectURI=wxJsMpService.oauth2buildAuthorizationUrl(wxMpProperties.getRedirectURI(),"snsapi_base",state);
			response.setContentType("text/html;charset=UTF-8");
			response.sendRedirect(redirectURI);
		}
	}

	/**
	 * jswx 授权登陆回调地址
	 * @param request
	 * @param response
	 * @param code
	 * @return
	 */
	@SuppressWarnings("static-access")
	@RequestMapping(path="/jswx/login", method=RequestMethod.GET)
	@ResponseBody
	public JSONObject jsWxLogin(HttpServletRequest request,HttpServletResponse response,
			@RequestParam("code") String code,@RequestParam("state") String state) {
		Map map=new HashMap();
		if(state!=null&& state.equals("1")) {
			String resRdmUrl= wxMpProperties.getOauth2RdmUri()+"?";
			try {
				WxMpOAuth2AccessToken oauth2AccessToken = wxJsMpService.oauth2getAccessToken(code);
				request.getSession().setAttribute("weixinOauth2AccessToken", oauth2AccessToken);//用于支付等安全校验
				map.put("openId",oauth2AccessToken.getOpenId());
				resRdmUrl+=this.buildQuery(200, "登陆成功!", map);
			} catch (WxErrorException e) {
				resRdmUrl+=this.buildQuery(500, "登录失败!"+e.getMessage(), map);
			}
			try {
				response.setContentType("text/html;charset=UTF-8");
				response.sendRedirect(resRdmUrl);
			} catch (IOException e) {
				e.printStackTrace();
			}
			return null;
		}
		return null;
	}

}

前端页面接收openId

onLoad(option) {
		if(this.isWeiXinBrowser()){
			if(option!=undefined&&option.code==200){
				uni.setStorageSync('openId', option.openId);
			}
		}
},
methods: {
        //判断是否在微信浏览器,true:是
		isWeiXinBrowser() {
			// window.navigator.userAgent属性包含了浏览器类型、版本、操作系统类型、浏览器引擎类型等信息,这个属性可以用来判断浏览器类型
			let ua = window.navigator.userAgent.toLowerCase();
			// 通过正则表达式匹配ua中是否含有MicroMessenger字符串
			if (ua.match(/MicroMessenger/i) == 'micromessenger') {
				return true;
			} else {
				return false;
			}
		}
}

创建实体类

package com.ltf.config;
 
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
/**
 * 微信支付商户基本信息
 * @author xhz
 *
 */
@Data
@Component
@ConfigurationProperties(prefix = "wx.pay")
public class WeChatPayProperties {
 
	/**
	 * appId
	 */
	private String appId;
	/**
	 * 公众平台密钥
	 */
	private String appSecret;
	/**
	 * 商户号
	 */
	private String mchId;
	/**
	 * 商户密钥
	 */
	private String mchKey;
	/**
	 * 证书
	 */
	private String keyPath;
	/**
	 * 交易类型
	 * 
	 * JSAPI--公众号支付
	 * NATIVE--原生扫码支付
	 * APP--app支付
	 * 
*/ private String tradeType; @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } }
package com.ltf.config;
 
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
/**
 * 微信支付商户基本信息
 * @author xhz
 *
 */
@Data
@Component
@ConfigurationProperties(prefix = "wx.mp")
public class WeChatMpProperties {
 
	/**
	 * appId
	 */
	private String appId;
 
	/**
	 * 公众平台密钥
	 */
	private String appSecret;
 
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this,
				ToStringStyle.MULTI_LINE_STYLE);
	}
 
}

将微信支付信息注入bean中

package com.ltf.config;
 
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
 
/**
 * 微信支付信息注入bean中
 * @author xhz
 *
 */
@Component
public class WeChatPayConfig {
 
	@Autowired
	private WeChatPayProperties properties;
 
	@Bean
	@ConditionalOnMissingBean
	public WxPayConfig payConfig() {
		WxPayConfig payConfig = new WxPayConfig();
		payConfig.setAppId(this.properties.getAppId());
		payConfig.setMchId(this.properties.getMchId());
		payConfig.setMchKey(this.properties.getMchKey());
		payConfig.setKeyPath(this.properties.getKeyPath());
		payConfig.setTradeType(this.properties.getTradeType());
		return payConfig;
	}
 
	@Bean
	public WxPayService wxPayService(WxPayConfig payConfig) {
		WxPayService wxPayService = new WxPayServiceImpl();
		wxPayService.setConfig(payConfig);
		return wxPayService;
	}
 
	@Bean
	public WxMpService wxMpService( ){
		WxMpService wxMpService = new WxMpServiceImpl();
		wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
		return wxMpService;
	}
 
	@Bean
	public WxMpConfigStorage wxMpConfigStorage(){
		WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
		wxMpConfigStorage.setAppId(this.properties.getAppId());
		wxMpConfigStorage.setSecret(this.properties.getAppSecret());
		return wxMpConfigStorage;
	}
 
}

创建控制层

package com.ltf.controller;

import com.ltf.common.OrderState;
import com.ltf.common.ReqChanle;
import com.ltf.config.WeChatAppletProperties;
import com.ltf.config.WeChatMpProperties;
import com.ltf.config.WeChatPayProperties;
import com.ltf.dao.MemberCardOrdersDao;
import com.ltf.dao.MemberCardTrxorderDetailDao;
import com.ltf.entity.MemberCardOrders;
import com.ltf.entity.MemberCardTrxorderDetail;
import com.ltf.service.MemberCardOrdersService;
import com.ltf.service.MemberCardTrxorderDetailService;
import com.ltf.service.QRCodeService;
import com.ltf.utils.HttpRequestUtil;
import com.ltf.utils.SingletonLoginUtils;
import com.ltf.utils.StringUtils;
import com.ltf.utils.WebUtils;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 微信支付
 * @author xhz
 *
 */
@RestController
@RequestMapping(value = "/api/client/pay/")
public class WeChatPayController extends BaseController{

	private static final Logger logger = LoggerFactory
			.getLogger(WeChatPayController.class);

	@Autowired
	private WxPayService wxPayService;
	@Autowired
	private WeChatPayProperties weChatPayProperties;
	@Autowired
	private MemberCardOrdersService memberCardOrdersService;
	@Autowired
	private MemberCardOrdersDao memberCardOrdersDao;
	@Autowired
	private MemberCardTrxorderDetailDao memberCardTrxorderDetailDao;
	@Autowired
	private MemberCardTrxorderDetailService memberCardTrxorderDetailService;
	@Autowired
	private WeChatMpProperties weChatMpProperties;

	/**
	 * 公众号支付
	 * @param request
	 * @param memberCardTypeId
	 * @param payType
	 * @param orderAmount
	 * @param memberCardTypeName
	 * @param code
	 * @return
	 */
	@SuppressWarnings("static-access")
	@GetMapping(value = "JSAPIPay")
	@ResponseBody
	public JSONObject JSAPIPay(HttpServletRequest request,
			@RequestParam("memberCardTypeId")String memberCardTypeId,
			@RequestParam("payType")String payType,
			@RequestParam("orderAmount")String orderAmount,
			@RequestParam("memberCardTypeName")String memberCardTypeName
			){
		try {
			Integer userId=SingletonLoginUtils.getLoginUserId(request);
			if(userId>0){
				Map sourceMap = new HashMap();
				sourceMap.put("memberCardTypeId", memberCardTypeId);// 会员卡类型id
				sourceMap.put("userId", userId+ "");//用户id
				sourceMap.put("reqchanle", ReqChanle.WEIXIN.toString());//用户请求来源
				sourceMap.put("payType", payType);// 支付类型
				sourceMap.put("reqIp", WebUtils.getIpAddr(request));// 用户ip
				sourceMap.put("orderAmount", orderAmount);// 订单原始金额,也是实际支付金额
				sourceMap.put("memberCardTypeName", memberCardTypeName);//会员卡类型名称
				Map res = memberCardOrdersService.addTrxorder(request,sourceMap);
				if(res.containsKey("msg")){
					return this.formatJSON(501, "微信公众号支付时会员卡订单创建失败!", res);
				}else{
					WxPayUnifiedOrderRequest orderRequest  = new WxPayUnifiedOrderRequest();
					orderRequest.setAppid(weChatMpProperties.getAppId());
					orderRequest.setBody(memberCardTypeName);
					orderRequest.setOutTradeNo(res.get("orderNo").toString());
					orderRequest.setTradeType("JSAPI");
					if(null!=request.getSession().getAttribute("weixinOauth2AccessToken")){
						WxMpOAuth2AccessToken oauth2AccessToken=(WxMpOAuth2AccessToken) request.getSession().getAttribute("weixinOauth2AccessToken");
						orderRequest.setOpenid(oauth2AccessToken.getOpenId());
					}
					orderRequest.setTotalFee(yuanToFee(new BigDecimal(orderAmount)));
					orderRequest.setSpbillCreateIp(InetAddress.getLoopbackAddress().getHostAddress());
					orderRequest.setNotifyUrl("https://你的域名/api/client/pay/JSAPIPayNotify");
					Object order = wxPayService.createOrder(orderRequest);
					res.put("payment", order);
					return this.formatJSON(200, "OK", res);
				}
			}else{
				return this.formatJSON(500, "当前登录状态已失效,请重新登录!",null);
			}
		} catch (Exception e) {
			logger.error("WeChatPayController.JSAPIPay()----error", e);
			return this.formatJSON(500, "微信公众号支付时会员卡订单创建失败!",null);
		}
	}

	/**
	 *
	 * @param xmlData 公众号支付返回的流
	 * @return
	 */
	@RequestMapping(value = "JSAPIPayNotify",method = {RequestMethod.GET,RequestMethod.POST})
	public String JSAPIPayNotify(@RequestBody String xmlData){
		try {
			final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
			// 支付成功,商户处理后同步返回给微信参数
			if (("SUCCESS").equals(notifyResult.getResultCode())) {
				//这里是存储我们发起支付时订单号的信息,所以取出来
				MemberCardOrders memberCardOrders=new MemberCardOrders();
				memberCardOrders.setOrderNo(notifyResult.getOutTradeNo());
				//根据订单号查询订单
				MemberCardOrders mco=memberCardOrdersDao.selectMemberCardOrdersByCondition(memberCardOrders);
				//验证商户id和价格,以防止篡改金额
				if(mco!=null){
					if(weChatPayProperties.getMchId().equals(notifyResult.getMchId())&¬ifyResult.getTotalFee().equals(yuanToFee(mco.getSumMoney()))){
						Map map=new HashMap();
						map.put("sumMoney", feeToYuan(notifyResult.getTotalFee()));//订单总金额
						map.put("outTradeNo", notifyResult.getTransactionId());//支付宝的交易号
						map.put("orderNo", notifyResult.getOutTradeNo());//商户系统的唯一订单号
						map.put("states", notifyResult.getResultCode());//交易状态
						map.put("payTime", notifyResult.getTimeEnd());//支付时间
						//修改会员卡订单信息
						String result1=memberCardOrdersService.updateMemberCardOrderInfoForNotify(map);
						if(result1.equals("error")){
							return WxPayNotifyResponse.fail("微信公众号支付时修改会员卡订单信息失败!");
						}
						//修改会员卡订单流水信息
						String result2=memberCardTrxorderDetailService.updateMemberCardTrxorderDetaiInfoForNotify(map);
						if(result2.equals("error")){
							return WxPayNotifyResponse.fail("微信公众号支付时修改会员卡订单流水信息失败!");
						}
						//成功后回调微信信息
						return WxPayNotifyResponse.success("支付成功!");
					}else{
						return WxPayNotifyResponse.fail("微信公众号支付时商户id和价格验证不通过!");
					}
				}else{
					return WxPayNotifyResponse.fail("微信公众号支付时订单号不存在!");
				}
			}else{
				// 支付失败, 记录流水失败
				MemberCardOrders memberCardOrders=new MemberCardOrders();
				memberCardOrders.setOrderNo(notifyResult.getOutTradeNo());//商户系统的唯一订单号
				memberCardOrders.setStates(notifyResult.getResultCode());//交易状态
				memberCardOrdersDao.updateMemberCardOrderStateForNotify(memberCardOrders);
				MemberCardTrxorderDetail memberCardTrxorderDetail=new MemberCardTrxorderDetail();
				memberCardTrxorderDetail.setRequestId(notifyResult.getOutTradeNo());//商户系统的唯一订单号
				memberCardTrxorderDetail.setTrxStatus(notifyResult.getResultCode());//交易状态
				memberCardTrxorderDetailDao.updateMemberCardTrxorderStateForNotify(memberCardTrxorderDetail);
				return WxPayNotifyResponse.fail("支付失败!");
			}
		} catch (WxPayException e) {
			logger.error("WeChatPayController.JSAPIPayNotify()----error", e);
			return WxPayNotifyResponse.fail("微信公众号支付时回调有误!");
		}
	}

	/**
	 * 1块钱转为 100 分
	 * 元转分
	 *
	 * @param bigDecimal 钱数目
	 * @return 分
	 */
	private int yuanToFee(BigDecimal bigDecimal) {
		return bigDecimal.multiply(new BigDecimal(100)).intValue();
	}

	/**
	 * 100分转为1块钱
	 * 分转元
	 * 
	 * @param price 钱数目
	 * @return 元
	 */
	private String feeToYuan(Integer price) {
		return BigDecimal.valueOf(Long.valueOf(price)).divide(new BigDecimal(100)).toString();
	}

}

 

你可能感兴趣的:(支付,Uni-app)