侧边栏壁纸
博主头像
王小木人

这是很长,很好的一生

  • 累计撰写 141 篇文章
  • 累计创建 43 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

微信公众号支付 uniapp微信支付 发起支付时不跳转页面

王小木人
2022-03-26 / 0 评论 / 0 点赞 / 1,423 阅读 / 8,590 字

使用uniapp 打包成h5发起微信公众号支付,总共大概有以下的步骤
1 跳转到微信支付中心再跳回我们页面 此时会在url上带上code
2 使用得到的code 调用我们后台获取到发起支付所需要的相关参数
3 发起支付并支付后 回调我们后台,在回调方法中处理我们业务例如 充值会员
4 告诉微信不要再回调了,微信为了确保业务处理 同一个支付会一直回调 所以在回调方法中结束时需要在回应微信 同时我们的方法也要避免多次调用而重复处理的麻烦

前端代码

<script>
	//#ifdef H5
	let jweixin = require('jweixin-module');
	//#endif
	export default {
		data() {
			return {	
				code: "",
			}
		},
		created() {
			// 首次进入就去跳转微信中心并跳回来 获取到code 后面发起支付时需要
			this.getWechatCode()
		},
		onLoad() {
		},
		methods: {
			//发起支付
			pay() {
				let self = this;
				//通过code 调用我们的后台获取发起支付所需的相关参数
				Server.get("/scan/wxorder", {
					'code': self.code,
					'id': reportid, // reportid为业务处理所需相关参数 我们自定义的 后面微信回调时会在传回来
				}, {
					success: (response) => {
						self.timeStamp = response.data.data.timeStamp;
						self.nonceStr = response.data.data.nonceStr;
						self.paySign = response.data.data.paySign;
						self.package = response.data.data.package;
						jweixin.config({
							//debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
							appId: self.appid, // 必填,公众号的唯一标识
							timestamp: self.timeStamp, // 必填,生成签名的时间戳
							nonceStr: self.nonceStr, // 必填,生成签名的随机串
							signature: self.paySign, // 必填,签名,见附录1
							jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
						});
						jweixin.ready(function() {
							jweixin.checkJsApi({
								jsApiList: ['chooseWXPay'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
								success: function(res) {
									console.log('checkjsapi Success')
									console.log(res);
								},
								fail: function(res) {
									console.log('res')
									console.log(res);
								}
							});
							jweixin.chooseWXPay({
								timestamp: self
									.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
								nonceStr: self.nonceStr, // 支付签名随机串,不长于 32 位
								package: self
									.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
								signType: 'MD5', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
								paySign: self.paySign, // 支付签名
								success: function(res) {
									//这里就是支付成功的前端处理 业务操作不建议在这里处理,可能用户会关掉等因素造成未处理的情况发生
								},
								cancel: function(res) {
									self.modelcontent = '支付取消';
									self.modeltitle = "提示";
									self.modelshow = true;
								},
								fail: function(res) {
									self.modelcontent = '支付失败';
									self.modeltitle = "提示";
									self.modelshow = true;

								}
							});
						});

						jweixin.error(function(res) {
							console.log('error')
							console.log(res)
							self.modelcontent = '支付失败';
							self.modeltitle = "提示";
							self.modelshow = true;
							// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
							/*alert("config信息验证失败");*/
						});
					},
					warnings: (response) => {
						/* self.modelcontent = response;
						self.modeltitle = "警告";
						self.modelshow = true; */
					},
					error: (response) => {
						self.modelcontent = response;
						self.modeltitle = "错误";
						self.modelshow = true;
					},
				});

			},
			// 在url上获取查询字符串
			getQueryVariable(variable) {
				let query = window.location.search.substring(1)
				let vars = query.split('&')
				for (let i = 0; i < vars.length; i++) {
					let pair = vars[i].split('=')
					if (pair[0] == variable) {
						return pair[1]
					}
				}
				return false
			},
			// 获取微信code
			getWechatCode() {
				let tcode = this.getQueryVariable('code')
				console.log("获取code到的:" + tcode)
				if (tcode) {
					this.code = tcode
				} else {
					this.getSystemInfo()
				}
			},
			// 获取系统参数配置,并获取微信授权
			getSystemInfo() {
				let that = this
				let redirect_uri = encodeURIComponent(window.location.href.split('?')[0])
                 //跳转到微信中心 并再跳回来 再次回来后url上会多上code信息
				//#ifdef H5
				window.location.href =
					'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' +
					that.appid +
					'&redirect_uri=' +
					redirect_uri +
					'&response_type=code&scope=snsapi_base&state=1#wechat_redirect'
				//#endif
			},
		}
	}
</script>

后端代码

通过code获取发起支付所需相关信息

 @GetMapping("/wxorder")
    public JrsfReturn wxorder(@RequestParam String code) throws Exception {
        
        MyWXConfig config = new MyWXConfig();
        WXPay wxpay = new WXPay(config);
        String appid = wxappid;
        String secret = wxsecret;
        String result = restTemplate.getForObject("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code", String.class);
        JSONObject jsonObject = JSONObject.parseObject(result);

        String openId = jsonObject.getString("openid");
        if (StringUtils.isBlank(openId)) {
            return JrsfReturn.error();
        }
        Map<String, String> data = new HashMap<String, String>();

        data.put("body", "会员");
        data.put("out_trade_no", DateUtil.dateToStr("yyyyMMddHHmmssSSS", new Date()));
        
        data.put("total_fee", "0.01");
        data.put("spbill_create_ip", EvCommonTool.getIpAddress());
        data.put("notify_url", wxnotifyUrl); //回调地址
        data.put("trade_type", "JSAPI");
        data.put("openid", openId);
        Map<String, Object> payInfo = new HashMap<>();//微信回调地址时 会回传给我们这里可以带上处理业务相关参数
        payInfo.put("userId", "1");
        payInfo.put("level", "1");
        payInfo.put("months", 1);
        data.put("attach", JSONObject.toJSONString(payInfo));
        Map<String, String> resp = wxpay.unifiedOrder(data);
        if (StringUtils.isNotBlank(resp.get("prepay_id"))) {
            String prepay_id = resp.get("prepay_id"); //预支付id
            Map<String, String> payMap = new HashMap<String, String>();
            payMap.put("appId", appid);
            payMap.put("timeStamp", String.valueOf(System.currentTimeMillis()));
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            payMap.put("signType", "MD5");
            payMap.put("package", "prepay_id=" + prepay_id);
            String paySign = WXPayUtil.generateSignature(payMap, config.getKey());
            payMap.put("paySign", paySign);
            return JrsfReturn.okData(payMap);
        } else {
            return JrsfReturn.error();
        }
    }

MyWXConfig类

import com.alipay.api.internal.util.file.IOUtils;
import com.github.wxpay.sdk.WXPayConfig;
import org.springframework.core.io.ClassPathResource;

import java.io.*;

public class MyWXConfig implements WXPayConfig {
    private byte[] certData;

    public MyWXConfig() throws Exception {
        ClassPathResource classPathResource = new ClassPathResource("apiclient_cert.p12");
        InputStream certStream = classPathResource.getInputStream();
        this.certData = IOUtils.toByteArray(certStream);
        certStream.read(this.certData);
        certStream.close();
    }

    @Override
    public String getAppID() {
        return "wx120a18c636fd8718";
    }

    @Override
    public String getMchID() {
        return "1614696304";
    }

    @Override
    public String getKey() {
        return "MIIEvQIBADANBgkqhkiG9w0BAQEFAASC";
    }

    @Override
    public InputStream getCertStream() {
        ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
        return certBis;
    }

    @Override
    public int getHttpConnectTimeoutMs() {
        return 8000;
    }

    @Override
    public int getHttpReadTimeoutMs() {
        return 10000;
    }
}

回调方法

   @PostMapping("/wx/notifyUrl")
    public String wxNotifyUrl(HttpServletRequest request, HttpServletResponse response) {
        //System.out.println("微信支付成功,微信发送的callback信息,请注意修改订单信息");
        InputStream is = null;
        try {
            is = request.getInputStream();//获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
            String xml = WXPayUtil.inputStream2String(is, "UTF-8");
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map
            if (notifyMap.get("return_code").equals("SUCCESS")) {
                if (notifyMap.get("result_code").equals("SUCCESS")) {
                    String ordersSn = notifyMap.get("out_trade_no");//商户订单号
                    String attach = notifyMap.get("attach");
                     //之前在获取支付信息时填入的
                    JSONObject jsonObject = JSONObject.parseObject(attach);

                    /*以下是自己的业务处理------仅做参考*/
            
                }
            }

            //告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
            response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
0

评论区