仅供学习参考:大神勿喷 (微信的文档真的很烂 其实很多东西都不是很复杂 ,
日志什么的没有加 ,可以自己随心来写 简单的demo 比较容易理解 理解了以后复杂的东西再加上去
先决条件
内网转发工具(可以自己找一下或者自己搭建一个frp 有教程 传送)
商户系统和微信支付系统主要交互:
1、商户server调用统一下单接口请求订单,api参见公共api【统一下单API】
2、商户server接收支付通知,api参见公共api【支付结果通知API】
3、商户server查询支付结果,api参见公共api【查询订单API】
HttpUtil 工具类
/// <summary>
/// Get访问
/// </summary>
/// <param name="Url"></param>
/// <returns></returns>
public static string HttpGet(string Url)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync(Url).Result;
string responseBody = response.Content.ReadAsStringAsync().Result;
return responseBody;
}
/// <summary>
/// Post访问提交Json
/// </summary>
/// <param name="Url">Api地址</param>
/// <returns></returns>
public static string HttpPost(string Url, string xml)
{
byte[] postData = Encoding.UTF8.GetBytes(xml);
WebClient wc = new WebClient();
wc.Headers.Add("Content-Type", "text/xml");
byte[] responseData = wc.UploadData(Url, "POST", postData);//得到返回字符
return Encoding.UTF8.GetString(responseData);
}
JSAPI (统一下单 )文档传送门(参照文档一起编码有些文档有的就不放出来了)
首先看配置文件 Config.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Model;
using BLL;
using System.Web.Services;
using System.EnterpriseServices;
public static string _Domain = "http://wxpay.***.*.com";//域名
public static string OrderRefund_Url = _Domain + "/ResultNotify/refund_notify";
/** * 支付完成后的异步回调 */
public static string Notify_Url = _Domain + "/ResultNotify/notify";
/** 微信统一下单url */
public static string UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
/** 微信申请退款url */
public static string REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
/** 微信交易类型:公众号支付 */
public static string TRADE_TYPE_JSAPI = "JSAPI";
/** 微信交易类型:原生扫码支付 */
public static string TRADE_TYPE_NATIVE = "NATIVE";
private static string AppID = ""//appid
public static string Authorization(string data)
{
return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + AppID + "&redirect_uri=" + _Domain + "%2FAuthorized%2Fcode&response_type=code&scope=snsapi_base&state=" +data + "#wechat_redirect";
}
public string getAppID()
{
// return //appid
}
public string getMchID()
{
// return 商户号-普通商户
}
public string getKey()
{
// return 密钥
}
//LOG 显示级别
public int GetLogLevel()
{
return 1;
}
具有可扩展性的工具类(可直接复制使用)
/// 下面类里面会用到
public class SafeXmlDocument:XmlDocument
{
public SafeXmlDocument()
{
this.XmlResolver = null;
}
}
随机数生成类
using System;
using System.Security;
using System.Security.Cryptography;
public class RandomGenerator
{
public uint GetRandomUInt()
{
var randomBytes = GenerateRandomBytes(sizeof(uint));
return BitConverter.ToUInt32(randomBytes, 0);
}
private byte[] GenerateRandomBytes(int bytesNumber)
{
byte[] buffer = new byte[bytesNumber];
csp.GetBytes(buffer);
return buffer;
}
}
using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
using System.Security.Cryptography;
using System.Text;
using WxService.WXPay.Config;
using LitJson;
using System.Linq;
using System.Web.Security;
public class WxPayData
{
public const string SIGN_TYPE_MD5 = "MD5";
public const string SIGN_TYPE_HMAC_SHA256 = "HMAC-SHA256";
public WxPayData()
{
}
//采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序
private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();
/**
* 设置某个字段的值
* @param key 字段名
* @param value 字段值
*/
public void SetValue(string key, object value)
{
m_values[key] = value;
}
/**
* 根据字段名获取某个字段的值
* @param key 字段名
* @return key对应的字段值
*/
public object GetValue(string key)
{
object o = null;
m_values.TryGetValue(key, out o);
return o;
}
/**
* 判断某个字段是否已设置
* @param key 字段名
* @return 若字段key已被设置,则返回true,否则返回false
*/
public bool IsSet(string key)
{
object o = null;
m_values.TryGetValue(key, out o);
if (null != o)
return true;
else
return false;
}
/**
* @将Dictionary转成xml
* @return 经转换得到的xml串
* @throws WxPayException
**/
public string ToXml()
{
//数据为空时不能转化为xml格式
if (0 == m_values.Count)
{
Log.Error(this.GetType().ToString(), "WxPayData数据为空!");
throw new WxPayException("WxPayData数据为空!");
}
string xml = "<xml>";
foreach (KeyValuePair<string, object> pair in m_values)
{
/