文章正文

抖音小程序支付(通用系统)开发教程(C#版本)

更新日期:2026-03-29来源:无忧酒店交易网浏览:11

为本站开发抖音小程序,到支付时,看了抖音官方文档,没有C#版本的,百度了几下,也是没有找到,本人是小白,就自己摸索了一下,总结如下,支付模式与微信小程序不一样。微信小程序下单流程是通过自已服务器下单,而抖音是通过自己服务器生成data和byteAuthorization,反回给前端,前端使用tt.requestOrder下单,获取订单号后调用tt.getOrderPayment发起支付,总体来说,还是比较复杂的,所以把开发过程记录下来,希望能够帮助有需要的。

一、开通通用交易系统OpenApi接口能力以及开通支付能力

(一)开通通用交易系统OpenApi接口能力。进入小程序控制台->能力->解决方案->交易类小程序通用,开通过过程需要填写预期使用场景和场景示意图。

预期使用场景:(如)在客户置顶信息是需要付费用。

场景示意图:就截图你已开发小程序需要支付的界面即可。

但我猜审核是系统审核,一般5分钟就开通了。

(二)开通支付能力。

进入小程序控制台->支付-支付能力,企业申请开通企事担保交易,个人的话也申请开通个人担保,开通后,可支持支付宝、微信支付。这一步需要准备法人证件,营业执照等。

二、类目配置

进入小程序控制台->设置->基础设置->类目与配置(点击去管理)-添加类目。这里的类目需要根据自己的实际需求进行填写。部分类目需要上传佐证资料。如果信息类的,建议选择工具-信息查询等,不需要上传其它辅助资料。

三、生成私钥与公钥

官方生成地址: https://developer.open-douyin.com/docs/openapi-explorer/sign ,选择PKCS8(JAVA适用),如下图

把生成的好的私钥和公钥复制,保存好,我使用的是privatekey.txt和publickey.txt保存在api目录下。以便调用,保存好之后,还需要把公钥上传到服务器:进入小程序控制台->开发->开发配置->密钥设置 把公钥粘贴进去->保存。

四、查询标签组信息

这一步,我直接填写官方文档上的goods_type和tag_group_id是不行的,还是需要写用httpclient发送post。方法如下:

(一)获取access_token

 获取AppID和AppSecret,进入小程序控制台->开发->开发配置,复制AppID,生成AppSecret不直接显示,生成一次记得复制保存。

 public static async Task<string> GetClientTokenAsync(string appId, string appSecret)

{

   try

   {

       // 1. 构建请求参数 (application/x-www-form-urlencoded)

       var parameters = new Dictionary<string, string>

   {

       { "client_key", appId },

       { "client_secret", appSecret },

       { "grant_type", "client_credential" }

   };

       using var content = new FormUrlEncodedContent(parameters);

       // 2. 发送 POST 请求

       var response = await _httpClient.PostAsync("https://open.douyin.com/oauth/client_token/", content);

       var responseBody = await response.Content.ReadAsStringAsync();

       return responseBody;

   }

   catch (Exception ex)

   {

       Console.WriteLine($"请求异常: {ex.Message}");

       return null;

   }

}

(二)获取goods_type和tag_group_id,GoodsType = 302这里需要根据你的类目来找,可以官方网站上获取。

public async Task<string> GetTypeAndTagid(string appId, string appSecret)

{

   string tagGroupId = null;

   string token = await requestOrder.GetClientTokenAsync(appId,, appSecret);

   var token1= JObject.Parse(token);

   string accessToken=token1["data"]["access_token"].ToString();

   string url = "https://open.douyin.com/api/trade_basic/v1/developer/tag_query/";

   HttpClient _httpClient= new HttpClient();

   // 2. 构建请求头

   _httpClient.DefaultRequestHeaders.Clear();

   _httpClient.DefaultRequestHeaders.Add("access-token", accessToken);

   // 3. 构建请求体

   var request = new TagQueryRequest

   {

       GoodsType = 302

   };

   string json = JsonConvert.SerializeObject(request);

   var content = new StringContent(json, Encoding.UTF8, "application/json");

   // 4. 发送请求

   using var response = await _httpClient.PostAsync(url, content);

   response.EnsureSuccessStatusCode();

   string responseJson = await response.Content.ReadAsStringAsync();

   return responseJson;

}

public class TagQueryRequest

{

   [JsonProperty("goods_type")]

   public int GoodsType { get; set; }

}

这一步下面,就能获取goods_type和tag_group_id,因为可能官网变化后,tag_group_id不一样,导致支付不了。

五、生成生成下单参数与签名

这一步非常关键,把这一步做好,后面基本就不成问题了。

(一)生成data,直接上方法

public static string BuildDouyinPayData(string outOrderNo, int totalAmount, string skuId, string title, string payNotifyUrl, string tagGroupId,string url,string myparams)

{

   // 构造官方格式对象

   var payData = new

   {

       skuList = new[]

       {

   new

   {

       skuId = skuId,

       price = totalAmount*100, // 单商品,价格=总金额

       quantity = 1,//数量

       title = title,//商品标题

       imageList = new[] { "https://www.xxxxxx.com/xxxx.png" }, // 可替换,商品图片

       type = 301, // 固定值 就就是第四步获取的goods_type

       tagGroupId = tagGroupId //第四步获取的tag_group_id

   }

},

       outOrderNo = outOrderNo,  //你自己的订单号

       totalAmount = totalAmount*100,//这里如果是多个商品,还需要*quantity

       payExpireSeconds = 300, // 5分钟

       orderEntrySchema = new { path =url, @params=myparams },//path为小程序业务路径,params为参数:“

{\"orderId\":\"123456\",\"userId\":\"12345678\"}"这种格式,特别重要,不要写错了

       payNotifyUrl = payNotifyUrl;//回调的url,就是支付成功后,返回给你api地址

   };

   // 序列化为 JSON(无格式化,符合抖音要求)

   return JsonConvert.SerializeObject(payData, Formatting.None);

}

(二)生成byteAuthorization

string data = BuildDouyinPayData(参数...)

string urlPath = "/requestOrder"; //这里一定是这个,不要更改

var auth = CreateByteAuthorization("POST", urlPath, data);//这条就是签名。

1. CreateByteAuthorization方法

public static string CreateByteAuthorization(string httpMethod, string urlPath, string requestBodyJson)

{

   // 1. 生成时间戳和随机串

   var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();

   var nonceStr = Guid.NewGuid().ToString("N"); // 官方示例使用 UUID 去掉横线

   // 2. 构造待签名字符串(5行,每行以 \n 结尾)

   var signContent = $"{httpMethod}\n{urlPath}\n{timestamp}\n{nonceStr}\n{requestBodyJson}\n";

   // 3. 使用私钥签名

   var signature = Sign(signContent);

   // 4. 构造 Byte-Authorization Header(注意参数名是 appid)

   return $"SHA256-RSA2048 appid={AppId},nonce_str={nonceStr},timestamp={timestamp},key_version=

{KeyVersion},signature={signature}";

}

2. Sign方法

public static string Sign(string content)

{

  using var rsa = LoadPrivateKey();

   var dataBytes = Encoding.UTF8.GetBytes(content);

   var signBytes = rsa.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

   return Convert.ToBase64String(signBytes);

}

3.LoadPrivateKey()方法

public static RSA LoadPrivateKey()

{

   var privateKeyPem = File.ReadAllText(Directory.GetCurrentDirectory()+ "/xxx/privatekey.txt");//放置privatekey.txt的位置

   var pem = privateKeyPem

       .Replace("-----BEGIN PRIVATE KEY-----", "")

       .Replace("-----END PRIVATE KEY-----", "")

       .Replace("\r", "")

       .Replace("\n", "")

       .Trim();

   var privateKeyBytes = Convert.FromBase64String(pem);

   var rsa = RSA.Create();

   rsa.ImportPkcs8PrivateKey(privateKeyBytes, out _);

   return rsa;

}

好,生成data和byteAuthorization(上面的auth)返回给前端。

六、发起支付

tt.requestOrder({

     data:data

     byteAuthorization: auth, // 开发者服务端返回的byteAuthorization

     success: (res) => {

       tt.getOrderPayment({

       orderId: res.orderId, // 替换为抖音开放平台内部的交易订单号

       success: (ress) => {

       console.log("支付成功", ress);

//把相关支付结果回传api

       tt.showToast({

         icon: "success",

         title: "支付成功",

       });

     },

     fail: (ress) => {

       console.error("支付失败", ress);

       const { errNo, errMsg } = ress;

       tt.showToast({

         icon: "fail",

         title: "支付失败",

       });

     },

   });

     },

     fail: (res) => {

       const { errLogId, errMsg, errNo } = res;

       console.log("errNo:", errNo);

       console.log("errMsg:", errMsg);

     },

   });。

按照本文思路,能够实现支付,建议开发过程中,一定要注意安全问题,上述代码只是实现部分核心关键。本文为

原创,转载请标明来自己无忧酒店交易网。

酒店转让信息推荐

无忧酒店交易网-- 版权所有--贵州宜住酒店管理有限公司 备案号:黔ICP备2025044839号-1

违法信息举报邮箱: jiudianzr@163.com 业务合作邮箱:jiudianzr@163.com

流量统计