首先不得不吐槽下腾讯,升级微信支付为毛不兼容V2版本呢?V2算是白研究了。


V3预支付文档几个坑,不知道你们有没有中招

  1. 商户号 mch_id 是 String(32) 微信支付分配的商户号   其实是邮件的“微信支付商户号(接口文档中的商户号MCHID)” ,我一直都以为是商户号。
  2. 预支付提交的xml节点值都必须带有<![CDATA[]]>,如果根据文档开发只带部分。那么你就开心了,一直都是sign签名错误。

回到正文,以下为实现代码

public class PaymentHandler : RequestHandler
{ public PaymentHandler(HttpContext context)
: base(context, WX_V3_CONFIG.config.PartnerKey)
{ } /// <summary>
/// 获取预支付订单号
/// </summary>
/// <returns></returns>
public string GetUnifiedOrder(string body, string openid, string trade_type)
{ base.setParameter("appid", WX_V3_CONFIG.config.AppID);
base.setParameter("mch_id", WX_V3_CONFIG.config.MCHID);
base.setParameter("nonce_str", TenpayUtil.getNoncestr());
base.setParameter("body", body);
base.setParameter("out_trade_no", TenpayUtil.getOrderNo());
base.setParameter("total_fee", "");
base.setParameter("spbill_create_ip", "192.168.1.1");//base.httpContext.Request.UserHostAddress);
base.setParameter("notify_url", "www.111.com");
base.setParameter("trade_type", "JSAPI");
base.setParameter("openid", openid);
base.createSign(); string s = HttpHelper.OpenReadWithHttps("https://api.mch.weixin.qq.com/pay/unifiedorder", base.parseXML());//post请求 return "";
}
}

RequestHandler帮助类

/// <summary>
/// RequestHandler 的摘要说明。
/// </summary>
public class RequestHandler
{ public RequestHandler(HttpContext httpContext, string key)
{
parameters = new Hashtable();
this.key = key;
this.httpContext = httpContext; }
/** 密钥 */
private string key; protected HttpContext httpContext; /** 请求的参数 */
protected Hashtable parameters; /** debug信息 */
private string debugInfo; /** 初始化函数 */
public virtual void init()
{
}
/** 获取debug信息 */
public String getDebugInfo()
{
return debugInfo;
}
/** 获取密钥 */
public String getKey()
{
return key;
} /** 设置密钥 */
public void setKey(string key)
{
this.key = key;
} /** 设置参数值 */
public void setParameter(string parameter, string parameterValue)
{
if (parameter != null && parameter != "")
{
if (parameters.Contains(parameter))
{
parameters.Remove(parameter);
} parameters.Add(parameter, parameterValue);
}
} /** 获取参数值 */
public string getParameter(string parameter)
{
string s = (string)parameters[parameter];
return (null == s) ? "" : s;
} //获取package带参数的签名包
public string getRequestURL()
{
this.createSign();
StringBuilder sb = new StringBuilder();
ArrayList akeys = new ArrayList(parameters.Keys);
akeys.Sort();
foreach (string k in akeys)
{
string v = (string)parameters[k];
if (null != v && "key".CompareTo(k) != )
{
sb.Append(k + "=" + TenpayUtil.UrlEncode(v, getCharset()) + "&");
}
} //去掉最后一个&
if (sb.Length > )
{
sb.Remove(sb.Length - , );
} return sb.ToString(); } //创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 protected virtual void createSign()
{
StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys);
akeys.Sort(); foreach (string k in akeys)
{
string v = (string)parameters[k];
if (null != v && "".CompareTo(v) !=
&& "sign".CompareTo(k) != && "key".CompareTo(k) != )
{
sb.Append(k + "=" + v + "&");
}
} sb.Append("key=" + this.getKey());
string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper(); this.setParameter("sign", sign); //debug信息
this.setDebugInfo(sb.ToString() + " => sign:" + sign);
} //创建package签名
public virtual string createMd5Sign()
{
StringBuilder sb = new StringBuilder();
ArrayList akeys = new ArrayList(parameters.Keys);
akeys.Sort(); foreach (string k in akeys)
{
string v = (string)parameters[k];
if (null != v && "".CompareTo(v) !=
&& "sign".CompareTo(k) != && "".CompareTo(v) != )
{
sb.Append(k + "=" + v + "&");
}
}
string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToLower(); this.setParameter("sign", sign);
return sign;
} //创建sha1签名
public string createSHA1Sign()
{
StringBuilder sb = new StringBuilder();
ArrayList akeys = new ArrayList(parameters.Keys);
akeys.Sort(); foreach (string k in akeys)
{
string v = (string)parameters[k];
if (null != v && "".CompareTo(v) !=
&& "sign".CompareTo(k) != && "key".CompareTo(k) != )
{
if (sb.Length == )
{
sb.Append(k + "=" + v);
}
else
{
sb.Append("&" + k + "=" + v);
}
}
}
string paySign = SHA1Util.getSha1(sb.ToString()).ToString().ToLower(); //debug信息
this.setDebugInfo(sb.ToString() + " => sign:" + paySign);
return paySign;
} //输出XML
public string parseXML()
{
StringBuilder sb = new StringBuilder();
sb.Append("<xml>");
foreach (string k in parameters.Keys)
{
string v = (string)parameters[k];
if (Regex.IsMatch(v, @"^[0-9.]$"))
{ sb.Append("<" + k + ">" + v + "</" + k + ">");
}
else
{
sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">");
} }
sb.Append("</xml>");
return sb.ToString();
} /** 设置debug信息 */
public void setDebugInfo(String debugInfo)
{
this.debugInfo = debugInfo;
} public Hashtable getAllParameters()
{
return this.parameters;
} protected virtual string getCharset()
{
return this.httpContext.Request.ContentEncoding.BodyName;
}
}

V3 微信支付-预支付C#的更多相关文章

  1. V3微信支付开发笔录

    真是坑爹啊,微信支付到处都是坑,一不小心就栽里面了, 文档也不怎么全,经过一周的奋斗终于把微信支付功能搞定,在此写下自己当时走入的误区和一些需要注意的地方,希望后边开发的朋友们可以少走弯路,少被微信坑 ...

  2. 微信扫码支付 php

    仔细看了一遍官方的那幅流程图,我来简化理解一下(注意:我这里针对的是扫码支付模式一,模式二没什么说的)网站后台生成二维码,当然是跟据前台传来的参数有条件的生成买家扫描二维码,扫描过程中,微信后台系统回 ...

  3. 微信公众号支付(三):页面调用微信支付JS并完成支付

    一.调用微信的JS文件 1.首先要绑定[JS接口安全域名],“公众号设置”的“功能设置”中 2.引入JS文件 备注:支持使用 AMD/CMD 标准模块加载方法加载 <script type=&q ...

  4. 微信小程序支付步骤

    http://blog.csdn.net/wangsf789/article/details/53419781 最近开发微信小程序进入到支付阶段,一直以来从事App开发,所以支付流程还是熟记于心的.但 ...

  5. 微信公众号支付开发全过程 --JAVA

    按照惯例,开头总得写点感想 ------------------------------------------------------------------ 业务流程 这个微信官网说的还是很详细的 ...

  6. Java 后端微信小程序支付demo (网上说的坑里面基本上都有)

    Java 后端微信小程序支付 一.遇到的问题 1. 商户号该产品权限未开通,请前往商户平台>产品中心检查后重试 2.签名错误 3.已经调起微信统一下单接口,可以拿到预支付ID,但是前端支付的时候 ...

  7. php对接微信小程序支付

    前言:这里我就假装你已经注册了微信小程序,并且基本的配置都已经好了.注: 个人注册小程序不支持微信支付,所以我还是假装你是企业或者个体工商户的微信小程序,其他的商户号注册,二者绑定,授权,支付开通,就 ...

  8. java微信公众号支付示例

    开始之前,先准备好:appid.商家号.商户密匙. 工具类: MD5Util.java package com.yiexpress.core.utils.wechat; import java.sec ...

  9. java版微信公众号支付(H5调微信内置API)

    最近需要做微信公众号支付,网上找了大堆的代码,大多都只说了个原理,自己踩了太多坑,所有的坑,都会再下面的文章中标注,代码我也贴上最全的(叫我雷锋)!!! 第一步:配置支付授权目录 你需要有将你公司的微 ...

随机推荐

  1. 蓝桥网试题 java 基础练习 十六进制转八进制

    - -------------------------------------------------------------------------------------------------- ...

  2. AR_Demon(使用vuforia平台提供的钥匙跟后台,实现相机拍图片读取模型以及视频的功能)

    1.https://developer.vuforia.com注册账号. 2.分别添加License Manager(连接钥匙),Target Manager(图片后台下载). 3.下载vuforia ...

  3. mysql常用语法

    创建表 create table <表名>( <字段名>  类型(长度) not null primary key auto_increment, **主键 name char ...

  4. JavaScript截取字符串的Slice、Substring、Substr函数简单比较还有indexof函数应用

    //截取字符,一看就明白!!! var str = "0123456789"; alert(str.substring(5)); 弹出 //56789 alert(str.subs ...

  5. C#基础笔记1

    1>>数据类型: Int double:小数 char:字符型,只能存储一个字符,并且存储的这个字符要用单引号引起来.如:'a'; string:字符串,可以储存多个字符,用双引号引起来( ...

  6. Java之路——敬JAVA初学者(作者:MoMo)

    作为一名大四的毕业生,大学三年过,有得有失.作为一个喜欢编程,喜欢JAVA的人,自学其实是一件美事,很有意思的事.要是能再找个女朋友一起学.嘿嘿,就不枉在大学走了一遭啊!    要离开学校了,还是想留 ...

  7. 纪中集训 Day 3

    这几天一直坚持写blog= =加油吧!! 早上醒来,说了"我要AK"(其实只是蒟蒻的妄想罢了QAQ) 然后为了不立flag,改成了我要rank 1 然后依旧是有一题不会做QAQ 好 ...

  8. react-router 中的history(react中关于后退键的处理用的到)

    react-router 中的history react-router 是建立在history之上的:我们来谈谈这个history吧. github: mjackson/history history ...

  9. centos7搭建nexus maven私服

    前置条件: 1.安装jdk,可参考 http://www.cnblogs.com/grey-wolf/p/6480489.html 2.nexus仓库管理器,分为两个版本,Nexus Reposito ...

  10. js方法提纲

    Math.random() 日期时间函数(需要用变量调用):var b = new Date(); //获取当前时间b.getTime() //获取时间戳b.getFullYear() //获取年份b ...