赞
踩
通常使用到微信扫描支付的场景,基本是在PC端,或者Android大屏端, 如京东商城PC端购物,或者在大街上饮料机购买饮料,都会用到扫码支付。那么如何
在流程图的第2步,商家后台向微信后台申请统一支付订单,微信后台会返回一个支付url(形式通常是weixin://wxpay/bizpayurl?pr=xxxxxx), 这个支付url就是支付的入口, 这个支付url在浏览器通常是不能访问的,它往往呈现在用户面前的是一个二维码, 那么如何转换呢?
在浏览器端,收到收到url后,使用 js (如QRCode.js) 对支付url 进行转换,并显示相应的图片。
在商家后台端,收到url后,用相应的库(java的通常使用com.google.zxing),把支付url 转换成二维码图片,然后浏览器端显示该图片。
由于方法2,更具普适性,后面的样例代码只提供方法2的,方法1的自行度娘了。
使用微信客户端,扫描以上二维码,扫码的结果是 weixin://wxpay/bizpayurl?pr=f9qZqIJzz ,微信客户端会识别该url, 并按流程唤起微信支付。
<template> <view class="container"> <top-layout topTitle="支付"></top-layout> <main-layout :alignLeft="false"> <template v-slot:contentPage> <total-layout btnText='确认支付' :isShowPrice="false" :btnBackFunc="goBack" :btnWantToFunc="confirmPay" :price="totalPrice"> <template v-slot:page> <view class="list" :style="{height: windowHeight + 'px'}"> <view class="price-area"> <view class="price-title">应付金额:</view> <view class="shop-price"> <text>¥</text> <text class="shop-price-text">{{ integerPriceStr }}</text> <text>{{ decimalPriceStr }}</text> </view> </view> <uni-section style="margin-top: 8px;" title="请选择支付方式" type="line"> <view class="uni-list"> <radio-group @change="payModeChange"> <label class="uni-list-cell uni-list-cell-pd" v-for="(item, index) in payModes" :key="item.value"> <view> <radio :value="item.value" :checked="index === currPayModeIndex" /> </view> <image class="payImg" :src="item.imgUrl" mode="aspectFill"></image> <view>{{item.text}}</view> </label> </radio-group> </view> </uni-section> </view> <uni-popup ref="popupQrCode" type="bottom" :is-mask-click="false" background-color="white" :round="10"> <view class="payCode-title">请使用微信扫码完成支付</view> <view style="text-align: center;"> <image class="payCode-img" :src="payCodeImgUrl" mode="widthFix"></image> </view> <view class="woodsbtn_cancle uni-bg-red" @click="cancelQrCodePay">取消支付</view> <view class="woodsbtn_finish" @click="finishPay">支付完成,通知商家</view> </uni-popup> </template> </total-layout> </template> </main-layout> </view> </template>
export default { data() { return { windowHeight: 0, orderName: "", //订单名称 orderNo: "", //订单号 orderType: 0, //订单类型, 0-未知,10-商城订单 totalPrice: 0, //订单合计 totalNum: 0, //订单商品总数量 integerPriceStr: "0", decimalPriceStr: ".00", goods: [], payModes: [], currPayModeIndex: 0, payCodeImgUrl: "", loginPageUrl: "", }; }, onLoad(options) { const sys = uni.getSystemInfoSync() this.windowHeight = sys.windowHeight this.payModes = [{ text: '微信扫码支付', value: "20", imgUrl: "/static/images/pay/wx.png", }]; }, confirmPay(orderNo, user) { let that = this let orderData = {} orderData.memberId = user.id; orderData.memberName = user.name; orderData.orderNo = orderNo; //订单号 orderData.payMode = that.payModes[that.currPayModeIndex].value; //支付方式 //正式请求支付信息 request({ url: '/mallOrder/requestPay', data: orderData, method: 'POST' }).then((res) => { if (res.code === '0') { let orderPayInfo = res.data; console.log('商城订单请求支付成功.订单号=' + orderPayInfo.orderNo); if (orderPayInfo.payMode === 20) { //微信扫码支付 if (orderPayInfo.payStatus === 10) { //10-未支付, 弹出扫码窗口。 console.info('支付URL=' + orderPayInfo.payCodeUrl); if (orderPayInfo.payCodeImgUrl) { that.payCodeImgUrl = config.QRCODE_BASE_URL + orderPayInfo.payCodeImgUrl; } that.openPopupQrCode() } else { uni.showToast({ title: '支付失败!' + res.msg, icon: 'error', duration: 2000 }); } } } else { uni.showToast({ title: '提交商城订单支付失败.' + res.msg, icon: 'error', duration: 2000 }); } }); }, }
/** * 生成二维码到Image * @author madifu * @param text 文字内容 * @param logoPath LOGO文件路径,如果没有LOGO可填空白 * @param note 说明 * @return = null 表示失败 * @throws WriterException * @throws IOException */ private static BufferedImage drawQRCodeImage(String text, String logoPath, String note ) throws WriterException, IOException { MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); // 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数 BitMatrix bm = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints); BufferedImage outImage = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE, BufferedImage.TYPE_INT_RGB); // 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色 for (int x = 0; x < QRCODE_SIZE; x++) { for (int y = 0; y < QRCODE_SIZE; y++) { outImage.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } int width = outImage.getWidth(); int height = outImage.getHeight(); if (checkImageExist(logoPath)) { // 构建绘图对象 Graphics2D g = outImage.createGraphics(); // 读取Logo图片 BufferedImage logo = ImageIO.read(new File(logoPath)); // 开始绘制logo图片 g.setBackground(Color.WHITE); g.clearRect(width * 2 / 5, height * 2 / 5, width * 2 / 10, height * 2 / 10); g.drawImage(logo, width * 2 / 5, height * 2 / 5, width * 2 / 10, height * 2 / 10, null); g.dispose(); logo.flush(); } // 自定义文本描述 if (!StringUtils.isEmpty(note)) { // 新的图片,把带logo的二维码下面加上文字 BufferedImage noteImage = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE+40, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D outg = noteImage.createGraphics(); // 画二维码到新的面板 outg.drawImage(outImage, 0, 0, outImage.getWidth(), outImage.getHeight(), null); // 画文字到新的面板 outg.setColor(Color.BLACK); outg.setFont(new Font("宋体", Font.BOLD, 30)); // 字体、字型、字号 int strWidth = outg.getFontMetrics().stringWidth(note); if (strWidth >= QRCODE_SIZE) { // //长度过长就截取前面部分 // 长度过长就换行 String note1 = note.substring(0, note.length() / 2); String note2 = note.substring(note.length() / 2, note.length()); int strWidth1 = outg.getFontMetrics().stringWidth(note1); int strWidth2 = outg.getFontMetrics().stringWidth(note2); outg.drawString(note1, (QRCODE_SIZE - strWidth1)/ 2, height + (noteImage.getHeight() - height) / 2 + 12); BufferedImage noteImage2 = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE+80, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D outg2 = noteImage2.createGraphics(); outg2.drawImage(noteImage, 0, 0, noteImage.getWidth(), noteImage.getHeight(), null); outg2.setColor(Color.BLACK); outg2.setFont(new Font("宋体", Font.BOLD, 30)); // 字体、字型、字号 outg2.drawString(note2, 200 - strWidth2 / 2, noteImage.getHeight() + (noteImage2.getHeight() - noteImage.getHeight()) / 2 + 5); outg2.dispose(); noteImage2.flush(); noteImage = noteImage2; } else { //outg.drawString(note, 200 - strWidth / 2, height + (outImage.getHeight() - height) / 2 + 12); // 画文字 outg.drawString(note, (QRCODE_SIZE - strWidth) / 2, height + (noteImage.getHeight() - height) / 2 + 12); // 画文字 } outg.dispose(); noteImage.flush(); outImage = noteImage; } outImage.flush(); return outImage; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。