The realization of WeChat payment scan code payment in uni-app【中】

Dolphin Elf : https://mgo.whhtjl.com

I believe you have found various materials on the Internet and read various documents. I will not repeat the whole process. If you have any doubts, you can check the details on the WeChat open platform. Web address: https:// pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_2

Not much nonsense, just go to the code:

Uni-app front-end code:

<template>
	<view>
		<page-head :title="title"></page-head>
		<view class="uni-padding-wrap">
			<view style="background:#FFF; padding:50rpx 0;">
				<view class="uni-hello-text uni-center font-lg text-danger">{
   
   { vipName }}</view>
				<view class="uni-h1 uni-center uni-common-mt">
					<span class="price">¥{
   
   { price }}</span>
				</view>
			</view>
			<view class="uni-btn-v uni-common-mt">
				<!-- #ifdef H5 -->
				<button type="primary" @click="scanCodePay" :loading="loading" class="flex align-center justify-center">
					<image :src="getImgUrl('/files/static/common/wx.png')" style="width: 60rpx;height: 60rpx;"></image>
					<span class="pl-1">微信扫码支付</span>
				</button>
				<!-- #endif -->
			</view>
		</view>
		<uni-popup id="popup" ref="popup" type="center" :animation="false" @change="change1">
			<view class="flex flex-column bg-white py-2">
				<view class="flex align-center justify-center"><image :src="codeUrl"></image></view>
				<view class="flex align-center justify-center" style="color: #7B7B7B;">请使用微信扫描二维码以完成支付</view>
			</view>
		</uni-popup>
	</view>
</template>
<script>
import uniPopup from '@/components/uni-popup/uni-popup.vue';
export default {
	components: { uniPopup },
	data() {
		return {
			title: 'request-payment',
			loading: false,
			typeId: 0,
			vipName: '',
			price: 1,
			providerList: [],
			user: '',
			baseLocation: '',
			memberCardOrders: [],
			codeUrl: '',
			header: { 'Content-Type': 'application/x-www-form-urlencoded' }
		};
	},
	onLoad: function(e) {
		this.baseLocation = getApp().globalData.BaseUrl;
		this.user = uni.getStorageSync('user');
		if (e.id) {
			this.typeId = e.id;
		}
		if (e.typeName) {
			this.vipName = e.typeName;
		}
		if (e.currentPrice) {
			this.price = e.currentPrice;
		}
	},
	methods: {
		//登录
		async login() {
			// #ifdef APP-PLUS || H5
			this.$loginForAppAndH5();
			// #endif

			// #ifdef MP-WEIXIN
			this.$loginForWeiXinApplet();
			// #endif
		},
		//扫码支付
		async scanCodePay() {
			if (this.user) {
				this.loading = true;
				const res = await this.$ajaxRequest({
					url: '/api/client/pay/scanCodePay',
					data: {
						memberCardTypeId: this.typeId,
						payType: 'SCANCODEPAY',
						orderAmount: this.price,
						memberCardTypeName: this.vipName
					}
				});
				if (res.data.code === 200) {
					this.codeUrl = res.data.codeUrl;
					this.$refs.popup.open();
					var interval = setInterval(function() {
						uni.request({
							url: 'https://你的域名/api/client/pay/selectPayResultForScanCodePay',
							header: {
								'Content-Type': 'application/x-www-form-urlencoded'
							},
							method: 'GET',
							dataType: 'json',
							data: {
								orderNo: res.data.orderNo
							},
							success: res => {
								if (res.data.code === 200) {
									uni.showToast({
										title: '支付成功,3s后将进入会员中心页!',
										icon: 'none',
										duration: 3000
									});
									clearInterval(interval);
									setTimeout(function() {
										uni.navigateTo({
											url: 'membercenter'
										});
									}, 3000);
								}
							},
							fail: err => {
								uni.showToast({
									title: err,
									icon: 'none',
									duration: 3000
								});
								return false;
							}
						});
					}, 3000);
					return true;
				} else {
					uni.showToast({
						title: res.data.message,
						icon: 'none',
						duration: 3000
					});
					return false;
				}
			} else {
				this.login();
			}
		}
	}
};
</script>

<style>
.rmbLogo {
	font-size: 40rpx;
}

button {
	background-color: #007aff;
	color: #ffffff;
}

.uni-h1.uni-center {
	display: flex;
	flex-direction: row;
	justify-content: center;
	align-items: flex-end;
}

.price {
	width: 200rpx;
	height: 80rpx;
	padding-bottom: 4rpx;
}

.ipaPayBtn {
	margin-top: 30rpx;
}
</style>

The SpringBoot and Maven project that I use for the back end here, the code is as follows:

<!--公众号(包括订阅号和服务号) -->
<dependency>
	<groupId>com.github.binarywang</groupId>
	<artifactId>weixin-java-mp</artifactId>
	<version>2.7.0</version>
</dependency>
<!--微信支付 -->
<dependency>
	<groupId>com.github.binarywang</groupId>
	<artifactId>weixin-java-pay</artifactId>
	<version>3.0.0</version>
</dependency>

Configure related information in application.properties

WeChat APP payment requires a certificate. You can go to the WeChat open platform to configure and download it and put it in the resources directory. You can directly import it with 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

Create entity class

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;
	/**
	 * 交易类型
	 * <pre>
	 * JSAPI--公众号支付
	 * NATIVE--原生扫码支付
	 * APP--app支付
	 * </pre>
	 */
	private String tradeType;
 
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this,
				ToStringStyle.MULTI_LINE_STYLE);
	}
 
}

Inject WeChat payment information into the 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;
	}
 
}

Create a control layer

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 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
	QRCodeService qrCodeService;

	/**
	 * 扫码支付
	 * @param request
	 * @param memberCardTypeId
	 * @param payType
	 * @param orderAmount
	 * @param memberCardTypeName
	 * @return
	 */
	@SuppressWarnings("static-access")
	@GetMapping(value = "scanCodePay")
	@ResponseBody
	public JSONObject scanCodePay(HttpServletRequest request,
			HttpServletResponse response,
			@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<String, String> sourceMap = new HashMap<String, String>();
				sourceMap.put("memberCardTypeId", memberCardTypeId);// 会员卡类型id
				sourceMap.put("userId", userId+ "");//用户id
				sourceMap.put("reqchanle", ReqChanle.WEB.toString());//用户请求来源
				sourceMap.put("payType", payType);// 支付类型
				sourceMap.put("reqIp", WebUtils.getIpAddr(request));// 用户ip
				sourceMap.put("orderAmount", orderAmount);// 订单原始金额,也是实际支付金额
				sourceMap.put("memberCardTypeName", memberCardTypeName);//会员卡类型名称
				Map<String, Object> res = memberCardOrdersService.addTrxorder(request,sourceMap);
				if(res.containsKey("msg")){
					return this.formatJSON(501, "会员卡订单创建失败!", res);
				}else{
					WxPayUnifiedOrderRequest orderRequest  = new WxPayUnifiedOrderRequest();
					orderRequest.setAppid(weChatPayProperties.getAppId());
					orderRequest.setMchId(weChatPayProperties.getMchId());
					orderRequest.setBody(memberCardTypeName);
					orderRequest.setTotalFee(yuanToFee(new BigDecimal(orderAmount)));
					orderRequest.setSpbillCreateIp(InetAddress.getLoopbackAddress().getHostAddress());
					orderRequest.setNotifyUrl("https://你的域名/api/client/pay/scanCodePayNotify");
					orderRequest.setTradeType("NATIVE");
					orderRequest.setProductId(res.get("orderNo").toString());
					orderRequest.setOutTradeNo(res.get("orderNo").toString());
					//发起支付
					WxPayNativeOrderResult orderResult=wxPayService.createOrder(orderRequest); 
					//获取二维码URL
					String code_url=orderResult.getCodeUrl();
					String codeUrl=qrCodeService.crateQRCode(code_url, 300, 300);
					res.put("codeUrl", codeUrl);
					return this.formatJSON(200, "OK", res);
				}
			}else{
				return this.formatJSON(500, "当前登录已失效,请重新登录!",null);
			}
		} catch (Exception e) {
			logger.error("WeChatPayController.scanCodePay()----error", e);
			return this.formatJSON(500, "扫码支付时会员卡订单创建失败!",null);
		}
	}

	/**
	 * 扫码支付返回的流
	 * @param xmlData
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "scanCodePayNotify",method = {RequestMethod.GET,RequestMethod.POST})
	public String h5PayNotify(@RequestBody String xmlData,HttpServletResponse response){
		try {
			final WxPayOrderNotifyResult orderNotifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
			// 支付成功,商户处理后同步返回给微信参数
			if (("SUCCESS").equals(orderNotifyResult.getResultCode())) {
				//这里是存储我们发起支付时订单号的信息,所以取出来
				MemberCardOrders memberCardOrders=new MemberCardOrders();
				memberCardOrders.setOrderNo(orderNotifyResult.getOutTradeNo());
				//根据订单号查询订单
				MemberCardOrders mco=memberCardOrdersDao.selectMemberCardOrdersByCondition(memberCardOrders);
				//验证商户id和价格,以防止篡改金额
				if(mco!=null){
					if(weChatPayProperties.getMchId().equals(orderNotifyResult.getMchId())&&orderNotifyResult.getTotalFee().equals(yuanToFee(mco.getSumMoney()))){
						Map<String,Object> map=new HashMap<String,Object>();
						map.put("sumMoney", feeToYuan(orderNotifyResult.getTotalFee()));//订单总金额 
						map.put("outTradeNo", orderNotifyResult.getTransactionId());//支付宝的交易号
						map.put("orderNo", orderNotifyResult.getOutTradeNo());//商户系统的唯一订单号
						map.put("states", orderNotifyResult.getResultCode());//交易状态
						map.put("payTime", orderNotifyResult.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("修改会员卡订单流水信息失败!");
						}
						// 通知微信已经收到消息,不要再给我发消息了,否则微信会8连击调用本接口
						return WxPayNotifyResponse.success("支付成功!");
					}else{
						return WxPayNotifyResponse.fail("商户id和价格验证不通过!");
					}
				}else{
					return WxPayNotifyResponse.fail("订单号不存在!");
				}
			} else {
				// 支付失败, 记录流水失败
				MemberCardOrders memberCardOrders=new MemberCardOrders();
				memberCardOrders.setOrderNo(orderNotifyResult.getOutTradeNo());//商户系统的唯一订单号
				memberCardOrders.setStates(orderNotifyResult.getResultCode());//交易状态
				memberCardOrdersDao.updateMemberCardOrderStateForNotify(memberCardOrders);
				MemberCardTrxorderDetail memberCardTrxorderDetail=new MemberCardTrxorderDetail();
				memberCardTrxorderDetail.setRequestId(orderNotifyResult.getOutTradeNo());//商户系统的唯一订单号
				memberCardTrxorderDetail.setTrxStatus(orderNotifyResult.getResultCode());//交易状态
				memberCardTrxorderDetailDao.updateMemberCardTrxorderStateForNotify(memberCardTrxorderDetail);
				return WxPayNotifyResponse.fail("支付失败!");
			}
		} catch (Exception e) {
			logger.error("WeChatPayController.scanCodePayNotify()----error", e);
			return WxPayNotifyResponse.fail("扫码支付回调有误!");
		}
	}

	/**
	 * 为扫码支付查询支付结果
	 * @param request
	 * @param response
	 * @param orderNo
	 * @return
	 */
	@SuppressWarnings("static-access")
	@GetMapping(value = "selectPayResultForScanCodePay")
	@ResponseBody
	public JSONObject selectPayResultForScanCodePay(
			@RequestParam("orderNo")String orderNo){
		try {
			if(orderNo!=null&&!"".equals(orderNo.trim())){
				MemberCardOrders memberCardOrders=new MemberCardOrders();
				memberCardOrders.setOrderNo(orderNo);
				MemberCardOrders mco=memberCardOrdersDao.selectMemberCardOrdersByCondition(memberCardOrders);
				if(mco!=null){
					if(mco.getStates().equals(OrderState.SUCCESS.toString())){
						return this.formatJSON(200, "支付成功!",null);
					}else{
						return this.formatJSON(201, "支付失败!",null);
					}
				}else{
					return this.formatJSON(500, "订单号错误,请联系管理员!",null);
				}
			}else{
				return this.formatJSON(500, "订单号不能为空,请联系管理员!",null);
			}
		} catch (Exception e) {
			logger.error("WeChatPayController.selectPayResultForScanCodePay()----error", e);
			return this.formatJSON(500, "扫码支付时支付结果查询失败!",null);
		}
	}

	/**
	 * 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();
	}

}

See the source code: https://download.csdn.net/download/qq_35393693/12667762

 

Guess you like

Origin blog.csdn.net/qq_35393693/article/details/107423433