通过C#生成支付宝收款码 四(支付宝官方SDK配合沙箱生成收款二维码)

前面三个章节是学习和摸索过程,现在进入主题,生成收款码。还是用沙箱环境来调试。

1.新建windowsform程序,根据章节三,导入支付宝SDK。

2.下载官方当面付DEMO程序:当面付DEMO
在这里插入图片描述
3.按照下图打开项目:
在这里插入图片描述
这是WEB版本的代码,由于官方的DEMO是集成所有接口的,会出现代码重复和代码岑余,所以不直接使用官方DEMO,只选取需要的部分,打开如下图所示界面:
在这里插入图片描述
生成收款码的接口程序就是这里,如下:

/// <summary>
    /// 功能:预下单接口接入页
    /// 日期:2016-12-27
    /// 说明:
    /// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
    /// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
    /// 
    /// /注意///
    /// 如果您在接口集成过程中遇到问题,可以按照下面的途径来解决
    /// 1、支持中心(https://support.open.alipay.com/alipay/support/index.htm),提交申请集成协助,我们会有专业的技术工程师主动联系您协助解决
    /// 2、开发者论坛(https://openclub.alipay.com/)
    /// </summary>
    public partial class PreCreate : System.Web.UI.Page
    {

        private LogHelper log = new LogHelper(AppDomain.CurrentDomain.BaseDirectory + "/log/log.txt");

       IAlipayTradeService serviceClient = F2FBiz.CreateClientInstance(Config.serverUrl, Config.appId, Config.merchant_private_key, Config.version,
                            Config.sign_type, Config.alipay_public_key, Config.charset);


        protected void Page_Load(object sender, EventArgs e)
        {

            
        }

        protected void Alipay_RSA_Submit(object sender, EventArgs e)
        {

            AlipayTradePrecreateContentBuilder builder = BuildPrecreateContent();
            string out_trade_no = builder.out_trade_no;

            //如果需要接收扫码支付异步通知,那么请把下面两行注释代替本行。
            //推荐使用轮询撤销机制,不推荐使用异步通知,避免单边账问题发生。
            AlipayF2FPrecreateResult precreateResult = serviceClient.tradePrecreate(builder);
            //string notify_url = "http://10.5.21.14/notify_url.aspx";  //商户接收异步通知的地址
            //AlipayF2FPrecreateResult precreateResult = serviceClient.tradePrecreate(builder, notify_url);

            //以下返回结果的处理供参考。
            //payResponse.QrCode即二维码对于的链接
            //将链接用二维码工具生成二维码打印出来,顾客可以用支付宝钱包扫码支付。
            string result = "";

            switch (precreateResult.Status)
            {
                case ResultEnum.SUCCESS:
                    DoWaitProcess(precreateResult);
                    break;
                case ResultEnum.FAILED:
                    result = precreateResult.response.Body;
                    Response.Redirect("result.aspx?Text=" + result);
                    break;

                case ResultEnum.UNKNOWN:
                    if (precreateResult.response == null)
                    {
                        result = "配置或网络异常,请检查后重试";
                    }
                    else
                    {
                        result = "系统异常,请更新外部订单后重新发起请求";
                    }
                    Response.Redirect("result.aspx?Text=" + result);
                    break;
            }

        }

        /// <summary>
        /// 构造支付请求数据
        /// </summary>
        /// <returns>请求数据集</returns>
        private AlipayTradePrecreateContentBuilder BuildPrecreateContent()
        {
            //线上联调时,请输入真实的外部订单号。
            string out_trade_no = "";
            if (String.IsNullOrEmpty(WIDout_request_no.Text.Trim()))
            {
                out_trade_no = System.DateTime.Now.ToString("yyyyMMddHHmmss") + "0000" + (new Random()).Next(1, 10000).ToString();
            }
            else
            {
                out_trade_no = WIDout_request_no.Text.Trim();
            }

            AlipayTradePrecreateContentBuilder builder = new AlipayTradePrecreateContentBuilder();
            //收款账号
            builder.seller_id = Config.pid;
            //订单编号
            builder.out_trade_no = out_trade_no;
            //订单总金额
            builder.total_amount = WIDtotal_fee.Text.Trim();
            //参与优惠计算的金额
            //builder.discountable_amount = "";
            //不参与优惠计算的金额
            //builder.undiscountable_amount = "";
            //订单名称
            builder.subject = WIDsubject.Text.Trim();
            //自定义超时时间
            builder.timeout_express = "5m";
            //订单描述
            builder.body = "";
            //门店编号,很重要的参数,可以用作之后的营销
            builder.store_id = "test store id";
            //操作员编号,很重要的参数,可以用作之后的营销
            builder.operator_id = "test";

            //传入商品信息详情
            List<GoodsInfo> gList = new List<GoodsInfo>();
            GoodsInfo goods = new GoodsInfo();
            goods.goods_id = "goods id";
            goods.goods_name = "goods name";
            goods.price = "0.01";
            goods.quantity = "1";
            gList.Add(goods);
            builder.goods_detail = gList;

            //系统商接入可以填此参数用作返佣
            //ExtendParams exParam = new ExtendParams();
            //exParam.sysServiceProviderId = "20880000000000";
            //builder.extendParams = exParam;

            return builder;

        }

        /// <summary>
        /// 生成二维码并展示到页面上
        /// </summary>
        /// <param name="precreateResult">二维码串</param>
        private void DoWaitProcess( AlipayF2FPrecreateResult precreateResult )
        {
            //打印出 preResponse.QrCode 对应的条码
            Bitmap bt;
            string enCodeString = precreateResult.response.QrCode;
            QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
            qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
            qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
            qrCodeEncoder.QRCodeScale = 3;
            qrCodeEncoder.QRCodeVersion = 8;
            bt = qrCodeEncoder.Encode(enCodeString, Encoding.UTF8);
            string filename = System.DateTime.Now.ToString("yyyyMMddHHmmss") + "0000" + (new Random()).Next(1, 10000).ToString()
             + ".jpg";
            bt.Save(Server.MapPath("~/images/") + filename);
            this.Image1.ImageUrl = "~/images/" + filename;

            //轮询订单结果
            //根据业务需要,选择是否新起线程进行轮询
            //ParameterizedThreadStart ParStart = new ParameterizedThreadStart(LoopQuery);
            //Thread myThread = new Thread(ParStart);
            //object o = precreateResult.response.OutTradeNo;
            //myThread.Start(o);

        }

        /// <summary>
        /// 轮询
        /// </summary>
        /// <param name="o">订单号</param>
        public void LoopQuery(object o)
        {
            AlipayF2FQueryResult queryResult = new AlipayF2FQueryResult();
            int count = 100;
            int interval = 10000;
            string out_trade_no = o.ToString();

            for (int i = 1; i <= count; i++)
            {
                Thread.Sleep(interval);
                queryResult = serviceClient.tradeQuery(out_trade_no);
                if (queryResult != null)
                {
                    if (queryResult.Status == ResultEnum.SUCCESS)
                    {
                        DoSuccessProcess(queryResult);                       
                        return;
                    }
                }
            }
            DoFailedProcess(queryResult);
        }

        /// <summary>
        /// 请添加支付成功后的处理
        /// </summary>
        private void DoSuccessProcess(AlipayF2FQueryResult queryResult)
        {
                //支付成功,请更新相应单据
            log.WriteLine("扫码支付成功:外部订单号" + queryResult.response.OutTradeNo);

        }

        /// <summary>
        /// 请添加支付失败后的处理
        /// </summary>
        private void DoFailedProcess(AlipayF2FQueryResult queryResult)
        {
            //支付失败,请更新相应单据
        }

然后根据自己的沙箱账号信息进行修改。验证代码,若成功,则支付宝会打印二维码的链接,例如支付宝反馈如下:

{"alipay_trade_precreate_response":{"code":"10000","msg":"Success","out_trade_no":"20210122023434655412652021-01-13 17:32:43","qr_code":"https://qr.alipay.com/bax07049mbi0yh6v2avuz000c"},"sign":"XAZYYP54rYRt2EpJ5UNnFVaIwPas4L40UgZ6ftdJhMOyQGwzV7ejjnYfQosQjn8UiDfi/TQ25FfdvfexoumQSbEoc8TZsORlPvkZy/C2c6HSR543TIumjol52WhHgurltYbtKsI5+SO78mspcncoxwCgrS+ZwPCA2vJqf14ldbXdGAIbveENMrMzlWlm73H0/rp2KpdInjEP0BKwWP+bfImW1ZvicGLE2f6Ul4KDsk4CuSYPXsajT6ROAl/0qXfr5WjqzkOv71NewTzzMNqM2RS8n01rrfKmF6AcpEM9/U+vpoAoOOCTojKEGh/dPB2UQGDG0Wi1ZsFIwuoFLSGbP1T9ifvGXJWfR8w=="}

其中需要生成二维码的链接是:“qr_code”:后面跟着的链接”https://qr.alipay.com/bax07049mbi0yh6va2vuz000c”,去掉‘ ” ’,去掉‘ ’,最后的字符串生成二维码即可。(”https://qr.alipay.com/bax07049mbi0yh6va2vuz000c”)

4.调用ThoughtWorks.QRCode.dll生成二维码

下载ThoughtWorks.QRCode.dll;ThoughtWorks.QRCode.dll

导入DLL到代码;

生成二维码代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using System.Drawing;
using System.Text;
using ThoughtWorks.QRCode.Codec;
using System.IO;

namespace App.Web.APIControllers
{
    /// <summary>
    /// 生成二维码
    /// </summary>    public class QRCodeController : Controller
    {
        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="enCodeString">要生成二维码的文字</param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public string QRCode(string enCodeString)
        {
            System.Drawing.Bitmap bt;
            QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
            qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;//编码方式(注意:BYTE能支持中文,ALPHA_NUMERIC扫描出来的都是数字)
            qrCodeEncoder.QRCodeScale = 10;//大小(值越大生成的二维码图片像素越高)
            qrCodeEncoder.QRCodeVersion = 0;//版本(注意:设置为0主要是防止编码的字符串太长时发生错误)
            qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;//错误效验、错误更正(有4个等级)
            qrCodeEncoder.QRCodeBackgroundColor = Color.White;//背景色
            qrCodeEncoder.QRCodeForegroundColor = Color.Black;//前景色
            bt = qrCodeEncoder.Encode(enCodeString, Encoding.UTF8);
            string filename = enCodeString;// "code";
            string file_path = AppDomain.CurrentDomain.BaseDirectory + "QRCode\";
            string codeUrl = file_path + filename + ".jpg";

            //根据文件名称,自动建立对应目录
            if (!System.IO.Directory.Exists(file_path))
            {
                System.IO.Directory.CreateDirectory(file_path);
            }
            防止内容重复,导致名称重复问题,
            若要每次更新,可去掉本段代码 ↓↓↓↓↓
            //int i = 1;
            //while (System.IO.File.Exists(codeUrl))
            //{               
            //    string _filename = filename + "("+i+")";
            //    codeUrl = file_path + _filename + ".jpg";
            //    i++;
            //}
               ↑↑↑↑↑↑↑

            bt.Save(codeUrl);//保存图片
            return codeUrl;
        }


        /// <summary>
        /// 生成二维码【方法二】
        /// </summary>
        /// <param name="qrCodeScale">尺寸4-15</param>
        /// <param name="qrCodeVersion">复杂级别3-12</param>
        /// <param name="qrCodeErrorCorrect">容错量"H","L","M","Q"</param>
        /// <param name="enCodeString">二维码信息</param>        
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public  string CreateEQcoder(int qrCodeScale, int qrCodeVersion, string qrCodeErrorCorrect, string enCodeString)
        {
            QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
            qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
            qrCodeEncoder.QRCodeScale = qrCodeScale;
            qrCodeEncoder.QRCodeVersion = qrCodeVersion;
            switch (qrCodeErrorCorrect)
            {
                case "H":
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
                    break;
                case "L":
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
                    break;
                case "M":
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
                    break;
                case "Q":
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.Q;
                    break;
            }
            qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
            Bitmap bmPhoto = qrCodeEncoder.Encode(enCodeString, System.Text.Encoding.GetEncoding("UTF-8"));
            string fileName = enCodeString+"_"+ qrCodeScale+"_"+qrCodeVersion+"_"+ qrCodeErrorCorrect;
            string file_path = AppDomain.CurrentDomain.BaseDirectory + "QRCode\";
            string savePath = file_path + fileName + ".jpg";
            try
            {
                if (!Directory.Exists(file_path))
                {
                    Directory.CreateDirectory(file_path);
                }

                //防止内容重复,导致名称重复问题,若要每次更新,可去掉本段代码 ↓↓↓↓↓
                int i = 1;
                while (System.IO.File.Exists(savePath))
                {
                    string _filename = fileName + "(" + i + ")";
                    savePath = file_path + _filename + ".jpg";
                    i++;
                }
                //↑↑↑↑↑↑↑
                bmPhoto.Save(savePath);
                bmPhoto.Dispose();
                return savePath ;
            }
            catch (Exception)
            {
                return "";
            }
            finally
            {
                bmPhoto.Dispose();
            }
        }
    }
}

根据自己情况适当修改。

5.最终将支付宝返回的二维码链接生成二维码即可。我的界面大致如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
研究了几天,总算出结果了,目前都只是沙箱的验证,实际用的话需要签约功能,签约的话需要营业执照。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注