uni-app中微信支付之app端微信支付的实现【上】

艾焕
2023-12-01

海豚精灵https://www.whhtjl.com优课GOhttps://mgo.whhtjl.com

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

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

uni-app前端代码:

<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">
                    <text class="rmbLogo">¥</text>
                    <input class="price" type="digit" :value="price" maxlength="5" @input="priceChange" />
                </view>
            </view>
            <view class="uni-btn-v uni-common-mt">
                <!-- #ifdef APP-PLUS -->
                <template v-if="providerList.length > 0">
                    <button class="flex align-center justify-center" v-for="(item,index) in providerList" :key="index" @click="requestPayment(item,index)"
                        :loading="item.loading"><image :src="item.logoUrl" style="height: 50rpx;width: 50rpx;" class="px-1"></image> {{item.name}}支付</button>
                </template>
                <!-- #endif -->
            </view>
        </view>
    </view>
    </view>
</template>
<script>
    export default {
        data() {
            return {
                title: 'request-payment',
                loading: false,
                typeId:0,
                vipName:'',
                price: 1,
                providerList: [],
                baseLocation: '',
                memberCardOrders:[],
                header: { 'Content-Type': 'application/x-www-form-urlencoded' }
            }
        },
        onLoad: function(e) {
			this.baseLocation = getApp().globalData.BaseUrl;
			if(e.id){
				this.typeId=e.id;
			}
			if(e.typeName){
				this.vipName=e.typeName;
			}
			if(e.currentPrice){
				this.price=e.currentPrice;
			}
            // #ifdef APP-PLUS
            uni.getProvider({
                service: "payment",
                success: (e) => {
                    let providerList = [];
                    e.provider.map((value) => {
                        switch (value) {
                            case 'wxpay':
                                providerList.push({
                                    name: '微信',
                                    id: value,
                                    loading: false,
				logoUrl:'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2598881869,3590388932&fm=26&gp=0.jpg'
                                });
                                break;
                            default:
                                break;
                        }
                    })
                    this.providerList = providerList;
                },
                fail: (e) => {
					return false;
                }
            });
            // #endif
        },
        methods: {
			//登录
			async login() {
				// #ifdef APP-PLUS || H5
				this.$loginForAppAndH5();
				// #endif
			
				// #ifdef MP-WEIXIN
				this.$loginForWeiXinApplet('membercenter');
				// #endif
			},
			//请求支付
            async requestPayment(e, index) {
                this.providerList[index].loading = true;
				//订单提交,服务端要做验证,下单时重新查询数据库
				let memberCardOrderInfo=await this.createOrder(e.id);
				if (memberCardOrderInfo.code === 200) {
					//使用 uni.requestPayment 向支付平台发起支付请求,拉起支付平台的客户端进行支付。
					uni.requestPayment({
					    provider: e.id,
						orderInfo: memberCardOrderInfo.data,
					    success: (e) => {
							uni.showToast({
								title:'支付成功,即将跳转到会员中心...',
								icon:'none',
								duration:1000
							})
							uni.reLaunch({
								url:'membercenter'
							})
					    },
					    fail: (e) => {
							uni.showModal({
							    content: "支付失败,其原因为: " + JSON.stringify(e),
							    showCancel: false
							})
					    },
					    complete: () => {
					        this.providerList[index].loading = false;
					    }
					})
                }else{
					uni.showModal({
					    content: "获得订单信息失败",
					    showCancel: false
					})
					return false;
				}
            },
			//下单
			createOrder(e){
					let ticket = uni.getStorageSync('ticket');
					if (ticket===null || ticket === '' || ticket === undefined || ticket === 'undefined') {
						this.login();
					}else{
							if(e=="wxpay"){
								e="WEIXIN";
							}
							return new Promise((result) => {
								uni.request({
										url: this.baseLocation + '/api/client/pay/weChatPay',
										header: {
											'content-type': 'application/x-www-form-urlencoded',
											cookie: 'ticket=' + ticket
										},
										method: 'GET',
										dataType: 'json',
										data: {
											memberCardTypeId: this.typeId,
											payType: e,
											orderAmount: this.price,
											memberCardTypeName: this.vipName
										},
										success: res => {
											result(res.data);
										},fail: err=>{
											uni.showToast({
												title:"出错啦:"+JSON.stringify(err),
												icon:'none',
												duration:3000
											})
											return false;
										}
								});
					})
					}
			},
			//价格计算
            priceChange(e) {
                this.price = e.detail.value;
            }
			
        }
    }
</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 {
        border-bottom: 1px solid #eee;
        width: 200rpx;
        height: 80rpx;
        padding-bottom: 4rpx;
    }

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

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

<!--公众号(包括订阅号和服务号) -->
<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>

在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=APP

创建实体类

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);
	}

}

将微信支付信息注入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.ReqChanle;
import com.ltf.config.WeChatPayProperties;
import com.ltf.dao.MemberCardOrdersDao;
import com.ltf.entity.MemberCardOrders;
import com.ltf.service.MemberCardOrdersService;
import com.ltf.service.MemberCardTrxorderDetailService;
import com.ltf.utils.HttpRequestUtil;
import com.ltf.utils.SingletonLoginUtils;
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.request.WxPayUnifiedOrderRequest;
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;

/**
 * 微信支付
 * @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 MemberCardTrxorderDetailService memberCardTrxorderDetailService;

	/**
	 * app支付
	 * @param request
	 * @param memberCardTypeId
	 * @param payType
	 * @param orderAmount
	 * @param memberCardTypeName
	 * @return
	 */
	@SuppressWarnings("static-access")
	@GetMapping(value = "weChatPay")
	@ResponseBody
	public JSONObject weChatPay(
			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<String, String> sourceMap = new HashMap<String, String>();
				sourceMap.put("memberCardTypeId", memberCardTypeId);// 会员卡类型id
				sourceMap.put("userId", userId+ "");//用户id
				sourceMap.put("reqchanle", ReqChanle.APP.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{
					/**
					 * 处理内部业务,校验订单等
					 */
					final WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
							//订单编号
							.outTradeNo(res.get("orderNo").toString())
							//订单金额
							.totalFee(yuanToFee(new BigDecimal(orderAmount)))
							//商品描述
							.body(memberCardTypeName)
							//获取本地IP
							.spbillCreateIp(InetAddress.getLoopbackAddress().getHostAddress())
							.notifyUrl("https://你的域名/api/client/pay/weChatPayNotify")
							.build();
					WxPayAppOrderResult wxPayAppOrderResult =null;
					try {
						wxPayAppOrderResult = wxPayService.createOrder(wxPayUnifiedOrderRequest);
					} catch (WxPayException e) {
						e.printStackTrace();
						throw new RuntimeException("微信支付调起失败!");
					}
					JSONObject  resOrderInfo=new JSONObject();
					resOrderInfo.put("appid",wxPayAppOrderResult.getAppId());
					resOrderInfo.put("noncestr",wxPayAppOrderResult.getNonceStr());
					resOrderInfo.put("package",wxPayAppOrderResult.getPackageValue());
					resOrderInfo.put("partnerid",wxPayAppOrderResult.getPartnerId());
					resOrderInfo.put("prepayid",wxPayAppOrderResult.getPrepayId());
					resOrderInfo.put("timestamp",wxPayAppOrderResult.getTimeStamp());
					resOrderInfo.put("sign",wxPayAppOrderResult.getSign());
					res.put("data", resOrderInfo);
					return this.formatJSON(200, "OK", res);}
			}else{
				return this.formatJSON(500, "当前登录已失效,请重新登录!",null);
			}
		} catch (Exception e) {
			logger.error("WeChatPayController.weChatPay()----error", e);
			return this.formatJSON(500, "APP内微信支付时会员卡订单创建失败!",null);
		}
	}

	/**
	 * app支付返回的流
	 * @param xmlData
	 * @return
	 */
	@RequestMapping(value = "weChatPayNotify",method = {RequestMethod.GET,RequestMethod.POST})
	public String weChatPayNotify(@RequestBody String xmlData){
		try {
			final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);
			//这里是存储我们发起支付时订单号的信息,所以取出来
			MemberCardOrders memberCardOrders=new MemberCardOrders();
			memberCardOrders.setOrderNo(notifyResult.getOutTradeNo());
			//根据订单号查询订单
			MemberCardOrders mco=memberCardOrdersDao.selectMemberCardOrdersByCondition(memberCardOrders);
			//验证商户id和价格,以防止篡改金额
			if(mco!=null){
				if(weChatPayProperties.getMchId().equals(notifyResult.getMchId())&&notifyResult.getTotalFee().equals(yuanToFee(mco.getSumMoney()))){
					Map<String,Object> map=new HashMap<String,Object>();
					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("订单号不存在!");
			}
		} catch (WxPayException e) {
			logger.error("WeChatPayController.weChatPayNotify()----error", e);
			return WxPayNotifyResponse.fail("APP内微信支付回调有误!");
		}
	}

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


}

源码见:https://download.csdn.net/download/qq_35393693/12667762

 

 类似资料: