Pago con código de escaneo WeChat (incluido appid, mch_id, key), que se puede ejecutar localmente

Nota: El appid, mch_id y la clave de este artículo son todos del podcast de Chuanzhi. Este artículo es solo para aprender y espero que los lectores no los utilicen con fines comerciales.

1. Vaya al documento de desarrollo de pagos de WeChat para obtener y descargar la demostración de Java  https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

Como se muestra en la figura:

 

Una vez finalizada la descarga, ábrela con la herramienta de desarrollo. Cada clase tiene un comentario de código correspondiente. El autor no los explicará uno por uno aquí.

 

2.Haga una simulación de la colocación unificada de pedidos de WeChat y podrá saber qué parámetros son necesarios a través de su documento de desarrollo

Dirección de pedido unificada de WeChat: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

3. Pegue el código directamente

appid, mch_id y key son todos del podcast de Chuanzhi. Espero que los lectores no los utilicen con fines comerciales, sino solo para aprender.

package com.github.wxpay.test;

import com.github.wxpay.sdk.IWXPayDomain;
import com.github.wxpay.sdk.WXPayConfig;

import java.io.InputStream;


public class Config extends WXPayConfig {

    /**
     * appId
     * */
    private static final String appId="wx8397f8696b538317";

    /**
     * mch_id
     * */
    private static final String mchId = "1473426802";

    /**
     * key
     * */
    private static final String key = "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb";

    @Override
    public String getAppID() {
        return appId;
    }


    @Override
    public String getMchID() {
        return mchId;
    }

    @Override
    public String getKey() {
        return key;
    }

    /**
     * 证书,暂时不需要
     * @return
     */
    @Override
    public InputStream getCertStream() {
        return null;
    }

    /**
     * 域名
     * @return
     */
    @Override
    public IWXPayDomain getWXPayDomain() {
        return  new IWXPayDomain() {
            public void report(String domain, long elapsedTimeMillis, Exception ex) {

            }

            public DomainInfo getDomain(WXPayConfig config) {
                return new DomainInfo("api.mch.weixin.qq.com",true);
            }
        };

    }
}

4. Prueba

package com.github.wxpay.test;

import com.github.wxpay.sdk.WXPayRequest;
import com.github.wxpay.sdk.WXPayUtil;

import java.util.HashMap;
import java.util.Map;


public class WXPayTest {
    public static void main(String[] args) throws Exception {
        Config config = new Config();
        //1、封装参数
        Map<String, String> map = new HashMap<String, String>();
        map.put("appid", config.getAppID());//公账号id
        map.put("mch_id", config.getMchID());//商户号
        map.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        map.put("body", "商品描述--测试");//商品描述
        map.put("out_trade_no", "22222122112");//商户订单号
        map.put("total_fee", "1");//金额
        map.put("spbill_create_ip", "127.0.0.1");//终端ip
        map.put("notify_url", "http://www.baidu.com");//通知地址
        map.put("trade_type", "NATIVE");//交易类型 native本地支付

        //微信提供的工具包
        String xmlParam = WXPayUtil.generateSignedXml(map, config.getKey());
        System.out.println("参数内容:" );
        System.out.println(xmlParam);

        //2、发送请求
        WXPayRequest wxPayRequest = new WXPayRequest(config);
        String xmlResult = wxPayRequest.requestWithCert("/pay/unifiedorder", null, xmlParam, false);
        System.out.println("参数结果:");
        System.out.println(xmlResult);

        //解析返回结果
        Map<String ,String> m = WXPayUtil.xmlToMap(xmlResult);
        String url = m.get("code_url");
        System.out.println("支付地址:"+url);
    }
}

proceso:

1) Parámetros de encapsulación: encapsula los parámetros necesarios en el orden unificado en un archivo xml

2) Enviar solicitud: envíe el xml encapsulado al sistema de pago WeChat

3) Analizar el resultado devuelto: Si no hay ningún problema con el xml, el sistema de pago WeChat nos dará una url, que es la dirección de pago.

Como se muestra en la figura:

 

5. El último paso es poner la dirección de pago en el código QR. Si tiene dificultades para generar el código QR, puede ver este artículo: https://blog.csdn.net/qq_36138652/article/details/114986021

Recuerde modificar el contenido del código QR, porque el contenido del código QR es la URL por la que pagó.

package com.code;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


public class QRCodeUtil {

    /**
     * CODE_WIDTH:二维码宽度,单位像素
     * CODE_HEIGHT:二维码高度,单位像素
     * FRONT_COLOR:二维码前景色,0x000000 表示黑色
     * BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色
     * 演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白
     */
    private static final int CODE_WIDTH = 400;
    private static final int CODE_HEIGHT = 400;
    private static final int FRONT_COLOR = 0x000000;
    private static final int BACKGROUND_COLOR = 0xFFFFFF;

    public static void main(String[] args) {
        String codeContent1 = "weixin://wxpay/bizpayurl?pr=JJ4LTGRzz";
        File file = new File("D:/codes");
        String fileName = "z"+System.currentTimeMillis()+".png";
        createCodeToFile(codeContent1, file, fileName,"");

    }
    /**
     * 生成二维码 并 保存为图片
     */
    /**
     * @param codeContent        :二维码参数内容,如果是一个网页地址,如 https://www.baidu.com/ 则 微信扫一扫会直接进入此地址
     *                           如果是一些参数,如 1541656080837,则微信扫一扫会直接回显这些参数值
     * @param codeImgFileSaveDir :二维码图片保存的目录,如 D:/codes
     * @param fileName           :二维码图片文件名称,带格式,如 123.png
     */
    public static void createCodeToFile(String codeContent, File codeImgFileSaveDir, String fileName,String note) {
        try {
            /** 参数检验*/
            if (codeContent == null || "".equals(codeContent)) {
                System.out.println("二维码内容为空,不进行操作...");
                return;
            }
            codeContent = codeContent.trim();
            if (codeImgFileSaveDir == null || codeImgFileSaveDir.isFile()) {
                codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
                System.out.println("二维码图片存在目录为空,默认放在桌面...");
            }
            if (!codeImgFileSaveDir.exists()) {
                codeImgFileSaveDir.mkdirs();
                System.out.println("二维码图片存在目录不存在,开始创建...");
            }
            if (fileName == null || "".equals(fileName)) {
                fileName = new Date().getTime() + ".png";
                System.out.println("二维码图片文件名为空,随机生成 png 格式图片...");
            }
            /**com.google.zxing.EncodeHintType:编码提示类型,枚举类型
             * EncodeHintType.CHARACTER_SET:设置字符编码类型
             * EncodeHintType.ERROR_CORRECTION:设置误差校正
             *      ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
             *      不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
             * EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
             * */
            Map<EncodeHintType, Object> hints = new HashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            hints.put(EncodeHintType.MARGIN, 1);

            /**
             * MultiFormatWriter:多格式写入,这是一个工厂类,里面重载了两个 encode 方法,用于写入条形码或二维码
             *      encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
             *      contents:条形码/二维码内容
             *      format:编码类型,如 条形码,二维码 等
             *      width:码的宽度
             *      height:码的高度
             *      hints:码内容的编码类型
             * BarcodeFormat:枚举该程序包已知的条形码格式,即创建何种码,如 1 维的条形码,2 维的二维码 等
             * BitMatrix:位(比特)矩阵或叫2D矩阵,也就是需要的二维码
             */
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            BitMatrix bitMatrix = multiFormatWriter.encode(codeContent, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);

            /**java.awt.image.BufferedImage:具有图像数据的可访问缓冲图像,实现了 RenderedImage 接口
             * BitMatrix 的 get(int x, int y) 获取比特矩阵内容,指定位置有值,则返回true,将其设置为前景色,否则设置为背景色
             * BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
             *      x:像素位置的横坐标,即列
             *      y:像素位置的纵坐标,即行
             *      rgb:像素的值,采用 16 进制,如 0xFFFFFF 白色
             */
            BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
            for (int x = 0; x < CODE_WIDTH; x++) {
                for (int y = 0; y < CODE_HEIGHT; y++) {
                    bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
                }
            }

            /**javax.imageio.ImageIO java 扩展的图像IO
             * write(RenderedImage im,String formatName,File output)
             *      im:待写入的图像
             *      formatName:图像写入的格式
             *      output:写入的图像文件,文件不存在时会自动创建
             *
             * 即将保存的二维码图片文件*/
            File codeImgFile = new File(codeImgFileSaveDir, fileName);
            ImageIO.write(bufferedImage, "png", codeImgFile);

            System.out.println("二维码图片生成成功:" + codeImgFile.getPath());


            // 自定义文本描述
            if (StringUtils.isNotEmpty(note)) {
                // 新的图片,把带logo的二维码下面加上文字
                BufferedImage outImage = new BufferedImage(400, 445, BufferedImage.TYPE_4BYTE_ABGR);
                Graphics2D outg = outImage.createGraphics();
                // 画二维码到新的面板
                outg.drawImage(bufferedImage, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), null);
                // 画文字到新的面板
                outg.setColor(Color.BLACK);
                outg.setFont(new Font("楷体", Font.BOLD, 30)); // 字体、字型、字号
                int strWidth = outg.getFontMetrics().stringWidth(note);
                Integer height = 400;
                if (strWidth > 399) {
                    //长度过长就截取前面部分
                    // 长度过长就换行
                    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, 200 - strWidth1 / 2, height + (outImage.getHeight() - height) / 2 + 12);
                    BufferedImage outImage2 = new BufferedImage(400, 485, BufferedImage.TYPE_4BYTE_ABGR);
                    Graphics2D outg2 = outImage2.createGraphics();
                    outg2.drawImage(outImage, 0, 0, outImage.getWidth(), outImage.getHeight(), null);
                    outg2.setColor(Color.BLACK);
                    outg2.setFont(new Font("宋体", Font.BOLD, 30)); // 字体、字型、字号

                    outg2.drawString(note2, 200 - strWidth2 / 2, outImage.getHeight() + (outImage2.getHeight() - outImage.getHeight()) / 2 + 5);
                    outg2.dispose();
                    outImage2.flush();
                    outImage = outImage2;
                } else {
                    outg.drawString(note, 200 - strWidth / 2, height + (outImage.getHeight() - height) / 2 + 12); // 画文字
                }
                outg.dispose();
                outImage.flush();
                bufferedImage = outImage;
            }

            bufferedImage.flush();
            /**
             * 区别就是以一句,输出到输出流中,如果第三个参数是 File,则输出到文件中
             */
            ImageIO.write(bufferedImage, "png",codeImgFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

 

Supongo que te gusta

Origin blog.csdn.net/qq_36138652/article/details/114601961
Recomendado
Clasificación