Abp.WeChat 微信支付

关于使用Abp.WeChat的记录

官方文档其实写的很清楚了 但是因为是小白第一次做,还是有很多读不懂的地方 下面做一个简单的记录

官方地址:https://github.com/EasyAbp/Abp.WeChat
官方使用说明:https://github.com/EasyAbp/Abp.WeChat/blob/master/docs/WeChatPay.md

微信支付:后端所需要的工作

1 前端访问支付用户同意授权,获取code,有两种情况:

(1)snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
(2)授权成功后,页面将跳转至 redirect_uri/?code=CODE&state=STATE
(3)此时前端将获取的code上送给后台

2 后台通过code获取openid

 public static string getopenid(string code)
        {
            string strJson = " ";
            string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx75550f6c7370fbc7&secret=41051f79b41945423195c72d3df54131&code=" + code + "&grant_type=authorization_code";

            //获取openid
            // //// 链接地址
            ////https://open.weixin.qq.com/connect/oauth2/authorize?appid=11111111111111111111111111111&redirect_uri=22222222222222222&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 
            //int id = Convert.ToInt32(Request.QueryString["ID"]);
            //string code = Request["code"].ToString();
            string html = string.Empty;
            //string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=11111111111111111111111111111111111&secret=2222222222222222222222228&code=" + code + "&grant_type=authorization_code";
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Method = "GET";
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            Stream ioStream = response.GetResponseStream();
            StreamReader sr = new StreamReader(ioStream, Encoding.UTF8);
            html = sr.ReadToEnd();
            sr.Close();
            ioStream.Close();
            response.Close();

            string key = "\"openid\":\"";
            int startIndex = html.IndexOf(key);
            if (startIndex != -1)
            {
                int endIndex = html.IndexOf("\",", startIndex);
                string openid = html.Substring(startIndex + key.Length, endIndex - startIndex - key.Length);
                //MyOpenId.Value=openid;
                return openid;

            }
            else
            {
                return "找不到OpenidID";
            }
        }

3 获取openid后,后台进行统一下单(我是叫前端直接传code和金额,后台获取penid后直接统一下单,把这两步放在了一个接口里面)

      [HttpGet]
        public async Task<UnifiedOrderResultDto> UnifiedOrder([FromQuery] UnifiedOrderDto input)
        {
            //元转分
            int money = int.Parse((input.Money * 100).ToString("0"));

            //
            string openid = GetOpenId.getopenid(input.Code);
            if (openid == "找不到OpenidID")
            {
                //return null;
                throw new ArgumentException($"当交易类型为 JsApi 时,参数 {nameof(openid)} 必须传递有效值。");
            }
            //订单号(当前时间和随机数)
            var ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            var times = Convert.ToInt64(ts.TotalSeconds).ToString();
            Random rd = new Random();
            var num = rd.Next().ToString();
            var OrderNum = times + num;

            var result = _ordinaryMerchantPayService.UnifiedOrderAsync(
        "你的 AppId",
        "你的商户 Id",
        "订单的描述信息",
        "附加数据",
        OrderNum,//"20150806125346",//"订单号", 订单号需要你自己生成,长度不超过 32 位。
        money, // 支付金额,单位是分。
        TradeType.JsApi,// 交易类型。
        openid//你的openId
        ).Result;

            var str = result.OuterXml;

            //加个判断 是成功还是失败
            string[] sArray1 = str.ToString().Split(new string[] { "<return_code><![CDATA[", "]]></return_code>" }, StringSplitOptions.RemoveEmptyEntries);
            if(sArray1[1]== "FAIL")
            {
                throw new ArgumentException($"当交易类型为 JsApi 时,统一下单失败。");
            }
            //成功 //截取id
            string[] sArray = str.Split(new string[] { "<prepay_id><![CDATA[", "]]></prepay_id>" }, StringSplitOptions.RemoveEmptyEntries);
            //返回值
            UnifiedOrderResultDto dto = new UnifiedOrderResultDto();
            dto.appId = "你的 AppId";
            dto.prepayId = sArray[1];
            return dto;
        }

对应的实体:

 public class UnifiedOrderDto
    {
        public string Code { get; set; }
        public double Money { get; set; }
    }

 public class UnifiedOrderResultDto
    {
        public string appId { get; set; }
        public string prepayId { get; set; }
    }

4 通过统一下单可以获取到预支付id(prepayId),通过ABP.WECHAT的原生接口/wechatpay/wechat-pay/js-sdk-config-parameters,获取签名及前端调起支付所需的参数

返回值:


图片.png

5 前端根据官方文档进行JSAPI调起支付

6 支付完成

所遇到的问题:

1 配置文件要匹配对,否则会报签名匹配失败的错误


图片.png

2 订单号,code,随机数之类的值, 每一次都必须是新的不能重复使用,会报错

3 接口和发布都得在80端口下,接口我们是读的域名

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容