[Mobile Payment].NET Alipay App payment access

I. Preface

Recently, blogs have been updating slowly because they are busy with new products. In order to facilitate users to pay, new products need Alipay scan code access. It fell to me. The product is desktop software under Windows system, which generates two-dimensional code payment through software. The interface is written in native MVVM. The following is a description of the basic process. The old driver who has done it can turn it off directly.

 

II. Application Interface

The first step is to apply for an interface.

  1. The company has Alipay account.
  2. The company has business qualifications (nonsense)
  3. Create applications, sign computer website payment, mobile payment, App payment.
  4. Create private key, public key, Alipay public key
  5. Configure Gateway and Callback Address

Attention should be paid to the following points:

  1. When creating an application, do not use the words "pay" or "pay" in the name. The picture suggests HD.
  2. When creating applications, contract payment requires some application materials, such as: business qualification photos, company photos 4, application introduction (name, download address, whether the company website has the application, the application has Alipay payment interface style).
  3. After signing the contract, it needs to be audited for about one day (Ali really fast, Tencent Weixin takes 4 days). After the approval, an email will be sent, which contains a link, click on the link to complete the signing.
  4. Create a private key, a public key, and a Alipay public key. There is an official tool on the Alipay interface website to download and use.
  5. Gateway and callback address should be associated with company website, such as secondary domain name; if gateway and callback address have no connection with company website, I am afraid not.

 

3. Code flow

There are three components. Client software, merchant server background, Alipay backstage

Client software clicks "Get Payment Two-Dimensional Code" to get a Payable Two-Dimensional Code:

Encapsulating some necessary information from the client and sending it back to the merchant server to form a merchant order

        /// <summary>
        /// Obtaining Two-Dimensional Code Information
        /// </summary>
        /// <param name="packageClientInfo">Packaging information</param>
        /// <param name="serverAddress">Merchant Product Server Address</param>
        /// <returns></returns>
        public static void GetQRCodeInfo(string packageClientInfo, string serverAddress, Action<string> getQRCodeAction)
        {
            if (!string.IsNullOrEmpty(packageClientInfo))
            {
                try
                {
                    HttpClient httpsClient = new HttpClient
                    {
                        BaseAddress = new Uri(serverAddress),
                        Timeout = TimeSpan.FromMinutes(20)
                    };

                    if (DsClientOperation.ConnectionTest(httpsClient))
                    {
                        StringContent strData = new StringContent(
                                                           packageClientInfo,
                                                           Encoding.UTF8,
                                                           RcCommonNames.JasonMediaType);
                        string PostUrl = httpsClient.BaseAddress + "api/AlipayForProduct/GetQRCodeString";
                        Uri address = new Uri(PostUrl);
                        Task<HttpResponseMessage> response = httpsClient.PostAsync(address, strData);
                        response.ContinueWith(
                            (postTask) =>
                            {
                                if (postTask.IsFaulted)
                                {
                                    throw postTask.Exception;
                                }
                                HttpResponseMessage postResponse = postTask.Result;
                                postResponse.EnsureSuccessStatusCode();
                                var result = postResponse.Content.ReadAsStringAsync().Result;
                                getQRCodeAction(JsonConvert.DeserializeObject<string>(result)); //Pay attention to this Commission
                                return result;
                            });
                    }
                }
                catch
                {
                    // ignored
                }
            }
        }

                 

The delegation method here is used to generate two-dimensional codes, when you return some strings (result s) from this "api/AlipayForProduct/GetQRCodeString", for example:

"Http://xxx.xxx.com/AlipayForProduct/SendInfoToAlipay?Ordernumber="+$"{orderNumber}"; (orderNumber is the merchant order number)

ThoughtWorks.QRCode.dll is then used to generate two-dimensional codes.

        /// <summary>
        /// Get the corresponding two-dimensional code from the string
        /// </summary>
        /// <param name="qrInfo"></param>
        /// <param name="productName"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        public static Image CreateQRCodeImage(string qrInfo, string productName, string version)
        {
            try
            {
                if (!string.IsNullOrEmpty(qrInfo))
                {
                    QRCodeEncoder encoder = new QRCodeEncoder
                    {
                        QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
                        QRCodeScale = 4,
                        QRCodeVersion = 0,
                        QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M
                    };
                    //Coding mode(Be careful: BYTE Can support Chinese, ALPHA_NUMERIC The scans are all numbers.)
                    //Size(The bigger the value, the higher the pixel of the two-dimensional code picture)
                    //Edition(Note: Setting to 0 prevents errors when encoding strings too long)
                    //Error Effect, Error Correction(There are four levels)

                    Image image = encoder.Encode(qrInfo, Encoding.GetEncoding("utf-8"));
                    string filename = $"{productName}_{version}.png";
                    var userLocalPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
                    var docPath = Path.Combine(userLocalPath, @"YourProduct\QRCode");
                    if (!Directory.Exists(docPath))
                    {
                        Directory.CreateDirectory(docPath);
                    }
                    string filepath = Path.Combine(docPath, filename); 
                    using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        image.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
                        fs.Close();
                        image.Dispose();
                    }
                    return image;
                }
            }
            catch (Exception)
            {
                return null;
            }
            return null;
        }

 

In this way, a two-dimensional code is generated. In other words, the api of a service is changed from a string into a picture. When the user uses Alipay app to sweep the two-dimensional code, it will ask the api:

"Http://xxx.xxx.com/AlipayForProduct/SendInfoToAlipay? Order number="+$"{orderNumber}"; (orderNumber is the merchant order number)

        public string SendInfoToAlipay()
        {
            string orderNumber = Request["orderNumber"];
            if (!string.IsNullOrEmpty(orderNumber))
            {
                var matchedItem = db.OrderInfoForProduct.FirstOrDefault(x => x.OrderNumber == orderNumber); //Verify that the merchant server backend has this order
                if (matchedItem != null && matchedItem.IsPaid == false)
                {
                    //Common parameter
                    var alipayServerURL = "https://openapi.alipay.com/gateway.do";
                    var app_id = appID;
                    var privateKeyPem = applicationPrivateKey;
                    var format = "json";
                    var version = "1.0";
                    var signType = "RSA2";

                    //Request parameters
                    var out_trade_no = orderNumber; //Merchant Order Number
                    var product_code = "FAST_INSTANT_TRADE_PAY"; //Sales product code
                    var total_amount = "Your Money";  //Total order amount
                    var subject = "Your Title"; //Order title
                    var body = "Your Body"; //Order description

                    IAopClient client = new DefaultAopClient(
                        alipayServerURL,
                        app_id,
                        privateKeyPem,
                        format,
                        version,
                        signType);

                    var returnurl = $"http://xxx.xxx.com/AlipayForProduct/AlipayResult";
                    var notifyurl = $"http://xxx.xxx.com/AlipayForProduct/UpdatePayStatus";
AlipayTradeWapPayRequest requestWap
= new AlipayTradeWapPayRequest { BizContent = "{" + " \"body\":\"" + body + "\"," + " \"subject\":\"" + subject + "\"," + " \"out_trade_no\":\"" + out_trade_no + "\"," + " \"total_amount\":" + total_amount + "," + " \"product_code\":\"" + product_code + "\"" + " }" }; requestWap.SetNotifyUrl(notifyurl); //Asynchronous request requestWap.SetReturnUrl(returnurl); //Synchronous request AlipayTradeWapPayResponse responseWap = client.pageExecute(requestWap); string divNone = "<div style='display:none'>" + responseWap.Body + "</div>"; return divNone; } } return string.Empty; }

 

Asynchronous requests generally need to do a few things:

  1. After the user scan code is paid, the background information of Alipay will send you all the information you need to verify, except that one parameter does not need to be signed, and the rest needs to be checked.
  2. If the signature is successful and the payment status is also successful, you need to update the status of the merchant server background about this merchant order, such as changing its payment status to paid, filling the payment time, etc.
        /// <summary>
        /// callback
        /// </summary>
        [HttpPost]
        public void UpdatePayStatus()
        {
            SortedDictionary<string, string> sPara = GetRequestPost();

            if (sPara.Count > 0)
            {
                //Non-checking parameters
                var sign_type = Request.Form["sign_type"];

                //Receive parameters and sort them
                var seller_id = Request.Form["seller_id"]; //Seller Alipay user number
                var trade_status = Request.Form["trade_status"]; //Trading status
                var notify_time = Request.Form["notify_time"]; //Notification time
                var app_id = Request.Form["app_id"]; //developer AppId
                var out_trade_no = Request.Form["out_trade_no"]; //Transaction Order Number
                var total_amount = Request.Form["total_amount"]; //Order amount
                var receipt_amount = Request.Form["receipt_amount"]; //Amount received
                var invoice_amount = Request.Form["invoice_amount"]; //Amount of invoice
                var buyer_pay_amount = Request.Form["buyer_pay_amount"]; //Payment amount
                var body = Request.Form["body"]; //Commodity Description
                var gmt_payment = Request.Form["gmt_payment"]; //Transaction Payment Time

                var tradeGuid = new Guid(out_trade_no);
                //Check sign
                try
                {
                    var isVerfied = AlipaySignature.RSACheckV1(sPara, alipayPublicKey, "utf-8", sign_type, false);
                    if (isVerfied)
                    {
                        if (app_id == appID && seller_id == sellerID)
                        {                          var isTradeSuccess = string.Equals(trade_status, "TRADE_SUCCESS") || string.Equals(trade_status, "TRADE_FINISHED");
                            if (isTradeSuccess)
                            {
                                //Business Verification Logic and Data Update Logic
                            }
                        }
                    }
                }
                catch (Exception)
                {
                   
                }
            }
            else
            {
                
            }
        }

/// <summary>
        /// Parametric Sorting Dictionary
        /// </summary>
        /// <returns></returns>
        private SortedDictionary<string, string> GetRequestPost()
        {
            SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
            NameValueCollection coll = Request.Form;
            String[] requestItem = coll.AllKeys;
            foreach (string t in requestItem)
            {
                sArray.Add(t, Request.Form[t]);
            }
            return sArray;
        }

          

Synchronization requests typically require several things:

1. When the asynchronous call is completed, if the payment is successful and the order number is processed correctly by the merchant server background, the synchronous request can be validated again.

2. If the verification is successful, jump the Payment Success Page; if it fails, jump the Payment Failure Page.

        public ActionResult AlipayResult()
        {
            SortedDictionary<string, string> sPara = GetRequestGet();
            if (sPara.Count > 0)
            {
                //Non-checking parameters
                var sign_type = Request.QueryString["sign_type"];

                //Receive parameters and sort them
                var seller_id = Request.QueryString["seller_id"]; //Seller Alipay user number
                var app_id = Request.QueryString["app_id"]; //developer AppId
                var out_trade_no = Request.QueryString["out_trade_no"]; //Transaction Order Number

                var orderNumberGuid = new Guid(out_trade_no);
                try
                {
                    var isVerfied = AlipaySignature.RSACheckV1(sPara, alipayPublicKey, "utf-8", sign_type, false);
                    if (isVerfied)
                    {
                        if (app_id == appID && seller_id == sellerID)
                        {
                           //Your Payment Success Page
                        }
                    }

                }
                catch
                {
                   //Your Payment Failure Page
                }
            }
            else
            {
               //Your Payment Failure Page
            }
            return View();
        }

        /// <summary>
        /// Parametric Sorting Dictionary
        /// </summary>
        /// <returns></returns>
        private SortedDictionary<string, string> GetRequestGet()
        {
            SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
            NameValueCollection coll = Request.QueryString;

            String[] requestItem = coll.AllKeys;

            foreach (string t in requestItem)
            {
                sArray.Add(t, Request.QueryString[t]);
            }
            return sArray;
        }

 

Four, ending

WPF has been my major since I joined the work. It's interesting to do the Web occasionally.

Keywords: C# encoding QRCode Windows Mobile

Added by stargate03 on Wed, 22 May 2019 22:18:15 +0300