我封装了,下单接口怎么调用?https://api.mch.weixin.qq.com/pay/unifiedorder,谁有源码可以参考?
public UnifiedOrderResponseModel UnifiedOrder(UnifiedOrderReqeustModel model) { return Client.PostAsync(ApiUrl.UnifiedOrder, new StringContent(model.ToXml(), System.Text.Encoding.UTF8, "application/xml")) .Result .Content .ReadAsStringAsync() .Result .XmlDeserialize<UnifiedOrderResponseModel>(); }
/// <summary> /// APP支付统一下单接口实体 /// </summary> [DataContract(Name = "xml", Namespace = "", IsReference = true)] [XmlRoot(ElementName = "xml", Namespace = "", IsNullable = false)] [XmlType(AnonymousType = true)] public class UnifiedOrderReqeustModel { /// <summary> 公众账号 ID /// 微信分配的公众账号 ID /// </summary> [XmlElement(ElementName = "appid")] [DataMember(Name = "appid", IsRequired = false)] public string AppId { get; set; } /// <summary> 商户号 /// 微信分配的公众账号 ID /// </summary> [XmlElement(ElementName = "mch_id", IsNullable = false)] [DataMember(Name = "mch_id", IsRequired = false)] public string MchId { get; set; } /// <summary> 附加信息 /// 终端设备号(商户自定义) /// </summary> [XmlElement(ElementName = "device_info", IsNullable = false)] [DataMember(Name = "device_info", IsRequired = false)] public string DeviceInfo { get; set; } /// <summary> 随机字符串 /// 不长于32位 /// </summary> [XmlElement(ElementName = "nonce_str", IsNullable = false)] [DataMember(Name = "nonce_str", IsRequired = false)] public string NonceStr { get; set; } /// <summary> 商品描述 </summary> [XmlElement(ElementName = "body", IsNullable = false)] [DataMember(Name = "body", IsRequired = false)] public string Body { get; set; } /// <summary> 商品描述 </summary> [XmlElement(ElementName = "detail", IsNullable = false)] [DataMember(Name = "detail", IsRequired = false)] public string Detail { get; set; } /// <summary> 附加数据 /// 附加数据,原样返回 /// </summary> [XmlElement(ElementName = "attach", IsNullable = false)] [DataMember(Name = "attach", IsRequired = false)] public string Attach { get; set; } /// <summary> 商户订单号 /// 商户系统内部的订单号,32 个字符内、可包含字母, 确保在商户系统唯一 /// 商户支付的订单号由商户自定义生成,微信支付要求商户订单号保持唯一性(建议根据当前系统时间加随机序列来生成订单号)。 /// 重新发起一笔支付要使用原订单号,避免重复支付;已支付过或已调用关单、撤销(请见后文的API列表)的订单号不能重新发起支付。 /// </summary> [XmlElement(ElementName = "out_trade_no", IsNullable = false)] [DataMember(Name = "out_trade_no", IsRequired = false)] public string OutTradeNo { get; set; } /// <summary> /// 符合ISO 4217标准的三位字母代码,默认人民币:CNY /// </summary> [XmlElement(ElementName = "fee_type", IsNullable = false)] [DataMember(Name = "fee_type", IsRequired = false)] public FeeType FeeType { get; set; } /// <summary> 订单总额 /// 订单总金额,单位为分,只能 整数 /// </summary> [XmlElement(ElementName = "total_fee", IsNullable = false)] [DataMember(Name = "total_fee", IsRequired = false)] public int TotalFee { get; set; } /// <summary> 终端IP /// 订单生成的机器IP /// </summary> [XmlElement(ElementName = "spbill_create_ip", IsNullable = false)] [DataMember(Name = "spbill_create_ip", IsRequired = false)] public string SpbillCreateIp { get; set; } [XmlElement(ElementName = "time_start", IsNullable = false)] [DataMember(Name = "time_start", IsRequired = false)] public string time_start { get; set; } /// <summary> 订单生成时间 /// 格式为 yyyyMMddHHmmss,如 2009 年 12月 25日 9 点 10 分 10 秒 /// 表示为 20091225091010。时 区为 GMT+8beijing。该时间取 自商户服务器 /// </summary> [IgnoreDataMember] public DateTime TimeStart { set { time_start = value.ToString("yyyyMMddHHmmss"); } } [XmlElement(ElementName = "time_expire", IsNullable = false)] [DataMember(Name = "time_expire", IsRequired = false)] public string time_expire { get; set; } /// <summary>订单失效时间 /// 格式为 yyyyMMddHHmmss,如 2009 年 12月 27日 9 点 10 分 10 秒 表示为 20091227091010。 /// 时 区为 GMT+8beijing。该时间取 自商户服务器 /// </summary> [XmlIgnore] [IgnoreDataMember] public DateTime TimeExpire { set { time_expire = value.ToString("yyyyMMddHHmmss"); } } /// <summary> 商品标记 /// 商品标记,微信平台配置的商 品标记,用于优惠券或者满减 使用,使用说明详见第 3 节 /// </summary> [XmlElement(ElementName = "goods_tag", IsNullable = false)] [DataMember(Name = "goods_tag", IsRequired = false)] public string GoodsTag { get; set; } /// <summary> 商品标记 /// 商品标记,微信平台配置的商 品标记,用于优惠券或者满减 使用,使用说明详见第 3 节 /// </summary> [XmlElement(ElementName = "notify_url", IsNullable = false)] [DataMember(Name = "notify_url", IsRequired = false)] public string NotifyUrl { get; set; } /// <summary> /// 订单类型,取值如下:JSAPI,NATIVE,APP,详细说明见 /// </summary> [XmlElement(ElementName = "trade_type", IsNullable = false)] [DataMember(Name = "trade_type", IsRequired = false)] public TradeType TradeType { set; get; } /// <summary> /// trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。 /// </summary> [XmlElement(ElementName = "product_id", IsNullable = false)] [DataMember(Name = "product_id", IsRequired = false)] public string ProductId { get; set; } /// <summary> /// trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。 /// 下单前需要调用【网页授权获取用户信息】接口获取到用户的Openid。 /// </summary> [XmlElement(ElementName = "openid", IsNullable = false)] [DataMember(Name = "openid", IsRequired = false)] public string OpenId { get; set; } /// <summary> /// 商户Key /// </summary> [IgnoreDataMember] [XmlIgnore] public string Key { get; set; } /// <summary> 签名 /// 由于数据中携带了生成订单的详细信息,因此在微信将对数据里面的内容进行鉴权, /// 确定携带的信息是真实、有效、合理的。因此,这里将定义生成sign字符串的方法。 /// a.对所有传入参数按照字段名的ASCII码从小到大排序(字典序)后, /// 使用URL键 值对的格式(即key1=value1&key2=value2…)拼接成字符串string1, /// 注意:值为空的 参数不参与签名; /// b.在string1最后拼接上key=paternerKey 得到stringSignTemp字符串, /// 并对 stringSignTemp进行md5运算,再将得到的字符串所有字符转换为大写,得到sign值 signValue。 /// </summary> [XmlElement(ElementName = "sign", IsNullable = false)] [DataMember(Name = "sign", IsRequired = false)] public string Sign { get { var list = new[] { new NameValue<string> {Name="appid",Value=AppId}, new NameValue<string> {Name="mch_id",Value=MchId}, new NameValue<string> {Name="device_info",Value=DeviceInfo}, new NameValue<string> {Name="nonce_str",Value=NonceStr}, new NameValue<string> {Name="body",Value=Body}, new NameValue<string> {Name="detail",Value=Detail}, new NameValue<string> {Name="attach",Value=Attach}, new NameValue<string> {Name="out_trade_no",Value=OutTradeNo}, new NameValue<string> {Name="fee_type",Value=this.FeeType.ToString()}, new NameValue<string> {Name="total_fee",Value=TotalFee.ToString()}, new NameValue<string> {Name="spbill_create_ip",Value=SpbillCreateIp}, new NameValue<string> {Name="time_start",Value=time_start}, new NameValue<string> {Name="time_expire",Value=time_expire}, new NameValue<string> {Name="goods_tag",Value=GoodsTag}, new NameValue<string> {Name="notify_url",Value=NotifyUrl}, new NameValue<string> {Name="trade_type",Value=this.TradeType.ToString().ToUpper()}, new NameValue<string> {Name="product_id",Value=this.ProductId}, new NameValue<string> {Name="openid",Value=OpenId}, }; var str = list .Where(m => !m.Value.IsNullOrWhiteSpace()) .OrderBy(m => m.Name) .Select(m => "{0}={1}".FormatExt(m.Name, m.Value)) .Concat(new[] { "key=" + Key }) .JoinStr("&"); return str .MD5Default() .ToUpper(); } set { } } } [XmlRoot(ElementName = "xml", Namespace = "", IsNullable = false)] [XmlType(AnonymousType = true)] public class UnifiedOrderResponseModel { /// <summary> /// SUCCESS/FAIL /// 此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断 /// </summary> [XmlElement("return_code")] public ReturnCode ReturnCode { get; set; } [XmlElement("return_msg")] public string ReturnMsg { get; set; } /// <summary> 公众账号 ID /// 微信分配的公众账号 ID /// </summary> [XmlElement("appid")] public string AppId { get; set; } [XmlElement("mch_id")] public string MchId { get; set; } [XmlElement("device_info")] public string DeviceInfo { get; set; } [XmlElement("nonce_str")] public string NonceStr { get; set; } [XmlElement("sign")] public string Sign { get; set; } [XmlElement("result_code")] public ReturnCode ResultCode { get; set; } [XmlElement("err_code")] public ErrorCode ErrCode { get; set; } /// <summary> /// 错误返回的信息描述 /// </summary> [XmlElement("err_code_des")] public string ErrCodeDes { get; set; } /// <summary> /// 订单类型,取值如下:JSAPI,NATIVE,APP,详细说明见 /// </summary> [XmlElement("trade_type")] public TradeType TradeType { get; set; } /// <summary> /// 微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时 /// </summary> [XmlElement("prepay_id")] public string PrepayId { get; set; } /// <summary> /// trade_type为NATIVE是有返回,可将该参数值生成二维码展示出来进行扫码支付 /// </summary> [XmlElement("code_url")] public string CodeUrl { get; set; } /// <summary> /// 校验签名是否正确 /// </summary> /// <param name="key">商家密钥</param> /// <returns></returns> public bool CheckSign(string key) { var list = new[] { new NameValue<string> {Name="return_code",Value=ReturnCode.ToString().ToUpper()}, new NameValue<string> {Name="return_msg",Value=ReturnMsg}, new NameValue<string> {Name="appid",Value=AppId}, new NameValue<string> {Name="mch_id",Value=MchId}, new NameValue<string> {Name="device_info",Value=DeviceInfo}, new NameValue<string> {Name="nonce_str",Value=NonceStr}, new NameValue<string> {Name="result_code",Value=ResultCode.ToString().ToUpper()}, new NameValue<string> {Name="err_code",Value=ErrCode.ToString().ToUpper()}, new NameValue<string> {Name="err_code_des",Value=ErrCodeDes}, new NameValue<string> {Name="trade_type",Value=TradeType.ToString().ToUpper()}, new NameValue<string> {Name="prepay_id",Value=PrepayId}, new NameValue<string> {Name="code_url",Value=CodeUrl} }; var str = list .Where(m => !m.Value.IsNullOrWhiteSpace()) .OrderBy(m => m.Name) .Select(m => "{0}={1}".FormatExt(m.Name, m.Value)) .Concat(new[] { "key=" + key }) .JoinStr("&"); return str .MD5Default() .ToUpper() == Sign; } }
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.Timeout = timeout * 1000;
//设置POST的数据类型和长度
request.ContentType = "text/xml";
byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
request.ContentLength = data.Length;
//往服务器写入数据
reqStream = request.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
//获取服务端返回
response = (HttpWebResponse)request.GetResponse();
//获取服务端返回数据
StreamReader sr = new StreamReader(response.GetResponseStream(),Encoding.GetEncoding("gb2312"));
result = sr.ReadToEnd().Trim();
sr.Close(); 我这样post数据怎么返回的是乱码是怎么回事?
@泡沫_之夏: 乱码都是因为编码格式原因.一个不行就换一个.
@吴瑞祥: 恩,改过来了,现在是签名错误。
@泡沫_之夏: 我用官网生成的xml发送,怎么也是返回签名错误,这个商户key,是商户平台登录的密码没错吧?
@泡沫_之夏: 签名封装错了。已解决。还是谢谢啊。
我调用接口的时候报错:
远程服务器返回错误: (404) 未找到。
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
这是什么原因啊?代码:
public static string HttpPost(string url, string data)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "text/xml";
//request.ContentType = "application/x-www-form-urlencoded";
//request.ContentLength = Encoding.UTF8.GetByteCount(data);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data); // 编码形式按照个人需求来设置
request.ContentLength = bytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return retString;
}
@lsboke: 别用这个东西,用webapiclient吧.那个方便.